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