• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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