xDS: remove v2 support (#31327)

* xDS: remove v2 support

* remove unnecessary templating in fake xDS server code

* remove now-unnecessary workaround for clang bug

* clang-format

* fix unit tests

* iwyu

* remove now-unused v2 proto files

* fix from merge

* clang-format

* fix typo
pull/31387/head
Mark D. Roth 2 years ago committed by GitHub
parent 3981105be6
commit bd4b5d70c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      BUILD
  2. 144
      CMakeLists.txt
  3. 2
      Makefile
  4. 33
      build_autogenerated.yaml
  5. 1
      config.m4
  6. 1
      config.w32
  7. 1
      gRPC-Core.podspec
  8. 1
      grpc.gemspec
  9. 1
      grpc.gyp
  10. 1
      package.xml
  11. 83
      src/core/ext/xds/xds_api.cc
  12. 10
      src/core/ext/xds/xds_api.h
  13. 1
      src/core/ext/xds/xds_bootstrap.h
  14. 11
      src/core/ext/xds/xds_bootstrap_grpc.cc
  15. 1
      src/core/ext/xds/xds_bootstrap_grpc.h
  16. 34
      src/core/ext/xds/xds_client.cc
  17. 2
      src/core/ext/xds/xds_client.h
  18. 6
      src/core/ext/xds/xds_cluster.cc
  19. 6
      src/core/ext/xds/xds_cluster.h
  20. 2
      src/core/ext/xds/xds_endpoint.cc
  21. 6
      src/core/ext/xds/xds_endpoint.h
  22. 226
      src/core/ext/xds/xds_listener.cc
  23. 6
      src/core/ext/xds/xds_listener.h
  24. 33
      src/core/ext/xds/xds_resource_type.cc
  25. 11
      src/core/ext/xds/xds_resource_type.h
  26. 69
      src/core/ext/xds/xds_route_config.cc
  27. 6
      src/core/ext/xds/xds_route_config.h
  28. 71
      src/proto/grpc/testing/xds/BUILD
  29. 51
      src/proto/grpc/testing/xds/ads_for_test.proto
  30. 186
      src/proto/grpc/testing/xds/cds_for_test.proto
  31. 517
      src/proto/grpc/testing/xds/eds_for_test.proto
  32. 215
      src/proto/grpc/testing/xds/lds_rds_for_test.proto
  33. 189
      src/proto/grpc/testing/xds/lrs_for_test.proto
  34. 1
      src/python/grpcio/grpc_core_dependencies.py
  35. 93
      test/core/xds/xds_client_test.cc
  36. 161
      test/core/xds/xds_cluster_resource_type_test.cc
  37. 89
      test/core/xds/xds_endpoint_resource_type_test.cc
  38. 7
      test/cpp/end2end/xds/BUILD
  39. 5
      test/cpp/end2end/xds/xds_end2end_test.cc
  40. 18
      test/cpp/end2end/xds/xds_end2end_test_lib.cc
  41. 14
      test/cpp/end2end/xds/xds_end2end_test_lib.h
  42. 4
      test/cpp/end2end/xds/xds_rls_end2end_test.cc
  43. 62
      test/cpp/end2end/xds/xds_routing_end2end_test.cc
  44. 2
      test/cpp/end2end/xds/xds_server.cc
  45. 875
      test/cpp/end2end/xds/xds_server.h
  46. 1
      tools/doxygen/Doxyfile.c++.internal
  47. 1
      tools/doxygen/Doxyfile.core.internal

@ -4572,7 +4572,6 @@ grpc_cc_library(
"//src/core:ext/xds/xds_bootstrap.cc",
"//src/core:ext/xds/xds_client.cc",
"//src/core:ext/xds/xds_client_stats.cc",
"//src/core:ext/xds/xds_resource_type.cc",
],
hdrs = [
"//src/core:ext/xds/xds_api.h",

144
CMakeLists.txt generated

@ -631,21 +631,6 @@ protobuf_generate_grpc_cpp_with_import_path_correction(
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/worker_service.proto src/proto/grpc/testing/worker_service.proto
)
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/ads_for_test.proto src/proto/grpc/testing/xds/ads_for_test.proto
)
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/cds_for_test.proto src/proto/grpc/testing/xds/cds_for_test.proto
)
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/eds_for_test.proto src/proto/grpc/testing/xds/eds_for_test.proto
)
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/lds_rds_for_test.proto src/proto/grpc/testing/xds/lds_rds_for_test.proto
)
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/lrs_for_test.proto src/proto/grpc/testing/xds/lrs_for_test.proto
)
protobuf_generate_grpc_cpp_with_import_path_correction(
src/proto/grpc/testing/xds/v3/address.proto src/proto/grpc/testing/xds/v3/address.proto
)
@ -2089,7 +2074,6 @@ add_library(grpc
src/core/ext/xds/xds_http_rbac_filter.cc
src/core/ext/xds/xds_lb_policy_registry.cc
src/core/ext/xds/xds_listener.cc
src/core/ext/xds/xds_resource_type.cc
src/core/ext/xds/xds_route_config.cc
src/core/ext/xds/xds_routing.cc
src/core/ext/xds/xds_server_config_fetcher.cc
@ -20274,18 +20258,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -20531,18 +20503,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -20787,18 +20747,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -21059,18 +21007,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -21241,26 +21177,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -21490,18 +21406,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -21912,18 +21816,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -22093,18 +21985,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -22279,18 +22159,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h
@ -22453,18 +22321,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/address.pb.h

2
Makefile generated

@ -1362,7 +1362,6 @@ LIBGRPC_SRC = \
src/core/ext/xds/xds_http_rbac_filter.cc \
src/core/ext/xds/xds_lb_policy_registry.cc \
src/core/ext/xds/xds_listener.cc \
src/core/ext/xds/xds_resource_type.cc \
src/core/ext/xds/xds_route_config.cc \
src/core/ext/xds/xds_routing.cc \
src/core/ext/xds/xds_server_config_fetcher.cc \
@ -3093,7 +3092,6 @@ src/core/ext/xds/xds_http_filters.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_http_rbac_filter.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_lb_policy_registry.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_listener.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_resource_type.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_route_config.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_routing.cc: $(OPENSSL_DEP)
src/core/ext/xds/xds_server_config_fetcher.cc: $(OPENSSL_DEP)

@ -1420,7 +1420,6 @@ libs:
- src/core/ext/xds/xds_http_rbac_filter.cc
- src/core/ext/xds/xds_lb_policy_registry.cc
- src/core/ext/xds/xds_listener.cc
- src/core/ext/xds/xds_resource_type.cc
- src/core/ext/xds/xds_route_config.cc
- src/core/ext/xds/xds_routing.cc
- src/core/ext/xds/xds_server_config_fetcher.cc
@ -10975,9 +10974,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/base.proto
@ -11055,9 +11051,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/aggregate_cluster.proto
@ -11146,9 +11139,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/base.proto
@ -11251,9 +11241,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/base.proto
@ -11311,11 +11298,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/cds_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lds_rds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/aggregate_cluster.proto
@ -11388,9 +11370,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/base.proto
@ -11533,9 +11512,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/base.proto
@ -11592,9 +11568,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/aggregate_cluster.proto
@ -11653,9 +11626,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/base.proto
@ -11711,9 +11681,6 @@ targets:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/ads_for_test.proto
- src/proto/grpc/testing/xds/eds_for_test.proto
- src/proto/grpc/testing/xds/lrs_for_test.proto
- src/proto/grpc/testing/xds/v3/address.proto
- src/proto/grpc/testing/xds/v3/ads.proto
- src/proto/grpc/testing/xds/v3/base.proto

1
config.m4 generated

@ -444,7 +444,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/xds/xds_http_rbac_filter.cc \
src/core/ext/xds/xds_lb_policy_registry.cc \
src/core/ext/xds/xds_listener.cc \
src/core/ext/xds/xds_resource_type.cc \
src/core/ext/xds/xds_route_config.cc \
src/core/ext/xds/xds_routing.cc \
src/core/ext/xds/xds_server_config_fetcher.cc \

1
config.w32 generated

@ -410,7 +410,6 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\xds\\xds_http_rbac_filter.cc " +
"src\\core\\ext\\xds\\xds_lb_policy_registry.cc " +
"src\\core\\ext\\xds\\xds_listener.cc " +
"src\\core\\ext\\xds\\xds_resource_type.cc " +
"src\\core\\ext\\xds\\xds_route_config.cc " +
"src\\core\\ext\\xds\\xds_routing.cc " +
"src\\core\\ext\\xds\\xds_server_config_fetcher.cc " +

1
gRPC-Core.podspec generated

@ -990,7 +990,6 @@ Pod::Spec.new do |s|
'src/core/ext/xds/xds_lb_policy_registry.h',
'src/core/ext/xds/xds_listener.cc',
'src/core/ext/xds/xds_listener.h',
'src/core/ext/xds/xds_resource_type.cc',
'src/core/ext/xds/xds_resource_type.h',
'src/core/ext/xds/xds_resource_type_impl.h',
'src/core/ext/xds/xds_route_config.cc',

1
grpc.gemspec generated

@ -901,7 +901,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/xds/xds_lb_policy_registry.h )
s.files += %w( src/core/ext/xds/xds_listener.cc )
s.files += %w( src/core/ext/xds/xds_listener.h )
s.files += %w( src/core/ext/xds/xds_resource_type.cc )
s.files += %w( src/core/ext/xds/xds_resource_type.h )
s.files += %w( src/core/ext/xds/xds_resource_type_impl.h )
s.files += %w( src/core/ext/xds/xds_route_config.cc )

1
grpc.gyp generated

@ -776,7 +776,6 @@
'src/core/ext/xds/xds_http_rbac_filter.cc',
'src/core/ext/xds/xds_lb_policy_registry.cc',
'src/core/ext/xds/xds_listener.cc',
'src/core/ext/xds/xds_resource_type.cc',
'src/core/ext/xds/xds_route_config.cc',
'src/core/ext/xds/xds_routing.cc',
'src/core/ext/xds/xds_server_config_fetcher.cc',

1
package.xml generated

@ -883,7 +883,6 @@
<file baseinstalldir="/" name="src/core/ext/xds/xds_lb_policy_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_listener.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_listener.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_resource_type.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_resource_type.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_resource_type_impl.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/xds/xds_route_config.cc" role="src" />

@ -82,10 +82,6 @@ XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer,
tracer_(tracer),
node_(node),
symtab_(symtab),
build_version_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING, " ",
grpc_version_string(),
GRPC_XDS_USER_AGENT_NAME_SUFFIX_STRING,
GRPC_XDS_USER_AGENT_VERSION_SUFFIX_STRING)),
user_agent_name_(absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING,
GRPC_XDS_USER_AGENT_NAME_SUFFIX_STRING)),
user_agent_version_(
@ -100,7 +96,6 @@ struct XdsApiContext {
TraceFlag* tracer;
upb_DefPool* symtab;
upb_Arena* arena;
bool use_v3;
};
void PopulateMetadataValue(const XdsApiContext& context,
@ -162,41 +157,7 @@ void PopulateMetadataValue(const XdsApiContext& context,
}
}
// Helper functions to manually do protobuf string encoding, so that we
// can populate the node build_version field that was removed in v3.
std::string EncodeVarint(uint64_t val) {
std::string data;
do {
uint8_t byte = val & 0x7fU;
val >>= 7;
if (val) byte |= 0x80U;
data += byte;
} while (val);
return data;
}
std::string EncodeTag(uint32_t field_number, uint8_t wire_type) {
return EncodeVarint((field_number << 3) | wire_type);
}
std::string EncodeStringField(uint32_t field_number, const std::string& str) {
static const uint8_t kDelimitedWireType = 2;
return EncodeTag(field_number, kDelimitedWireType) +
EncodeVarint(str.size()) + str;
}
void PopulateBuildVersion(const XdsApiContext& context,
envoy_config_core_v3_Node* node_msg,
const std::string& build_version) {
std::string encoded_build_version = EncodeStringField(5, build_version);
// TODO(roth): This should use upb_Message_AddUnknown(), but that API is
// broken in the current version of upb, so we're using the internal
// API for now. Change this once we upgrade to a version of upb that
// fixes this bug.
_upb_Message_AddUnknown(node_msg, encoded_build_version.data(),
encoded_build_version.size(), context.arena);
}
void PopulateNode(const XdsApiContext& context, const XdsBootstrap::Node* node,
const std::string& build_version,
const std::string& user_agent_name,
const std::string& user_agent_version,
envoy_config_core_v3_Node* node_msg) {
@ -232,9 +193,6 @@ void PopulateNode(const XdsApiContext& context, const XdsBootstrap::Node* node,
}
}
}
if (!context.use_v3) {
PopulateBuildVersion(context, node_msg, build_version);
}
envoy_config_core_v3_Node_set_user_agent_name(
node_msg, StdStringToUpbString(user_agent_name));
envoy_config_core_v3_Node_set_user_agent_version(
@ -271,13 +229,11 @@ std::string SerializeDiscoveryRequest(
} // namespace
std::string XdsApi::CreateAdsRequest(
const XdsBootstrap::XdsServer& server, absl::string_view type_url,
absl::string_view version, absl::string_view nonce,
const std::vector<std::string>& resource_names, absl::Status status,
bool populate_node) {
absl::string_view type_url, absl::string_view version,
absl::string_view nonce, const std::vector<std::string>& resource_names,
absl::Status status, bool populate_node) {
upb::Arena arena;
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr(),
server.ShouldUseV3()};
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr()};
// Create a request.
envoy_service_discovery_v3_DiscoveryRequest* request =
envoy_service_discovery_v3_DiscoveryRequest_new(arena.ptr());
@ -317,8 +273,8 @@ std::string XdsApi::CreateAdsRequest(
envoy_config_core_v3_Node* node_msg =
envoy_service_discovery_v3_DiscoveryRequest_mutable_node(request,
arena.ptr());
PopulateNode(context, node_, build_version_, user_agent_name_,
user_agent_version_, node_msg);
PopulateNode(context, node_, user_agent_name_, user_agent_version_,
node_msg);
envoy_config_core_v3_Node_add_client_features(
node_msg, upb_StringView_FromString("xds.config.resource-in-sotw"),
context.arena);
@ -350,12 +306,10 @@ void MaybeLogDiscoveryResponse(
} // namespace
absl::Status XdsApi::ParseAdsResponse(const XdsBootstrap::XdsServer& server,
absl::string_view encoded_response,
absl::Status XdsApi::ParseAdsResponse(absl::string_view encoded_response,
AdsResponseParserInterface* parser) {
upb::Arena arena;
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr(),
server.ShouldUseV3()};
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr()};
// Decode the response.
const envoy_service_discovery_v3_DiscoveryResponse* response =
envoy_service_discovery_v3_DiscoveryResponse_parse(
@ -391,8 +345,7 @@ absl::Status XdsApi::ParseAdsResponse(const XdsBootstrap::XdsServer& server,
UpbStringToAbsl(google_protobuf_Any_value(resources[i]));
// Unwrap Resource messages, if so wrapped.
absl::string_view resource_name;
if (type_url == "envoy.api.v2.Resource" ||
type_url == "envoy.service.discovery.v3.Resource") {
if (type_url == "envoy.service.discovery.v3.Resource") {
const auto* resource_wrapper = envoy_service_discovery_v3_Resource_parse(
serialized_resource.data(), serialized_resource.size(), arena.ptr());
if (resource_wrapper == nullptr) {
@ -442,11 +395,9 @@ std::string SerializeLrsRequest(
} // namespace
std::string XdsApi::CreateLrsInitialRequest(
const XdsBootstrap::XdsServer& server) {
std::string XdsApi::CreateLrsInitialRequest() {
upb::Arena arena;
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr(),
server.ShouldUseV3()};
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr()};
// Create a request.
envoy_service_load_stats_v3_LoadStatsRequest* request =
envoy_service_load_stats_v3_LoadStatsRequest_new(arena.ptr());
@ -454,8 +405,7 @@ std::string XdsApi::CreateLrsInitialRequest(
envoy_config_core_v3_Node* node_msg =
envoy_service_load_stats_v3_LoadStatsRequest_mutable_node(request,
arena.ptr());
PopulateNode(context, node_, build_version_, user_agent_name_,
user_agent_version_, node_msg);
PopulateNode(context, node_, user_agent_name_, user_agent_version_, node_msg);
envoy_config_core_v3_Node_add_client_features(
node_msg,
upb_StringView_FromString("envoy.lrs.supports_send_all_clusters"),
@ -517,8 +467,7 @@ void LocalityStatsPopulate(
std::string XdsApi::CreateLrsRequest(
ClusterLoadReportMap cluster_load_report_map) {
upb::Arena arena;
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr(),
/*use_v3=*/false};
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr()};
// Create a request.
envoy_service_load_stats_v3_LoadStatsRequest* request =
envoy_service_load_stats_v3_LoadStatsRequest_new(arena.ptr());
@ -636,10 +585,8 @@ std::string XdsApi::AssembleClientConfig(
// Fill-in the node information
auto* node = envoy_service_status_v3_ClientConfig_mutable_node(client_config,
arena.ptr());
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr(),
/*use_v3=*/true};
PopulateNode(context, node_, build_version_, user_agent_name_,
user_agent_version_, node);
const XdsApiContext context = {client_, tracer_, symtab_->ptr(), arena.ptr()};
PopulateNode(context, node_, user_agent_name_, user_agent_version_, node);
// Dump each resource.
std::vector<std::string> type_url_storage;
for (const auto& p : resource_type_metadata_map) {

@ -150,9 +150,7 @@ class XdsApi {
upb::SymbolTable* symtab);
// Creates an ADS request.
// Takes ownership of \a error.
std::string CreateAdsRequest(const XdsBootstrap::XdsServer& server,
absl::string_view type_url,
std::string CreateAdsRequest(absl::string_view type_url,
absl::string_view version,
absl::string_view nonce,
const std::vector<std::string>& resource_names,
@ -160,12 +158,11 @@ class XdsApi {
// Returns non-OK when failing to deserialize response message.
// Otherwise, all events are reported to the parser.
absl::Status ParseAdsResponse(const XdsBootstrap::XdsServer& server,
absl::string_view encoded_response,
absl::Status ParseAdsResponse(absl::string_view encoded_response,
AdsResponseParserInterface* parser);
// Creates an initial LRS request.
std::string CreateLrsInitialRequest(const XdsBootstrap::XdsServer& server);
std::string CreateLrsInitialRequest();
// Creates an LRS request sending a client-side load report.
std::string CreateLrsRequest(ClusterLoadReportMap cluster_load_report_map);
@ -186,7 +183,6 @@ class XdsApi {
TraceFlag* tracer_;
const XdsBootstrap::Node* node_; // Do not own.
upb::SymbolTable* symtab_; // Do not own.
const std::string build_version_;
const std::string user_agent_name_;
const std::string user_agent_version_;
};

@ -46,7 +46,6 @@ class XdsBootstrap {
virtual ~XdsServer() = default;
virtual const std::string& server_uri() const = 0;
virtual bool ShouldUseV3() const = 0;
virtual bool IgnoreResourceDeletion() const = 0;
virtual bool Equals(const XdsServer& other) const = 0;

@ -94,17 +94,11 @@ GrpcXdsBootstrap::GrpcXdsServer::ChannelCreds::JsonLoader(const JsonArgs&) {
namespace {
constexpr absl::string_view kServerFeatureXdsV3 = "xds_v3";
constexpr absl::string_view kServerFeatureIgnoreResourceDeletion =
"ignore_resource_deletion";
} // namespace
bool GrpcXdsBootstrap::GrpcXdsServer::ShouldUseV3() const {
return server_features_.find(std::string(kServerFeatureXdsV3)) !=
server_features_.end();
}
bool GrpcXdsBootstrap::GrpcXdsServer::IgnoreResourceDeletion() const {
return server_features_.find(std::string(
kServerFeatureIgnoreResourceDeletion)) != server_features_.end();
@ -167,9 +161,8 @@ void GrpcXdsBootstrap::GrpcXdsServer::JsonPostLoad(const Json& json,
const Json::Array& array = it->second.array_value();
for (const Json& feature_json : array) {
if (feature_json.type() == Json::Type::STRING &&
(feature_json.string_value() == kServerFeatureXdsV3 ||
feature_json.string_value() ==
kServerFeatureIgnoreResourceDeletion)) {
(feature_json.string_value() ==
kServerFeatureIgnoreResourceDeletion)) {
server_features_.insert(feature_json.string_value());
}
}

@ -74,7 +74,6 @@ class GrpcXdsBootstrap : public XdsBootstrap {
public:
const std::string& server_uri() const override { return server_uri_; }
bool ShouldUseV3() const override;
bool IgnoreResourceDeletion() const override;
bool Equals(const XdsServer& other) const override;

@ -720,8 +720,7 @@ void XdsClient::ChannelState::AdsCallState::AdsResponseParser::ParseResource(
"resource index ", idx, ": ",
resource_name.empty() ? "" : absl::StrCat(resource_name, ": "));
// Check the type_url of the resource.
bool is_v2 = false;
if (!result_.type->IsType(type_url, &is_v2)) {
if (result_.type_url != type_url) {
result_.errors.emplace_back(
absl::StrCat(error_prefix, "incorrect resource type ", type_url,
" (should be ", result_.type_url, ")"));
@ -732,7 +731,7 @@ void XdsClient::ChannelState::AdsCallState::AdsResponseParser::ParseResource(
xds_client(), ads_call_state_->chand()->server_, &grpc_xds_client_trace,
xds_client()->symtab_.ptr(), arena};
XdsResourceType::DecodeResult decode_result =
result_.type->Decode(context, serialized_resource, is_v2);
result_.type->Decode(context, serialized_resource);
// If we didn't already have the resource name from the Resource
// wrapper, try to get it from the decoding result.
if (resource_name.empty()) {
@ -873,11 +872,8 @@ XdsClient::ChannelState::AdsCallState::AdsCallState(
GPR_ASSERT(xds_client() != nullptr);
// Init the ADS call.
const char* method =
chand()->server_.ShouldUseV3()
? "/envoy.service.discovery.v3.AggregatedDiscoveryService/"
"StreamAggregatedResources"
: "/envoy.service.discovery.v2.AggregatedDiscoveryService/"
"StreamAggregatedResources";
"/envoy.service.discovery.v3.AggregatedDiscoveryService/"
"StreamAggregatedResources";
call_ = chand()->transport_->CreateStreamingCall(
method, std::make_unique<StreamEventHandler>(
// Passing the initial ref here. This ref will go away when
@ -930,9 +926,7 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked(
}
auto& state = state_map_[type];
std::string serialized_message = xds_client()->api_.CreateAdsRequest(
chand()->server_,
chand()->server_.ShouldUseV3() ? type->type_url() : type->v2_type_url(),
chand()->resource_type_version_map_[type], state.nonce,
type->type_url(), chand()->resource_type_version_map_[type], state.nonce,
ResourceNamesForRequest(type), state.status, !sent_initial_message_);
sent_initial_message_ = true;
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) {
@ -1005,8 +999,7 @@ void XdsClient::ChannelState::AdsCallState::OnRecvMessage(
if (!IsCurrentCallOnChannel()) return;
// Parse and validate the response.
AdsResponseParser parser(this);
absl::Status status =
xds_client()->api_.ParseAdsResponse(chand()->server_, payload, &parser);
absl::Status status = xds_client()->api_.ParseAdsResponse(payload, &parser);
if (!status.ok()) {
// Ignore unparsable response.
gpr_log(GPR_ERROR,
@ -1262,11 +1255,8 @@ XdsClient::ChannelState::LrsCallState::LrsCallState(
// activity in xds_client()->interested_parties_, which is comprised of
// the polling entities from client_channel.
GPR_ASSERT(xds_client() != nullptr);
const char* method = chand()->server_.ShouldUseV3()
? "/envoy.service.load_stats.v3."
"LoadReportingService/StreamLoadStats"
: "/envoy.service.load_stats.v2."
"LoadReportingService/StreamLoadStats";
const char* method =
"/envoy.service.load_stats.v3.LoadReportingService/StreamLoadStats";
call_ = chand()->transport_->CreateStreamingCall(
method, std::make_unique<StreamEventHandler>(
// Passing the initial ref here. This ref will go away when
@ -1282,8 +1272,7 @@ XdsClient::ChannelState::LrsCallState::LrsCallState(
call_.get());
}
// Send the initial request.
std::string serialized_payload =
xds_client()->api_.CreateLrsInitialRequest(chand()->server_);
std::string serialized_payload = xds_client()->api_.CreateLrsInitialRequest();
call_->SendMessage(std::move(serialized_payload));
send_message_pending_ = true;
}
@ -1653,7 +1642,6 @@ void XdsClient::MaybeRegisterResourceTypeLocked(
return;
}
resource_types_.emplace(resource_type->type_url(), resource_type);
v2_resource_types_.emplace(resource_type->v2_type_url(), resource_type);
resource_type->InitUpbSymtab(symtab_.ptr());
}
@ -1661,8 +1649,6 @@ const XdsResourceType* XdsClient::GetResourceTypeLocked(
absl::string_view resource_type) {
auto it = resource_types_.find(resource_type);
if (it != resource_types_.end()) return it->second;
auto it2 = v2_resource_types_.find(resource_type);
if (it2 != v2_resource_types_.end()) return it2->second;
return nullptr;
}
@ -1680,7 +1666,7 @@ absl::StatusOr<XdsClient::XdsResourceName> XdsClient::ParseXdsResourceName(
// Split the resource type off of the path to get the id.
std::pair<absl::string_view, absl::string_view> path_parts = absl::StrSplit(
absl::StripPrefix(uri->path(), "/"), absl::MaxSplits('/', 1));
if (!type->IsType(path_parts.first, nullptr)) {
if (type->type_url() != path_parts.first) {
return absl::InvalidArgumentError(
"xdstp URI path must indicate valid xDS resource type");
}

@ -314,8 +314,6 @@ class XdsClient : public DualRefCounted<XdsClient> {
// Stores resource type objects seen by type URL.
std::map<absl::string_view /*resource_type*/, const XdsResourceType*>
resource_types_ ABSL_GUARDED_BY(mu_);
std::map<absl::string_view /*v2_resource_type*/, const XdsResourceType*>
v2_resource_types_ ABSL_GUARDED_BY(mu_);
upb::SymbolTable symtab_ ABSL_GUARDED_BY(mu_);
// Map of existing xDS server channels.

@ -275,7 +275,7 @@ void AggregateClusterParse(const XdsResourceType::DecodeContext& context,
absl::StatusOr<XdsClusterResource> CdsResourceParse(
const XdsResourceType::DecodeContext& context,
const envoy_config_cluster_v3_Cluster* cluster, bool /*is_v2*/) {
const envoy_config_cluster_v3_Cluster* cluster) {
XdsClusterResource cds_update;
ValidationErrors errors;
// Check the cluster discovery type.
@ -580,7 +580,7 @@ void MaybeLogCluster(const XdsResourceType::DecodeContext& context,
XdsResourceType::DecodeResult XdsClusterResourceType::Decode(
const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource, bool is_v2) const {
absl::string_view serialized_resource) const {
DecodeResult result;
// Parse serialized proto.
auto* resource = envoy_config_cluster_v3_Cluster_parse(
@ -594,7 +594,7 @@ XdsResourceType::DecodeResult XdsClusterResourceType::Decode(
// Validate resource.
result.name =
UpbStringToStdString(envoy_config_cluster_v3_Cluster_name(resource));
auto cds_resource = CdsResourceParse(context, resource, is_v2);
auto cds_resource = CdsResourceParse(context, resource);
if (!cds_resource.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) {
gpr_log(GPR_ERROR, "[xds_client %p] invalid Cluster %s: %s",

@ -94,13 +94,9 @@ class XdsClusterResourceType
absl::string_view type_url() const override {
return "envoy.config.cluster.v3.Cluster";
}
absl::string_view v2_type_url() const override {
return "envoy.api.v2.Cluster";
}
DecodeResult Decode(const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource,
bool is_v2) const override;
absl::string_view serialized_resource) const override;
bool AllResourcesRequiredInSotW() const override { return true; }

@ -430,7 +430,7 @@ absl::StatusOr<XdsEndpointResource> EdsResourceParse(
XdsResourceType::DecodeResult XdsEndpointResourceType::Decode(
const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource, bool /*is_v2*/) const {
absl::string_view serialized_resource) const {
DecodeResult result;
// Parse serialized proto.
auto* resource = envoy_config_endpoint_v3_ClusterLoadAssignment_parse(

@ -124,13 +124,9 @@ class XdsEndpointResourceType
absl::string_view type_url() const override {
return "envoy.config.endpoint.v3.ClusterLoadAssignment";
}
absl::string_view v2_type_url() const override {
return "envoy.api.v2.ClusterLoadAssignment";
}
DecodeResult Decode(const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource,
bool is_v2) const override;
absl::string_view serialized_resource) const override;
void InitUpbSymtab(upb_DefPool* symtab) const override {
envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab);

@ -60,7 +60,6 @@
#include "src/core/lib/gprpp/validation_errors.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/json/json.h"
namespace grpc_core {
@ -291,8 +290,7 @@ absl::StatusOr<XdsListenerResource::HttpConnectionManager>
HttpConnectionManagerParse(
bool is_client, const XdsResourceType::DecodeContext& context,
const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager*
http_connection_manager_proto,
bool is_v2) {
http_connection_manager_proto) {
MaybeLogHttpConnectionManager(context, http_connection_manager_proto);
std::vector<std::string> errors;
XdsListenerResource::HttpConnectionManager http_connection_manager;
@ -325,119 +323,108 @@ HttpConnectionManagerParse(
}
}
// Parse filters.
if (!is_v2) {
size_t num_filters = 0;
const auto* http_filters =
envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_http_filters(
http_connection_manager_proto, &num_filters);
std::set<absl::string_view> names_seen;
for (size_t i = 0; i < num_filters; ++i) {
const auto* http_filter = http_filters[i];
absl::string_view name = UpbStringToAbsl(
envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_name(
http_filter));
if (name.empty()) {
errors.emplace_back(absl::StrCat("empty filter name at index ", i));
continue;
}
if (names_seen.find(name) != names_seen.end()) {
errors.emplace_back(absl::StrCat("duplicate HTTP filter name: ", name));
continue;
}
names_seen.insert(name);
const bool is_optional =
envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_is_optional(
http_filter);
const google_protobuf_Any* any =
envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_typed_config(
http_filter);
if (any == nullptr) {
if (!is_optional) {
errors.emplace_back(absl::StrCat(
"no filter config specified for filter name ", name));
}
continue;
}
ValidationErrors validation_errors;
ValidationErrors::ScopedField field(
&validation_errors,
absl::StrCat(".http_filters[", i, "].typed_config"));
auto extension = ExtractXdsExtension(context, any, &validation_errors);
if (!validation_errors.ok()) {
size_t num_filters = 0;
const auto* http_filters =
envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_http_filters(
http_connection_manager_proto, &num_filters);
std::set<absl::string_view> names_seen;
for (size_t i = 0; i < num_filters; ++i) {
const auto* http_filter = http_filters[i];
absl::string_view name = UpbStringToAbsl(
envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_name(
http_filter));
if (name.empty()) {
errors.emplace_back(absl::StrCat("empty filter name at index ", i));
continue;
}
if (names_seen.find(name) != names_seen.end()) {
errors.emplace_back(absl::StrCat("duplicate HTTP filter name: ", name));
continue;
}
names_seen.insert(name);
const bool is_optional =
envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_is_optional(
http_filter);
const google_protobuf_Any* any =
envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_typed_config(
http_filter);
if (any == nullptr) {
if (!is_optional) {
errors.emplace_back(
validation_errors.status(absl::StrCat("filter name ", name))
.message());
continue;
absl::StrCat("no filter config specified for filter name ", name));
}
GPR_ASSERT(extension.has_value());
const XdsHttpFilterImpl* filter_impl =
XdsHttpFilterRegistry::GetFilterForType(extension->type);
if (filter_impl == nullptr) {
if (!is_optional) {
errors.emplace_back(absl::StrCat(
"no filter registered for config type ", extension->type));
}
continue;
}
if ((is_client && !filter_impl->IsSupportedOnClients()) ||
(!is_client && !filter_impl->IsSupportedOnServers())) {
if (!is_optional) {
errors.emplace_back(absl::StrFormat(
"Filter %s is not supported on %s", extension->type,
is_client ? "clients" : "servers"));
}
continue;
}
absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config =
filter_impl->GenerateFilterConfig(std::move(*extension),
context.arena);
if (!filter_config.ok()) {
continue;
}
ValidationErrors validation_errors;
ValidationErrors::ScopedField field(
&validation_errors,
absl::StrCat(".http_filters[", i, "].typed_config"));
auto extension = ExtractXdsExtension(context, any, &validation_errors);
if (!validation_errors.ok()) {
errors.emplace_back(
validation_errors.status(absl::StrCat("filter name ", name))
.message());
continue;
}
GPR_ASSERT(extension.has_value());
const XdsHttpFilterImpl* filter_impl =
XdsHttpFilterRegistry::GetFilterForType(extension->type);
if (filter_impl == nullptr) {
if (!is_optional) {
errors.emplace_back(absl::StrCat(
"filter config for type ", extension->type,
" failed to parse: ", StatusToString(filter_config.status())));
continue;
"no filter registered for config type ", extension->type));
}
http_connection_manager.http_filters.emplace_back(
XdsListenerResource::HttpConnectionManager::HttpFilter{
std::string(name), std::move(*filter_config)});
}
if (http_connection_manager.http_filters.empty()) {
errors.emplace_back("Expected at least one HTTP filter");
continue;
}
// Make sure that the last filter is terminal and non-last filters are
// non-terminal. Note that this check is being performed in a separate loop
// to take care of the case where there are two terminal filters in the list
// out of which only one gets added in the final list.
for (const auto& http_filter : http_connection_manager.http_filters) {
const XdsHttpFilterImpl* filter_impl =
XdsHttpFilterRegistry::GetFilterForType(
http_filter.config.config_proto_type_name);
if (&http_filter != &http_connection_manager.http_filters.back()) {
// Filters before the last filter must not be terminal.
if (filter_impl->IsTerminalFilter()) {
errors.emplace_back(
absl::StrCat("terminal filter for config type ",
http_filter.config.config_proto_type_name,
" must be the last filter in the chain"));
}
} else {
// The last filter must be terminal.
if (!filter_impl->IsTerminalFilter()) {
errors.emplace_back(
absl::StrCat("non-terminal filter for config type ",
http_filter.config.config_proto_type_name,
" is the last filter in the chain"));
}
if ((is_client && !filter_impl->IsSupportedOnClients()) ||
(!is_client && !filter_impl->IsSupportedOnServers())) {
if (!is_optional) {
errors.emplace_back(absl::StrFormat("Filter %s is not supported on %s",
extension->type,
is_client ? "clients" : "servers"));
}
continue;
}
absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config =
filter_impl->GenerateFilterConfig(std::move(*extension), context.arena);
if (!filter_config.ok()) {
errors.emplace_back(absl::StrCat(
"filter config for type ", extension->type,
" failed to parse: ", StatusToString(filter_config.status())));
continue;
}
} else {
// If using a v2 config, we just hard-code a list containing only the
// router filter without actually looking at the config. This ensures
// that the right thing happens in the xds resolver without having
// to expose whether the resource we received was v2 or v3.
http_connection_manager.http_filters.emplace_back(
XdsListenerResource::HttpConnectionManager::HttpFilter{
"router", {kXdsHttpRouterFilterConfigName, Json()}});
std::string(name), std::move(*filter_config)});
}
if (http_connection_manager.http_filters.empty()) {
errors.emplace_back("Expected at least one HTTP filter");
}
// Make sure that the last filter is terminal and non-last filters are
// non-terminal. Note that this check is being performed in a separate loop
// to take care of the case where there are two terminal filters in the list
// out of which only one gets added in the final list.
for (const auto& http_filter : http_connection_manager.http_filters) {
const XdsHttpFilterImpl* filter_impl =
XdsHttpFilterRegistry::GetFilterForType(
http_filter.config.config_proto_type_name);
if (&http_filter != &http_connection_manager.http_filters.back()) {
// Filters before the last filter must not be terminal.
if (filter_impl->IsTerminalFilter()) {
errors.emplace_back(
absl::StrCat("terminal filter for config type ",
http_filter.config.config_proto_type_name,
" must be the last filter in the chain"));
}
} else {
// The last filter must be terminal.
if (!filter_impl->IsTerminalFilter()) {
errors.emplace_back(
absl::StrCat("non-terminal filter for config type ",
http_filter.config.config_proto_type_name,
" is the last filter in the chain"));
}
}
}
// Found inlined route_config. Parse it to find the cluster_name.
if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config(
@ -490,7 +477,7 @@ HttpConnectionManagerParse(
absl::StatusOr<XdsListenerResource> LdsResourceParseClient(
const XdsResourceType::DecodeContext& context,
const envoy_config_listener_v3_ApiListener* api_listener, bool is_v2) {
const envoy_config_listener_v3_ApiListener* api_listener) {
const upb_StringView encoded_api_listener = google_protobuf_Any_value(
envoy_config_listener_v3_ApiListener_api_listener(api_listener));
const auto* http_connection_manager =
@ -501,7 +488,7 @@ absl::StatusOr<XdsListenerResource> LdsResourceParseClient(
"Could not parse HttpConnectionManager config from ApiListener");
}
auto hcm = HttpConnectionManagerParse(true /* is_client */, context,
http_connection_manager, is_v2);
http_connection_manager);
if (!hcm.ok()) return hcm.status();
XdsListenerResource lds_update;
lds_update.type = XdsListenerResource::ListenerType::kHttpApiListener;
@ -691,8 +678,7 @@ absl::StatusOr<FilterChain::FilterChainMatch> FilterChainMatchParse(
absl::StatusOr<FilterChain> FilterChainParse(
const XdsResourceType::DecodeContext& context,
const envoy_config_listener_v3_FilterChain* filter_chain_proto,
bool is_v2) {
const envoy_config_listener_v3_FilterChain* filter_chain_proto) {
FilterChain filter_chain;
std::vector<std::string> errors;
auto* filter_chain_match =
@ -742,7 +728,7 @@ absl::StatusOr<FilterChain> FilterChainParse(
"typed_config");
} else {
auto hcm = HttpConnectionManagerParse(
/*is_client=*/false, context, http_connection_manager, is_v2);
/*is_client=*/false, context, http_connection_manager);
if (!hcm.ok()) {
errors.emplace_back(hcm.status().message());
} else {
@ -985,7 +971,7 @@ absl::StatusOr<XdsListenerResource::FilterChainMap> BuildFilterChainMap(
absl::StatusOr<XdsListenerResource> LdsResourceParseServer(
const XdsResourceType::DecodeContext& context,
const envoy_config_listener_v3_Listener* listener, bool is_v2) {
const envoy_config_listener_v3_Listener* listener) {
XdsListenerResource lds_update;
lds_update.type = XdsListenerResource::ListenerType::kTcpListener;
auto address =
@ -1006,7 +992,7 @@ absl::StatusOr<XdsListenerResource> LdsResourceParseServer(
std::vector<FilterChain> parsed_filter_chains;
parsed_filter_chains.reserve(size);
for (size_t i = 0; i < size; i++) {
auto filter_chain = FilterChainParse(context, filter_chains[i], is_v2);
auto filter_chain = FilterChainParse(context, filter_chains[i]);
if (!filter_chain.ok()) return filter_chain.status();
parsed_filter_chains.push_back(std::move(*filter_chain));
}
@ -1016,7 +1002,7 @@ absl::StatusOr<XdsListenerResource> LdsResourceParseServer(
auto* default_filter_chain =
envoy_config_listener_v3_Listener_default_filter_chain(listener);
if (default_filter_chain != nullptr) {
auto filter_chain = FilterChainParse(context, default_filter_chain, is_v2);
auto filter_chain = FilterChainParse(context, default_filter_chain);
if (!filter_chain.ok()) return filter_chain.status();
if (filter_chain->filter_chain_data != nullptr) {
lds_update.default_filter_chain =
@ -1031,7 +1017,7 @@ absl::StatusOr<XdsListenerResource> LdsResourceParseServer(
absl::StatusOr<XdsListenerResource> LdsResourceParse(
const XdsResourceType::DecodeContext& context,
const envoy_config_listener_v3_Listener* listener, bool is_v2) {
const envoy_config_listener_v3_Listener* listener) {
// Check whether it's a client or server listener.
const envoy_config_listener_v3_ApiListener* api_listener =
envoy_config_listener_v3_Listener_api_listener(listener);
@ -1050,9 +1036,9 @@ absl::StatusOr<XdsListenerResource> LdsResourceParse(
// If api_listener is present, it's for a client; otherwise, it's
// for a server.
if (api_listener != nullptr) {
return LdsResourceParseClient(context, api_listener, is_v2);
return LdsResourceParseClient(context, api_listener);
}
return LdsResourceParseServer(context, listener, is_v2);
return LdsResourceParseServer(context, listener);
}
void MaybeLogListener(const XdsResourceType::DecodeContext& context,
@ -1071,7 +1057,7 @@ void MaybeLogListener(const XdsResourceType::DecodeContext& context,
XdsResourceType::DecodeResult XdsListenerResourceType::Decode(
const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource, bool is_v2) const {
absl::string_view serialized_resource) const {
DecodeResult result;
// Parse serialized proto.
auto* resource = envoy_config_listener_v3_Listener_parse(
@ -1085,7 +1071,7 @@ XdsResourceType::DecodeResult XdsListenerResourceType::Decode(
// Validate resource.
result.name =
UpbStringToStdString(envoy_config_listener_v3_Listener_name(resource));
auto listener = LdsResourceParse(context, resource, is_v2);
auto listener = LdsResourceParse(context, resource);
if (!listener.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) {
gpr_log(GPR_ERROR, "[xds_client %p] invalid Listener %s: %s",

@ -205,13 +205,9 @@ class XdsListenerResourceType
absl::string_view type_url() const override {
return "envoy.config.listener.v3.Listener";
}
absl::string_view v2_type_url() const override {
return "envoy.api.v2.Listener";
}
DecodeResult Decode(const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource,
bool is_v2) const override;
absl::string_view serialized_resource) const override;
bool AllResourcesRequiredInSotW() const override { return true; }

@ -1,33 +0,0 @@
//
// Copyright 2021 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <grpc/support/port_platform.h>
#include "src/core/ext/xds/xds_resource_type.h"
namespace grpc_core {
bool XdsResourceType::IsType(absl::string_view resource_type,
bool* is_v2) const {
if (resource_type == type_url()) return true;
if (resource_type == v2_type_url()) {
if (is_v2 != nullptr) *is_v2 = true;
return true;
}
return false;
}
} // namespace grpc_core

@ -69,13 +69,9 @@ class XdsResourceType {
// Returns v3 resource type.
virtual absl::string_view type_url() const = 0;
// Returns v2 resource type.
virtual absl::string_view v2_type_url() const = 0;
// Decodes and validates a serialized resource proto.
virtual DecodeResult Decode(const DecodeContext& context,
absl::string_view serialized_resource,
bool is_v2) const = 0;
absl::string_view serialized_resource) const = 0;
// Returns true if r1 and r2 are equal.
// Must be invoked only on resources returned by this object's Decode()
@ -100,11 +96,6 @@ class XdsResourceType {
// Note: This won't actually work properly until upb adds support for
// Any fields in textproto printing (internal b/178821188).
virtual void InitUpbSymtab(upb_DefPool* symtab) const = 0;
// Convenience method for checking if resource_type matches this type.
// Checks against both type_url() and v2_type_url().
// If is_v2 is non-null, it will be set to true if matching v2_type_url().
bool IsType(absl::string_view resource_type, bool* is_v2) const;
};
} // namespace grpc_core

@ -57,7 +57,6 @@
#include <grpc/support/log.h>
#include "src/core/ext/xds/upb_utils.h"
#include "src/core/ext/xds/xds_bootstrap.h"
#include "src/core/ext/xds/xds_cluster_specifier_plugin.h"
#include "src/core/ext/xds/xds_common_types.h"
#include "src/core/ext/xds/xds_http_filters.h"
@ -795,19 +794,17 @@ absl::StatusOr<XdsRouteConfigResource::Route::RouteAction> RouteActionParse(
cluster.weight = google_protobuf_UInt32Value_value(weight);
if (cluster.weight == 0) continue;
sum_of_weights += cluster.weight;
if (context.server.ShouldUseV3()) {
auto typed_per_filter_config = ParseTypedPerFilterConfig<
envoy_config_route_v3_WeightedCluster_ClusterWeight,
envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry>(
context, cluster_weight,
envoy_config_route_v3_WeightedCluster_ClusterWeight_typed_per_filter_config_next,
envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_key,
envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_value);
if (!typed_per_filter_config.ok()) {
return typed_per_filter_config.status();
}
cluster.typed_per_filter_config = std::move(*typed_per_filter_config);
auto typed_per_filter_config = ParseTypedPerFilterConfig<
envoy_config_route_v3_WeightedCluster_ClusterWeight,
envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry>(
context, cluster_weight,
envoy_config_route_v3_WeightedCluster_ClusterWeight_typed_per_filter_config_next,
envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_key,
envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_value);
if (!typed_per_filter_config.ok()) {
return typed_per_filter_config.status();
}
cluster.typed_per_filter_config = std::move(*typed_per_filter_config);
action_weighted_clusters.emplace_back(std::move(cluster));
}
if (total_weight != sum_of_weights) {
@ -996,19 +993,17 @@ absl::StatusOr<XdsRouteConfigResource> XdsRouteConfigResource::Parse(
return absl::InvalidArgumentError("VirtualHost has no domains");
}
// Parse typed_per_filter_config.
if (context.server.ShouldUseV3()) {
auto typed_per_filter_config = ParseTypedPerFilterConfig<
envoy_config_route_v3_VirtualHost,
envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry>(
context, virtual_hosts[i],
envoy_config_route_v3_VirtualHost_typed_per_filter_config_next,
envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_key,
envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_value);
if (!typed_per_filter_config.ok()) {
return typed_per_filter_config.status();
}
vhost.typed_per_filter_config = std::move(*typed_per_filter_config);
auto typed_per_filter_config = ParseTypedPerFilterConfig<
envoy_config_route_v3_VirtualHost,
envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry>(
context, virtual_hosts[i],
envoy_config_route_v3_VirtualHost_typed_per_filter_config_next,
envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_key,
envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_value);
if (!typed_per_filter_config.ok()) {
return typed_per_filter_config.status();
}
vhost.typed_per_filter_config = std::move(*typed_per_filter_config);
// Parse retry policy.
absl::optional<XdsRouteConfigResource::RetryPolicy>
virtual_host_retry_policy;
@ -1079,19 +1074,17 @@ absl::StatusOr<XdsRouteConfigResource> XdsRouteConfigResource::Parse(
route.action
.emplace<XdsRouteConfigResource::Route::NonForwardingAction>();
}
if (context.server.ShouldUseV3()) {
auto typed_per_filter_config = ParseTypedPerFilterConfig<
envoy_config_route_v3_Route,
envoy_config_route_v3_Route_TypedPerFilterConfigEntry>(
context, routes[j],
envoy_config_route_v3_Route_typed_per_filter_config_next,
envoy_config_route_v3_Route_TypedPerFilterConfigEntry_key,
envoy_config_route_v3_Route_TypedPerFilterConfigEntry_value);
if (!typed_per_filter_config.ok()) {
return typed_per_filter_config.status();
}
route.typed_per_filter_config = std::move(*typed_per_filter_config);
auto typed_per_filter_config = ParseTypedPerFilterConfig<
envoy_config_route_v3_Route,
envoy_config_route_v3_Route_TypedPerFilterConfigEntry>(
context, routes[j],
envoy_config_route_v3_Route_typed_per_filter_config_next,
envoy_config_route_v3_Route_TypedPerFilterConfigEntry_key,
envoy_config_route_v3_Route_TypedPerFilterConfigEntry_value);
if (!typed_per_filter_config.ok()) {
return typed_per_filter_config.status();
}
route.typed_per_filter_config = std::move(*typed_per_filter_config);
vhost.routes.emplace_back(std::move(route));
}
if (vhost.routes.empty()) {
@ -1130,7 +1123,7 @@ void MaybeLogRouteConfiguration(
XdsResourceType::DecodeResult XdsRouteConfigResourceType::Decode(
const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource, bool /*is_v2*/) const {
absl::string_view serialized_resource) const {
DecodeResult result;
// Parse serialized proto.
auto* resource = envoy_config_route_v3_RouteConfiguration_parse(

@ -220,13 +220,9 @@ class XdsRouteConfigResourceType
absl::string_view type_url() const override {
return "envoy.config.route.v3.RouteConfiguration";
}
absl::string_view v2_type_url() const override {
return "envoy.api.v2.RouteConfiguration";
}
DecodeResult Decode(const XdsResourceType::DecodeContext& context,
absl::string_view serialized_resource,
bool /*is_v2*/) const override;
absl::string_view serialized_resource) const override;
void InitUpbSymtab(upb_DefPool* symtab) const override {
envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab);

@ -1,71 +0,0 @@
# Copyright 2017 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
licenses(["notice"])
grpc_package(
name = "xds",
visibility = "public",
)
grpc_proto_library(
name = "ads_for_test_proto",
srcs = [
"ads_for_test.proto",
],
has_services = True,
deps = ["eds_for_test_proto"],
)
grpc_proto_library(
name = "cds_for_test_proto",
srcs = [
"cds_for_test.proto",
],
well_known_protos = True,
)
grpc_proto_library(
name = "eds_for_test_proto",
srcs = [
"eds_for_test.proto",
],
has_services = True,
well_known_protos = True,
)
grpc_proto_library(
name = "lds_rds_for_test_proto",
srcs = [
"lds_rds_for_test.proto",
],
has_services = True,
well_known_protos = True,
deps = [
"cds_for_test_proto",
"eds_for_test_proto",
],
)
grpc_proto_library(
name = "lrs_for_test_proto",
srcs = [
"lrs_for_test.proto",
],
has_services = True,
well_known_protos = True,
deps = ["eds_for_test_proto"],
)

@ -1,51 +0,0 @@
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains the eds protocol and its dependency.
//
// TODO(juanlishen): This file is a hack to avoid a problem we're
// currently having where we can't depend on a proto file in an external
// repo due to bazel limitations. Once that's fixed, this should be
// removed. Until this, it should be used in the gRPC tests only, or else it
// will cause a conflict due to the same proto messages being defined in
// multiple files in the same binary.
syntax = "proto3";
package envoy.service.discovery.v2;
import "src/proto/grpc/testing/xds/eds_for_test.proto";
// [#not-implemented-hide:] Discovery services for endpoints, clusters, routes,
// and listeners are retained in the package `envoy.api.v2` for backwards
// compatibility with existing management servers. New development in discovery
// services should proceed in the package `envoy.service.discovery.v2`.
// See https://github.com/lyft/envoy-api#apis for a description of the role of
// ADS and how it is intended to be used by a management server. ADS requests
// have the same structure as their singleton xDS counterparts, but can
// multiplex many resource types on a single stream. The type_url in the
// DiscoveryRequest/DiscoveryResponse provides sufficient information to recover
// the multiplexed singleton APIs at the Envoy instance and management server.
service AggregatedDiscoveryService {
// This is a gRPC-only API.
rpc StreamAggregatedResources(stream envoy.api.v2.DiscoveryRequest)
returns (stream envoy.api.v2.DiscoveryResponse) {
}
// Commented out so that we don't have to copy the request/response protos.
// rpc DeltaAggregatedResources(stream api.v2.DeltaDiscoveryRequest)
// returns (stream api.v2.DeltaDiscoveryResponse) {
// }
}

@ -1,186 +0,0 @@
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains the xds protocol and its dependency. It can't be used by
// the gRPC library; otherwise there can be duplicate definition problems if
// users depend on both gRPC and Envoy. It can only be used by gRPC tests.
//
// TODO(juanlishen): This file is a hack to avoid a problem we're
// currently having where we can't depend on a proto file in an external
// repo due to bazel limitations. Once that's fixed, this should be
// removed. Until this, it should be used in the gRPC tests only, or else it
// will cause a conflict due to the same proto messages being defined in
// multiple files in the same binary.
syntax = "proto3";
package envoy.api.v2;
import "google/protobuf/wrappers.proto";
// Aggregated Discovery Service (ADS) options. This is currently empty, but when
// set in :ref:`ConfigSource <envoy_api_msg_core.ConfigSource>` can be used to
// specify that ADS is to be used.
message AggregatedConfigSource {
}
message SelfConfigSource {
}
message ConfigSource {
oneof config_source_specifier {
// When set, ADS will be used to fetch resources. The ADS API configuration
// source in the bootstrap configuration is used.
AggregatedConfigSource ads = 3;
// [#not-implemented-hide:]
// When set, the client will access the resources from the same server it got the
// ConfigSource from, although not necessarily from the same stream. This is similar to the
// :ref:`ads<envoy_api_field.ConfigSource.ads>` field, except that the client may use a
// different stream to the same server. As a result, this field can be used for things
// like LRS that cannot be sent on an ADS stream. It can also be used to link from (e.g.)
// LDS to RDS on the same server without requiring the management server to know its name
// or required credentials.
// [#next-major-version: In xDS v3, consider replacing the ads field with this one, since
// this field can implicitly mean to use the same stream in the case where the ConfigSource
// is provided via ADS and the specified data can also be obtained via ADS.]
SelfConfigSource self = 5;
}
}
enum RoutingPriority {
DEFAULT = 0;
HIGH = 1;
}
message CircuitBreakers {
message Thresholds {
RoutingPriority priority = 1;
google.protobuf.UInt32Value max_requests = 4;
}
repeated Thresholds thresholds = 1;
}
message ClusterConfig {
repeated string clusters = 1;
}
message CustomClusterType {
string name = 1;
ClusterConfig typed_config = 2;
}
message Cluster {
// Refer to :ref:`service discovery type <arch_overview_service_discovery_types>`
// for an explanation on each type.
enum DiscoveryType {
// Refer to the :ref:`static discovery type<arch_overview_service_discovery_types_static>`
// for an explanation.
STATIC = 0;
// Refer to the :ref:`strict DNS discovery
// type<arch_overview_service_discovery_types_strict_dns>`
// for an explanation.
STRICT_DNS = 1;
// Refer to the :ref:`logical DNS discovery
// type<arch_overview_service_discovery_types_logical_dns>`
// for an explanation.
LOGICAL_DNS = 2;
// Refer to the :ref:`service discovery type<arch_overview_service_discovery_types_eds>`
// for an explanation.
EDS = 3;
// Refer to the :ref:`original destination discovery
// type<arch_overview_service_discovery_types_original_destination>`
// for an explanation.
ORIGINAL_DST = 4;
}
string name = 1;
oneof cluster_discovery_type {
// The :ref:`service discovery type <arch_overview_service_discovery_types>`
// to use for resolving the cluster.
DiscoveryType type = 2;
// The custom cluster type: aggregate cluster in this case.
CustomClusterType cluster_type = 38;
}
// Only valid when discovery type is EDS.
message EdsClusterConfig {
// Configuration for the source of EDS updates for this Cluster.
ConfigSource eds_config = 1;
// Optional alternative to cluster name to present to EDS. This does not
// have the same restrictions as cluster name, i.e. it may be arbitrary
// length.
string service_name = 2;
}
// Refer to :ref:`load balancer type <arch_overview_load_balancing_types>` architecture
// overview section for information on each type.
enum LbPolicy {
// Refer to the :ref:`round robin load balancing
// policy<arch_overview_load_balancing_types_round_robin>`
// for an explanation.
ROUND_ROBIN = 0;
// Refer to the :ref:`least request load balancing
// policy<arch_overview_load_balancing_types_least_request>`
// for an explanation.
LEAST_REQUEST = 1;
// Refer to the :ref:`ring hash load balancing
// policy<arch_overview_load_balancing_types_ring_hash>`
// for an explanation.
RING_HASH = 2;
// Refer to the :ref:`random load balancing
// policy<arch_overview_load_balancing_types_random>`
// for an explanation.
RANDOM = 3;
// Refer to the :ref:`original destination load balancing
// policy<arch_overview_load_balancing_types_original_destination>`
// for an explanation.
//
// .. attention::
//
// **This load balancing policy is deprecated**. Use CLUSTER_PROVIDED instead.
//
ORIGINAL_DST_LB = 4;
// Refer to the :ref:`Maglev load balancing policy<arch_overview_load_balancing_types_maglev>`
// for an explanation.
MAGLEV = 5;
// This load balancer type must be specified if the configured cluster provides a cluster
// specific load balancer. Consult the configured cluster's documentation for whether to set
// this option or not.
CLUSTER_PROVIDED = 6;
}
// The :ref:`load balancer type <arch_overview_load_balancing_types>` to use
// when picking a host in the cluster.
LbPolicy lb_policy = 6;
// Configuration to use for EDS updates for the Cluster.
EdsClusterConfig eds_cluster_config = 3;
CircuitBreakers circuit_breakers = 10;
ConfigSource lrs_server = 42;
}

@ -1,517 +0,0 @@
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains the xds protocol and its dependency. It can't be used by
// the gRPC library; otherwise there can be duplicate definition problems if
// users depend on both gRPC and Envoy. It can only be used by gRPC tests.
//
// TODO(juanlishen): This file is a hack to avoid a problem we're
// currently having where we can't depend on a proto file in an external
// repo due to bazel limitations. Once that's fixed, this should be
// removed. Until this, it should be used in the gRPC tests only, or else it
// will cause a conflict due to the same proto messages being defined in
// multiple files in the same binary.
syntax = "proto3";
package envoy.api.v2;
import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/wrappers.proto";
message Status {
// The status code, which should be an enum value of [google.rpc.Code][].
int32 code = 1;
// A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the
// [google.rpc.Status.details][] field, or localized by the client.
string message = 2;
// A list of messages that carry the error details. There is a common set of
// message types for APIs to use.
repeated google.protobuf.Any details = 3;
}
///////////////////////////////////////////////////////////////////////////////
// Identifies location of where either Envoy runs or where upstream hosts run.
message Locality {
// Region this :ref:`zone <envoy_api_field_core.Locality.zone>` belongs to.
string region = 1;
// Defines the local service zone where Envoy is running. Though optional, it
// should be set if discovery service routing is used and the discovery
// service exposes :ref:`zone data <envoy_api_field_endpoint.LocalityLbEndpoints.locality>`,
// either in this message or via :option:`--service-zone`. The meaning of zone
// is context dependent, e.g. `Availability Zone (AZ)
// <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html>`_
// on AWS, `Zone <https://cloud.google.com/compute/docs/regions-zones/>`_ on
// GCP, etc.
string zone = 2;
// When used for locality of upstream hosts, this field further splits zone
// into smaller chunks of sub-zones so they can be load balanced
// independently.
string sub_zone = 3;
}
// Identifies a specific Envoy instance. The node identifier is presented to the
// management server, which may use this identifier to distinguish per Envoy
// configuration for serving.
message Node {
// An opaque node identifier for the Envoy node. This also provides the local
// service node name. It should be set if any of the following features are
// used: :ref:`statsd <arch_overview_statistics>`, :ref:`CDS
// <config_cluster_manager_cds>`, and :ref:`HTTP tracing
// <arch_overview_tracing>`, either in this message or via
// :option:`--service-node`.
string id = 1;
// Defines the local service cluster name where Envoy is running. Though
// optional, it should be set if any of the following features are used:
// :ref:`statsd <arch_overview_statistics>`, :ref:`health check cluster
// verification <envoy_api_field_core.HealthCheck.HttpHealthCheck.service_name>`,
// :ref:`runtime override directory <envoy_api_msg_config.bootstrap.v2.Runtime>`,
// :ref:`user agent addition
// <envoy_api_field_config.filter.network.http_connection_manager.v2.HttpConnectionManager.add_user_agent>`,
// :ref:`HTTP global rate limiting <config_http_filters_rate_limit>`,
// :ref:`CDS <config_cluster_manager_cds>`, and :ref:`HTTP tracing
// <arch_overview_tracing>`, either in this message or via
// :option:`--service-cluster`.
string cluster = 2;
// Opaque metadata extending the node identifier. Envoy will pass this
// directly to the management server.
google.protobuf.Struct metadata = 3;
// Locality specifying where the Envoy instance is running.
Locality locality = 4;
// This is motivated by informing a management server during canary which
// version of Envoy is being tested in a heterogeneous fleet. This will be set
// by Envoy in management server RPCs.
string build_version = 5 [deprecated = true];
// Free-form string that identifies the entity requesting config.
// E.g. "envoy" or "grpc"
string user_agent_name = 6;
oneof user_agent_version_type {
// Free-form string that identifies the version of the entity requesting config.
// E.g. "1.12.2" or "abcd1234", or "SpecialEnvoyBuild"
string user_agent_version = 7;
}
// Client feature support list. These are well known features described
// in the Envoy API repository for a given major version of an API. Client features
// use reverse DNS naming scheme, for example `com.acme.feature`.
// See :ref:`the list of features <client_features>` that xDS client may
// support.
repeated string client_features = 10;
}
///////////////////////////////////////////////////////////////////////////////
// A DiscoveryRequest requests a set of versioned resources of the same type for
// a given Envoy node on some API.
message DiscoveryRequest {
// The version_info provided in the request messages will be the version_info
// received with the most recent successfully processed response or empty on
// the first request. It is expected that no new request is sent after a
// response is received until the Envoy instance is ready to ACK/NACK the new
// configuration. ACK/NACK takes place by returning the new API config version
// as applied or the previous API config version respectively. Each type_url
// (see below) has an independent version associated with it.
string version_info = 1;
// The node making the request.
Node node = 2;
// List of resources to subscribe to, e.g. list of cluster names or a route
// configuration name. If this is empty, all resources for the API are
// returned. LDS/CDS expect empty resource_names, since this is global
// discovery for the Envoy instance. The LDS and CDS responses will then imply
// a number of resources that need to be fetched via EDS/RDS, which will be
// explicitly enumerated in resource_names.
repeated string resource_names = 3;
// Type of the resource that is being requested, e.g.
// "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment". This is implicit
// in requests made via singleton xDS APIs such as CDS, LDS, etc. but is
// required for ADS.
string type_url = 4;
// nonce corresponding to DiscoveryResponse being ACK/NACKed. See above
// discussion on version_info and the DiscoveryResponse nonce comment. This
// may be empty if no nonce is available, e.g. at startup or for non-stream
// xDS implementations.
string response_nonce = 5;
// This is populated when the previous :ref:`DiscoveryResponse <envoy_api_msg_DiscoveryResponse>`
// failed to update configuration. The *message* field in *error_details* provides the Envoy
// internal exception related to the failure. It is only intended for consumption during manual
// debugging, the string provided is not guaranteed to be stable across Envoy versions.
Status error_detail = 6;
}
message DiscoveryResponse {
// The version of the response data.
string version_info = 1;
// The response resources. These resources are typed and depend on the API being called.
repeated google.protobuf.Any resources = 2;
// [#not-implemented-hide:]
// Canary is used to support two Envoy command line flags:
//
// * --terminate-on-canary-transition-failure. When set, Envoy is able to
// terminate if it detects that configuration is stuck at canary. Consider
// this example sequence of updates:
// - Management server applies a canary config successfully.
// - Management server rolls back to a production config.
// - Envoy rejects the new production config.
// Since there is no sensible way to continue receiving configuration
// updates, Envoy will then terminate and apply production config from a
// clean slate.
// * --dry-run-canary. When set, a canary response will never be applied, only
// validated via a dry run.
bool canary = 3;
// Type URL for resources. This must be consistent with the type_url in the
// Any messages for resources if resources is non-empty. This effectively
// identifies the xDS API when muxing over ADS.
string type_url = 4;
// For gRPC based subscriptions, the nonce provides a way to explicitly ack a
// specific DiscoveryResponse in a following DiscoveryRequest. Additional
// messages may have been sent by Envoy to the management server for the
// previous version on the stream prior to this DiscoveryResponse, that were
// unprocessed at response send time. The nonce allows the management server
// to ignore any further DiscoveryRequests for the previous version until a
// DiscoveryRequest bearing the nonce. The nonce is optional and is not
// required for non-stream based xDS implementations.
string nonce = 5;
}
///////////////////////////////////////////////////////////////////////////////
message Pipe {
// Unix Domain Socket path. On Linux, paths starting with '@' will use the
// abstract namespace. The starting '@' is replaced by a null byte by Envoy.
// Paths starting with '@' will result in an error in environments other than
// Linux.
string path = 1;
}
message SocketAddress {
enum Protocol {
TCP = 0;
// [#not-implemented-hide:]
UDP = 1;
}
Protocol protocol = 1;
// The address for this socket. :ref:`Listeners <config_listeners>` will bind
// to the address. An empty address is not allowed. Specify ``0.0.0.0`` or ``::``
// to bind to any address. [#comment:TODO(zuercher) reinstate when implemented:
// It is possible to distinguish a Listener address via the prefix/suffix matching
// in :ref:`FilterChainMatch <envoy_api_msg_listener.FilterChainMatch>`.] When used
// within an upstream :ref:`BindConfig <envoy_api_msg_core.BindConfig>`, the address
// controls the source address of outbound connections. For :ref:`clusters
// <envoy_api_msg_Cluster>`, the cluster type determines whether the
// address must be an IP (*STATIC* or *EDS* clusters) or a hostname resolved by DNS
// (*STRICT_DNS* or *LOGICAL_DNS* clusters). Address resolution can be customized
// via :ref:`resolver_name <envoy_api_field_core.SocketAddress.resolver_name>`.
string address = 2;
oneof port_specifier {
uint32 port_value = 3;
// This is only valid if :ref:`resolver_name
// <envoy_api_field_core.SocketAddress.resolver_name>` is specified below and the
// named resolver is capable of named port resolution.
string named_port = 4;
}
// The name of the resolver. This must have been registered with Envoy. If this is
// empty, a context dependent default applies. If address is a hostname this
// should be set for resolution other than DNS. If the address is a concrete
// IP address, no resolution will occur.
string resolver_name = 5;
// When binding to an IPv6 address above, this enables `IPv4 compatibity
// <https://tools.ietf.org/html/rfc3493#page-11>`_. Binding to ``::`` will
// allow both IPv4 and IPv6 connections, with peer IPv4 addresses mapped into
// IPv6 space as ``::FFFF:<IPv4-address>``.
bool ipv4_compat = 6;
}
// Addresses specify either a logical or physical address and port, which are
// used to tell Envoy where to bind/listen, connect to upstream and find
// management servers.
message Address {
oneof address {
SocketAddress socket_address = 1;
Pipe pipe = 2;
}
}
///////////////////////////////////////////////////////////////////////////////
message Metadata {
// Key is the reverse DNS filter name, e.g. com.acme.widget. The envoy.*
// namespace is reserved for Envoy's built-in filters.
map<string, google.protobuf.Struct> filter_metadata = 1;
}
///////////////////////////////////////////////////////////////////////////////
// Endpoint health status.
enum HealthStatus {
// The health status is not known. This is interpreted by Envoy as *HEALTHY*.
UNKNOWN = 0;
// Healthy.
HEALTHY = 1;
// Unhealthy.
UNHEALTHY = 2;
// Connection draining in progress. E.g.,
// `<https://aws.amazon.com/blogs/aws/elb-connection-draining-remove-instances-from-service-with-care/>`_
// or
// `<https://cloud.google.com/compute/docs/load-balancing/enabling-connection-draining>`_.
// This is interpreted by Envoy as *UNHEALTHY*.
DRAINING = 3;
// Health check timed out. This is part of HDS and is interpreted by Envoy as
// *UNHEALTHY*.
TIMEOUT = 4;
}
///////////////////////////////////////////////////////////////////////////////
// Upstream host identifier.
message Endpoint {
// The upstream host address.
//
// .. attention::
//
// The form of host address depends on the given cluster type. For STATIC or EDS,
// it is expected to be a direct IP address (or something resolvable by the
// specified :ref:`resolver <envoy_api_field_core.SocketAddress.resolver_name>`
// in the Address). For LOGICAL or STRICT DNS, it is expected to be hostname,
// and will be resolved via DNS.
Address address = 1;
// The optional health check configuration.
message HealthCheckConfig {
// Optional alternative health check port value.
//
// By default the health check address port of an upstream host is the same
// as the host's serving address port. This provides an alternative health
// check port. Setting this with a non-zero value allows an upstream host
// to have different health check address port.
uint32 port_value = 1;
}
// The optional health check configuration is used as configuration for the
// health checker to contact the health checked host.
//
// .. attention::
//
// This takes into effect only for upstream clusters with
// :ref:`active health checking <arch_overview_health_checking>` enabled.
HealthCheckConfig health_check_config = 2;
}
// An Endpoint that Envoy can route traffic to.
message LbEndpoint {
// Upstream host identifier
Endpoint endpoint = 1;
// Optional health status when known and supplied by EDS server.
HealthStatus health_status = 2;
// The endpoint metadata specifies values that may be used by the load
// balancer to select endpoints in a cluster for a given request. The filter
// name should be specified as *envoy.lb*. An example boolean key-value pair
// is *canary*, providing the optional canary status of the upstream host.
// This may be matched against in a route's
// :ref:`RouteAction <envoy_api_msg_route.RouteAction>` metadata_match field
// to subset the endpoints considered in cluster load balancing.
Metadata metadata = 3;
// The optional load balancing weight of the upstream host, in the range 1 -
// 128. Envoy uses the load balancing weight in some of the built in load
// balancers. The load balancing weight for an endpoint is divided by the sum
// of the weights of all endpoints in the endpoint's locality to produce a
// percentage of traffic for the endpoint. This percentage is then further
// weighted by the endpoint's locality's load balancing weight from
// LocalityLbEndpoints. If unspecified, each host is presumed to have equal
// weight in a locality.
//
// .. attention::
//
// The limit of 128 is somewhat arbitrary, but is applied due to performance
// concerns with the current implementation and can be removed when
// `this issue <https://github.com/envoyproxy/envoy/issues/1285>`_ is fixed.
google.protobuf.UInt32Value load_balancing_weight = 4;
}
// A group of endpoints belonging to a Locality.
// One can have multiple LocalityLbEndpoints for a locality, but this is
// generally only done if the different groups need to have different load
// balancing weights or different priorities.
message LocalityLbEndpoints {
// Identifies location of where the upstream hosts run.
Locality locality = 1;
// The group of endpoints belonging to the locality specified.
repeated LbEndpoint lb_endpoints = 2;
// Optional: Per priority/region/zone/sub_zone weight - range 1-128. The load
// balancing weight for a locality is divided by the sum of the weights of all
// localities at the same priority level to produce the effective percentage
// of traffic for the locality.
//
// Locality weights are only considered when :ref:`locality weighted load
// balancing <arch_overview_load_balancing_locality_weighted_lb>` is
// configured. These weights are ignored otherwise. If no weights are
// specificed when locality weighted load balancing is enabled, the cluster is
// assumed to have a weight of 1.
//
// .. attention::
//
// The limit of 128 is somewhat arbitrary, but is applied due to performance
// concerns with the current implementation and can be removed when
// `this issue <https://github.com/envoyproxy/envoy/issues/1285>`_ is fixed.
google.protobuf.UInt32Value load_balancing_weight = 3;
// Optional: the priority for this LocalityLbEndpoints. If unspecified this will
// default to the highest priority (0).
//
// Under usual circumstances, Envoy will only select endpoints for the highest
// priority (0). In the event all endpoints for a particular priority are
// unavailable/unhealthy, Envoy will fail over to selecting endpoints for the
// next highest priority group.
//
// Priorities should range from 0 (highest) to N (lowest) without skipping.
uint32 priority = 5;
}
///////////////////////////////////////////////////////////////////////////////
message FractionalPercent {
// Specifies the numerator. Defaults to 0.
uint32 numerator = 1;
// Fraction percentages support several fixed denominator values.
enum DenominatorType {
// 100.
//
// **Example**: 1/100 = 1%.
HUNDRED = 0;
// 10,000.
//
// **Example**: 1/10000 = 0.01%.
TEN_THOUSAND = 1;
// 1,000,000.
//
// **Example**: 1/1000000 = 0.0001%.
MILLION = 2;
}
// Specifies the denominator. If the denominator specified is less than the numerator, the final
// fractional percentage is capped at 1 (100%).
DenominatorType denominator = 2;
}
///////////////////////////////////////////////////////////////////////////////
// [#protodoc-title: EDS]
// Endpoint discovery :ref:`architecture overview <arch_overview_service_discovery_types_eds>`
service EndpointDiscoveryService {
// The resource_names field in DiscoveryRequest specifies a list of clusters
// to subscribe to updates for.
rpc StreamEndpoints(stream DiscoveryRequest) returns (stream DiscoveryResponse) {
}
}
// Each route from RDS will map to a single cluster or traffic split across
// clusters using weights expressed in the RDS WeightedCluster.
//
// With EDS, each cluster is treated independently from a LB perspective, with
// LB taking place between the Localities within a cluster and at a finer
// granularity between the hosts within a locality. For a given cluster, the
// effective weight of a host is its load_balancing_weight multiplied by the
// load_balancing_weight of its Locality.
message ClusterLoadAssignment {
// Name of the cluster. This will be the :ref:`service_name
// <envoy_api_field_Cluster.EdsClusterConfig.service_name>` value if specified
// in the cluster :ref:`EdsClusterConfig
// <envoy_api_msg_Cluster.EdsClusterConfig>`.
string cluster_name = 1;
// List of endpoints to load balance to.
repeated LocalityLbEndpoints endpoints = 2;
// Load balancing policy settings.
message Policy {
reserved 1;
message DropOverload {
// Identifier for the policy specifying the drop.
string category = 1;
// Percentage of traffic that should be dropped for the category.
FractionalPercent drop_percentage = 2;
}
// Action to trim the overall incoming traffic to protect the upstream
// hosts. This action allows protection in case the hosts are unable to
// recover from an outage, or unable to autoscale or unable to handle
// incoming traffic volume for any reason.
//
// At the client each category is applied one after the other to generate
// the 'actual' drop percentage on all outgoing traffic. For example:
//
// .. code-block:: json
//
// { "drop_overloads": [
// { "category": "throttle", "drop_percentage": 60 }
// { "category": "lb", "drop_percentage": 50 }
// ]}
//
// The actual drop percentages applied to the traffic at the clients will be
// "throttle"_drop = 60%
// "lb"_drop = 20% // 50% of the remaining 'actual' load, which is 40%.
// actual_outgoing_load = 20% // remaining after applying all categories.
repeated DropOverload drop_overloads = 2;
// Priority levels and localities are considered overprovisioned with this
// factor (in percentage). This means that we don't consider a priority
// level or locality unhealthy until the percentage of healthy hosts
// multiplied by the overprovisioning factor drops below 100.
// With the default value 140(1.4), Envoy doesn't consider a priority level
// or a locality unhealthy until their percentage of healthy hosts drops
// below 72%.
// Read more at :ref:`priority levels <arch_overview_load_balancing_priority_levels>` and
// :ref:`localities <arch_overview_load_balancing_locality_weighted_lb>`.
google.protobuf.UInt32Value overprovisioning_factor = 3;
}
// Load balancing policy settings.
Policy policy = 4;
}

@ -1,215 +0,0 @@
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains the eds protocol and its dependency.
//
// TODO(juanlishen): This file is a hack to avoid a problem we're
// currently having where we can't depend on a proto file in an external
// repo due to bazel limitations. Once that's fixed, this should be
// removed. Until this, it should be used in the gRPC tests only, or else it
// will cause a conflict due to the same proto messages being defined in
// multiple files in the same binary.
syntax = "proto3";
package envoy.api.v2;
import "google/protobuf/any.proto";
import "google/protobuf/wrappers.proto";
import "src/proto/grpc/testing/xds/cds_for_test.proto";
import "src/proto/grpc/testing/xds/eds_for_test.proto";
message RegexMatcher {
message GoogleRE2 {
google.protobuf.UInt32Value max_program_size = 1;
}
oneof engine_type {
GoogleRE2 google_re2 = 1;
}
string regex = 2;
}
message Int64Range {
// start of the range (inclusive)
int64 start = 1;
// end of the range (exclusive)
int64 end = 2;
}
message BoolValue {
// The bool value.
bool value = 1;
}
message HeaderMatcher {
string name = 1;
oneof header_match_specifier {
string exact_match = 4;
RegexMatcher safe_regex_match = 11;
Int64Range range_match = 6;
bool present_match = 7;
string prefix_match = 9;
string suffix_match = 10;
}
bool invert_match = 8;
}
message QueryParameterMatcher {
string name = 1;
}
message RuntimeFractionalPercent {
FractionalPercent default_value = 1;
}
message RouteMatch {
oneof path_specifier {
// If specified, the route is a prefix rule meaning that the prefix must
// match the beginning of the *:path* header.
string prefix = 1;
string path = 2;
RegexMatcher safe_regex = 10;
}
BoolValue case_sensitive = 4;
repeated QueryParameterMatcher query_parameters = 7;
RuntimeFractionalPercent runtime_fraction = 9;
repeated HeaderMatcher headers = 6;
}
message WeightedCluster {
message ClusterWeight {
string name = 1;
google.protobuf.UInt32Value weight = 2;
}
repeated ClusterWeight clusters = 1;
google.protobuf.UInt32Value total_weight = 3;
}
message RouteAction {
oneof cluster_specifier {
// Indicates the upstream cluster to which the request should be routed
// to.
string cluster = 1;
// Envoy will determine the cluster to route to by reading the value of the
// HTTP header named by cluster_header from the request headers. If the
// header is not found or the referenced cluster does not exist, Envoy will
// return a 404 response.
//
// .. attention::
//
// Internally, Envoy always uses the HTTP/2 *:authority* header to represent the HTTP/1
// *Host* header. Thus, if attempting to match on *Host*, match on *:authority* instead.
string cluster_header = 2;
// Multiple upstream clusters can be specified for a given route. The
// request is routed to one of the upstream clusters based on weights
// assigned to each cluster. See
// :ref:`traffic splitting <config_http_conn_man_route_table_traffic_splitting_split>`
// for additional documentation.
WeightedCluster weighted_clusters = 3;
}
}
message RedirectAction {}
message Route {
RouteMatch match = 1;
oneof action {
// Route request to some upstream cluster.
RouteAction route = 2;
// Return a redirect.
RedirectAction redirect = 3;
}
}
message VirtualHost {
repeated string domains = 2;
repeated Route routes = 3;
}
message Rds {
// Configuration source specifier for RDS.
ConfigSource config_source = 1;
// The name of the route configuration. This name will be passed to the RDS
// API. This allows an Envoy configuration with multiple HTTP listeners (and
// associated HTTP connection manager filters) to use different route
// configurations.
string route_config_name = 2;
}
message RouteConfiguration {
// The name of the route configuration. For example, it might match
// :ref:`route_config_name
// <envoy_api_field_config.filter.network.http_connection_manager.v2.Rds.route_config_name>` in
// :ref:`envoy_api_msg_config.filter.network.http_connection_manager.v2.Rds`.
string name = 1;
// An array of virtual hosts that make up the route table.
repeated VirtualHost virtual_hosts = 2;
}
message ScopedRoutes {}
message HttpConnectionManager {
oneof route_specifier {
// The connection managers route table will be dynamically loaded via the RDS API.
Rds rds = 3;
// The route table for the connection manager is static and is specified in this property.
RouteConfiguration route_config = 4;
// A route table will be dynamically assigned to each request based on request attributes
// (e.g., the value of a header). The "routing scopes" (i.e., route tables) and "scope keys" are
// specified in this message.
ScopedRoutes scoped_routes = 31;
}
}
message ApiListener {
// The type in this field determines the type of API listener. At present, the following
// types are supported:
// envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager (HTTP)
// [#next-major-version: In the v3 API, replace this Any field with a oneof containing the
// specific config message for each type of API listener. We could not do this in v2 because
// it would have caused circular dependencies for go protos: lds.proto depends on this file,
// and http_connection_manager.proto depends on rds.proto, which is in the same directory as
// lds.proto, so lds.proto cannot depend on this file.]
google.protobuf.Any api_listener = 1;
}
message Listener {
string name = 1;
// Used to represent an API listener, which is used in non-proxy clients. The type of API
// exposed to the non-proxy application depends on the type of API listener.
// When this field is set, no other field except for :ref:`name<envoy_api_field_Listener.name>`
// should be set.
//
// .. note::
//
// Currently only one ApiListener can be installed; and it can only be done via bootstrap config,
// not LDS.
//
// [#next-major-version: In the v3 API, instead of this messy approach where the socket
// listener fields are directly in the top-level Listener message and the API listener types
// are in the ApiListener message, the socket listener messages should be in their own message,
// and the top-level Listener should essentially be a oneof that selects between the
// socket listener and the various types of API listener. That way, a given Listener message
// can structurally only contain the fields of the relevant type.]
ApiListener api_listener = 19;
}

@ -1,189 +0,0 @@
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains the eds protocol and its dependency.
//
// TODO(juanlishen): This file is a hack to avoid a problem we're
// currently having where we can't depend on a proto file in an external
// repo due to bazel limitations. Once that's fixed, this should be
// removed. Until this, it should be used in the gRPC tests only, or else it
// will cause a conflict due to the same proto messages being defined in
// multiple files in the same binary.
syntax = "proto3";
package envoy.service.load_stats.v2;
import "google/protobuf/duration.proto";
import "src/proto/grpc/testing/xds/eds_for_test.proto";
// [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs.
message EndpointLoadMetricStats {
// Name of the metric; may be empty.
string metric_name = 1;
// Number of calls that finished and included this metric.
uint64 num_requests_finished_with_metric = 2;
// Sum of metric values across all calls that finished with this metric for
// load_reporting_interval.
double total_metric_value = 3;
}
message UpstreamLocalityStats {
// Name of zone, region and optionally endpoint group these metrics were
// collected from. Zone and region names could be empty if unknown.
envoy.api.v2.Locality locality = 1;
// The total number of requests successfully completed by the endpoints in the
// locality.
uint64 total_successful_requests = 2;
// The total number of unfinished requests
uint64 total_requests_in_progress = 3;
// The total number of requests that failed due to errors at the endpoint,
// aggregated over all endpoints in the locality.
uint64 total_error_requests = 4;
// The total number of requests that were issued by this Envoy since
// the last report. This information is aggregated over all the
// upstream endpoints in the locality.
uint64 total_issued_requests = 8;
// Stats for multi-dimensional load balancing.
repeated EndpointLoadMetricStats load_metric_stats = 5;
// // Endpoint granularity stats information for this locality. This information
// // is populated if the Server requests it by setting
// // :ref:`LoadStatsResponse.report_endpoint_granularity<envoy_api_field_load_stats.LoadStatsResponse.report_endpoint_granularity>`.
// repeated UpstreamEndpointStats upstream_endpoint_stats = 7;
// [#not-implemented-hide:] The priority of the endpoint group these metrics
// were collected from.
uint32 priority = 6;
}
// Per cluster load stats. Envoy reports these stats a management server in a
// :ref:`LoadStatsRequest<envoy_api_msg_load_stats.LoadStatsRequest>`
// [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs.
// Next ID: 7
message ClusterStats {
// The name of the cluster.
string cluster_name = 1;
// The eds_cluster_config service_name of the cluster.
// It's possible that two clusters send the same service_name to EDS,
// in that case, the management server is supposed to do aggregation on the load reports.
string cluster_service_name = 6;
// Need at least one.
repeated UpstreamLocalityStats upstream_locality_stats = 2;
// Cluster-level stats such as total_successful_requests may be computed by
// summing upstream_locality_stats. In addition, below there are additional
// cluster-wide stats.
//
// The total number of dropped requests. This covers requests
// deliberately dropped by the drop_overload policy and circuit breaking.
uint64 total_dropped_requests = 3;
message DroppedRequests {
// Identifier for the policy specifying the drop.
string category = 1;
// Total number of deliberately dropped requests for the category.
uint64 dropped_count = 2;
}
// Information about deliberately dropped requests for each category specified
// in the DropOverload policy.
repeated DroppedRequests dropped_requests = 5;
// Period over which the actual load report occurred. This will be guaranteed to include every
// request reported. Due to system load and delays between the *LoadStatsRequest* sent from Envoy
// and the *LoadStatsResponse* message sent from the management server, this may be longer than
// the requested load reporting interval in the *LoadStatsResponse*.
google.protobuf.Duration load_report_interval = 4;
}
// [#protodoc-title: Load reporting service]
service LoadReportingService {
// Advanced API to allow for multi-dimensional load balancing by remote
// server. For receiving LB assignments, the steps are:
// 1, The management server is configured with per cluster/zone/load metric
// capacity configuration. The capacity configuration definition is
// outside of the scope of this document.
// 2. Envoy issues a standard {Stream,Fetch}Endpoints request for the clusters
// to balance.
//
// Independently, Envoy will initiate a StreamLoadStats bidi stream with a
// management server:
// 1. Once a connection establishes, the management server publishes a
// LoadStatsResponse for all clusters it is interested in learning load
// stats about.
// 2. For each cluster, Envoy load balances incoming traffic to upstream hosts
// based on per-zone weights and/or per-instance weights (if specified)
// based on intra-zone LbPolicy. This information comes from the above
// {Stream,Fetch}Endpoints.
// 3. When upstream hosts reply, they optionally add header <define header
// name> with ASCII representation of EndpointLoadMetricStats.
// 4. Envoy aggregates load reports over the period of time given to it in
// LoadStatsResponse.load_reporting_interval. This includes aggregation
// stats Envoy maintains by itself (total_requests, rpc_errors etc.) as
// well as load metrics from upstream hosts.
// 5. When the timer of load_reporting_interval expires, Envoy sends new
// LoadStatsRequest filled with load reports for each cluster.
// 6. The management server uses the load reports from all reported Envoys
// from around the world, computes global assignment and prepares traffic
// assignment destined for each zone Envoys are located in. Goto 2.
rpc StreamLoadStats(stream LoadStatsRequest) returns (stream LoadStatsResponse) {
}
}
// A load report Envoy sends to the management server.
// [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs.
message LoadStatsRequest {
// Node identifier for Envoy instance.
envoy.api.v2.Node node = 1;
// A list of load stats to report.
repeated ClusterStats cluster_stats = 2;
}
// The management server sends envoy a LoadStatsResponse with all clusters it
// is interested in learning load stats about.
// [#not-implemented-hide:] Not configuration. TBD how to doc proto APIs.
message LoadStatsResponse {
// Clusters to report stats for.
// Not populated if *send_all_clusters* is true.
repeated string clusters = 1;
// If true, the client should send all clusters it knows about.
// Only clients that advertise the "envoy.lrs.supports_send_all_clusters" capability in their
// :ref:`client_features<envoy_api_field_core.Node.client_features>` field will honor this field.
bool send_all_clusters = 4;
// The minimum interval of time to collect stats over. This is only a minimum for two reasons:
// 1. There may be some delay from when the timer fires until stats sampling occurs.
// 2. For clusters that were already feature in the previous *LoadStatsResponse*, any traffic
// that is observed in between the corresponding previous *LoadStatsRequest* and this
// *LoadStatsResponse* will also be accumulated and billed to the cluster. This avoids a period
// of inobservability that might otherwise exists between the messages. New clusters are not
// subject to this consideration.
google.protobuf.Duration load_reporting_interval = 2;
// Set to *true* if the management server supports endpoint granularity
// report.
bool report_endpoint_granularity = 3;
}

@ -419,7 +419,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/xds/xds_http_rbac_filter.cc',
'src/core/ext/xds/xds_lb_policy_registry.cc',
'src/core/ext/xds/xds_listener.cc',
'src/core/ext/xds/xds_resource_type.cc',
'src/core/ext/xds/xds_route_config.cc',
'src/core/ext/xds/xds_routing.cc',
'src/core/ext/xds/xds_server_config_fetcher.cc',

@ -116,27 +116,24 @@ class XdsClientTest : public ::testing::Test {
class FakeXdsServer : public XdsServer {
public:
const std::string& server_uri() const override { return server_uri_; }
bool ShouldUseV3() const override { return use_v3_; }
bool IgnoreResourceDeletion() const override {
return ignore_resource_deletion_;
}
bool Equals(const XdsServer& other) const override {
const auto& o = static_cast<const FakeXdsServer&>(other);
return server_uri_ == o.server_uri_ && use_v3_ == o.use_v3_ &&
return server_uri_ == o.server_uri_ &&
ignore_resource_deletion_ == o.ignore_resource_deletion_;
}
void set_server_uri(std::string server_uri) {
server_uri_ = std::move(server_uri);
}
void set_use_v3(bool use_v3) { use_v3_ = use_v3; }
void set_ignore_resource_deletion(bool ignore_resource_deletion) {
ignore_resource_deletion_ = ignore_resource_deletion;
}
private:
std::string server_uri_ = "default_xds_server";
bool use_v3_ = true;
bool ignore_resource_deletion_ = false;
};
@ -158,10 +155,6 @@ class XdsClientTest : public ::testing::Test {
public:
Builder() { node_.emplace(); }
Builder& set_use_v2() {
server_.set_use_v3(false);
return *this;
}
Builder& set_node_id(std::string id) {
if (!node_.has_value()) node_.emplace();
node_->set_id(std::move(id));
@ -220,8 +213,7 @@ class XdsClientTest : public ::testing::Test {
// The specified ResourceStruct must provide the following:
// - a static JsonLoader() method, as described in json_object_loader.h
// - an AsJsonString() method that returns the object in JSON string form
// - a static TypeUrl() method that returns the V3 resource type
// - a static TypeUrlV2() method that returns the V2 resource type
// - a static TypeUrl() method that returns the resource type
template <typename ResourceStruct>
class XdsTestResourceType
: public XdsResourceTypeImpl<XdsTestResourceType<ResourceStruct>,
@ -340,12 +332,9 @@ class XdsClientTest : public ::testing::Test {
absl::string_view type_url() const override {
return ResourceStruct::TypeUrl();
}
absl::string_view v2_type_url() const override {
return ResourceStruct::TypeUrlV2();
}
XdsResourceType::DecodeResult Decode(
const XdsResourceType::DecodeContext& /*context*/,
absl::string_view serialized_resource, bool /*is_v2*/) const override {
absl::string_view serialized_resource) const override {
auto json = Json::Parse(serialized_resource);
XdsResourceType::DecodeResult result;
if (!json.ok()) {
@ -403,7 +392,6 @@ class XdsClientTest : public ::testing::Test {
}
static absl::string_view TypeUrl() { return "test.v3.foo"; }
static absl::string_view TypeUrlV2() { return "test.v2.foo"; }
};
using XdsFooResourceType = XdsTestResourceType<XdsFooResource>;
@ -434,7 +422,6 @@ class XdsClientTest : public ::testing::Test {
}
static absl::string_view TypeUrl() { return "test.v3.bar"; }
static absl::string_view TypeUrlV2() { return "test.v2.bar"; }
};
using XdsBarResourceType = XdsTestResourceType<XdsBarResource>;
@ -626,7 +613,6 @@ class XdsClientTest : public ::testing::Test {
// Helper function to check the contents of the node message in a
// request against the client's node info.
void CheckRequestNode(const DiscoveryRequest& request,
bool check_build_version = false,
SourceLocation location = SourceLocation()) {
// These fields come from the bootstrap config.
EXPECT_EQ(request.node().id(), xds_client_->bootstrap().node()->id())
@ -669,28 +655,6 @@ class XdsClientTest : public ::testing::Test {
EXPECT_EQ(request.node().user_agent_version(),
absl::StrCat("C-core ", grpc_version_string()))
<< location.file() << ":" << location.line();
if (check_build_version) {
auto build_version = GetBuildVersion(request.node());
ASSERT_TRUE(build_version.has_value())
<< location.file() << ":" << location.line();
EXPECT_EQ(*build_version,
absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING, " ",
grpc_version_string()))
<< location.file() << ":" << location.line();
}
}
// Helper function to find the "build_version" field, which was
// removed in v3, but which we still populate in v2.
static absl::optional<std::string> GetBuildVersion(
const envoy::config::core::v3::Node& node) {
const auto& unknown_field_set =
node.GetReflection()->GetUnknownFields(node);
for (int i = 0; i < unknown_field_set.field_count(); ++i) {
const auto& unknown_field = unknown_field_set.field(i);
if (unknown_field.number() == 5) return unknown_field.length_delimited();
}
return absl::nullopt;
}
RefCountedPtr<FakeXdsTransportFactory> transport_factory_;
@ -1872,57 +1836,6 @@ TEST_F(XdsClientTest, MultipleResourceTypes) {
}
}
TEST_F(XdsClientTest, BasicWatchV2) {
InitXdsClient(FakeXdsBootstrap::Builder().set_use_v2());
// Start a watch for "foo1".
auto watcher = StartFooWatch("foo1");
// Watcher should initially not see any resource reported.
EXPECT_FALSE(watcher->HasEvent());
// XdsClient should have created an ADS stream.
auto stream = transport_factory_->WaitForStream(
xds_client_->bootstrap().server(), FakeXdsTransportFactory::kAdsV2Method,
absl::Seconds(5) * grpc_test_slowdown_factor());
ASSERT_TRUE(stream != nullptr);
// XdsClient should have sent a subscription request on the ADS stream.
auto request = WaitForRequest(stream.get());
ASSERT_TRUE(request.has_value());
CheckRequest(*request, XdsFooResourceType::Get()->v2_type_url(),
/*version_info=*/"", /*response_nonce=*/"",
/*error_detail=*/absl::OkStatus(),
/*resource_names=*/{"foo1"});
// Node Should be present on the first request.
CheckRequestNode(*request, /*check_build_version=*/true);
// Send a response.
stream->SendMessageToClient(
ResponseBuilder(XdsFooResourceType::Get()->v2_type_url())
.set_version_info("1")
.set_nonce("A")
.AddFooResource(XdsFooResource("foo1", 6))
.Serialize());
// XdsClient should have delivered the response to the watcher.
auto resource = watcher->WaitForNextResource();
ASSERT_TRUE(resource.has_value());
EXPECT_EQ(resource->name, "foo1");
EXPECT_EQ(resource->value, 6);
// XdsClient should have sent an ACK message to the xDS server.
request = WaitForRequest(stream.get());
ASSERT_TRUE(request.has_value());
CheckRequest(*request, XdsFooResourceType::Get()->v2_type_url(),
/*version_info=*/"1", /*response_nonce=*/"A",
/*error_detail=*/absl::OkStatus(),
/*resource_names=*/{"foo1"});
// Cancel watch.
CancelFooWatch(watcher.get(), "foo1");
// The XdsClient may or may not send an unsubscription message
// before it closes the transport, depending on callback timing.
request = WaitForRequest(stream.get());
if (request.has_value()) {
CheckRequest(*request, XdsFooResourceType::Get()->v2_type_url(),
/*version_info=*/"1", /*response_nonce=*/"A",
/*error_detail=*/absl::OkStatus(), /*resource_names=*/{});
}
}
TEST_F(XdsClientTest, Federation) {
ScopedExperimentalEnvVar env_var("GRPC_EXPERIMENTAL_XDS_FEDERATION");
constexpr char kAuthority[] = "xds.example.com";

@ -115,15 +115,14 @@ TEST_F(XdsClusterTest, Definition) {
auto* resource_type = XdsClusterResourceType::Get();
ASSERT_NE(resource_type, nullptr);
EXPECT_EQ(resource_type->type_url(), "envoy.config.cluster.v3.Cluster");
EXPECT_EQ(resource_type->v2_type_url(), "envoy.api.v2.Cluster");
EXPECT_TRUE(resource_type->AllResourcesRequiredInSotW());
}
TEST_F(XdsClusterTest, UnparseableProto) {
std::string serialized_resource("\0", 1);
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
EXPECT_EQ(decode_result.resource.status().code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(decode_result.resource.status().message(),
@ -139,8 +138,8 @@ TEST_F(XdsClusterTest, MinimumValidConfig) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -170,8 +169,8 @@ TEST_F(ClusterTypeTest, EdsConfigSourceAds) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -190,8 +189,8 @@ TEST_F(ClusterTypeTest, EdsServiceName) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -206,8 +205,8 @@ TEST_F(ClusterTypeTest, DiscoveryTypeNotPresent) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -225,8 +224,8 @@ TEST_F(ClusterTypeTest, EdsClusterConfigMissing) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -245,8 +244,8 @@ TEST_F(ClusterTypeTest, EdsConfigSourceMissing) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -265,8 +264,8 @@ TEST_F(ClusterTypeTest, EdsConfigSourceWrongType) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -293,8 +292,8 @@ TEST_F(ClusterTypeTest, LogicalDnsValid) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -310,8 +309,8 @@ TEST_F(ClusterTypeTest, LogicalDnsMissingLoadAssignment) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -331,8 +330,8 @@ TEST_F(ClusterTypeTest, LogicalDnsMissingLocalities) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -353,8 +352,8 @@ TEST_F(ClusterTypeTest, LogicalDnsTooManyLocalities) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -374,8 +373,8 @@ TEST_F(ClusterTypeTest, LogicalDnsLocalityMissingEndpoints) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -397,8 +396,8 @@ TEST_F(ClusterTypeTest, LogicalDnsLocalityTooManyEndpoints) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -418,8 +417,8 @@ TEST_F(ClusterTypeTest, LogicalDnsEndpointMissing) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -442,8 +441,8 @@ TEST_F(ClusterTypeTest, LogicalDnsAddressMissing) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -467,8 +466,8 @@ TEST_F(ClusterTypeTest, LogicalDnsSocketAddressMissing) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -494,8 +493,8 @@ TEST_F(ClusterTypeTest, LogicalDnsSocketAddressInvalid) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -525,8 +524,8 @@ TEST_F(ClusterTypeTest, AggregateClusterValid) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -548,8 +547,8 @@ TEST_F(ClusterTypeTest, AggregateClusterUnparseableProto) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -577,8 +576,8 @@ TEST_F(LbPolicyTest, LbPolicyRingHash) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -600,8 +599,8 @@ TEST_F(LbPolicyTest, LbPolicyRingHashSetMinAndMaxRingSize) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -623,8 +622,8 @@ TEST_F(LbPolicyTest, LbPolicyRingHashSetMinAndMaxRingSizeToZero) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -650,8 +649,8 @@ TEST_F(LbPolicyTest, LbPolicyRingHashSetMinAndMaxRingSizeTooLarge) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -677,8 +676,8 @@ TEST_F(LbPolicyTest, LbPolicyRingHashSetMinRingSizeLargerThanMaxRingSize) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -701,8 +700,8 @@ TEST_F(LbPolicyTest, LbPolicyRingHashUnsupportedHashFunction) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -723,8 +722,8 @@ TEST_F(LbPolicyTest, UnsupportedPolicy) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -759,8 +758,8 @@ TEST_F(TlsConfigTest, MinimumValidConfig) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -794,8 +793,8 @@ TEST_F(TlsConfigTest, UnknownCertificateProviderInstance) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -820,8 +819,8 @@ TEST_F(TlsConfigTest, TransportSocketTypedConfigUnset) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -846,8 +845,8 @@ TEST_F(TlsConfigTest, UnknownTransportSocketType) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -871,8 +870,8 @@ TEST_F(TlsConfigTest, CaCertProviderUnset) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -901,8 +900,8 @@ TEST_F(LrsTest, Valid) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -921,8 +920,8 @@ TEST_F(LrsTest, NotSelfConfigSource) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -956,8 +955,8 @@ TEST_F(CircuitBreakingTest, Valid) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -976,8 +975,8 @@ TEST_F(CircuitBreakingTest, NoDefaultThreshold) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -995,8 +994,8 @@ TEST_F(CircuitBreakingTest, DefaultThresholdWithMaxRequestsUnset) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -1019,8 +1018,8 @@ TEST_F(OutlierDetectionTest, DefaultValues) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -1050,8 +1049,8 @@ TEST_F(OutlierDetectionTest, AllFieldsSet) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -1096,8 +1095,8 @@ TEST_F(OutlierDetectionTest, InvalidValues) {
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),

@ -103,15 +103,14 @@ TEST_F(XdsEndpointTest, Definition) {
ASSERT_NE(resource_type, nullptr);
EXPECT_EQ(resource_type->type_url(),
"envoy.config.endpoint.v3.ClusterLoadAssignment");
EXPECT_EQ(resource_type->v2_type_url(), "envoy.api.v2.ClusterLoadAssignment");
EXPECT_FALSE(resource_type->AllResourcesRequiredInSotW());
}
TEST_F(XdsEndpointTest, UnparseableProto) {
std::string serialized_resource("\0", 1);
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
EXPECT_EQ(decode_result.resource.status().code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(decode_result.resource.status().message(),
@ -137,8 +136,8 @@ TEST_F(XdsEndpointTest, MinimumValidConfig) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -185,8 +184,8 @@ TEST_F(XdsEndpointTest, EndpointWeight) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -235,8 +234,8 @@ TEST_F(XdsEndpointTest, IgnoresLocalityWithNoWeight) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -286,8 +285,8 @@ TEST_F(XdsEndpointTest, IgnoresLocalityWithZeroWeight) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -328,8 +327,8 @@ TEST_F(XdsEndpointTest, LocalityWithNoEndpoints) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -362,8 +361,8 @@ TEST_F(XdsEndpointTest, NoLocality) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -392,8 +391,8 @@ TEST_F(XdsEndpointTest, InvalidPort) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -423,8 +422,8 @@ TEST_F(XdsEndpointTest, InvalidAddress) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -450,8 +449,8 @@ TEST_F(XdsEndpointTest, MissingSocketAddress) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -476,8 +475,8 @@ TEST_F(XdsEndpointTest, MissingAddress) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -502,8 +501,8 @@ TEST_F(XdsEndpointTest, MissingEndpoint) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -533,8 +532,8 @@ TEST_F(XdsEndpointTest, EndpointWeightZero) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -576,8 +575,8 @@ TEST_F(XdsEndpointTest, DuplicateLocalityName) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -621,8 +620,8 @@ TEST_F(XdsEndpointTest, SparsePriorityList) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -668,8 +667,8 @@ TEST_F(XdsEndpointTest, LocalityWeightsWithinPriorityExceedUint32Max) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -713,8 +712,8 @@ TEST_F(XdsEndpointTest, DuplicateAddresses) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -757,8 +756,8 @@ TEST_F(XdsEndpointTest, DropConfig) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -795,8 +794,8 @@ TEST_F(XdsEndpointTest, CapsDropPercentageAt100) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
@ -829,8 +828,8 @@ TEST_F(XdsEndpointTest, MissingDropCategoryName) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -862,8 +861,8 @@ TEST_F(XdsEndpointTest, MissingDropPercentage) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),
@ -898,8 +897,8 @@ TEST_F(XdsEndpointTest, DropPercentageInvalidDenominator) {
std::string serialized_resource;
ASSERT_TRUE(cla.SerializeToString(&serialized_resource));
auto* resource_type = XdsEndpointResourceType::Get();
auto decode_result = resource_type->Decode(
decode_context_, serialized_resource, /*is_v2=*/false);
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.name.has_value());
EXPECT_EQ(*decode_result.name, "foo");
EXPECT_EQ(decode_result.resource.status().code(),

@ -33,8 +33,6 @@ grpc_cc_library(
"//:gpr",
"//:grpc",
"//:grpc++",
"//src/proto/grpc/testing/xds:ads_for_test_proto",
"//src/proto/grpc/testing/xds:lrs_for_test_proto",
"//src/proto/grpc/testing/xds/v3:ads_proto",
"//src/proto/grpc/testing/xds/v3:cluster_proto",
"//src/proto/grpc/testing/xds/v3:discovery_proto",
@ -73,8 +71,6 @@ grpc_cc_library(
"//src/proto/grpc/testing:echo_messages_proto",
"//src/proto/grpc/testing:echo_proto",
"//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
"//src/proto/grpc/testing/xds:ads_for_test_proto",
"//src/proto/grpc/testing/xds:lrs_for_test_proto",
"//src/proto/grpc/testing/xds/v3:ads_proto",
"//src/proto/grpc/testing/xds/v3:cluster_proto",
"//src/proto/grpc/testing/xds/v3:discovery_proto",
@ -125,9 +121,6 @@ grpc_cc_test(
"//src/proto/grpc/testing:echo_messages_proto",
"//src/proto/grpc/testing:echo_proto",
"//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
"//src/proto/grpc/testing/xds:cds_for_test_proto",
"//src/proto/grpc/testing/xds:eds_for_test_proto",
"//src/proto/grpc/testing/xds:lds_rds_for_test_proto",
"//src/proto/grpc/testing/xds/v3:aggregate_cluster_proto",
"//src/proto/grpc/testing/xds/v3:cluster_proto",
"//src/proto/grpc/testing/xds/v3:endpoint_proto",

@ -86,11 +86,6 @@
#include "src/cpp/client/secure_credentials.h"
#include "src/cpp/server/secure_server_credentials.h"
#include "src/proto/grpc/testing/echo.grpc.pb.h"
#include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"

@ -283,10 +283,8 @@ XdsEnd2endTest::BalancerServerThread::BalancerServerThread(
void XdsEnd2endTest::BalancerServerThread::RegisterAllServices(
ServerBuilder* builder) {
builder->RegisterService(ads_service_->v2_rpc_service());
builder->RegisterService(ads_service_->v3_rpc_service());
builder->RegisterService(lrs_service_->v2_rpc_service());
builder->RegisterService(lrs_service_->v3_rpc_service());
builder->RegisterService(ads_service_.get());
builder->RegisterService(lrs_service_.get());
}
void XdsEnd2endTest::BalancerServerThread::StartAllServices() {
@ -337,7 +335,6 @@ std::string XdsEnd2endTest::BootstrapBuilder::MakeXdsServersText(
" }\n"
" ]";
std::vector<std::string> server_features;
if (!v2_) server_features.push_back("\"xds_v3\"");
if (ignore_resource_deletion_) {
server_features.push_back("\"ignore_resource_deletion\"");
}
@ -470,12 +467,10 @@ XdsEnd2endTest::XdsEnd2endTest() : balancer_(CreateAndStartBalancer()) {
// Construct LDS resource.
default_listener_.set_name(kServerName);
HttpConnectionManager http_connection_manager;
if (!GetParam().use_v2()) {
auto* filter = http_connection_manager.add_http_filters();
filter->set_name("router");
filter->mutable_typed_config()->PackFrom(
envoy::extensions::filters::http::router::v3::Router());
}
auto* filter = http_connection_manager.add_http_filters();
filter->set_name("router");
filter->mutable_typed_config()->PackFrom(
envoy::extensions::filters::http::router::v3::Router());
default_listener_.mutable_api_listener()->mutable_api_listener()->PackFrom(
http_connection_manager);
// Construct RDS resource.
@ -748,7 +743,6 @@ void XdsEnd2endTest::InitClient(BootstrapBuilder builder,
xds_channel_args_.args = xds_channel_args_to_add_.data();
// Initialize XdsClient state.
builder.SetDefaultServer(absl::StrCat("localhost:", balancer_->port()));
if (GetParam().use_v2()) builder.SetV2();
bootstrap_ = builder.Build();
if (GetParam().bootstrap_source() == XdsTestType::kBootstrapFromEnvVar) {
grpc_core::SetEnv("GRPC_XDS_BOOTSTRAP_CONFIG", bootstrap_.c_str());

@ -73,11 +73,6 @@ class XdsTestType {
return *this;
}
XdsTestType& set_use_v2() {
use_v2_ = true;
return *this;
}
XdsTestType& set_use_xds_credentials() {
use_xds_credentials_ = true;
return *this;
@ -105,7 +100,6 @@ class XdsTestType {
bool enable_load_reporting() const { return enable_load_reporting_; }
bool enable_rds_testing() const { return enable_rds_testing_; }
bool use_v2() const { return use_v2_; }
bool use_xds_credentials() const { return use_xds_credentials_; }
bool use_csds_streaming() const { return use_csds_streaming_; }
HttpFilterConfigLocation filter_config_setup() const {
@ -117,7 +111,7 @@ class XdsTestType {
}
std::string AsString() const {
std::string retval = use_v2_ ? "V2" : "V3";
std::string retval = "V3";
if (enable_load_reporting_) retval += "WithLoadReporting";
if (enable_rds_testing_) retval += "Rds";
if (use_xds_credentials_) retval += "XdsCreds";
@ -146,7 +140,6 @@ class XdsTestType {
private:
bool enable_load_reporting_ = false;
bool enable_rds_testing_ = false;
bool use_v2_ = false;
bool use_xds_credentials_ = false;
bool use_csds_streaming_ = false;
HttpFilterConfigLocation filter_config_setup_ = kHttpFilterConfigInListener;
@ -397,10 +390,6 @@ class XdsEnd2endTest : public ::testing::TestWithParam<XdsTestType> {
class BootstrapBuilder {
public:
BootstrapBuilder() {}
BootstrapBuilder& SetV2() {
v2_ = true;
return *this;
}
BootstrapBuilder& SetIgnoreResourceDeletion() {
ignore_resource_deletion_ = true;
return *this;
@ -452,7 +441,6 @@ class XdsEnd2endTest : public ::testing::TestWithParam<XdsTestType> {
std::string MakeCertificateProviderText();
std::string MakeAuthorityText();
bool v2_ = false;
bool ignore_resource_deletion_ = false;
std::string top_server_;
std::string client_default_listener_resource_name_template_;

@ -91,9 +91,7 @@ class RlsTest : public XdsEnd2endTest {
// Test both with and without RDS.
INSTANTIATE_TEST_SUITE_P(
XdsTest, RlsTest,
::testing::Values(XdsTestType(), XdsTestType().set_enable_rds_testing(),
// Also test with xDS v2.
XdsTestType().set_enable_rds_testing().set_use_v2()),
::testing::Values(XdsTestType(), XdsTestType().set_enable_rds_testing()),
&XdsTestType::Name);
TEST_P(RlsTest, XdsRoutingClusterSpecifierPlugin) {

@ -427,34 +427,6 @@ TEST_P(LdsTest, RejectsNonEmptyOriginalIpDetectionExtensions) {
::testing::HasSubstr("'original_ip_detection_extensions' must be empty"));
}
using LdsV2Test = XdsEnd2endTest;
INSTANTIATE_TEST_SUITE_P(XdsTest, LdsV2Test,
::testing::Values(XdsTestType().set_use_v2()),
&XdsTestType::Name);
// Tests that we ignore the HTTP filter list in v2.
// TODO(roth): The test framework is not set up to allow us to test
// the server sending v2 resources when the client requests v3, so this
// just tests a pure v2 setup. When we have time, fix this.
TEST_P(LdsV2Test, IgnoresHttpFilters) {
CreateAndStartBackends(1);
auto listener = default_listener_;
HttpConnectionManager http_connection_manager;
listener.mutable_api_listener()->mutable_api_listener()->UnpackTo(
&http_connection_manager);
auto* filter = http_connection_manager.add_http_filters();
filter->set_name("unknown");
filter->mutable_typed_config()->PackFrom(Listener());
listener.mutable_api_listener()->mutable_api_listener()->PackFrom(
http_connection_manager);
SetListenerAndRouteConfiguration(balancer_.get(), listener,
default_route_config_);
EdsResourceArgs args({{"locality0", CreateEndpointsForBackends()}});
balancer_->ads_service()->SetEdsResource(BuildEdsResource(args));
CheckRpcSendOk(DEBUG_LOCATION);
}
class LdsDeletionTest : public XdsEnd2endTest {
protected:
void SetUp() override {} // Individual tests call InitClient().
@ -536,11 +508,9 @@ TEST_P(LdsDeletionTest, ListenerDeletionIgnored) {
using LdsRdsTest = XdsEnd2endTest;
// Test with and without RDS.
// Also test with v2 and RDS to ensure that we handle those cases.
INSTANTIATE_TEST_SUITE_P(
XdsTest, LdsRdsTest,
::testing::Values(XdsTestType(), XdsTestType().set_enable_rds_testing(),
XdsTestType().set_enable_rds_testing().set_use_v2()),
::testing::Values(XdsTestType(), XdsTestType().set_enable_rds_testing()),
&XdsTestType::Name);
MATCHER_P2(AdjustedClockInRange, t1, t2, "equals time") {
@ -556,18 +526,6 @@ MATCHER_P2(AdjustedClockInRange, t1, t2, "equals time") {
return ok;
}
// Tests that XdsClient sends an ACK for the RouteConfiguration, whether or
// not it was inlined into the LDS response.
TEST_P(LdsRdsTest, Vanilla) {
(void)SendRpc();
auto response_state = RouteConfigurationResponseState(balancer_.get());
ASSERT_TRUE(response_state.has_value());
EXPECT_EQ(response_state->state, AdsServiceImpl::ResponseState::ACKED);
// Make sure we actually used the RPC service for the right version of xDS.
EXPECT_EQ(balancer_->ads_service()->seen_v2_client(), GetParam().use_v2());
EXPECT_NE(balancer_->ads_service()->seen_v3_client(), GetParam().use_v2());
}
TEST_P(LdsRdsTest, DefaultRouteSpecifiesSlashPrefix) {
CreateAndStartBackends(1);
RouteConfiguration route_config = default_route_config_;
@ -2807,7 +2765,6 @@ TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) {
// Test that we NACK unknown filter types in VirtualHost.
TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config =
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
@ -2824,7 +2781,6 @@ TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) {
// Test that we ignore optional unknown filter types in VirtualHost.
TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) {
CreateAndStartBackends(1);
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config =
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
@ -2844,7 +2800,6 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) {
// Test that we NACK filters without configs in VirtualHost.
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInVirtualHost) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config =
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
@ -2860,7 +2815,6 @@ TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInVirtualHost) {
// Test that we NACK filters without configs in FilterConfig in VirtualHost.
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInVirtualHost) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config =
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
@ -2877,7 +2831,6 @@ TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInVirtualHost) {
// Test that we ignore optional filters without configs in VirtualHost.
TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInVirtualHost) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
CreateAndStartBackends(1);
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config =
@ -2899,7 +2852,6 @@ TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInVirtualHost) {
// Test that we NACK unparseable filter types in VirtualHost.
TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config =
route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config();
@ -2916,7 +2868,6 @@ TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) {
// Test that we NACK unknown filter types in Route.
TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)
@ -2933,7 +2884,6 @@ TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) {
// Test that we ignore optional unknown filter types in Route.
TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
CreateAndStartBackends(1);
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config = route_config.mutable_virtual_hosts(0)
@ -2955,7 +2905,6 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) {
// Test that we NACK filters without configs in Route.
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInRoute) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)
@ -2972,7 +2921,6 @@ TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInRoute) {
// Test that we NACK filters without configs in FilterConfig in Route.
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInRoute) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)
@ -2990,7 +2938,6 @@ TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInRoute) {
// Test that we ignore optional filters without configs in Route.
TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInRoute) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
CreateAndStartBackends(1);
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config = route_config.mutable_virtual_hosts(0)
@ -3011,7 +2958,6 @@ TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInRoute) {
// Test that we NACK unparseable filter types in Route.
TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* per_filter_config = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)
@ -3029,7 +2975,6 @@ TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) {
// Test that we NACK unknown filter types in ClusterWeight.
TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* cluster_weight = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)
@ -3051,7 +2996,6 @@ TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) {
// Test that we ignore optional unknown filter types in ClusterWeight.
TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
CreateAndStartBackends(1);
RouteConfiguration route_config = default_route_config_;
auto* cluster_weight = route_config.mutable_virtual_hosts(0)
@ -3078,7 +3022,6 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) {
// Test that we NACK filters without configs in ClusterWeight.
TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInClusterWeight) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* cluster_weight = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)
@ -3101,7 +3044,6 @@ TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInClusterWeight) {
// Test that we NACK filters without configs in FilterConfig in ClusterWeight.
TEST_P(LdsRdsTest,
RejectsHttpFilterWithoutConfigInFilterConfigInClusterWeight) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* cluster_weight = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)
@ -3124,7 +3066,6 @@ TEST_P(LdsRdsTest,
// Test that we ignore optional filters without configs in ClusterWeight.
TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInClusterWeight) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
CreateAndStartBackends(1);
RouteConfiguration route_config = default_route_config_;
auto* cluster_weight = route_config.mutable_virtual_hosts(0)
@ -3150,7 +3091,6 @@ TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInClusterWeight) {
// Test that we NACK unparseable filter types in ClusterWeight.
TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInClusterWeight) {
if (GetParam().use_v2()) return; // Filters supported in v3 only.
RouteConfiguration route_config = default_route_config_;
auto* cluster_weight = route_config.mutable_virtual_hosts(0)
->mutable_routes(0)

@ -31,8 +31,6 @@
#include "src/core/lib/address_utils/parse_address.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h"

@ -32,8 +32,6 @@
#include "src/core/lib/address_utils/parse_address.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h"
#include "src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h"
@ -57,15 +55,11 @@ constexpr char kCdsTypeUrl[] =
constexpr char kEdsTypeUrl[] =
"type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment";
constexpr char kLdsV2TypeUrl[] = "type.googleapis.com/envoy.api.v2.Listener";
constexpr char kRdsV2TypeUrl[] =
"type.googleapis.com/envoy.api.v2.RouteConfiguration";
constexpr char kCdsV2TypeUrl[] = "type.googleapis.com/envoy.api.v2.Cluster";
constexpr char kEdsV2TypeUrl[] =
"type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
// An ADS service implementation.
class AdsServiceImpl : public std::enable_shared_from_this<AdsServiceImpl> {
class AdsServiceImpl
: public CountedService<
::envoy::service::discovery::v3::AggregatedDiscoveryService::Service>,
public std::enable_shared_from_this<AdsServiceImpl> {
public:
// State for a given xDS resource type.
struct ResponseState {
@ -77,22 +71,7 @@ class AdsServiceImpl : public std::enable_shared_from_this<AdsServiceImpl> {
std::string error_message;
};
AdsServiceImpl()
: v2_rpc_service_(this, /*is_v2=*/true),
v3_rpc_service_(this, /*is_v2=*/false) {}
bool seen_v2_client() const { return seen_v2_client_; }
bool seen_v3_client() const { return seen_v3_client_; }
::envoy::service::discovery::v2::AggregatedDiscoveryService::Service*
v2_rpc_service() {
return &v2_rpc_service_;
}
::envoy::service::discovery::v3::AggregatedDiscoveryService::Service*
v3_rpc_service() {
return &v3_rpc_service_;
}
AdsServiceImpl() {}
void set_wrap_resources(bool wrap_resources) {
grpc_core::MutexLock lock(&ads_mu_);
@ -237,419 +216,332 @@ class AdsServiceImpl : public std::enable_shared_from_this<AdsServiceImpl> {
using ResourceMap = std::map<std::string /* type_url */, ResourceTypeState>;
// Templated RPC service implementation, works for both v2 and v3.
template <class RpcApi, class DiscoveryRequest, class DiscoveryResponse>
class RpcService : public RpcApi::Service {
public:
using Stream = ServerReaderWriter<DiscoveryResponse, DiscoveryRequest>;
RpcService(AdsServiceImpl* parent, bool is_v2)
: parent_(parent), is_v2_(is_v2) {}
Status StreamAggregatedResources(ServerContext* context,
Stream* stream) override {
gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources starts", this);
using DiscoveryRequest = ::envoy::service::discovery::v3::DiscoveryRequest;
using DiscoveryResponse = ::envoy::service::discovery::v3::DiscoveryResponse;
using Stream = ServerReaderWriter<DiscoveryResponse, DiscoveryRequest>;
Status StreamAggregatedResources(ServerContext* context,
Stream* stream) override {
gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources starts", this);
{
grpc_core::MutexLock lock(&ads_mu_);
if (forced_ads_failure_.has_value()) {
gpr_log(GPR_INFO,
"ADS[%p]: StreamAggregatedResources forcing early failure "
"with status code: %d, message: %s",
this, forced_ads_failure_.value().error_code(),
forced_ads_failure_.value().error_message().c_str());
return forced_ads_failure_.value();
}
}
AddClient(context->peer());
// Take a reference of the AdsServiceImpl object, which will go
// out of scope when this request handler returns. This ensures
// that the parent won't be destroyed until this stream is complete.
std::shared_ptr<AdsServiceImpl> ads_service_impl = shared_from_this();
// Resources (type/name pairs) that have changed since the client
// subscribed to them.
UpdateQueue update_queue;
// Resources that the client will be subscribed to keyed by resource type
// url.
SubscriptionMap subscription_map;
// Sent state for each resource type.
std::map<std::string /*type_url*/, SentState> sent_state_map;
// Spawn a thread to read requests from the stream.
// Requests will be delivered to this thread in a queue.
std::deque<DiscoveryRequest> requests;
bool stream_closed = false;
std::thread reader(std::bind(&AdsServiceImpl::BlockingRead, this, stream,
&requests, &stream_closed));
// Main loop to process requests and updates.
while (true) {
// Boolean to keep track if the loop received any work to do: a
// request or an update; regardless whether a response was actually
// sent out.
bool did_work = false;
// Look for new requests and decide what to handle.
absl::optional<DiscoveryResponse> response;
{
grpc_core::MutexLock lock(&parent_->ads_mu_);
if (parent_->forced_ads_failure_.has_value()) {
grpc_core::MutexLock lock(&ads_mu_);
// If the stream has been closed or our parent is being shut
// down, stop immediately.
if (stream_closed || ads_done_) break;
// Otherwise, see if there's a request to read from the queue.
if (!requests.empty()) {
DiscoveryRequest request = std::move(requests.front());
requests.pop_front();
did_work = true;
gpr_log(GPR_INFO,
"ADS[%p]: StreamAggregatedResources forcing early failure "
"with status code: %d, message: %s",
this, parent_->forced_ads_failure_.value().error_code(),
parent_->forced_ads_failure_.value().error_message().c_str());
return parent_->forced_ads_failure_.value();
"ADS[%p]: Received request for type %s with content %s", this,
request.type_url().c_str(), request.DebugString().c_str());
SentState& sent_state = sent_state_map[request.type_url()];
// Process request.
ProcessRequest(request, &update_queue, &subscription_map, &sent_state,
&response);
}
}
parent_->AddClient(context->peer());
if (is_v2_) {
parent_->seen_v2_client_ = true;
} else {
parent_->seen_v3_client_ = true;
if (response.has_value()) {
gpr_log(GPR_INFO, "ADS[%p]: Sending response: %s", this,
response->DebugString().c_str());
stream->Write(response.value());
}
// Take a reference of the AdsServiceImpl object, which will go
// out of scope when this request handler returns. This ensures
// that the parent won't be destroyed until this stream is complete.
std::shared_ptr<AdsServiceImpl> ads_service_impl =
parent_->shared_from_this();
// Resources (type/name pairs) that have changed since the client
// subscribed to them.
UpdateQueue update_queue;
// Resources that the client will be subscribed to keyed by resource type
// url.
SubscriptionMap subscription_map;
// Sent state for each resource type.
std::map<std::string /*type_url*/, SentState> sent_state_map;
// Spawn a thread to read requests from the stream.
// Requests will be delivered to this thread in a queue.
std::deque<DiscoveryRequest> requests;
bool stream_closed = false;
std::thread reader(std::bind(&RpcService::BlockingRead, this, stream,
&requests, &stream_closed));
// Main loop to process requests and updates.
while (true) {
// Boolean to keep track if the loop received any work to do: a
// request or an update; regardless whether a response was actually
// sent out.
bool did_work = false;
// Look for new requests and and decide what to handle.
absl::optional<DiscoveryResponse> response;
{
grpc_core::MutexLock lock(&parent_->ads_mu_);
// If the stream has been closed or our parent is being shut
// down, stop immediately.
if (stream_closed || parent_->ads_done_) break;
// Otherwise, see if there's a request to read from the queue.
if (!requests.empty()) {
DiscoveryRequest request = std::move(requests.front());
requests.pop_front();
did_work = true;
gpr_log(GPR_INFO,
"ADS[%p]: Received request for type %s with content %s",
this, request.type_url().c_str(),
request.DebugString().c_str());
const std::string v3_resource_type =
TypeUrlToV3(request.type_url());
SentState& sent_state = sent_state_map[v3_resource_type];
// Process request.
ProcessRequest(request, v3_resource_type, &update_queue,
&subscription_map, &sent_state, &response);
}
}
if (response.has_value()) {
gpr_log(GPR_INFO, "ADS[%p]: Sending response: %s", this,
response->DebugString().c_str());
stream->Write(response.value());
}
response.reset();
// Look for updates and decide what to handle.
{
grpc_core::MutexLock lock(&parent_->ads_mu_);
if (!update_queue.empty()) {
const std::string resource_type =
std::move(update_queue.front().first);
const std::string resource_name =
std::move(update_queue.front().second);
update_queue.pop_front();
did_work = true;
SentState& sent_state = sent_state_map[resource_type];
ProcessUpdate(resource_type, resource_name, &subscription_map,
&sent_state, &response);
}
}
if (response.has_value()) {
gpr_log(GPR_INFO, "ADS[%p]: Sending update response: %s", this,
response->DebugString().c_str());
stream->Write(response.value());
}
{
grpc_core::MutexLock lock(&parent_->ads_mu_);
if (parent_->ads_done_) {
break;
}
response.reset();
// Look for updates and decide what to handle.
{
grpc_core::MutexLock lock(&ads_mu_);
if (!update_queue.empty()) {
const std::string resource_type =
std::move(update_queue.front().first);
const std::string resource_name =
std::move(update_queue.front().second);
update_queue.pop_front();
did_work = true;
SentState& sent_state = sent_state_map[resource_type];
ProcessUpdate(resource_type, resource_name, &subscription_map,
&sent_state, &response);
}
// If we didn't find anything to do, delay before the next loop
// iteration; otherwise, check whether we should exit and then
// immediately continue.
gpr_sleep_until(
grpc_timeout_milliseconds_to_deadline(did_work ? 0 : 10));
}
// Done with main loop. Clean up before returning.
// Join reader thread.
reader.join();
// Clean up any subscriptions that were still active when the call
// finished.
if (response.has_value()) {
gpr_log(GPR_INFO, "ADS[%p]: Sending update response: %s", this,
response->DebugString().c_str());
stream->Write(response.value());
}
{
grpc_core::MutexLock lock(&parent_->ads_mu_);
for (auto& p : subscription_map) {
const std::string& type_url = p.first;
SubscriptionNameMap& subscription_name_map = p.second;
for (auto& q : subscription_name_map) {
const std::string& resource_name = q.first;
SubscriptionState& subscription_state = q.second;
ResourceNameMap& resource_name_map =
parent_->resource_map_[type_url].resource_name_map;
ResourceState& resource_state = resource_name_map[resource_name];
resource_state.subscriptions.erase(&subscription_state);
}
grpc_core::MutexLock lock(&ads_mu_);
if (ads_done_) {
break;
}
}
gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources done", this);
parent_->RemoveClient(context->peer());
return Status::OK;
// If we didn't find anything to do, delay before the next loop
// iteration; otherwise, check whether we should exit and then
// immediately continue.
gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(did_work ? 0 : 10));
}
private:
// NB: clang's annotalysis is confused by the use of inner template
// classes here and *ignores* the exclusive lock annotation on some
// functions. See https://bugs.llvm.org/show_bug.cgi?id=51368.
//
// This class is used for a dual purpose:
// - it convinces clang that the lock is held in a given scope
// - when used in a function that is annotated to require the inner lock it
// will cause compilation to fail if the upstream bug is fixed!
//
// If you arrive here because of a compilation failure, that might mean the
// clang bug is fixed! Please report that on the ticket.
//
// Since the buggy compiler will still need to be supported, consider
// wrapping this class in a compiler version #if and replace its usage
// with a macro whose expansion is conditional on the compiler version. In
// time (years? decades?) this code can be deleted altogether.
class ABSL_SCOPED_LOCKABLE NoopMutexLock {
public:
explicit NoopMutexLock(grpc_core::Mutex& mu)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) {}
~NoopMutexLock() ABSL_UNLOCK_FUNCTION() {}
};
// Processes a response read from the client.
// Populates response if needed.
void ProcessRequest(const DiscoveryRequest& request,
const std::string& v3_resource_type,
UpdateQueue* update_queue,
SubscriptionMap* subscription_map,
SentState* sent_state,
absl::optional<DiscoveryResponse>* response)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
NoopMutexLock mu(parent_->ads_mu_);
// Check the nonce sent by the client, if any.
// (This will be absent on the first request on a stream.)
if (request.response_nonce().empty()) {
int client_resource_type_version = 0;
if (!request.version_info().empty()) {
GPR_ASSERT(absl::SimpleAtoi(request.version_info(),
&client_resource_type_version));
}
EXPECT_GE(client_resource_type_version,
parent_->resource_type_min_versions_[v3_resource_type])
<< "resource_type: " << v3_resource_type;
} else {
int client_nonce;
GPR_ASSERT(absl::SimpleAtoi(request.response_nonce(), &client_nonce));
// Check for ACK or NACK.
ResponseState response_state;
if (!request.has_error_detail()) {
response_state.state = ResponseState::ACKED;
gpr_log(GPR_INFO, "ADS[%p]: client ACKed resource_type=%s version=%s",
this, request.type_url().c_str(),
request.version_info().c_str());
} else {
response_state.state = ResponseState::NACKED;
EXPECT_EQ(request.error_detail().code(),
GRPC_STATUS_INVALID_ARGUMENT);
response_state.error_message = request.error_detail().message();
gpr_log(GPR_INFO,
"ADS[%p]: client NACKed resource_type=%s version=%s: %s",
this, request.type_url().c_str(),
request.version_info().c_str(),
response_state.error_message.c_str());
// Done with main loop. Clean up before returning.
// Join reader thread.
reader.join();
// Clean up any subscriptions that were still active when the call
// finished.
{
grpc_core::MutexLock lock(&ads_mu_);
for (auto& p : subscription_map) {
const std::string& type_url = p.first;
SubscriptionNameMap& subscription_name_map = p.second;
for (auto& q : subscription_name_map) {
const std::string& resource_name = q.first;
SubscriptionState& subscription_state = q.second;
ResourceNameMap& resource_name_map =
resource_map_[type_url].resource_name_map;
ResourceState& resource_state = resource_name_map[resource_name];
resource_state.subscriptions.erase(&subscription_state);
}
parent_->resource_type_response_state_[v3_resource_type].emplace_back(
std::move(response_state));
// Ignore requests with stale nonces.
if (client_nonce < sent_state->nonce) return;
}
// Ignore resource types as requested by tests.
if (parent_->resource_types_to_ignore_.find(v3_resource_type) !=
parent_->resource_types_to_ignore_.end()) {
return;
}
gpr_log(GPR_INFO, "ADS[%p]: StreamAggregatedResources done", this);
RemoveClient(context->peer());
return Status::OK;
}
// Processes a response read from the client.
// Populates response if needed.
void ProcessRequest(const DiscoveryRequest& request,
UpdateQueue* update_queue,
SubscriptionMap* subscription_map, SentState* sent_state,
absl::optional<DiscoveryResponse>* response)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(ads_mu_) {
// Check the nonce sent by the client, if any.
// (This will be absent on the first request on a stream.)
if (request.response_nonce().empty()) {
int client_resource_type_version = 0;
if (!request.version_info().empty()) {
GPR_ASSERT(absl::SimpleAtoi(request.version_info(),
&client_resource_type_version));
}
// Inject bad resources if needed.
if (parent_->inject_bad_resources_for_resource_type_ ==
v3_resource_type) {
response->emplace();
// Unparseable Resource wrapper.
auto* resource = (*response)->add_resources();
resource->set_type_url(
"type.googleapis.com/envoy.service.discovery.v3.Resource");
resource->set_value(std::string("\0", 1));
// Unparseable resource within Resource wrapper.
envoy::service::discovery::v3::Resource resource_wrapper;
resource_wrapper.set_name("foo");
resource = resource_wrapper.mutable_resource();
resource->set_type_url(v3_resource_type);
resource->set_value(std::string("\0", 1));
(*response)->add_resources()->PackFrom(resource_wrapper);
EXPECT_GE(client_resource_type_version,
resource_type_min_versions_[request.type_url()])
<< "resource_type: " << request.type_url();
} else {
int client_nonce;
GPR_ASSERT(absl::SimpleAtoi(request.response_nonce(), &client_nonce));
// Check for ACK or NACK.
ResponseState response_state;
if (!request.has_error_detail()) {
response_state.state = ResponseState::ACKED;
gpr_log(GPR_INFO, "ADS[%p]: client ACKed resource_type=%s version=%s",
this, request.type_url().c_str(),
request.version_info().c_str());
} else {
response_state.state = ResponseState::NACKED;
EXPECT_EQ(request.error_detail().code(), GRPC_STATUS_INVALID_ARGUMENT);
response_state.error_message = request.error_detail().message();
gpr_log(GPR_INFO,
"ADS[%p]: client NACKed resource_type=%s version=%s: %s", this,
request.type_url().c_str(), request.version_info().c_str(),
response_state.error_message.c_str());
}
// Look at all the resource names in the request.
auto& subscription_name_map = (*subscription_map)[v3_resource_type];
auto& resource_type_state = parent_->resource_map_[v3_resource_type];
auto& resource_name_map = resource_type_state.resource_name_map;
std::set<std::string> resources_in_current_request;
std::set<std::string> resources_added_to_response;
for (const std::string& resource_name : request.resource_names()) {
resources_in_current_request.emplace(resource_name);
auto& subscription_state = subscription_name_map[resource_name];
auto& resource_state = resource_name_map[resource_name];
// Subscribe if needed.
// Send the resource in the response if either (a) this is
// a new subscription or (b) there is an updated version of
// this resource to send.
if (parent_->MaybeSubscribe(v3_resource_type, resource_name,
&subscription_state, &resource_state,
update_queue) ||
ClientNeedsResourceUpdate(resource_type_state, resource_state,
sent_state->resource_type_version)) {
gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
request.type_url().c_str(), resource_name.c_str());
resources_added_to_response.emplace(resource_name);
if (!response->has_value()) response->emplace();
if (resource_state.resource.has_value()) {
auto* resource = (*response)->add_resources();
resource->CopyFrom(resource_state.resource.value());
if (is_v2_) {
resource->set_type_url(request.type_url());
}
if (parent_->wrap_resources_) {
envoy::service::discovery::v3::Resource resource_wrapper;
*resource_wrapper.mutable_resource() = std::move(*resource);
resource->PackFrom(resource_wrapper);
}
resource_type_response_state_[request.type_url()].emplace_back(
std::move(response_state));
// Ignore requests with stale nonces.
if (client_nonce < sent_state->nonce) return;
}
// Ignore resource types as requested by tests.
if (resource_types_to_ignore_.find(request.type_url()) !=
resource_types_to_ignore_.end()) {
return;
}
// Inject bad resources if needed.
if (inject_bad_resources_for_resource_type_ == request.type_url()) {
response->emplace();
// Unparseable Resource wrapper.
auto* resource = (*response)->add_resources();
resource->set_type_url(
"type.googleapis.com/envoy.service.discovery.v3.Resource");
resource->set_value(std::string("\0", 1));
// Unparseable resource within Resource wrapper.
envoy::service::discovery::v3::Resource resource_wrapper;
resource_wrapper.set_name("foo");
resource = resource_wrapper.mutable_resource();
resource->set_type_url(request.type_url());
resource->set_value(std::string("\0", 1));
(*response)->add_resources()->PackFrom(resource_wrapper);
}
// Look at all the resource names in the request.
auto& subscription_name_map = (*subscription_map)[request.type_url()];
auto& resource_type_state = resource_map_[request.type_url()];
auto& resource_name_map = resource_type_state.resource_name_map;
std::set<std::string> resources_in_current_request;
std::set<std::string> resources_added_to_response;
for (const std::string& resource_name : request.resource_names()) {
resources_in_current_request.emplace(resource_name);
auto& subscription_state = subscription_name_map[resource_name];
auto& resource_state = resource_name_map[resource_name];
// Subscribe if needed.
// Send the resource in the response if either (a) this is
// a new subscription or (b) there is an updated version of
// this resource to send.
if (MaybeSubscribe(request.type_url(), resource_name, &subscription_state,
&resource_state, update_queue) ||
ClientNeedsResourceUpdate(resource_type_state, resource_state,
sent_state->resource_type_version)) {
gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
request.type_url().c_str(), resource_name.c_str());
resources_added_to_response.emplace(resource_name);
if (!response->has_value()) response->emplace();
if (resource_state.resource.has_value()) {
auto* resource = (*response)->add_resources();
resource->CopyFrom(resource_state.resource.value());
if (wrap_resources_) {
envoy::service::discovery::v3::Resource resource_wrapper;
*resource_wrapper.mutable_resource() = std::move(*resource);
resource->PackFrom(resource_wrapper);
}
} else {
gpr_log(GPR_INFO,
"ADS[%p]: client does not need update for type=%s name=%s",
this, request.type_url().c_str(), resource_name.c_str());
}
} else {
gpr_log(GPR_INFO,
"ADS[%p]: client does not need update for type=%s name=%s",
this, request.type_url().c_str(), resource_name.c_str());
}
// Process unsubscriptions for any resource no longer
// present in the request's resource list.
parent_->ProcessUnsubscriptions(
v3_resource_type, resources_in_current_request,
&subscription_name_map, &resource_name_map);
// Construct response if needed.
if (!resources_added_to_response.empty()) {
CompleteBuildingDiscoveryResponse(
v3_resource_type, request.type_url(),
resource_type_state.resource_type_version, subscription_name_map,
resources_added_to_response, sent_state, &response->value());
}
}
// Process unsubscriptions for any resource no longer
// present in the request's resource list.
ProcessUnsubscriptions(request.type_url(), resources_in_current_request,
&subscription_name_map, &resource_name_map);
// Construct response if needed.
if (!resources_added_to_response.empty()) {
CompleteBuildingDiscoveryResponse(
request.type_url(), resource_type_state.resource_type_version,
subscription_name_map, resources_added_to_response, sent_state,
&response->value());
}
}
// Processes a resource update from the test.
// Populates response if needed.
void ProcessUpdate(const std::string& resource_type,
const std::string& resource_name,
SubscriptionMap* subscription_map, SentState* sent_state,
absl::optional<DiscoveryResponse>* response)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
NoopMutexLock mu(parent_->ads_mu_);
const std::string v2_resource_type = TypeUrlToV2(resource_type);
gpr_log(GPR_INFO, "ADS[%p]: Received update for type=%s name=%s", this,
resource_type.c_str(), resource_name.c_str());
auto& subscription_name_map = (*subscription_map)[resource_type];
auto& resource_type_state = parent_->resource_map_[resource_type];
auto& resource_name_map = resource_type_state.resource_name_map;
auto it = subscription_name_map.find(resource_name);
if (it != subscription_name_map.end()) {
ResourceState& resource_state = resource_name_map[resource_name];
if (ClientNeedsResourceUpdate(resource_type_state, resource_state,
sent_state->resource_type_version)) {
gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
resource_type.c_str(), resource_name.c_str());
response->emplace();
if (resource_state.resource.has_value()) {
auto* resource = (*response)->add_resources();
resource->CopyFrom(resource_state.resource.value());
if (is_v2_) {
resource->set_type_url(v2_resource_type);
}
}
CompleteBuildingDiscoveryResponse(
resource_type, v2_resource_type,
resource_type_state.resource_type_version, subscription_name_map,
{resource_name}, sent_state, &response->value());
// Processes a resource update from the test.
// Populates response if needed.
void ProcessUpdate(const std::string& resource_type,
const std::string& resource_name,
SubscriptionMap* subscription_map, SentState* sent_state,
absl::optional<DiscoveryResponse>* response)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(ads_mu_) {
gpr_log(GPR_INFO, "ADS[%p]: Received update for type=%s name=%s", this,
resource_type.c_str(), resource_name.c_str());
auto& subscription_name_map = (*subscription_map)[resource_type];
auto& resource_type_state = resource_map_[resource_type];
auto& resource_name_map = resource_type_state.resource_name_map;
auto it = subscription_name_map.find(resource_name);
if (it != subscription_name_map.end()) {
ResourceState& resource_state = resource_name_map[resource_name];
if (ClientNeedsResourceUpdate(resource_type_state, resource_state,
sent_state->resource_type_version)) {
gpr_log(GPR_INFO, "ADS[%p]: Sending update for type=%s name=%s", this,
resource_type.c_str(), resource_name.c_str());
response->emplace();
if (resource_state.resource.has_value()) {
auto* resource = (*response)->add_resources();
resource->CopyFrom(resource_state.resource.value());
}
CompleteBuildingDiscoveryResponse(
resource_type, resource_type_state.resource_type_version,
subscription_name_map, {resource_name}, sent_state,
&response->value());
}
}
}
// Starting a thread to do blocking read on the stream until cancel.
void BlockingRead(Stream* stream, std::deque<DiscoveryRequest>* requests,
bool* stream_closed) {
DiscoveryRequest request;
bool seen_first_request = false;
while (stream->Read(&request)) {
if (!seen_first_request) {
EXPECT_TRUE(request.has_node());
EXPECT_THAT(request.node().client_features(),
::testing::UnorderedElementsAre(
"envoy.lb.does_not_support_overprovisioning",
"xds.config.resource-in-sotw"));
CheckBuildVersion(request);
seen_first_request = true;
}
{
grpc_core::MutexLock lock(&parent_->ads_mu_);
requests->emplace_back(std::move(request));
}
// Starting a thread to do blocking read on the stream until cancel.
void BlockingRead(Stream* stream, std::deque<DiscoveryRequest>* requests,
bool* stream_closed) {
DiscoveryRequest request;
bool seen_first_request = false;
while (stream->Read(&request)) {
if (!seen_first_request) {
EXPECT_TRUE(request.has_node());
EXPECT_THAT(request.node().client_features(),
::testing::UnorderedElementsAre(
"envoy.lb.does_not_support_overprovisioning",
"xds.config.resource-in-sotw"));
seen_first_request = true;
}
{
grpc_core::MutexLock lock(&ads_mu_);
requests->emplace_back(std::move(request));
}
gpr_log(GPR_INFO, "ADS[%p]: Null read, stream closed", this);
grpc_core::MutexLock lock(&parent_->ads_mu_);
*stream_closed = true;
}
gpr_log(GPR_INFO, "ADS[%p]: Null read, stream closed", this);
grpc_core::MutexLock lock(&ads_mu_);
*stream_closed = true;
}
// Completing the building a DiscoveryResponse by adding common information
// for all resources and by adding all subscribed resources for LDS and CDS.
void CompleteBuildingDiscoveryResponse(
const std::string& resource_type, const std::string& v2_resource_type,
const int version, const SubscriptionNameMap& subscription_name_map,
const std::set<std::string>& resources_added_to_response,
SentState* sent_state, DiscoveryResponse* response)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->ads_mu_) {
NoopMutexLock mu(parent_->ads_mu_);
response->set_type_url(is_v2_ ? v2_resource_type : resource_type);
response->set_version_info(std::to_string(version));
response->set_nonce(std::to_string(++sent_state->nonce));
if (resource_type == kLdsTypeUrl || resource_type == kCdsTypeUrl) {
// For LDS and CDS we must send back all subscribed resources
// (even the unchanged ones)
for (const auto& p : subscription_name_map) {
const std::string& resource_name = p.first;
if (resources_added_to_response.find(resource_name) ==
resources_added_to_response.end()) {
ResourceNameMap& resource_name_map =
parent_->resource_map_[resource_type].resource_name_map;
const ResourceState& resource_state =
resource_name_map[resource_name];
if (resource_state.resource.has_value()) {
auto* resource = response->add_resources();
resource->CopyFrom(resource_state.resource.value());
if (is_v2_) {
resource->set_type_url(v2_resource_type);
}
}
// Completing the building a DiscoveryResponse by adding common information
// for all resources and by adding all subscribed resources for LDS and CDS.
void CompleteBuildingDiscoveryResponse(
const std::string& resource_type, const int version,
const SubscriptionNameMap& subscription_name_map,
const std::set<std::string>& resources_added_to_response,
SentState* sent_state, DiscoveryResponse* response)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(ads_mu_) {
response->set_type_url(resource_type);
response->set_version_info(std::to_string(version));
response->set_nonce(std::to_string(++sent_state->nonce));
if (resource_type == kLdsTypeUrl || resource_type == kCdsTypeUrl) {
// For LDS and CDS we must send back all subscribed resources
// (even the unchanged ones)
for (const auto& p : subscription_name_map) {
const std::string& resource_name = p.first;
if (resources_added_to_response.find(resource_name) ==
resources_added_to_response.end()) {
ResourceNameMap& resource_name_map =
resource_map_[resource_type].resource_name_map;
const ResourceState& resource_state =
resource_name_map[resource_name];
if (resource_state.resource.has_value()) {
auto* resource = response->add_resources();
resource->CopyFrom(resource_state.resource.value());
}
}
}
sent_state->resource_type_version = version;
}
static std::string TypeUrlToV2(const std::string& resource_type) {
if (resource_type == kLdsTypeUrl) return kLdsV2TypeUrl;
if (resource_type == kRdsTypeUrl) return kRdsV2TypeUrl;
if (resource_type == kCdsTypeUrl) return kCdsV2TypeUrl;
if (resource_type == kEdsTypeUrl) return kEdsV2TypeUrl;
return resource_type;
}
static std::string TypeUrlToV3(const std::string& resource_type) {
if (resource_type == kLdsV2TypeUrl) return kLdsTypeUrl;
if (resource_type == kRdsV2TypeUrl) return kRdsTypeUrl;
if (resource_type == kCdsV2TypeUrl) return kCdsTypeUrl;
if (resource_type == kEdsV2TypeUrl) return kEdsTypeUrl;
return resource_type;
}
static void CheckBuildVersion(
const ::envoy::api::v2::DiscoveryRequest& request) {
EXPECT_FALSE(request.node().build_version().empty());
}
static void CheckBuildVersion(
const ::envoy::service::discovery::v3::DiscoveryRequest& /*request*/) {}
AdsServiceImpl* parent_;
const bool is_v2_;
};
sent_state->resource_type_version = version;
}
// Checks whether the client needs to receive a newer version of
// the resource.
@ -683,18 +575,6 @@ class AdsServiceImpl : public std::enable_shared_from_this<AdsServiceImpl> {
clients_.erase(client);
}
RpcService<::envoy::service::discovery::v2::AggregatedDiscoveryService,
::envoy::api::v2::DiscoveryRequest,
::envoy::api::v2::DiscoveryResponse>
v2_rpc_service_;
RpcService<::envoy::service::discovery::v3::AggregatedDiscoveryService,
::envoy::service::discovery::v3::DiscoveryRequest,
::envoy::service::discovery::v3::DiscoveryResponse>
v3_rpc_service_;
std::atomic_bool seen_v2_client_{false};
std::atomic_bool seen_v3_client_{false};
grpc_core::CondVar ads_cond_;
grpc_core::Mutex ads_mu_;
bool ads_done_ ABSL_GUARDED_BY(ads_mu_) = false;
@ -719,7 +599,10 @@ class AdsServiceImpl : public std::enable_shared_from_this<AdsServiceImpl> {
};
// An LRS service implementation.
class LrsServiceImpl : public std::enable_shared_from_this<LrsServiceImpl> {
class LrsServiceImpl
: public CountedService<
::envoy::service::load_stats::v3::LoadReportingService::Service>,
public std::enable_shared_from_this<LrsServiceImpl> {
public:
// Stats reported by client.
class ClientStats {
@ -729,9 +612,9 @@ class LrsServiceImpl : public std::enable_shared_from_this<LrsServiceImpl> {
LocalityStats() {}
// Converts from proto message class.
template <class UpstreamLocalityStats>
explicit LocalityStats(
const UpstreamLocalityStats& upstream_locality_stats)
const ::envoy::config::endpoint::v3::UpstreamLocalityStats&
upstream_locality_stats)
: total_successful_requests(
upstream_locality_stats.total_successful_requests()),
total_requests_in_progress(
@ -758,8 +641,8 @@ class LrsServiceImpl : public std::enable_shared_from_this<LrsServiceImpl> {
ClientStats() {}
// Converts from proto message class.
template <class ClusterStats>
explicit ClientStats(const ClusterStats& cluster_stats)
explicit ClientStats(
const ::envoy::config::endpoint::v3::ClusterStats& cluster_stats)
: cluster_name_(cluster_stats.cluster_name()),
eds_service_name_(cluster_stats.cluster_service_name()),
total_dropped_requests_(cluster_stats.total_dropped_requests()) {
@ -803,30 +686,10 @@ class LrsServiceImpl : public std::enable_shared_from_this<LrsServiceImpl> {
LrsServiceImpl(int client_load_reporting_interval_seconds,
std::set<std::string> cluster_names)
: v2_rpc_service_(this),
v3_rpc_service_(this),
client_load_reporting_interval_seconds_(
: client_load_reporting_interval_seconds_(
client_load_reporting_interval_seconds),
cluster_names_(std::move(cluster_names)) {}
::envoy::service::load_stats::v2::LoadReportingService::Service*
v2_rpc_service() {
return &v2_rpc_service_;
}
::envoy::service::load_stats::v3::LoadReportingService::Service*
v3_rpc_service() {
return &v3_rpc_service_;
}
size_t request_count() {
return v2_rpc_service_.request_count() + v3_rpc_service_.request_count();
}
size_t response_count() {
return v2_rpc_service_.response_count() + v3_rpc_service_.response_count();
}
// Must be called before the LRS call is started.
void set_send_all_clusters(bool send_all_clusters) {
send_all_clusters_ = send_all_clusters;
@ -842,81 +705,61 @@ class LrsServiceImpl : public std::enable_shared_from_this<LrsServiceImpl> {
std::vector<ClientStats> WaitForLoadReport();
private:
// Templated RPC service implementation, works for both v2 and v3.
template <class RpcApi, class LoadStatsRequest, class LoadStatsResponse>
class RpcService : public CountedService<typename RpcApi::Service> {
public:
using Stream = ServerReaderWriter<LoadStatsResponse, LoadStatsRequest>;
explicit RpcService(LrsServiceImpl* parent) : parent_(parent) {}
Status StreamLoadStats(ServerContext* /*context*/,
Stream* stream) override {
gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats starts", this);
EXPECT_GT(parent_->client_load_reporting_interval_seconds_, 0);
// Take a reference of the LrsServiceImpl object, reference will go
// out of scope after this method exits.
std::shared_ptr<LrsServiceImpl> lrs_service_impl =
parent_->shared_from_this();
// Read initial request.
LoadStatsRequest request;
if (stream->Read(&request)) {
CountedService<typename RpcApi::Service>::IncreaseRequestCount();
// Verify client features.
EXPECT_THAT(
request.node().client_features(),
::testing::Contains("envoy.lrs.supports_send_all_clusters"));
// Send initial response.
LoadStatsResponse response;
if (parent_->send_all_clusters_) {
response.set_send_all_clusters(true);
} else {
for (const std::string& cluster_name : parent_->cluster_names_) {
response.add_clusters(cluster_name);
}
using LoadStatsRequest = ::envoy::service::load_stats::v3::LoadStatsRequest;
using LoadStatsResponse = ::envoy::service::load_stats::v3::LoadStatsResponse;
using Stream = ServerReaderWriter<LoadStatsResponse, LoadStatsRequest>;
Status StreamLoadStats(ServerContext* /*context*/, Stream* stream) override {
gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats starts", this);
EXPECT_GT(client_load_reporting_interval_seconds_, 0);
// Take a reference of the LrsServiceImpl object, reference will go
// out of scope after this method exits.
std::shared_ptr<LrsServiceImpl> lrs_service_impl = shared_from_this();
// Read initial request.
LoadStatsRequest request;
if (stream->Read(&request)) {
IncreaseRequestCount();
// Verify client features.
EXPECT_THAT(request.node().client_features(),
::testing::Contains("envoy.lrs.supports_send_all_clusters"));
// Send initial response.
LoadStatsResponse response;
if (send_all_clusters_) {
response.set_send_all_clusters(true);
} else {
for (const std::string& cluster_name : cluster_names_) {
response.add_clusters(cluster_name);
}
response.mutable_load_reporting_interval()->set_seconds(
parent_->client_load_reporting_interval_seconds_ *
grpc_test_slowdown_factor());
stream->Write(response);
CountedService<typename RpcApi::Service>::IncreaseResponseCount();
// Wait for report.
request.Clear();
while (stream->Read(&request)) {
gpr_log(GPR_INFO, "LRS[%p]: received client load report message: %s",
this, request.DebugString().c_str());
std::vector<ClientStats> stats;
for (const auto& cluster_stats : request.cluster_stats()) {
stats.emplace_back(cluster_stats);
}
grpc_core::MutexLock lock(&parent_->load_report_mu_);
parent_->result_queue_.emplace_back(std::move(stats));
if (parent_->load_report_cond_ != nullptr) {
parent_->load_report_cond_->Signal();
}
}
response.mutable_load_reporting_interval()->set_seconds(
client_load_reporting_interval_seconds_ *
grpc_test_slowdown_factor());
stream->Write(response);
IncreaseResponseCount();
// Wait for report.
request.Clear();
while (stream->Read(&request)) {
gpr_log(GPR_INFO, "LRS[%p]: received client load report message: %s",
this, request.DebugString().c_str());
std::vector<ClientStats> stats;
for (const auto& cluster_stats : request.cluster_stats()) {
stats.emplace_back(cluster_stats);
}
// Wait until notified done.
grpc_core::MutexLock lock(&parent_->lrs_mu_);
while (!parent_->lrs_done_) {
parent_->lrs_cv_.Wait(&parent_->lrs_mu_);
grpc_core::MutexLock lock(&load_report_mu_);
result_queue_.emplace_back(std::move(stats));
if (load_report_cond_ != nullptr) {
load_report_cond_->Signal();
}
}
gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats done", this);
return Status::OK;
// Wait until notified done.
grpc_core::MutexLock lock(&lrs_mu_);
while (!lrs_done_) {
lrs_cv_.Wait(&lrs_mu_);
}
}
private:
LrsServiceImpl* parent_;
};
RpcService<::envoy::service::load_stats::v2::LoadReportingService,
::envoy::service::load_stats::v2::LoadStatsRequest,
::envoy::service::load_stats::v2::LoadStatsResponse>
v2_rpc_service_;
RpcService<::envoy::service::load_stats::v3::LoadReportingService,
::envoy::service::load_stats::v3::LoadStatsRequest,
::envoy::service::load_stats::v3::LoadStatsResponse>
v3_rpc_service_;
gpr_log(GPR_INFO, "LRS[%p]: StreamLoadStats done", this);
return Status::OK;
}
const int client_load_reporting_interval_seconds_;
bool send_all_clusters_ = false;

@ -1886,7 +1886,6 @@ src/core/ext/xds/xds_lb_policy_registry.cc \
src/core/ext/xds/xds_lb_policy_registry.h \
src/core/ext/xds/xds_listener.cc \
src/core/ext/xds/xds_listener.h \
src/core/ext/xds/xds_resource_type.cc \
src/core/ext/xds/xds_resource_type.h \
src/core/ext/xds/xds_resource_type_impl.h \
src/core/ext/xds/xds_route_config.cc \

@ -1672,7 +1672,6 @@ src/core/ext/xds/xds_lb_policy_registry.cc \
src/core/ext/xds/xds_lb_policy_registry.h \
src/core/ext/xds/xds_listener.cc \
src/core/ext/xds/xds_listener.h \
src/core/ext/xds/xds_resource_type.cc \
src/core/ext/xds/xds_resource_type.h \
src/core/ext/xds/xds_resource_type_impl.h \
src/core/ext/xds/xds_route_config.cc \

Loading…
Cancel
Save