@@ -78,23 +78,67 @@ void Utility::checkFilesystemSubscriptionBackingPath(const std::string& path) {
7878 }
7979}
8080
81- void Utility::checkApiConfigSourceSubscriptionBackingCluster (
82- const Upstream::ClusterManager::ClusterInfoMap& clusters,
81+ void Utility::checkApiConfigSourceNames (
8382 const envoy::api::v2::core::ApiConfigSource& api_config_source) {
84- if (api_config_source.cluster_names ().size () != 1 ) {
85- // TODO(htuch): Add support for multiple clusters, #1170.
86- throw EnvoyException (
87- " envoy::api::v2::core::ConfigSource must have a singleton cluster name specified" );
83+ const bool is_grpc =
84+ (api_config_source.api_type () == envoy::api::v2::core::ApiConfigSource::GRPC);
85+
86+ if (is_grpc) {
87+ if (api_config_source.cluster_names ().size () != 0 ) {
88+ throw EnvoyException (
89+ " envoy::api::v2::core::ConfigSource::GRPC must not have a cluster name specified" );
90+ }
91+ if (api_config_source.grpc_services ().size () != 1 ) {
92+ throw EnvoyException (
93+ " envoy::api::v2::core::ConfigSource::GRPC must have a single gRPC service specified" );
94+ }
95+ } else {
96+ if (api_config_source.grpc_services ().size () != 0 ) {
97+ throw EnvoyException (" envoy::api::v2::core::ConfigSource, if not of type gRPC, must not have "
98+ " a gRPC service specified" );
99+ }
100+ if (api_config_source.cluster_names ().size () != 1 ) {
101+ throw EnvoyException (
102+ " envoy::api::v2::core::ConfigSource must have a singleton cluster name specified" );
103+ }
88104 }
105+ }
89106
90- const auto & cluster_name = api_config_source.cluster_names ()[0 ];
91- const auto & it = clusters.find (cluster_name);
92- if (it == clusters.end () || it->second .get ().info ()->addedViaApi () ||
93- it->second .get ().info ()->type () == envoy::api::v2::Cluster::EDS) {
94- throw EnvoyException (fmt::format (
95- " envoy::api::v2::core::ConfigSource must have a statically "
96- " defined non-EDS cluster: '{}' does not exist, was added via api, or is an EDS cluster" ,
97- cluster_name));
107+ void Utility::checkApiConfigSourceSubscriptionBackingCluster (
108+ const Upstream::ClusterManager::ClusterInfoMap& clusters,
109+ const envoy::api::v2::core::ApiConfigSource& api_config_source) {
110+ Utility::checkApiConfigSourceNames (api_config_source);
111+
112+ const bool is_grpc =
113+ (api_config_source.api_type () == envoy::api::v2::core::ApiConfigSource::GRPC);
114+
115+ // We ought to validate the cluster name if and only if there is a cluster name.
116+ if (is_grpc) {
117+ // Some ApiConfigSources of type GRPC won't have a cluster name, such as if
118+ // they've been configured with google_grpc.
119+ if (api_config_source.grpc_services ()[0 ].has_envoy_grpc ()) {
120+ const std::string& cluster_name =
121+ api_config_source.grpc_services ()[0 ].envoy_grpc ().cluster_name ();
122+ const auto & it = clusters.find (cluster_name);
123+ if (it == clusters.end () || it->second .get ().info ()->addedViaApi () ||
124+ it->second .get ().info ()->type () == envoy::api::v2::Cluster::EDS) {
125+ throw EnvoyException (fmt::format (
126+ " envoy::api::v2::core::ConfigSource must have a statically "
127+ " defined non-EDS cluster: '{}' does not exist, was added via api, or is an EDS cluster" ,
128+ cluster_name));
129+ }
130+ }
131+ } else {
132+ // All ApiConfigSources of type REST and REST_LEGACY should have cluster_names.
133+ const std::string& cluster_name = api_config_source.cluster_names ()[0 ];
134+ const auto & it = clusters.find (cluster_name);
135+ if (it == clusters.end () || it->second .get ().info ()->addedViaApi () ||
136+ it->second .get ().info ()->type () == envoy::api::v2::Cluster::EDS) {
137+ throw EnvoyException (fmt::format (
138+ " envoy::api::v2::core::ConfigSource must have a statically "
139+ " defined non-EDS cluster: '{}' does not exist, was added via api, or is an EDS cluster" ,
140+ cluster_name));
141+ }
98142 }
99143}
100144
@@ -161,36 +205,13 @@ void Utility::checkObjNameLength(const std::string& error_prefix, const std::str
161205 }
162206}
163207
164- Grpc::AsyncClientFactoryPtr
165- Utility::factoryForApiConfigSource (Grpc::AsyncClientManager& async_client_manager,
166- const envoy::api::v2::core::ApiConfigSource& api_config_source,
167- Stats::Scope& scope) {
168- ASSERT (api_config_source.api_type () == envoy::api::v2::core::ApiConfigSource::GRPC);
169- envoy::api::v2::core::GrpcService grpc_service;
170- if (api_config_source.cluster_names ().empty ()) {
171- if (api_config_source.grpc_services ().empty ()) {
172- throw EnvoyException (
173- fmt::format (" Missing gRPC services in envoy::api::v2::core::ApiConfigSource: {}" ,
174- api_config_source.DebugString ()));
175- }
176- // TODO(htuch): Implement multiple gRPC services.
177- if (api_config_source.grpc_services ().size () != 1 ) {
178- throw EnvoyException (fmt::format (" Only singleton gRPC service lists supported in "
179- " envoy::api::v2::core::ApiConfigSource: {}" ,
180- api_config_source.DebugString ()));
181- }
182- grpc_service.MergeFrom (api_config_source.grpc_services (0 ));
183- } else {
184- // TODO(htuch): cluster_names is deprecated, remove after 1.6.0.
185- if (api_config_source.cluster_names ().size () != 1 ) {
186- throw EnvoyException (fmt::format (" Only singleton cluster name lists supported in "
187- " envoy::api::v2::core::ApiConfigSource: {}" ,
188- api_config_source.DebugString ()));
189- }
190- grpc_service.mutable_envoy_grpc ()->set_cluster_name (api_config_source.cluster_names (0 ));
191- }
208+ Grpc::AsyncClientFactoryPtr Utility::factoryForGrpcApiConfigSource (
209+ Grpc::AsyncClientManager& async_client_manager,
210+ const envoy::api::v2::core::ApiConfigSource& api_config_source, Stats::Scope& scope) {
211+ Utility::checkApiConfigSourceNames (api_config_source);
192212
193- return async_client_manager.factoryForGrpcService (grpc_service, scope, false );
213+ return async_client_manager.factoryForGrpcService (api_config_source.grpc_services (0 ), scope,
214+ false );
194215}
195216
196217} // namespace Config
0 commit comments