xref: /aosp_15_r20/external/grpc-grpc/test/cpp/end2end/xds/xds_utils.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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