grpc 1.49.0.pre1-x86_64-linux → 1.50.0.pre1-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (277) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +54 -153
  3. data/include/grpc/event_engine/endpoint_config.h +11 -5
  4. data/include/grpc/event_engine/event_engine.h +1 -1
  5. data/include/grpc/impl/codegen/atm_gcc_atomic.h +19 -28
  6. data/include/grpc/impl/codegen/atm_gcc_sync.h +0 -2
  7. data/include/grpc/impl/codegen/atm_windows.h +0 -2
  8. data/include/grpc/impl/codegen/grpc_types.h +6 -0
  9. data/src/core/ext/filters/channel_idle/channel_idle_filter.cc +3 -3
  10. data/src/core/ext/filters/client_channel/backup_poller.cc +4 -6
  11. data/src/core/ext/filters/client_channel/client_channel.cc +41 -22
  12. data/src/core/ext/filters/client_channel/client_channel.h +1 -1
  13. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +0 -16
  14. data/src/core/ext/filters/client_channel/http_proxy.cc +12 -19
  15. data/src/core/ext/filters/client_channel/http_proxy.h +3 -2
  16. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +6 -4
  17. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h +5 -4
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +0 -2
  19. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +114 -103
  20. data/src/core/ext/filters/client_channel/lb_policy/oob_backend_metric.cc +20 -11
  21. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc +106 -108
  22. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.h +16 -0
  23. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +20 -13
  24. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +165 -257
  25. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +218 -231
  26. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +10 -6
  27. data/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +389 -444
  28. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +16 -16
  29. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +8 -13
  30. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +87 -96
  31. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +38 -37
  32. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +106 -186
  33. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +106 -93
  34. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +170 -218
  35. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +2 -2
  36. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +1 -1
  37. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +38 -18
  38. data/src/core/ext/filters/client_channel/resolver/polling_resolver.cc +84 -37
  39. data/src/core/ext/filters/client_channel/resolver/polling_resolver.h +11 -0
  40. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +1 -0
  41. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +5 -3
  42. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +5 -4
  43. data/src/core/ext/filters/client_channel/retry_filter.cc +25 -29
  44. data/src/core/ext/filters/client_channel/subchannel.cc +38 -33
  45. data/src/core/ext/filters/client_channel/subchannel.h +12 -3
  46. data/src/core/ext/filters/client_channel/subchannel_stream_client.cc +1 -2
  47. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +23 -16
  48. data/src/core/ext/filters/fault_injection/fault_injection_filter.h +8 -0
  49. data/src/core/ext/filters/http/client/http_client_filter.cc +1 -2
  50. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +2 -4
  51. data/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +0 -2
  52. data/src/core/ext/filters/http/server/http_server_filter.cc +1 -2
  53. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +12 -8
  54. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +32 -26
  55. data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +1 -1
  56. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +25 -130
  57. data/src/core/ext/transport/chttp2/transport/decode_huff.cc +287 -0
  58. data/src/core/ext/transport/chttp2/transport/decode_huff.h +1018 -0
  59. data/src/core/ext/transport/chttp2/transport/flow_control.cc +83 -51
  60. data/src/core/ext/transport/chttp2/transport/flow_control.h +11 -6
  61. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +1 -2
  62. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +2 -20
  63. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +28 -28
  64. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +1 -10
  65. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +11 -6
  66. data/src/core/ext/transport/chttp2/transport/internal.h +2 -0
  67. data/src/core/ext/transport/chttp2/transport/parsing.cc +44 -0
  68. data/src/core/ext/transport/chttp2/transport/writing.cc +3 -14
  69. data/src/core/ext/transport/inproc/inproc_transport.cc +1 -3
  70. data/src/core/ext/xds/certificate_provider_store.cc +63 -3
  71. data/src/core/ext/xds/certificate_provider_store.h +9 -1
  72. data/src/core/ext/xds/file_watcher_certificate_provider_factory.cc +5 -5
  73. data/src/core/ext/xds/file_watcher_certificate_provider_factory.h +1 -1
  74. data/src/core/ext/xds/xds_api.cc +21 -17
  75. data/src/core/ext/xds/xds_api.h +7 -0
  76. data/src/core/ext/xds/xds_bootstrap.cc +5 -537
  77. data/src/core/ext/xds/xds_bootstrap.h +39 -111
  78. data/src/core/ext/xds/xds_bootstrap_grpc.cc +370 -0
  79. data/src/core/ext/xds/xds_bootstrap_grpc.h +169 -0
  80. data/src/core/ext/xds/xds_client.cc +219 -145
  81. data/src/core/ext/xds/xds_client.h +19 -17
  82. data/src/core/ext/xds/xds_client_grpc.cc +18 -80
  83. data/src/core/ext/xds/xds_client_grpc.h +2 -25
  84. data/src/core/ext/xds/xds_client_stats.cc +4 -4
  85. data/src/core/ext/xds/xds_cluster.cc +87 -79
  86. data/src/core/ext/xds/xds_cluster.h +5 -5
  87. data/src/core/ext/xds/xds_cluster_specifier_plugin.cc +3 -1
  88. data/src/core/ext/xds/xds_common_types.cc +13 -5
  89. data/src/core/ext/xds/xds_endpoint.cc +8 -6
  90. data/src/core/ext/xds/xds_endpoint.h +3 -4
  91. data/src/core/ext/xds/xds_lb_policy_registry.cc +4 -2
  92. data/src/core/ext/xds/xds_listener.cc +25 -20
  93. data/src/core/ext/xds/xds_listener.h +3 -4
  94. data/src/core/ext/xds/xds_resource_type.h +11 -8
  95. data/src/core/ext/xds/xds_route_config.cc +15 -16
  96. data/src/core/ext/xds/xds_route_config.h +3 -3
  97. data/src/core/ext/xds/xds_server_config_fetcher.cc +7 -5
  98. data/src/core/ext/xds/xds_transport_grpc.cc +15 -7
  99. data/src/core/lib/backoff/backoff.cc +2 -4
  100. data/src/core/lib/channel/call_finalization.h +1 -3
  101. data/src/core/lib/channel/channel_args.h +114 -14
  102. data/src/core/lib/channel/channel_trace.cc +3 -4
  103. data/src/core/lib/channel/promise_based_filter.cc +18 -19
  104. data/src/core/lib/channel/status_util.cc +27 -0
  105. data/src/core/lib/channel/status_util.h +10 -0
  106. data/src/core/lib/config/core_configuration.cc +5 -1
  107. data/src/core/lib/config/core_configuration.h +33 -0
  108. data/src/core/lib/debug/stats.cc +26 -30
  109. data/src/core/lib/debug/stats.h +2 -12
  110. data/src/core/lib/debug/stats_data.cc +118 -614
  111. data/src/core/lib/debug/stats_data.h +67 -465
  112. data/src/core/lib/debug/trace.cc +0 -2
  113. data/src/core/lib/event_engine/channel_args_endpoint_config.cc +12 -20
  114. data/src/core/lib/event_engine/channel_args_endpoint_config.h +13 -7
  115. data/src/core/lib/event_engine/forkable.cc +19 -16
  116. data/src/core/lib/event_engine/poller.h +14 -12
  117. data/src/core/lib/event_engine/posix_engine/timer_manager.cc +53 -32
  118. data/src/core/lib/event_engine/posix_engine/timer_manager.h +23 -1
  119. data/src/core/lib/event_engine/thread_pool.cc +131 -94
  120. data/src/core/lib/event_engine/thread_pool.h +56 -23
  121. data/src/core/lib/event_engine/time_util.cc +30 -0
  122. data/src/core/lib/event_engine/time_util.h +32 -0
  123. data/src/core/lib/event_engine/utils.cc +0 -5
  124. data/src/core/lib/event_engine/utils.h +0 -4
  125. data/src/core/lib/event_engine/windows/iocp.cc +13 -7
  126. data/src/core/lib/event_engine/windows/iocp.h +2 -1
  127. data/src/core/lib/event_engine/windows/win_socket.cc +1 -1
  128. data/src/core/lib/experiments/config.cc +146 -0
  129. data/src/core/lib/experiments/config.h +43 -0
  130. data/src/core/lib/experiments/experiments.cc +75 -0
  131. data/src/core/lib/experiments/experiments.h +56 -0
  132. data/src/core/lib/gpr/alloc.cc +1 -9
  133. data/src/core/lib/gpr/log_windows.cc +0 -1
  134. data/src/core/lib/gpr/string_util_windows.cc +3 -30
  135. data/src/core/lib/gpr/sync_abseil.cc +0 -14
  136. data/src/core/lib/gpr/sync_posix.cc +0 -14
  137. data/src/core/lib/gpr/time_posix.cc +0 -6
  138. data/src/core/lib/gpr/time_precise.h +1 -1
  139. data/src/core/lib/gpr/tmpfile_windows.cc +5 -7
  140. data/src/core/lib/gpr/useful.h +11 -0
  141. data/src/core/lib/{gpr → gprpp}/env.h +25 -12
  142. data/src/core/lib/{gpr → gprpp}/env_linux.cc +20 -15
  143. data/src/core/lib/{gpr → gprpp}/env_posix.cc +11 -10
  144. data/src/core/lib/gprpp/env_windows.cc +56 -0
  145. data/src/core/lib/gprpp/fork.cc +14 -22
  146. data/src/core/lib/gprpp/fork.h +0 -8
  147. data/src/core/lib/gprpp/global_config_env.cc +7 -6
  148. data/src/core/lib/gprpp/notification.h +67 -0
  149. data/src/core/lib/gprpp/packed_table.h +40 -0
  150. data/src/core/lib/gprpp/ref_counted_ptr.h +20 -33
  151. data/src/core/lib/gprpp/sorted_pack.h +98 -0
  152. data/src/core/lib/gprpp/status_helper.h +6 -0
  153. data/src/core/lib/gprpp/table.h +9 -1
  154. data/src/core/lib/gprpp/tchar.cc +49 -0
  155. data/src/core/lib/gprpp/tchar.h +33 -0
  156. data/src/core/lib/gprpp/time.cc +21 -0
  157. data/src/core/lib/gprpp/time.h +55 -0
  158. data/src/core/lib/gprpp/validation_errors.cc +61 -0
  159. data/src/core/lib/gprpp/validation_errors.h +110 -0
  160. data/src/core/{ext/filters/client_channel → lib/handshaker}/proxy_mapper.h +3 -3
  161. data/src/core/{ext/filters/client_channel → lib/handshaker}/proxy_mapper_registry.cc +14 -36
  162. data/src/core/lib/handshaker/proxy_mapper_registry.h +75 -0
  163. data/src/core/lib/iomgr/call_combiner.cc +0 -8
  164. data/src/core/lib/iomgr/closure.h +0 -1
  165. data/src/core/lib/iomgr/endpoint_pair_posix.cc +14 -10
  166. data/src/core/lib/iomgr/endpoint_pair_windows.cc +2 -2
  167. data/src/core/lib/iomgr/ev_epoll1_linux.cc +1 -38
  168. data/src/core/lib/iomgr/ev_poll_posix.cc +2 -17
  169. data/src/core/lib/iomgr/exec_ctx.cc +0 -10
  170. data/src/core/lib/iomgr/exec_ctx.h +7 -31
  171. data/src/core/lib/iomgr/iocp_windows.cc +1 -2
  172. data/src/core/lib/iomgr/iomgr.cc +6 -8
  173. data/src/core/lib/iomgr/iomgr_fwd.h +1 -0
  174. data/src/core/lib/iomgr/pollset.h +1 -1
  175. data/src/core/lib/iomgr/pollset_set.h +0 -1
  176. data/src/core/lib/iomgr/resolve_address.h +1 -0
  177. data/src/core/lib/iomgr/resolve_address_impl.h +1 -0
  178. data/src/core/lib/iomgr/resolve_address_posix.cc +5 -0
  179. data/src/core/lib/iomgr/resolve_address_windows.cc +5 -0
  180. data/src/core/lib/iomgr/sockaddr_utils_posix.cc +2 -1
  181. data/src/core/lib/iomgr/socket_utils_common_posix.cc +12 -34
  182. data/src/core/lib/iomgr/socket_utils_posix.cc +83 -1
  183. data/src/core/lib/iomgr/socket_utils_posix.h +98 -6
  184. data/src/core/lib/iomgr/tcp_client.cc +6 -7
  185. data/src/core/lib/iomgr/tcp_client.h +11 -11
  186. data/src/core/lib/iomgr/tcp_client_cfstream.cc +6 -6
  187. data/src/core/lib/iomgr/tcp_client_posix.cc +33 -29
  188. data/src/core/lib/iomgr/tcp_client_posix.h +12 -9
  189. data/src/core/lib/iomgr/tcp_client_windows.cc +6 -6
  190. data/src/core/lib/iomgr/tcp_posix.cc +131 -114
  191. data/src/core/lib/iomgr/tcp_posix.h +3 -1
  192. data/src/core/lib/iomgr/tcp_server.cc +5 -4
  193. data/src/core/lib/iomgr/tcp_server.h +9 -6
  194. data/src/core/lib/iomgr/tcp_server_posix.cc +17 -28
  195. data/src/core/lib/iomgr/tcp_server_utils_posix.h +2 -2
  196. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +3 -3
  197. data/src/core/lib/iomgr/tcp_server_windows.cc +6 -7
  198. data/src/core/lib/iomgr/tcp_windows.cc +0 -1
  199. data/src/core/lib/iomgr/tcp_windows.h +0 -1
  200. data/src/core/lib/iomgr/timer_generic.cc +4 -4
  201. data/src/core/lib/iomgr/timer_manager.cc +1 -2
  202. data/src/core/lib/iomgr/wakeup_fd_eventfd.cc +0 -2
  203. data/src/core/lib/json/json_object_loader.cc +21 -52
  204. data/src/core/lib/json/json_object_loader.h +56 -76
  205. data/src/core/lib/json/json_util.cc +2 -1
  206. data/src/core/lib/load_balancing/lb_policy.h +5 -5
  207. data/src/core/lib/load_balancing/lb_policy_registry.cc +29 -55
  208. data/src/core/lib/load_balancing/lb_policy_registry.h +23 -11
  209. data/src/core/lib/promise/activity.h +2 -3
  210. data/src/core/lib/promise/context.h +1 -1
  211. data/src/core/lib/promise/sleep.cc +16 -4
  212. data/src/core/lib/promise/sleep.h +8 -2
  213. data/src/core/lib/resolver/resolver.h +13 -3
  214. data/src/core/lib/resource_quota/api.cc +9 -0
  215. data/src/core/lib/resource_quota/api.h +6 -0
  216. data/src/core/lib/resource_quota/arena.cc +1 -3
  217. data/src/core/lib/resource_quota/memory_quota.cc +8 -24
  218. data/src/core/lib/resource_quota/memory_quota.h +6 -19
  219. data/src/core/lib/resource_quota/periodic_update.cc +2 -3
  220. data/src/core/{ext/xds → lib/security/certificate_provider}/certificate_provider_factory.h +3 -3
  221. data/src/core/lib/security/certificate_provider/certificate_provider_registry.cc +60 -0
  222. data/src/core/lib/security/certificate_provider/certificate_provider_registry.h +70 -0
  223. data/src/core/lib/security/credentials/channel_creds_registry_init.cc +1 -0
  224. data/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +15 -16
  225. data/src/core/lib/security/credentials/external/external_account_credentials.cc +2 -1
  226. data/src/core/lib/security/credentials/google_default/credentials_generic.cc +5 -8
  227. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +6 -6
  228. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +3 -2
  229. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +1 -1
  230. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -2
  231. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc +4 -3
  232. data/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h +4 -2
  233. data/src/core/lib/security/credentials/tls/tls_utils.cc +3 -1
  234. data/src/core/lib/security/transport/client_auth_filter.cc +12 -1
  235. data/src/core/lib/security/transport/secure_endpoint.cc +0 -4
  236. data/src/core/lib/surface/call.cc +1 -11
  237. data/src/core/lib/surface/channel.cc +3 -2
  238. data/src/core/lib/surface/completion_queue.cc +16 -28
  239. data/src/core/lib/surface/completion_queue.h +1 -1
  240. data/src/core/lib/surface/completion_queue_factory.cc +5 -0
  241. data/src/core/lib/surface/init.cc +16 -11
  242. data/src/core/lib/surface/init_internally.cc +24 -0
  243. data/src/core/lib/surface/init_internally.h +28 -0
  244. data/src/core/lib/surface/server.cc +1 -7
  245. data/src/core/lib/surface/server.h +4 -6
  246. data/src/core/lib/surface/version.cc +2 -2
  247. data/src/core/lib/transport/bdp_estimator.cc +1 -3
  248. data/src/core/lib/transport/metadata_batch.cc +2 -3
  249. data/src/core/lib/transport/metadata_batch.h +9 -7
  250. data/src/core/lib/transport/parsed_metadata.h +4 -2
  251. data/src/core/lib/transport/status_conversion.cc +1 -3
  252. data/src/core/lib/transport/tcp_connect_handshaker.cc +9 -5
  253. data/src/core/lib/transport/transport.h +0 -1
  254. data/src/core/lib/transport/transport_impl.h +0 -1
  255. data/src/core/plugin_registry/grpc_plugin_registry.cc +23 -46
  256. data/src/core/plugin_registry/grpc_plugin_registry_extra.cc +13 -25
  257. data/src/ruby/ext/grpc/extconf.rb +1 -1
  258. data/src/ruby/lib/grpc/2.6/grpc_c.so +0 -0
  259. data/src/ruby/lib/grpc/2.7/grpc_c.so +0 -0
  260. data/src/ruby/lib/grpc/3.0/grpc_c.so +0 -0
  261. data/src/ruby/lib/grpc/3.1/grpc_c.so +0 -0
  262. data/src/ruby/lib/grpc/grpc_c.so +0 -0
  263. data/src/ruby/lib/grpc/version.rb +1 -1
  264. data/src/ruby/spec/channel_spec.rb +5 -0
  265. data/src/ruby/spec/generic/server_interceptors_spec.rb +1 -1
  266. data/src/ruby/spec/user_agent_spec.rb +1 -1
  267. metadata +32 -19
  268. data/src/core/ext/filters/client_channel/proxy_mapper_registry.h +0 -56
  269. data/src/core/ext/xds/certificate_provider_registry.cc +0 -103
  270. data/src/core/ext/xds/certificate_provider_registry.h +0 -59
  271. data/src/core/lib/event_engine/promise.h +0 -78
  272. data/src/core/lib/gpr/env_windows.cc +0 -74
  273. data/src/core/lib/gpr/string_windows.h +0 -32
  274. data/src/core/lib/profiling/basic_timers.cc +0 -295
  275. data/src/core/lib/profiling/stap_timers.cc +0 -50
  276. data/src/core/lib/profiling/timers.h +0 -94
  277. data/src/ruby/lib/grpc/2.5/grpc_c.so +0 -0
@@ -75,6 +75,7 @@
75
75
  #include "src/core/lib/gprpp/ref_counted_ptr.h"
76
76
  #include "src/core/lib/gprpp/sync.h"
77
77
  #include "src/core/lib/gprpp/time.h"
78
+ #include "src/core/lib/gprpp/validation_errors.h"
78
79
  #include "src/core/lib/gprpp/work_serializer.h"
79
80
  #include "src/core/lib/iomgr/closure.h"
80
81
  #include "src/core/lib/iomgr/error.h"
@@ -82,7 +83,8 @@
82
83
  #include "src/core/lib/iomgr/pollset_set.h"
83
84
  #include "src/core/lib/iomgr/timer.h"
84
85
  #include "src/core/lib/json/json.h"
85
- #include "src/core/lib/json/json_util.h"
86
+ #include "src/core/lib/json/json_args.h"
87
+ #include "src/core/lib/json/json_object_loader.h"
86
88
  #include "src/core/lib/load_balancing/lb_policy.h"
87
89
  #include "src/core/lib/load_balancing/lb_policy_factory.h"
88
90
  #include "src/core/lib/load_balancing/lb_policy_registry.h"
@@ -142,25 +144,24 @@ class RlsLbConfig : public LoadBalancingPolicy::Config {
142
144
  struct RouteLookupConfig {
143
145
  KeyBuilderMap key_builder_map;
144
146
  std::string lookup_service;
145
- Duration lookup_service_timeout;
146
- Duration max_age;
147
- Duration stale_age;
147
+ Duration lookup_service_timeout = kDefaultLookupServiceTimeout;
148
+ Duration max_age = kMaxMaxAge;
149
+ Duration stale_age = kMaxMaxAge;
148
150
  int64_t cache_size_bytes = 0;
149
151
  std::string default_target;
152
+
153
+ static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
154
+ void JsonPostLoad(const Json& json, const JsonArgs& args,
155
+ ValidationErrors* errors);
150
156
  };
151
157
 
152
- RlsLbConfig(RouteLookupConfig route_lookup_config,
153
- std::string rls_channel_service_config, Json child_policy_config,
154
- std::string child_policy_config_target_field_name,
155
- RefCountedPtr<LoadBalancingPolicy::Config>
156
- default_child_policy_parsed_config)
157
- : route_lookup_config_(std::move(route_lookup_config)),
158
- rls_channel_service_config_(std::move(rls_channel_service_config)),
159
- child_policy_config_(std::move(child_policy_config)),
160
- child_policy_config_target_field_name_(
161
- std::move(child_policy_config_target_field_name)),
162
- default_child_policy_parsed_config_(
163
- std::move(default_child_policy_parsed_config)) {}
158
+ RlsLbConfig() = default;
159
+
160
+ RlsLbConfig(const RlsLbConfig&) = delete;
161
+ RlsLbConfig& operator=(const RlsLbConfig&) = delete;
162
+
163
+ RlsLbConfig(RlsLbConfig&& other) = delete;
164
+ RlsLbConfig& operator=(RlsLbConfig&& other) = delete;
164
165
 
165
166
  absl::string_view name() const override { return kRls; }
166
167
 
@@ -193,6 +194,10 @@ class RlsLbConfig : public LoadBalancingPolicy::Config {
193
194
  return default_child_policy_parsed_config_;
194
195
  }
195
196
 
197
+ static const JsonLoaderInterface* JsonLoader(const JsonArgs&);
198
+ void JsonPostLoad(const Json& json, const JsonArgs&,
199
+ ValidationErrors* errors);
200
+
196
201
  private:
197
202
  RouteLookupConfig route_lookup_config_;
198
203
  std::string rls_channel_service_config_;
@@ -208,7 +213,7 @@ class RlsLb : public LoadBalancingPolicy {
208
213
  explicit RlsLb(Args args);
209
214
 
210
215
  absl::string_view name() const override { return kRls; }
211
- void UpdateLocked(UpdateArgs args) override;
216
+ absl::Status UpdateLocked(UpdateArgs args) override;
212
217
  void ExitIdleLocked() override;
213
218
  void ResetBackoffLocked() override;
214
219
 
@@ -293,7 +298,7 @@ class RlsLb : public LoadBalancingPolicy {
293
298
  //
294
299
  // Both methods grab the data they need from the parent object.
295
300
  void StartUpdate() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_);
296
- void MaybeFinishUpdate() ABSL_LOCKS_EXCLUDED(&RlsLb::mu_);
301
+ absl::Status MaybeFinishUpdate() ABSL_LOCKS_EXCLUDED(&RlsLb::mu_);
297
302
 
298
303
  void ExitIdleLocked() {
299
304
  if (child_policy_ != nullptr) child_policy_->ExitIdleLocked();
@@ -742,28 +747,32 @@ void RlsLb::ChildPolicyWrapper::Orphan() {
742
747
  picker_.reset();
743
748
  }
744
749
 
745
- grpc_error_handle InsertOrUpdateChildPolicyField(const std::string& field,
746
- const std::string& value,
747
- Json* config) {
750
+ bool InsertOrUpdateChildPolicyField(const std::string& field,
751
+ const std::string& value, Json* config,
752
+ ValidationErrors* errors) {
748
753
  if (config->type() != Json::Type::ARRAY) {
749
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
750
- "child policy configuration is not an array");
754
+ errors->AddError("is not an array");
755
+ return false;
751
756
  }
752
- std::vector<grpc_error_handle> error_list;
753
- for (Json& child_json : *config->mutable_array()) {
757
+ bool success = true;
758
+ for (size_t i = 0; i < config->array_value().size(); ++i) {
759
+ Json& child_json = (*config->mutable_array())[i];
760
+ ValidationErrors::ScopedField json_field(errors, absl::StrCat("[", i, "]"));
754
761
  if (child_json.type() != Json::Type::OBJECT) {
755
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
756
- "child policy item is not an object"));
762
+ errors->AddError("is not an object");
763
+ success = false;
757
764
  } else {
758
765
  Json::Object& child = *child_json.mutable_object();
759
766
  if (child.size() != 1) {
760
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
761
- "child policy item contains more than one field"));
767
+ errors->AddError("child policy object contains more than one field");
768
+ success = false;
762
769
  } else {
770
+ ValidationErrors::ScopedField json_field(
771
+ errors, absl::StrCat("[\"", child.begin()->first, "\"]"));
763
772
  Json& child_config_json = child.begin()->second;
764
773
  if (child_config_json.type() != Json::Type::OBJECT) {
765
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
766
- "child policy item config is not an object"));
774
+ errors->AddError("child policy config is not an object");
775
+ success = false;
767
776
  } else {
768
777
  Json::Object& child_config = *child_config_json.mutable_object();
769
778
  child_config[field] = Json(value);
@@ -771,18 +780,15 @@ grpc_error_handle InsertOrUpdateChildPolicyField(const std::string& field,
771
780
  }
772
781
  }
773
782
  }
774
- return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
775
- absl::StrCat("errors when inserting field \"", field,
776
- "\" for child policy"),
777
- &error_list);
783
+ return success;
778
784
  }
779
785
 
780
786
  void RlsLb::ChildPolicyWrapper::StartUpdate() {
781
787
  Json child_policy_config = lb_policy_->config_->child_policy_config();
782
- grpc_error_handle error = InsertOrUpdateChildPolicyField(
788
+ ValidationErrors errors;
789
+ GPR_ASSERT(InsertOrUpdateChildPolicyField(
783
790
  lb_policy_->config_->child_policy_config_target_field_name(), target_,
784
- &child_policy_config);
785
- GPR_ASSERT(GRPC_ERROR_IS_NONE(error));
791
+ &child_policy_config, &errors));
786
792
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
787
793
  gpr_log(
788
794
  GPR_INFO,
@@ -790,8 +796,9 @@ void RlsLb::ChildPolicyWrapper::StartUpdate() {
790
796
  lb_policy_.get(), this, target_.c_str(),
791
797
  child_policy_config.Dump().c_str());
792
798
  }
793
- auto config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
794
- child_policy_config);
799
+ auto config =
800
+ CoreConfiguration::Get().lb_policy_registry().ParseLoadBalancingConfig(
801
+ child_policy_config);
795
802
  // Returned RLS target fails the validation.
796
803
  if (!config.ok()) {
797
804
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
@@ -810,10 +817,10 @@ void RlsLb::ChildPolicyWrapper::StartUpdate() {
810
817
  }
811
818
  }
812
819
 
813
- void RlsLb::ChildPolicyWrapper::MaybeFinishUpdate() {
820
+ absl::Status RlsLb::ChildPolicyWrapper::MaybeFinishUpdate() {
814
821
  // If pending_config_ is not set, that means StartUpdate() failed, so
815
822
  // there's nothing to do here.
816
- if (pending_config_ == nullptr) return;
823
+ if (pending_config_ == nullptr) return absl::OkStatus();
817
824
  // If child policy doesn't yet exist, create it.
818
825
  if (child_policy_ == nullptr) {
819
826
  Args create_args;
@@ -843,7 +850,7 @@ void RlsLb::ChildPolicyWrapper::MaybeFinishUpdate() {
843
850
  update_args.config = std::move(pending_config_);
844
851
  update_args.addresses = lb_policy_->addresses_;
845
852
  update_args.args = lb_policy_->channel_args_;
846
- child_policy_->UpdateLocked(std::move(update_args));
853
+ return child_policy_->UpdateLocked(std::move(update_args));
847
854
  }
848
855
 
849
856
  //
@@ -1013,7 +1020,7 @@ LoadBalancingPolicy::PickResult RlsLb::Picker::Pick(PickArgs args) {
1013
1020
  gpr_log(GPR_INFO, "[rlslb %p] picker=%p: request keys: %s",
1014
1021
  lb_policy_.get(), this, key.ToString().c_str());
1015
1022
  }
1016
- Timestamp now = ExecCtx::Get()->Now();
1023
+ Timestamp now = Timestamp::Now();
1017
1024
  MutexLock lock(&lb_policy_->mu_);
1018
1025
  if (lb_policy_->is_shutdown_) {
1019
1026
  return PickResult::Fail(
@@ -1163,7 +1170,7 @@ RlsLb::Cache::Entry::Entry(RefCountedPtr<RlsLb> lb_policy,
1163
1170
  GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace) ? "CacheEntry" : nullptr),
1164
1171
  lb_policy_(std::move(lb_policy)),
1165
1172
  backoff_state_(MakeCacheEntryBackoff()),
1166
- min_expiration_time_(ExecCtx::Get()->Now() + kMinExpirationTime),
1173
+ min_expiration_time_(Timestamp::Now() + kMinExpirationTime),
1167
1174
  lru_iterator_(lb_policy_->cache_.lru_list_.insert(
1168
1175
  lb_policy_->cache_.lru_list_.end(), key)) {}
1169
1176
 
@@ -1241,12 +1248,12 @@ void RlsLb::Cache::Entry::ResetBackoff() {
1241
1248
  }
1242
1249
 
1243
1250
  bool RlsLb::Cache::Entry::ShouldRemove() const {
1244
- Timestamp now = ExecCtx::Get()->Now();
1251
+ Timestamp now = Timestamp::Now();
1245
1252
  return data_expiration_time_ < now && backoff_expiration_time_ < now;
1246
1253
  }
1247
1254
 
1248
1255
  bool RlsLb::Cache::Entry::CanEvict() const {
1249
- Timestamp now = ExecCtx::Get()->Now();
1256
+ Timestamp now = Timestamp::Now();
1250
1257
  return min_expiration_time_ < now;
1251
1258
  }
1252
1259
 
@@ -1272,7 +1279,7 @@ RlsLb::Cache::Entry::OnRlsResponseLocked(
1272
1279
  backoff_state_ = MakeCacheEntryBackoff();
1273
1280
  }
1274
1281
  backoff_time_ = backoff_state_->NextAttemptTime();
1275
- Timestamp now = ExecCtx::Get()->Now();
1282
+ Timestamp now = Timestamp::Now();
1276
1283
  backoff_expiration_time_ = now + (backoff_time_ - now) * 2;
1277
1284
  backoff_timer_ = MakeOrphanable<BackoffTimer>(
1278
1285
  Ref(DEBUG_LOCATION, "BackoffTimer"), backoff_time_);
@@ -1281,7 +1288,7 @@ RlsLb::Cache::Entry::OnRlsResponseLocked(
1281
1288
  }
1282
1289
  // Request succeeded, so store the result.
1283
1290
  header_data_ = std::move(response.header_data);
1284
- Timestamp now = ExecCtx::Get()->Now();
1291
+ Timestamp now = Timestamp::Now();
1285
1292
  data_expiration_time_ = now + lb_policy_->config_->max_age();
1286
1293
  stale_time_ = now + lb_policy_->config_->stale_age();
1287
1294
  status_ = absl::OkStatus();
@@ -1347,7 +1354,7 @@ RlsLb::Cache::Entry::OnRlsResponseLocked(
1347
1354
  //
1348
1355
 
1349
1356
  RlsLb::Cache::Cache(RlsLb* lb_policy) : lb_policy_(lb_policy) {
1350
- Timestamp now = ExecCtx::Get()->Now();
1357
+ Timestamp now = Timestamp::Now();
1351
1358
  lb_policy_->Ref(DEBUG_LOCATION, "CacheCleanupTimer").release();
1352
1359
  GRPC_CLOSURE_INIT(&timer_callback_, OnCleanupTimer, this, nullptr);
1353
1360
  grpc_timer_init(&cleanup_timer_, now + kCacheCleanupTimerInterval,
@@ -1430,7 +1437,7 @@ void RlsLb::Cache::OnCleanupTimer(void* arg, grpc_error_handle error) {
1430
1437
  ++it;
1431
1438
  }
1432
1439
  }
1433
- Timestamp now = ExecCtx::Get()->Now();
1440
+ Timestamp now = Timestamp::Now();
1434
1441
  lb_policy.release();
1435
1442
  grpc_timer_init(&cache->cleanup_timer_,
1436
1443
  now + kCacheCleanupTimerInterval,
@@ -1499,7 +1506,7 @@ void RlsLb::RlsChannel::StateWatcher::OnConnectivityStateChange(
1499
1506
  //
1500
1507
 
1501
1508
  bool RlsLb::RlsChannel::Throttle::ShouldThrottle() {
1502
- Timestamp now = ExecCtx::Get()->Now();
1509
+ Timestamp now = Timestamp::Now();
1503
1510
  while (!requests_.empty() && now - requests_.front() > window_size_) {
1504
1511
  requests_.pop_front();
1505
1512
  }
@@ -1527,7 +1534,7 @@ bool RlsLb::RlsChannel::Throttle::ShouldThrottle() {
1527
1534
  }
1528
1535
 
1529
1536
  void RlsLb::RlsChannel::Throttle::RegisterResponse(bool success) {
1530
- Timestamp now = ExecCtx::Get()->Now();
1537
+ Timestamp now = Timestamp::Now();
1531
1538
  requests_.push_back(now);
1532
1539
  if (!success) failures_.push_back(now);
1533
1540
  }
@@ -1707,7 +1714,7 @@ void RlsLb::RlsRequest::StartCallLocked() {
1707
1714
  MutexLock lock(&lb_policy_->mu_);
1708
1715
  if (lb_policy_->is_shutdown_) return;
1709
1716
  }
1710
- Timestamp now = ExecCtx::Get()->Now();
1717
+ Timestamp now = Timestamp::Now();
1711
1718
  deadline_ = now + lb_policy_->config_->lookup_service_timeout();
1712
1719
  grpc_metadata_array_init(&recv_initial_metadata_);
1713
1720
  grpc_metadata_array_init(&recv_trailing_metadata_);
@@ -1808,7 +1815,9 @@ void RlsLb::RlsRequest::OnRlsCallCompleteLocked(grpc_error_handle error) {
1808
1815
  // Now that we've released the lock, finish the update on any newly
1809
1816
  // created child policies.
1810
1817
  for (ChildPolicyWrapper* child : child_policies_to_finish_update) {
1811
- child->MaybeFinishUpdate();
1818
+ // TODO(roth): If the child reports an error with the update, we
1819
+ // need to propagate that back to the resolver somehow.
1820
+ (void)child->MaybeFinishUpdate();
1812
1821
  }
1813
1822
  }
1814
1823
 
@@ -1896,7 +1905,7 @@ RlsLb::RlsLb(Args args)
1896
1905
  }
1897
1906
  }
1898
1907
 
1899
- void RlsLb::UpdateLocked(UpdateArgs args) {
1908
+ absl::Status RlsLb::UpdateLocked(UpdateArgs args) {
1900
1909
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
1901
1910
  gpr_log(GPR_INFO, "[rlslb %p] policy updated", this);
1902
1911
  }
@@ -1987,19 +1996,28 @@ void RlsLb::UpdateLocked(UpdateArgs args) {
1987
1996
  }
1988
1997
  }
1989
1998
  // Now that we've released the lock, finish update of child policies.
1999
+ std::vector<std::string> errors;
1990
2000
  if (update_child_policies) {
1991
2001
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
1992
2002
  gpr_log(GPR_INFO, "[rlslb %p] finishing child policy updates", this);
1993
2003
  }
1994
2004
  for (auto& p : child_policy_map_) {
1995
- p.second->MaybeFinishUpdate();
2005
+ absl::Status status = p.second->MaybeFinishUpdate();
2006
+ if (!status.ok()) {
2007
+ errors.emplace_back(
2008
+ absl::StrCat("target ", p.first, ": ", status.ToString()));
2009
+ }
1996
2010
  }
1997
2011
  } else if (created_default_child) {
1998
2012
  if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
1999
2013
  gpr_log(GPR_INFO, "[rlslb %p] finishing default child policy update",
2000
2014
  this);
2001
2015
  }
2002
- default_child_policy_->MaybeFinishUpdate();
2016
+ absl::Status status = default_child_policy_->MaybeFinishUpdate();
2017
+ if (!status.ok()) {
2018
+ errors.emplace_back(absl::StrCat("target ", config_->default_target(),
2019
+ ": ", status.ToString()));
2020
+ }
2003
2021
  }
2004
2022
  update_in_progress_ = false;
2005
2023
  // In principle, we need to update the picker here only if the config
@@ -2009,6 +2027,12 @@ void RlsLb::UpdateLocked(UpdateArgs args) {
2009
2027
  // remember to update the code here. So for now, we just unconditionally
2010
2028
  // update the picker here, even though it's probably redundant.
2011
2029
  UpdatePickerLocked();
2030
+ // Return status.
2031
+ if (!errors.empty()) {
2032
+ return absl::UnavailableError(absl::StrCat(
2033
+ "errors from children: [", absl::StrJoin(errors, "; "), "]"));
2034
+ }
2035
+ return absl::OkStatus();
2012
2036
  }
2013
2037
 
2014
2038
  void RlsLb::ExitIdleLocked() {
@@ -2125,345 +2149,342 @@ void RlsLb::UpdatePickerLocked() {
2125
2149
  // RlsLbFactory
2126
2150
  //
2127
2151
 
2128
- grpc_error_handle ParseJsonHeaders(size_t idx, const Json& json,
2129
- std::string* key,
2130
- std::vector<std::string>* headers) {
2131
- if (json.type() != Json::Type::OBJECT) {
2132
- return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
2133
- "field:headers index:", idx, " error:type should be OBJECT"));
2134
- }
2135
- std::vector<grpc_error_handle> error_list;
2136
- // requiredMatch must not be present.
2137
- if (json.object_value().find("requiredMatch") != json.object_value().end()) {
2138
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2139
- "field:requiredMatch error:must not be present"));
2140
- }
2141
- // Find key.
2142
- if (ParseJsonObjectField(json.object_value(), "key", key, &error_list) &&
2143
- key->empty()) {
2144
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2145
- "field:key error:must be non-empty"));
2146
- }
2147
- // Find headers.
2148
- const Json::Array* headers_json = nullptr;
2149
- ParseJsonObjectField(json.object_value(), "names", &headers_json,
2150
- &error_list);
2151
- if (headers_json != nullptr) {
2152
- if (headers_json->empty()) {
2153
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2154
- "field:names error:list is empty"));
2155
- } else {
2156
- size_t name_idx = 0;
2157
- for (const Json& name_json : *headers_json) {
2158
- if (name_json.type() != Json::Type::STRING) {
2159
- error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
2160
- "field:names index:", name_idx, " error:type should be STRING")));
2161
- } else if (name_json.string_value().empty()) {
2162
- error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
2163
- absl::StrCat("field:names index:", name_idx,
2164
- " error:header name must be non-empty")));
2165
- } else {
2166
- headers->push_back(name_json.string_value());
2152
+ struct GrpcKeyBuilder {
2153
+ struct Name {
2154
+ std::string service;
2155
+ std::string method;
2156
+
2157
+ static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
2158
+ static const auto* loader = JsonObjectLoader<Name>()
2159
+ .Field("service", &Name::service)
2160
+ .OptionalField("method", &Name::method)
2161
+ .Finish();
2162
+ return loader;
2163
+ }
2164
+ };
2165
+
2166
+ struct NameMatcher {
2167
+ std::string key;
2168
+ std::vector<std::string> names;
2169
+ absl::optional<bool> required_match;
2170
+
2171
+ static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
2172
+ static const auto* loader =
2173
+ JsonObjectLoader<NameMatcher>()
2174
+ .Field("key", &NameMatcher::key)
2175
+ .Field("names", &NameMatcher::names)
2176
+ .OptionalField("requiredMatch", &NameMatcher::required_match)
2177
+ .Finish();
2178
+ return loader;
2179
+ }
2180
+
2181
+ void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors) {
2182
+ // key must be non-empty.
2183
+ {
2184
+ ValidationErrors::ScopedField field(errors, ".key");
2185
+ if (!errors->FieldHasErrors() && key.empty()) {
2186
+ errors->AddError("must be non-empty");
2167
2187
  }
2168
- ++name_idx;
2169
2188
  }
2170
- }
2171
- }
2172
- return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
2173
- absl::StrCat("field:headers index:", idx), &error_list);
2174
- }
2175
-
2176
- std::string ParseJsonMethodName(size_t idx, const Json& json,
2177
- grpc_error_handle* error) {
2178
- if (json.type() != Json::Type::OBJECT) {
2179
- *error = GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
2180
- "field:names index:", idx, " error:type should be OBJECT"));
2181
- return "";
2182
- }
2183
- std::vector<grpc_error_handle> error_list;
2184
- // Find service name.
2185
- absl::string_view service_name;
2186
- ParseJsonObjectField(json.object_value(), "service", &service_name,
2187
- &error_list);
2188
- // Find method name.
2189
- absl::string_view method_name;
2190
- ParseJsonObjectField(json.object_value(), "method", &method_name, &error_list,
2191
- /*required=*/false);
2192
- // Return error, if any.
2193
- *error = GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
2194
- absl::StrCat("field:names index:", idx), &error_list);
2195
- // Construct path.
2196
- return absl::StrCat("/", service_name, "/", method_name);
2197
- }
2198
-
2199
- grpc_error_handle ParseGrpcKeybuilder(
2200
- size_t idx, const Json& json, RlsLbConfig::KeyBuilderMap* key_builder_map) {
2201
- if (json.type() != Json::Type::OBJECT) {
2202
- return GRPC_ERROR_CREATE_FROM_CPP_STRING(absl::StrCat(
2203
- "field:grpc_keybuilders index:", idx, " error:type should be OBJECT"));
2204
- }
2205
- std::vector<grpc_error_handle> error_list;
2206
- // Parse names.
2207
- std::set<std::string> names;
2208
- const Json::Array* names_array = nullptr;
2209
- if (ParseJsonObjectField(json.object_value(), "names", &names_array,
2210
- &error_list)) {
2211
- if (names_array->empty()) {
2212
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2213
- "field:names error:list is empty"));
2214
- } else {
2215
- size_t name_idx = 0;
2216
- for (const Json& name_json : *names_array) {
2217
- grpc_error_handle child_error = GRPC_ERROR_NONE;
2218
- std::string name =
2219
- ParseJsonMethodName(name_idx++, name_json, &child_error);
2220
- if (!GRPC_ERROR_IS_NONE(child_error)) {
2221
- error_list.push_back(child_error);
2222
- } else {
2223
- bool inserted = names.insert(name).second;
2224
- if (!inserted) {
2225
- error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
2226
- absl::StrCat("field:names error:duplicate entry for ", name)));
2189
+ // List of header names must be non-empty.
2190
+ {
2191
+ ValidationErrors::ScopedField field(errors, ".names");
2192
+ if (!errors->FieldHasErrors() && names.empty()) {
2193
+ errors->AddError("must be non-empty");
2194
+ }
2195
+ // Individual header names must be non-empty.
2196
+ for (size_t i = 0; i < names.size(); ++i) {
2197
+ ValidationErrors::ScopedField field(errors,
2198
+ absl::StrCat("[", i, "]"));
2199
+ if (!errors->FieldHasErrors() && names[i].empty()) {
2200
+ errors->AddError("must be non-empty");
2227
2201
  }
2228
2202
  }
2229
2203
  }
2230
- }
2231
- }
2232
- // Helper function to check for duplicate keys.
2233
- std::set<std::string> all_keys;
2234
- auto duplicate_key_check_func = [&all_keys,
2235
- &error_list](const std::string& key) {
2236
- auto it = all_keys.find(key);
2237
- if (it != all_keys.end()) {
2238
- error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
2239
- absl::StrCat("key \"", key, "\" listed multiple times")));
2240
- } else {
2241
- all_keys.insert(key);
2204
+ // requiredMatch must not be present.
2205
+ {
2206
+ ValidationErrors::ScopedField field(errors, ".requiredMatch");
2207
+ if (required_match.has_value()) {
2208
+ errors->AddError("must not be present");
2209
+ }
2210
+ }
2242
2211
  }
2243
2212
  };
2244
- // Parse headers.
2245
- RlsLbConfig::KeyBuilder key_builder;
2246
- const Json::Array* headers_array = nullptr;
2247
- ParseJsonObjectField(json.object_value(), "headers", &headers_array,
2248
- &error_list, /*required=*/false);
2249
- if (headers_array != nullptr) {
2250
- size_t header_idx = 0;
2251
- for (const Json& header_json : *headers_array) {
2252
- std::string key;
2253
- std::vector<std::string> headers;
2254
- grpc_error_handle child_error =
2255
- ParseJsonHeaders(header_idx++, header_json, &key, &headers);
2256
- if (!GRPC_ERROR_IS_NONE(child_error)) {
2257
- error_list.push_back(child_error);
2258
- } else {
2259
- duplicate_key_check_func(key);
2260
- key_builder.header_keys.emplace(key, std::move(headers));
2261
- }
2213
+
2214
+ struct ExtraKeys {
2215
+ absl::optional<std::string> host_key;
2216
+ absl::optional<std::string> service_key;
2217
+ absl::optional<std::string> method_key;
2218
+
2219
+ static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
2220
+ static const auto* loader =
2221
+ JsonObjectLoader<ExtraKeys>()
2222
+ .OptionalField("host", &ExtraKeys::host_key)
2223
+ .OptionalField("service", &ExtraKeys::service_key)
2224
+ .OptionalField("method", &ExtraKeys::method_key)
2225
+ .Finish();
2226
+ return loader;
2262
2227
  }
2228
+
2229
+ void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors) {
2230
+ auto check_field = [&](const std::string& field_name,
2231
+ absl::optional<std::string>* struct_field) {
2232
+ ValidationErrors::ScopedField field(errors,
2233
+ absl::StrCat(".", field_name));
2234
+ if (struct_field->has_value() && (*struct_field)->empty()) {
2235
+ errors->AddError("must be non-empty if set");
2236
+ }
2237
+ };
2238
+ check_field("host", &host_key);
2239
+ check_field("service", &service_key);
2240
+ check_field("method", &method_key);
2241
+ }
2242
+ };
2243
+
2244
+ std::vector<Name> names;
2245
+ std::vector<NameMatcher> headers;
2246
+ ExtraKeys extra_keys;
2247
+ std::map<std::string /*key*/, std::string /*value*/> constant_keys;
2248
+
2249
+ static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
2250
+ static const auto* loader =
2251
+ JsonObjectLoader<GrpcKeyBuilder>()
2252
+ .Field("names", &GrpcKeyBuilder::names)
2253
+ .OptionalField("headers", &GrpcKeyBuilder::headers)
2254
+ .OptionalField("extraKeys", &GrpcKeyBuilder::extra_keys)
2255
+ .OptionalField("constantKeys", &GrpcKeyBuilder::constant_keys)
2256
+ .Finish();
2257
+ return loader;
2263
2258
  }
2264
- // Parse extraKeys.
2265
- const Json::Object* extra_keys = nullptr;
2266
- ParseJsonObjectField(json.object_value(), "extraKeys", &extra_keys,
2267
- &error_list, /*required=*/false);
2268
- if (extra_keys != nullptr) {
2269
- std::vector<grpc_error_handle> extra_keys_errors;
2270
- if (ParseJsonObjectField(*extra_keys, "host", &key_builder.host_key,
2271
- &extra_keys_errors, /*required=*/false) &&
2272
- key_builder.host_key.empty()) {
2273
- extra_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2274
- "field:host error:must be non-empty"));
2259
+
2260
+ void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors) {
2261
+ // The names field must be non-empty.
2262
+ {
2263
+ ValidationErrors::ScopedField field(errors, ".names");
2264
+ if (!errors->FieldHasErrors() && names.empty()) {
2265
+ errors->AddError("must be non-empty");
2266
+ }
2275
2267
  }
2276
- if (!key_builder.host_key.empty()) {
2277
- duplicate_key_check_func(key_builder.host_key);
2268
+ // Make sure no key in constantKeys is empty.
2269
+ if (constant_keys.find("") != constant_keys.end()) {
2270
+ ValidationErrors::ScopedField field(errors, ".constantKeys[\"\"]");
2271
+ errors->AddError("key must be non-empty");
2278
2272
  }
2279
- if (ParseJsonObjectField(*extra_keys, "service", &key_builder.service_key,
2280
- &extra_keys_errors, /*required=*/false) &&
2281
- key_builder.service_key.empty()) {
2282
- extra_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2283
- "field:service error:must be non-empty"));
2273
+ // Check for duplicate keys.
2274
+ std::set<absl::string_view> keys_seen;
2275
+ auto duplicate_key_check_func = [&keys_seen, errors](
2276
+ const std::string& key,
2277
+ const std::string& field_name) {
2278
+ if (key.empty()) return; // Already generated an error about this.
2279
+ ValidationErrors::ScopedField field(errors, field_name);
2280
+ auto it = keys_seen.find(key);
2281
+ if (it != keys_seen.end()) {
2282
+ errors->AddError(absl::StrCat("duplicate key \"", key, "\""));
2283
+ } else {
2284
+ keys_seen.insert(key);
2285
+ }
2286
+ };
2287
+ for (size_t i = 0; i < headers.size(); ++i) {
2288
+ NameMatcher& header = headers[i];
2289
+ duplicate_key_check_func(header.key,
2290
+ absl::StrCat(".headers[", i, "].key"));
2284
2291
  }
2285
- if (!key_builder.service_key.empty()) {
2286
- duplicate_key_check_func(key_builder.service_key);
2292
+ for (const auto& p : constant_keys) {
2293
+ duplicate_key_check_func(
2294
+ p.first, absl::StrCat(".constantKeys[\"", p.first, "\"]"));
2287
2295
  }
2288
- if (ParseJsonObjectField(*extra_keys, "method", &key_builder.method_key,
2289
- &extra_keys_errors, /*required=*/false) &&
2290
- key_builder.method_key.empty()) {
2291
- extra_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2292
- "field:method error:must be non-empty"));
2296
+ if (extra_keys.host_key.has_value()) {
2297
+ duplicate_key_check_func(*extra_keys.host_key, ".extraKeys.host");
2293
2298
  }
2294
- if (!key_builder.method_key.empty()) {
2295
- duplicate_key_check_func(key_builder.method_key);
2299
+ if (extra_keys.service_key.has_value()) {
2300
+ duplicate_key_check_func(*extra_keys.service_key, ".extraKeys.service");
2296
2301
  }
2297
- if (!extra_keys_errors.empty()) {
2298
- error_list.push_back(
2299
- GRPC_ERROR_CREATE_FROM_VECTOR("field:extraKeys", &extra_keys_errors));
2302
+ if (extra_keys.method_key.has_value()) {
2303
+ duplicate_key_check_func(*extra_keys.method_key, ".extraKeys.method");
2300
2304
  }
2301
2305
  }
2302
- // Parse constantKeys.
2303
- const Json::Object* constant_keys = nullptr;
2304
- ParseJsonObjectField(json.object_value(), "constantKeys", &constant_keys,
2305
- &error_list, /*required=*/false);
2306
- if (constant_keys != nullptr) {
2307
- std::vector<grpc_error_handle> constant_keys_errors;
2308
- for (const auto& p : *constant_keys) {
2309
- const std::string& key = p.first;
2310
- const Json& value = p.second;
2311
- if (key.empty()) {
2312
- constant_keys_errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2313
- "error:keys must be non-empty"));
2306
+ };
2307
+
2308
+ const JsonLoaderInterface* RlsLbConfig::RouteLookupConfig::JsonLoader(
2309
+ const JsonArgs&) {
2310
+ static const auto* loader =
2311
+ JsonObjectLoader<RouteLookupConfig>()
2312
+ // Note: Some fields require manual processing and are handled in
2313
+ // JsonPostLoad() instead.
2314
+ .Field("lookupService", &RouteLookupConfig::lookup_service)
2315
+ .OptionalField("lookupServiceTimeout",
2316
+ &RouteLookupConfig::lookup_service_timeout)
2317
+ .OptionalField("maxAge", &RouteLookupConfig::max_age)
2318
+ .OptionalField("staleAge", &RouteLookupConfig::stale_age)
2319
+ .Field("cacheSizeBytes", &RouteLookupConfig::cache_size_bytes)
2320
+ .OptionalField("defaultTarget", &RouteLookupConfig::default_target)
2321
+ .Finish();
2322
+ return loader;
2323
+ }
2324
+
2325
+ void RlsLbConfig::RouteLookupConfig::JsonPostLoad(const Json& json,
2326
+ const JsonArgs& args,
2327
+ ValidationErrors* errors) {
2328
+ // Parse grpcKeybuilders.
2329
+ auto grpc_keybuilders = LoadJsonObjectField<std::vector<GrpcKeyBuilder>>(
2330
+ json.object_value(), args, "grpcKeybuilders", errors);
2331
+ if (grpc_keybuilders.has_value()) {
2332
+ ValidationErrors::ScopedField field(errors, ".grpcKeybuilders");
2333
+ for (size_t i = 0; i < grpc_keybuilders->size(); ++i) {
2334
+ ValidationErrors::ScopedField field(errors, absl::StrCat("[", i, "]"));
2335
+ auto& grpc_keybuilder = (*grpc_keybuilders)[i];
2336
+ // Construct KeyBuilder.
2337
+ RlsLbConfig::KeyBuilder key_builder;
2338
+ for (const auto& header : grpc_keybuilder.headers) {
2339
+ key_builder.header_keys.emplace(header.key, header.names);
2340
+ }
2341
+ if (grpc_keybuilder.extra_keys.host_key.has_value()) {
2342
+ key_builder.host_key = std::move(*grpc_keybuilder.extra_keys.host_key);
2343
+ }
2344
+ if (grpc_keybuilder.extra_keys.service_key.has_value()) {
2345
+ key_builder.service_key =
2346
+ std::move(*grpc_keybuilder.extra_keys.service_key);
2347
+ }
2348
+ if (grpc_keybuilder.extra_keys.method_key.has_value()) {
2349
+ key_builder.method_key =
2350
+ std::move(*grpc_keybuilder.extra_keys.method_key);
2351
+ }
2352
+ key_builder.constant_keys = std::move(grpc_keybuilder.constant_keys);
2353
+ // Add entries to map.
2354
+ for (const auto& name : grpc_keybuilder.names) {
2355
+ std::string path = absl::StrCat("/", name.service, "/", name.method);
2356
+ bool inserted = key_builder_map.emplace(path, key_builder).second;
2357
+ if (!inserted) {
2358
+ errors->AddError(absl::StrCat("duplicate entry for \"", path, "\""));
2359
+ }
2314
2360
  }
2315
- duplicate_key_check_func(key);
2316
- ExtractJsonString(value, key, &key_builder.constant_keys[key],
2317
- &constant_keys_errors);
2318
2361
  }
2319
- if (!constant_keys_errors.empty()) {
2320
- error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
2321
- "field:constantKeys", &constant_keys_errors));
2362
+ }
2363
+ // Validate lookupService.
2364
+ {
2365
+ ValidationErrors::ScopedField field(errors, ".lookupService");
2366
+ if (!errors->FieldHasErrors() &&
2367
+ !CoreConfiguration::Get().resolver_registry().IsValidTarget(
2368
+ lookup_service)) {
2369
+ errors->AddError("must be valid gRPC target URI");
2322
2370
  }
2323
2371
  }
2324
- // Insert key_builder into key_builder_map.
2325
- for (const std::string& name : names) {
2326
- bool inserted = key_builder_map->emplace(name, key_builder).second;
2327
- if (!inserted) {
2328
- error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(
2329
- absl::StrCat("field:names error:duplicate entry for ", name)));
2372
+ // Clamp maxAge to the max allowed value.
2373
+ if (max_age > kMaxMaxAge) max_age = kMaxMaxAge;
2374
+ // If staleAge is set, then maxAge must also be set.
2375
+ if (json.object_value().find("staleAge") != json.object_value().end() &&
2376
+ json.object_value().find("maxAge") == json.object_value().end()) {
2377
+ ValidationErrors::ScopedField field(errors, ".maxAge");
2378
+ errors->AddError("must be set if staleAge is set");
2379
+ }
2380
+ // Ignore staleAge if greater than or equal to maxAge.
2381
+ if (stale_age >= max_age) stale_age = max_age;
2382
+ // Validate cacheSizeBytes.
2383
+ {
2384
+ ValidationErrors::ScopedField field(errors, ".cacheSizeBytes");
2385
+ if (!errors->FieldHasErrors() && cache_size_bytes <= 0) {
2386
+ errors->AddError("must be greater than 0");
2330
2387
  }
2331
2388
  }
2332
- return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING(
2333
- absl::StrCat("index:", idx), &error_list);
2334
- }
2335
-
2336
- RlsLbConfig::KeyBuilderMap ParseGrpcKeybuilders(
2337
- const Json::Array& key_builder_list, grpc_error_handle* error) {
2338
- RlsLbConfig::KeyBuilderMap key_builder_map;
2339
- if (key_builder_list.empty()) {
2340
- *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2341
- "field:grpcKeybuilders error:list is empty");
2342
- return key_builder_map;
2389
+ // Clamp cacheSizeBytes to the max allowed value.
2390
+ if (cache_size_bytes > kMaxCacheSizeBytes) {
2391
+ cache_size_bytes = kMaxCacheSizeBytes;
2343
2392
  }
2344
- std::vector<grpc_error_handle> error_list;
2345
- size_t idx = 0;
2346
- for (const Json& key_builder : key_builder_list) {
2347
- grpc_error_handle child_error =
2348
- ParseGrpcKeybuilder(idx++, key_builder, &key_builder_map);
2349
- if (!GRPC_ERROR_IS_NONE(child_error)) error_list.push_back(child_error);
2393
+ // Validate defaultTarget.
2394
+ {
2395
+ ValidationErrors::ScopedField field(errors, ".defaultTarget");
2396
+ if (!errors->FieldHasErrors() &&
2397
+ json.object_value().find("defaultTarget") !=
2398
+ json.object_value().end() &&
2399
+ default_target.empty()) {
2400
+ errors->AddError("must be non-empty if set");
2401
+ }
2350
2402
  }
2351
- *error = GRPC_ERROR_CREATE_FROM_VECTOR("field:grpcKeybuilders", &error_list);
2352
- return key_builder_map;
2353
2403
  }
2354
2404
 
2355
- RlsLbConfig::RouteLookupConfig ParseRouteLookupConfig(
2356
- const Json::Object& json, grpc_error_handle* error) {
2357
- std::vector<grpc_error_handle> error_list;
2358
- RlsLbConfig::RouteLookupConfig route_lookup_config;
2359
- // Parse grpcKeybuilders.
2360
- const Json::Array* keybuilder_list = nullptr;
2361
- ParseJsonObjectField(json, "grpcKeybuilders", &keybuilder_list, &error_list);
2362
- if (keybuilder_list != nullptr) {
2405
+ const JsonLoaderInterface* RlsLbConfig::JsonLoader(const JsonArgs&) {
2406
+ static const auto* loader =
2407
+ JsonObjectLoader<RlsLbConfig>()
2408
+ // Note: Some fields require manual processing and are handled in
2409
+ // JsonPostLoad() instead.
2410
+ .Field("routeLookupConfig", &RlsLbConfig::route_lookup_config_)
2411
+ .Field("childPolicyConfigTargetFieldName",
2412
+ &RlsLbConfig::child_policy_config_target_field_name_)
2413
+ .Finish();
2414
+ return loader;
2415
+ }
2416
+
2417
+ void RlsLbConfig::JsonPostLoad(const Json& json, const JsonArgs&,
2418
+ ValidationErrors* errors) {
2419
+ // Parse routeLookupChannelServiceConfig.
2420
+ auto it = json.object_value().find("routeLookupChannelServiceConfig");
2421
+ if (it != json.object_value().end()) {
2422
+ ValidationErrors::ScopedField field(errors,
2423
+ ".routeLookupChannelServiceConfig");
2363
2424
  grpc_error_handle child_error = GRPC_ERROR_NONE;
2364
- route_lookup_config.key_builder_map =
2365
- ParseGrpcKeybuilders(*keybuilder_list, &child_error);
2366
- if (!GRPC_ERROR_IS_NONE(child_error)) error_list.push_back(child_error);
2367
- }
2368
- // Parse lookupService.
2369
- if (ParseJsonObjectField(json, "lookupService",
2370
- &route_lookup_config.lookup_service, &error_list)) {
2371
- if (!CoreConfiguration::Get().resolver_registry().IsValidTarget(
2372
- route_lookup_config.lookup_service)) {
2373
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2374
- "field:lookupService error:must be valid gRPC target URI"));
2425
+ rls_channel_service_config_ = it->second.Dump();
2426
+ auto service_config = MakeRefCounted<ServiceConfigImpl>(
2427
+ ChannelArgs(), rls_channel_service_config_, it->second, &child_error);
2428
+ if (!GRPC_ERROR_IS_NONE(child_error)) {
2429
+ errors->AddError(grpc_error_std_string(child_error));
2430
+ GRPC_ERROR_UNREF(child_error);
2375
2431
  }
2376
2432
  }
2377
- // Parse lookupServiceTimeout.
2378
- route_lookup_config.lookup_service_timeout = kDefaultLookupServiceTimeout;
2379
- ParseJsonObjectFieldAsDuration(json, "lookupServiceTimeout",
2380
- &route_lookup_config.lookup_service_timeout,
2381
- &error_list, /*required=*/false);
2382
- // Parse maxAge.
2383
- route_lookup_config.max_age = kMaxMaxAge;
2384
- bool max_age_set = ParseJsonObjectFieldAsDuration(
2385
- json, "maxAge", &route_lookup_config.max_age, &error_list,
2386
- /*required=*/false);
2387
- // Clamp maxAge to the max allowed value.
2388
- if (route_lookup_config.max_age > kMaxMaxAge) {
2389
- route_lookup_config.max_age = kMaxMaxAge;
2390
- }
2391
- // Parse staleAge.
2392
- route_lookup_config.stale_age = kMaxMaxAge;
2393
- bool stale_age_set = ParseJsonObjectFieldAsDuration(
2394
- json, "staleAge", &route_lookup_config.stale_age, &error_list,
2395
- /*required=*/false);
2396
- // If staleAge is set, then maxAge must also be set.
2397
- if (stale_age_set && !max_age_set) {
2398
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2399
- "field:maxAge error:must be set if staleAge is set"));
2400
- }
2401
- // Ignore staleAge if greater than or equal to maxAge.
2402
- if (route_lookup_config.stale_age >= route_lookup_config.max_age) {
2403
- route_lookup_config.stale_age = route_lookup_config.max_age;
2404
- }
2405
- // Parse cacheSizeBytes.
2406
- ParseJsonObjectField(json, "cacheSizeBytes",
2407
- &route_lookup_config.cache_size_bytes, &error_list);
2408
- if (route_lookup_config.cache_size_bytes <= 0) {
2409
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2410
- "field:cacheSizeBytes error:must be greater than 0"));
2411
- }
2412
- // Clamp cacheSizeBytes to the max allowed value.
2413
- if (route_lookup_config.cache_size_bytes > kMaxCacheSizeBytes) {
2414
- route_lookup_config.cache_size_bytes = kMaxCacheSizeBytes;
2415
- }
2416
- // Parse defaultTarget.
2417
- if (ParseJsonObjectField(json, "defaultTarget",
2418
- &route_lookup_config.default_target, &error_list,
2419
- /*required=*/false)) {
2420
- if (route_lookup_config.default_target.empty()) {
2421
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2422
- "field:defaultTarget error:must be non-empty if set"));
2433
+ // Validate childPolicyConfigTargetFieldName.
2434
+ {
2435
+ ValidationErrors::ScopedField field(errors,
2436
+ ".childPolicyConfigTargetFieldName");
2437
+ if (!errors->FieldHasErrors() &&
2438
+ child_policy_config_target_field_name_.empty()) {
2439
+ errors->AddError("must be non-empty");
2423
2440
  }
2424
2441
  }
2425
- *error =
2426
- GRPC_ERROR_CREATE_FROM_VECTOR("field:routeLookupConfig", &error_list);
2427
- return route_lookup_config;
2428
- }
2429
-
2430
- grpc_error_handle ValidateChildPolicyList(
2431
- const Json& child_policy_list,
2432
- const std::string& child_policy_config_target_field_name,
2433
- const std::string& default_target, Json* child_policy_config,
2434
- RefCountedPtr<LoadBalancingPolicy::Config>*
2435
- default_child_policy_parsed_config) {
2436
- // Add target to each entry in the config proto.
2437
- *child_policy_config = child_policy_list;
2438
- std::string target =
2439
- default_target.empty() ? kFakeTargetFieldValue : default_target;
2440
- grpc_error_handle error = InsertOrUpdateChildPolicyField(
2441
- child_policy_config_target_field_name, target, child_policy_config);
2442
- if (!GRPC_ERROR_IS_NONE(error)) return error;
2443
- // Parse the config.
2444
- auto parsed_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
2445
- *child_policy_config);
2446
- if (!parsed_config.ok()) {
2447
- return absl_status_to_grpc_error(parsed_config.status());
2448
- }
2449
- // Find the chosen config and return it in JSON form.
2450
- // We remove all non-selected configs, and in the selected config, we leave
2451
- // the target field in place, set to the default value. This slightly
2452
- // optimizes what we need to do later when we update a child policy for a
2453
- // given target.
2454
- for (Json& config : *(child_policy_config->mutable_array())) {
2455
- if (config.object_value().begin()->first == (*parsed_config)->name()) {
2456
- Json save_config = std::move(config);
2457
- child_policy_config->mutable_array()->clear();
2458
- child_policy_config->mutable_array()->push_back(std::move(save_config));
2459
- break;
2442
+ // Parse childPolicy.
2443
+ {
2444
+ ValidationErrors::ScopedField field(errors, ".childPolicy");
2445
+ auto it = json.object_value().find("childPolicy");
2446
+ if (it == json.object_value().end()) {
2447
+ errors->AddError("field not present");
2448
+ } else {
2449
+ // Add target to all child policy configs in the list.
2450
+ child_policy_config_ = it->second;
2451
+ std::string target = route_lookup_config_.default_target.empty()
2452
+ ? kFakeTargetFieldValue
2453
+ : route_lookup_config_.default_target;
2454
+ if (InsertOrUpdateChildPolicyField(child_policy_config_target_field_name_,
2455
+ target, &child_policy_config_,
2456
+ errors)) {
2457
+ // Parse the config.
2458
+ auto parsed_config =
2459
+ CoreConfiguration::Get()
2460
+ .lb_policy_registry()
2461
+ .ParseLoadBalancingConfig(child_policy_config_);
2462
+ if (!parsed_config.ok()) {
2463
+ errors->AddError(parsed_config.status().message());
2464
+ } else {
2465
+ // Find the chosen config and return it in JSON form.
2466
+ // We remove all non-selected configs, and in the selected config,
2467
+ // we leave the target field in place, set to the default value.
2468
+ // This slightly optimizes what we need to do later when we update
2469
+ // a child policy for a given target.
2470
+ for (Json& config : *(child_policy_config_.mutable_array())) {
2471
+ if (config.object_value().begin()->first ==
2472
+ (*parsed_config)->name()) {
2473
+ Json save_config = std::move(config);
2474
+ child_policy_config_.mutable_array()->clear();
2475
+ child_policy_config_.mutable_array()->push_back(
2476
+ std::move(save_config));
2477
+ break;
2478
+ }
2479
+ }
2480
+ // If default target is set, set the default child config.
2481
+ if (!route_lookup_config_.default_target.empty()) {
2482
+ default_child_policy_parsed_config_ = std::move(*parsed_config);
2483
+ }
2484
+ }
2485
+ }
2460
2486
  }
2461
2487
  }
2462
- // If default target is set, return the parsed config.
2463
- if (!default_target.empty()) {
2464
- *default_child_policy_parsed_config = std::move(*parsed_config);
2465
- }
2466
- return GRPC_ERROR_NONE;
2467
2488
  }
2468
2489
 
2469
2490
  class RlsLbFactory : public LoadBalancingPolicyFactory {
@@ -2476,93 +2497,17 @@ class RlsLbFactory : public LoadBalancingPolicyFactory {
2476
2497
  }
2477
2498
 
2478
2499
  absl::StatusOr<RefCountedPtr<LoadBalancingPolicy::Config>>
2479
- ParseLoadBalancingConfig(const Json& config) const override {
2480
- std::vector<grpc_error_handle> error_list;
2481
- // Parse routeLookupConfig.
2482
- RlsLbConfig::RouteLookupConfig route_lookup_config;
2483
- const Json::Object* route_lookup_config_json = nullptr;
2484
- if (ParseJsonObjectField(config.object_value(), "routeLookupConfig",
2485
- &route_lookup_config_json, &error_list)) {
2486
- grpc_error_handle child_error = GRPC_ERROR_NONE;
2487
- route_lookup_config =
2488
- ParseRouteLookupConfig(*route_lookup_config_json, &child_error);
2489
- if (!GRPC_ERROR_IS_NONE(child_error)) error_list.push_back(child_error);
2490
- }
2491
- // Parse routeLookupChannelServiceConfig.
2492
- std::string rls_channel_service_config;
2493
- const Json::Object* rls_channel_service_config_json_obj = nullptr;
2494
- if (ParseJsonObjectField(config.object_value(),
2495
- "routeLookupChannelServiceConfig",
2496
- &rls_channel_service_config_json_obj, &error_list,
2497
- /*required=*/false)) {
2498
- grpc_error_handle child_error = GRPC_ERROR_NONE;
2499
- Json rls_channel_service_config_json(
2500
- *rls_channel_service_config_json_obj);
2501
- rls_channel_service_config = rls_channel_service_config_json.Dump();
2502
- auto service_config = MakeRefCounted<ServiceConfigImpl>(
2503
- ChannelArgs(), rls_channel_service_config,
2504
- std::move(rls_channel_service_config_json), &child_error);
2505
- if (!GRPC_ERROR_IS_NONE(child_error)) {
2506
- error_list.push_back(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
2507
- "field:routeLookupChannelServiceConfig", &child_error, 1));
2508
- GRPC_ERROR_UNREF(child_error);
2509
- }
2510
- }
2511
- // Parse childPolicyConfigTargetFieldName.
2512
- std::string child_policy_config_target_field_name;
2513
- if (ParseJsonObjectField(
2514
- config.object_value(), "childPolicyConfigTargetFieldName",
2515
- &child_policy_config_target_field_name, &error_list)) {
2516
- if (child_policy_config_target_field_name.empty()) {
2517
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2518
- "field:childPolicyConfigTargetFieldName error:must be non-empty"));
2519
- }
2520
- }
2521
- // Parse childPolicy.
2522
- Json child_policy_config;
2523
- RefCountedPtr<LoadBalancingPolicy::Config>
2524
- default_child_policy_parsed_config;
2525
- auto it = config.object_value().find("childPolicy");
2526
- if (it == config.object_value().end()) {
2527
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2528
- "field:childPolicy error:does not exist."));
2529
- } else if (it->second.type() != Json::Type::ARRAY) {
2530
- error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2531
- "field:childPolicy error:type should be ARRAY"));
2532
- } else {
2533
- grpc_error_handle child_error = ValidateChildPolicyList(
2534
- it->second, child_policy_config_target_field_name,
2535
- route_lookup_config.default_target, &child_policy_config,
2536
- &default_child_policy_parsed_config);
2537
- if (!GRPC_ERROR_IS_NONE(child_error)) {
2538
- error_list.push_back(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
2539
- "field:childPolicy", &child_error, 1));
2540
- GRPC_ERROR_UNREF(child_error);
2541
- }
2542
- }
2543
- // Return result.
2544
- if (!error_list.empty()) {
2545
- grpc_error_handle error = GRPC_ERROR_CREATE_FROM_VECTOR(
2546
- "errors parsing RLS LB policy config", &error_list);
2547
- std::string error_string = grpc_error_std_string(error);
2548
- GRPC_ERROR_UNREF(error);
2549
- return absl::InvalidArgumentError(error_string);
2550
- }
2551
- return MakeRefCounted<RlsLbConfig>(
2552
- std::move(route_lookup_config), std::move(rls_channel_service_config),
2553
- std::move(child_policy_config),
2554
- std::move(child_policy_config_target_field_name),
2555
- std::move(default_child_policy_parsed_config));
2500
+ ParseLoadBalancingConfig(const Json& json) const override {
2501
+ return LoadRefCountedFromJson<RlsLbConfig>(
2502
+ json, JsonArgs(), "errors validing RLS LB policy config");
2556
2503
  }
2557
2504
  };
2558
2505
 
2559
2506
  } // namespace
2560
2507
 
2561
- void RlsLbPluginInit() {
2562
- LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory(
2508
+ void RegisterRlsLbPolicy(CoreConfiguration::Builder* builder) {
2509
+ builder->lb_policy_registry()->RegisterLoadBalancingPolicyFactory(
2563
2510
  absl::make_unique<RlsLbFactory>());
2564
2511
  }
2565
2512
 
2566
- void RlsLbPluginShutdown() {}
2567
-
2568
2513
  } // namespace grpc_core