1 // Copyright 2017 gRPC authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 16 #ifndef GRPC_TEST_CPP_END2END_XDS_XDS_UTILS_H 17 #define GRPC_TEST_CPP_END2END_XDS_XDS_UTILS_H 18 19 #include <string> 20 #include <vector> 21 22 #include "absl/strings/string_view.h" 23 24 #include "src/proto/grpc/testing/xds/v3/cluster.pb.h" 25 #include "src/proto/grpc/testing/xds/v3/endpoint.pb.h" 26 #include "src/proto/grpc/testing/xds/v3/http_connection_manager.pb.h" 27 #include "src/proto/grpc/testing/xds/v3/listener.pb.h" 28 #include "src/proto/grpc/testing/xds/v3/route.pb.h" 29 #include "test/cpp/end2end/xds/xds_server.h" 30 31 namespace grpc { 32 namespace testing { 33 34 // A builder for the xDS bootstrap config. 35 class XdsBootstrapBuilder { 36 public: XdsBootstrapBuilder()37 XdsBootstrapBuilder() {} SetIgnoreResourceDeletion()38 XdsBootstrapBuilder& SetIgnoreResourceDeletion() { 39 ignore_resource_deletion_ = true; 40 return *this; 41 } SetServers(absl::Span<const absl::string_view> servers)42 XdsBootstrapBuilder& SetServers(absl::Span<const absl::string_view> servers) { 43 servers_ = std::vector<std::string>(servers.begin(), servers.end()); 44 return *this; 45 } SetXdsChannelCredentials(const std::string & type)46 XdsBootstrapBuilder& SetXdsChannelCredentials(const std::string& type) { 47 xds_channel_creds_type_ = type; 48 return *this; 49 } SetClientDefaultListenerResourceNameTemplate(const std::string & client_default_listener_resource_name_template)50 XdsBootstrapBuilder& SetClientDefaultListenerResourceNameTemplate( 51 const std::string& client_default_listener_resource_name_template) { 52 client_default_listener_resource_name_template_ = 53 client_default_listener_resource_name_template; 54 return *this; 55 } 56 XdsBootstrapBuilder& AddCertificateProviderPlugin( 57 const std::string& key, const std::string& name, 58 const std::string& plugin_config = "") { 59 plugins_[key] = {name, plugin_config}; 60 return *this; 61 } 62 XdsBootstrapBuilder& AddAuthority( 63 const std::string& authority, const std::string& server = "", 64 const std::string& client_listener_resource_name_template = "") { 65 return AddAuthority(authority, 66 server.empty() ? std::vector<std::string>() 67 : std::vector<std::string>({server}), 68 client_listener_resource_name_template); 69 } 70 XdsBootstrapBuilder& AddAuthority( 71 const std::string& authority, const std::vector<std::string>& servers, 72 const std::string& client_listener_resource_name_template = "") { 73 authorities_[authority] = {servers, client_listener_resource_name_template}; 74 return *this; 75 } 76 XdsBootstrapBuilder& SetServerListenerResourceNameTemplate( 77 const std::string& server_listener_resource_name_template = "") { 78 server_listener_resource_name_template_ = 79 server_listener_resource_name_template; 80 return *this; 81 } 82 83 std::string Build(); 84 85 private: 86 struct PluginInfo { 87 std::string name; 88 std::string plugin_config; 89 }; 90 struct AuthorityInfo { 91 std::vector<std::string> servers; 92 std::string client_listener_resource_name_template; 93 }; 94 95 std::string MakeXdsServersText(absl::Span<const std::string> server_uris); 96 std::string MakeNodeText(); 97 std::string MakeCertificateProviderText(); 98 std::string MakeAuthorityText(); 99 100 bool ignore_resource_deletion_ = false; 101 std::vector<std::string> servers_; 102 std::string xds_channel_creds_type_ = "fake"; 103 std::string client_default_listener_resource_name_template_; 104 std::map<std::string /*key*/, PluginInfo> plugins_; 105 std::map<std::string /*authority_name*/, AuthorityInfo> authorities_; 106 std::string server_listener_resource_name_template_ = 107 "grpc/server?xds.resource.listening_address=%s"; 108 }; 109 110 // Utilities for constructing xDS resources. 111 class XdsResourceUtils { 112 public: 113 using HttpConnectionManager = envoy::extensions::filters::network:: 114 http_connection_manager::v3::HttpConnectionManager; 115 using Listener = envoy::config::listener::v3::Listener; 116 using RouteConfiguration = envoy::config::route::v3::RouteConfiguration; 117 using Cluster = envoy::config::cluster::v3::Cluster; 118 using ClusterLoadAssignment = 119 envoy::config::endpoint::v3::ClusterLoadAssignment; 120 121 // Interface for accessing HttpConnectionManager config in Listener. 122 class HcmAccessor { 123 public: 124 virtual ~HcmAccessor() = default; 125 virtual HttpConnectionManager Unpack(const Listener& listener) const = 0; 126 virtual void Pack(const HttpConnectionManager& hcm, 127 Listener* listener) const = 0; 128 }; 129 130 // Client-side impl. 131 class ClientHcmAccessor : public HcmAccessor { 132 public: 133 HttpConnectionManager Unpack(const Listener& listener) const override; 134 void Pack(const HttpConnectionManager& hcm, 135 Listener* listener) const override; 136 }; 137 138 // Server-side impl. 139 class ServerHcmAccessor : public HcmAccessor { 140 public: 141 HttpConnectionManager Unpack(const Listener& listener) const override; 142 void Pack(const HttpConnectionManager& hcm, 143 Listener* listener) const override; 144 }; 145 146 // Default values for locality fields. 147 static const char kDefaultLocalityRegion[]; 148 static const char kDefaultLocalityZone[]; 149 static const uint32_t kDefaultLocalityWeight = 3; 150 static const int kDefaultLocalityPriority = 0; 151 152 // Default resource names. 153 static const char kServerName[]; 154 static const char kDefaultRouteConfigurationName[]; 155 static const char kDefaultClusterName[]; 156 static const char kDefaultEdsServiceName[]; 157 static const char kDefaultServerRouteConfigurationName[]; 158 159 // Returns default xDS resources. 160 static Listener DefaultListener(); 161 static RouteConfiguration DefaultRouteConfig(); 162 static Cluster DefaultCluster(); 163 static Listener DefaultServerListener(); 164 static RouteConfiguration DefaultServerRouteConfig(); 165 static HttpConnectionManager DefaultHcm(); 166 167 // Returns the name of the server-side xDS Listener resource for a 168 // backend on the specified port. 169 static std::string GetServerListenerName(int port); 170 171 // Returns a copy of listener_template with the server-side resource 172 // name and the port in the socket address populated. 173 static Listener PopulateServerListenerNameAndPort( 174 const Listener& listener_template, int port); 175 176 // Sets the Listener and RouteConfiguration resource on the specified 177 // balancer. If RDS is in use, they will be set as separate resources; 178 // otherwise, the RouteConfig will be inlined into the Listener. 179 static void SetListenerAndRouteConfiguration( 180 AdsServiceImpl* ads_service, Listener listener, 181 const RouteConfiguration& route_config, bool use_rds = false, 182 const HcmAccessor& hcm_accessor = ClientHcmAccessor()); 183 184 // A convenient wrapper for setting the Listener and 185 // RouteConfiguration resources on the server side. 186 static void SetServerListenerNameAndRouteConfiguration( 187 AdsServiceImpl* ads_service, Listener listener, int port, 188 const RouteConfiguration& route_config, bool use_rds = false) { 189 SetListenerAndRouteConfiguration( 190 ads_service, PopulateServerListenerNameAndPort(listener, port), 191 route_config, use_rds, ServerHcmAccessor()); 192 } 193 194 // Sets the RouteConfiguration resource on the specified balancer. 195 // If RDS is in use, it will be set directly as an independent 196 // resource; otherwise, it will be inlined into a Listener resource 197 // (either listener_to_copy, or if that is null, default_listener_). 198 static void SetRouteConfiguration(AdsServiceImpl* ads_service, 199 const RouteConfiguration& route_config, 200 bool use_rds = false, 201 const Listener* listener_to_copy = nullptr); 202 203 // Returns a string representing the locality with the specified sub_zone. 204 static std::string LocalityNameString(absl::string_view sub_zone); 205 206 // Arguments for constructing an EDS resource. 207 struct EdsResourceArgs { 208 // An individual endpoint for a backend running on a specified port. 209 struct Endpoint { 210 explicit Endpoint(int port, 211 ::envoy::config::core::v3::HealthStatus health_status = 212 ::envoy::config::core::v3::HealthStatus::UNKNOWN, 213 int lb_weight = 1, 214 std::vector<int> additional_ports = {}) portEdsResourceArgs::Endpoint215 : port(port), 216 health_status(health_status), 217 lb_weight(lb_weight), 218 additional_ports(std::move(additional_ports)) {} 219 220 int port; 221 ::envoy::config::core::v3::HealthStatus health_status; 222 int lb_weight; 223 std::vector<int> additional_ports; 224 }; 225 226 // A locality. 227 struct Locality { 228 Locality(std::string sub_zone, std::vector<Endpoint> endpoints, 229 uint32_t lb_weight = kDefaultLocalityWeight, 230 int priority = kDefaultLocalityPriority) sub_zoneEdsResourceArgs::Locality231 : sub_zone(std::move(sub_zone)), 232 endpoints(std::move(endpoints)), 233 lb_weight(lb_weight), 234 priority(priority) {} 235 236 const std::string sub_zone; 237 std::vector<Endpoint> endpoints; 238 uint32_t lb_weight; 239 int priority; 240 }; 241 242 EdsResourceArgs() = default; EdsResourceArgsEdsResourceArgs243 explicit EdsResourceArgs(std::vector<Locality> locality_list) 244 : locality_list(std::move(locality_list)) {} 245 246 std::vector<Locality> locality_list; 247 std::map<std::string, uint32_t> drop_categories; 248 ::envoy::type::v3::FractionalPercent::DenominatorType drop_denominator = 249 ::envoy::type::v3::FractionalPercent::MILLION; 250 }; 251 252 // Constructs an EDS resource. 253 static ClusterLoadAssignment BuildEdsResource( 254 const EdsResourceArgs& args, 255 absl::string_view eds_service_name = kDefaultEdsServiceName); 256 }; 257 258 } // namespace testing 259 } // namespace grpc 260 261 #endif // GRPC_TEST_CPP_END2END_XDS_XDS_UTILS_H 262