| // 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. |
| // |
| |
| #ifndef GRPC_TEST_CPP_END2END_XDS_XDS_UTILS_H |
| #define GRPC_TEST_CPP_END2END_XDS_XDS_UTILS_H |
| |
| #include <string> |
| #include <vector> |
| |
| #include "absl/strings/string_view.h" |
| |
| #include "src/proto/grpc/testing/xds/v3/cluster.pb.h" |
| #include "src/proto/grpc/testing/xds/v3/endpoint.pb.h" |
| #include "src/proto/grpc/testing/xds/v3/http_connection_manager.pb.h" |
| #include "src/proto/grpc/testing/xds/v3/listener.pb.h" |
| #include "src/proto/grpc/testing/xds/v3/route.pb.h" |
| #include "test/cpp/end2end/xds/xds_server.h" |
| |
| namespace grpc { |
| namespace testing { |
| |
| // A builder for the xDS bootstrap config. |
| class XdsBootstrapBuilder { |
| public: |
| XdsBootstrapBuilder() {} |
| XdsBootstrapBuilder& SetIgnoreResourceDeletion() { |
| ignore_resource_deletion_ = true; |
| return *this; |
| } |
| XdsBootstrapBuilder& SetServers(absl::Span<const absl::string_view> servers) { |
| servers_ = std::vector<std::string>(servers.begin(), servers.end()); |
| return *this; |
| } |
| XdsBootstrapBuilder& SetXdsChannelCredentials(const std::string& type) { |
| xds_channel_creds_type_ = type; |
| return *this; |
| } |
| XdsBootstrapBuilder& SetClientDefaultListenerResourceNameTemplate( |
| const std::string& client_default_listener_resource_name_template) { |
| client_default_listener_resource_name_template_ = |
| client_default_listener_resource_name_template; |
| return *this; |
| } |
| XdsBootstrapBuilder& AddCertificateProviderPlugin( |
| const std::string& key, const std::string& name, |
| const std::string& plugin_config = "") { |
| plugins_[key] = {name, plugin_config}; |
| return *this; |
| } |
| XdsBootstrapBuilder& AddAuthority( |
| const std::string& authority, const std::string& server = "", |
| const std::string& client_listener_resource_name_template = "") { |
| return AddAuthority(authority, |
| server.empty() ? std::vector<std::string>() |
| : std::vector<std::string>({server}), |
| client_listener_resource_name_template); |
| } |
| XdsBootstrapBuilder& AddAuthority( |
| const std::string& authority, const std::vector<std::string>& servers, |
| const std::string& client_listener_resource_name_template = "") { |
| authorities_[authority] = {servers, client_listener_resource_name_template}; |
| return *this; |
| } |
| XdsBootstrapBuilder& SetServerListenerResourceNameTemplate( |
| const std::string& server_listener_resource_name_template = "") { |
| server_listener_resource_name_template_ = |
| server_listener_resource_name_template; |
| return *this; |
| } |
| |
| std::string Build(); |
| |
| private: |
| struct PluginInfo { |
| std::string name; |
| std::string plugin_config; |
| }; |
| struct AuthorityInfo { |
| std::vector<std::string> servers; |
| std::string client_listener_resource_name_template; |
| }; |
| |
| std::string MakeXdsServersText(absl::Span<const std::string> server_uris); |
| std::string MakeNodeText(); |
| std::string MakeCertificateProviderText(); |
| std::string MakeAuthorityText(); |
| |
| bool ignore_resource_deletion_ = false; |
| std::vector<std::string> servers_; |
| std::string xds_channel_creds_type_ = "fake"; |
| std::string client_default_listener_resource_name_template_; |
| std::map<std::string /*key*/, PluginInfo> plugins_; |
| std::map<std::string /*authority_name*/, AuthorityInfo> authorities_; |
| std::string server_listener_resource_name_template_ = |
| "grpc/server?xds.resource.listening_address=%s"; |
| }; |
| |
| // Utilities for constructing xDS resources. |
| class XdsResourceUtils { |
| public: |
| using HttpConnectionManager = envoy::extensions::filters::network:: |
| http_connection_manager::v3::HttpConnectionManager; |
| using Listener = envoy::config::listener::v3::Listener; |
| using RouteConfiguration = envoy::config::route::v3::RouteConfiguration; |
| using Cluster = envoy::config::cluster::v3::Cluster; |
| using ClusterLoadAssignment = |
| envoy::config::endpoint::v3::ClusterLoadAssignment; |
| |
| // Interface for accessing HttpConnectionManager config in Listener. |
| class HcmAccessor { |
| public: |
| virtual ~HcmAccessor() = default; |
| virtual HttpConnectionManager Unpack(const Listener& listener) const = 0; |
| virtual void Pack(const HttpConnectionManager& hcm, |
| Listener* listener) const = 0; |
| }; |
| |
| // Client-side impl. |
| class ClientHcmAccessor : public HcmAccessor { |
| public: |
| HttpConnectionManager Unpack(const Listener& listener) const override; |
| void Pack(const HttpConnectionManager& hcm, |
| Listener* listener) const override; |
| }; |
| |
| // Server-side impl. |
| class ServerHcmAccessor : public HcmAccessor { |
| public: |
| HttpConnectionManager Unpack(const Listener& listener) const override; |
| void Pack(const HttpConnectionManager& hcm, |
| Listener* listener) const override; |
| }; |
| |
| // Default values for locality fields. |
| static const char kDefaultLocalityRegion[]; |
| static const char kDefaultLocalityZone[]; |
| static const uint32_t kDefaultLocalityWeight = 3; |
| static const int kDefaultLocalityPriority = 0; |
| |
| // Default resource names. |
| static const char kServerName[]; |
| static const char kDefaultRouteConfigurationName[]; |
| static const char kDefaultClusterName[]; |
| static const char kDefaultEdsServiceName[]; |
| static const char kDefaultServerRouteConfigurationName[]; |
| |
| // Returns default xDS resources. |
| static Listener DefaultListener(); |
| static RouteConfiguration DefaultRouteConfig(); |
| static Cluster DefaultCluster(); |
| static Listener DefaultServerListener(); |
| static RouteConfiguration DefaultServerRouteConfig(); |
| static HttpConnectionManager DefaultHcm(); |
| |
| // Returns the name of the server-side xDS Listener resource for a |
| // backend on the specified port. |
| static std::string GetServerListenerName(int port); |
| |
| // Returns a copy of listener_template with the server-side resource |
| // name and the port in the socket address populated. |
| static Listener PopulateServerListenerNameAndPort( |
| const Listener& listener_template, int port); |
| |
| // Sets the Listener and RouteConfiguration resource on the specified |
| // balancer. If RDS is in use, they will be set as separate resources; |
| // otherwise, the RouteConfig will be inlined into the Listener. |
| static void SetListenerAndRouteConfiguration( |
| AdsServiceImpl* ads_service, Listener listener, |
| const RouteConfiguration& route_config, bool use_rds = false, |
| const HcmAccessor& hcm_accessor = ClientHcmAccessor()); |
| |
| // A convenient wrapper for setting the Listener and |
| // RouteConfiguration resources on the server side. |
| static void SetServerListenerNameAndRouteConfiguration( |
| AdsServiceImpl* ads_service, Listener listener, int port, |
| const RouteConfiguration& route_config, bool use_rds = false) { |
| SetListenerAndRouteConfiguration( |
| ads_service, PopulateServerListenerNameAndPort(listener, port), |
| route_config, use_rds, ServerHcmAccessor()); |
| } |
| |
| // Sets the RouteConfiguration resource on the specified balancer. |
| // If RDS is in use, it will be set directly as an independent |
| // resource; otherwise, it will be inlined into a Listener resource |
| // (either listener_to_copy, or if that is null, default_listener_). |
| static void SetRouteConfiguration(AdsServiceImpl* ads_service, |
| const RouteConfiguration& route_config, |
| bool use_rds = false, |
| const Listener* listener_to_copy = nullptr); |
| |
| // Returns a string representing the locality with the specified sub_zone. |
| static std::string LocalityNameString(absl::string_view sub_zone); |
| |
| // Arguments for constructing an EDS resource. |
| struct EdsResourceArgs { |
| // An individual endpoint for a backend running on a specified port. |
| struct Endpoint { |
| explicit Endpoint(int port, |
| ::envoy::config::core::v3::HealthStatus health_status = |
| ::envoy::config::core::v3::HealthStatus::UNKNOWN, |
| int lb_weight = 1, |
| std::vector<int> additional_ports = {}) |
| : port(port), |
| health_status(health_status), |
| lb_weight(lb_weight), |
| additional_ports(std::move(additional_ports)) {} |
| |
| int port; |
| ::envoy::config::core::v3::HealthStatus health_status; |
| int lb_weight; |
| std::vector<int> additional_ports; |
| }; |
| |
| // A locality. |
| struct Locality { |
| Locality(std::string sub_zone, std::vector<Endpoint> endpoints, |
| uint32_t lb_weight = kDefaultLocalityWeight, |
| int priority = kDefaultLocalityPriority) |
| : sub_zone(std::move(sub_zone)), |
| endpoints(std::move(endpoints)), |
| lb_weight(lb_weight), |
| priority(priority) {} |
| |
| const std::string sub_zone; |
| std::vector<Endpoint> endpoints; |
| uint32_t lb_weight; |
| int priority; |
| }; |
| |
| EdsResourceArgs() = default; |
| explicit EdsResourceArgs(std::vector<Locality> locality_list) |
| : locality_list(std::move(locality_list)) {} |
| |
| std::vector<Locality> locality_list; |
| std::map<std::string, uint32_t> drop_categories; |
| ::envoy::type::v3::FractionalPercent::DenominatorType drop_denominator = |
| ::envoy::type::v3::FractionalPercent::MILLION; |
| }; |
| |
| // Constructs an EDS resource. |
| static ClusterLoadAssignment BuildEdsResource( |
| const EdsResourceArgs& args, |
| absl::string_view eds_service_name = kDefaultEdsServiceName); |
| }; |
| |
| } // namespace testing |
| } // namespace grpc |
| |
| #endif // GRPC_TEST_CPP_END2END_XDS_XDS_UTILS_H |