Line data Source code
1 : #include "source/common/config/subscription_factory_impl.h"
2 :
3 : #include "envoy/config/core/v3/config_source.pb.h"
4 : #include "envoy/config/xds_resources_delegate.h"
5 :
6 : #include "source/common/config/custom_config_validators_impl.h"
7 : #include "source/common/config/type_to_endpoint.h"
8 : #include "source/common/config/utility.h"
9 : #include "source/common/config/xds_resource.h"
10 : #include "source/common/http/utility.h"
11 : #include "source/common/protobuf/protobuf.h"
12 : #include "source/common/protobuf/utility.h"
13 :
14 : namespace Envoy {
15 : namespace Config {
16 :
17 : SubscriptionFactoryImpl::SubscriptionFactoryImpl(
18 : const LocalInfo::LocalInfo& local_info, Event::Dispatcher& dispatcher,
19 : Upstream::ClusterManager& cm, ProtobufMessage::ValidationVisitor& validation_visitor,
20 : Api::Api& api, const Server::Instance& server,
21 : XdsResourcesDelegateOptRef xds_resources_delegate, XdsConfigTrackerOptRef xds_config_tracker)
22 : : local_info_(local_info), dispatcher_(dispatcher), cm_(cm),
23 : validation_visitor_(validation_visitor), api_(api), server_(server),
24 131 : xds_resources_delegate_(xds_resources_delegate), xds_config_tracker_(xds_config_tracker) {}
25 :
26 : SubscriptionPtr SubscriptionFactoryImpl::subscriptionFromConfigSource(
27 : const envoy::config::core::v3::ConfigSource& config, absl::string_view type_url,
28 : Stats::Scope& scope, SubscriptionCallbacks& callbacks,
29 205 : OpaqueResourceDecoderSharedPtr resource_decoder, const SubscriptionOptions& options) {
30 205 : Config::Utility::checkLocalInfo(type_url, local_info_);
31 205 : SubscriptionStats stats = Utility::generateStats(scope);
32 :
33 205 : std::string subscription_type = "";
34 205 : ConfigSubscriptionFactory::SubscriptionData data{local_info_,
35 205 : dispatcher_,
36 205 : cm_,
37 205 : validation_visitor_,
38 205 : api_,
39 205 : server_,
40 205 : xds_resources_delegate_,
41 205 : xds_config_tracker_,
42 205 : config,
43 205 : type_url,
44 205 : scope,
45 205 : callbacks,
46 205 : resource_decoder,
47 205 : options,
48 205 : absl::nullopt,
49 205 : stats};
50 :
51 205 : switch (config.config_source_specifier_case()) {
52 0 : case envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kPath: {
53 0 : Utility::checkFilesystemSubscriptionBackingPath(config.path(), api_);
54 0 : subscription_type = "envoy.config_subscription.filesystem";
55 0 : break;
56 0 : }
57 70 : case envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kPathConfigSource: {
58 70 : Utility::checkFilesystemSubscriptionBackingPath(config.path_config_source().path(), api_);
59 70 : subscription_type = "envoy.config_subscription.filesystem";
60 70 : break;
61 0 : }
62 0 : case envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kApiConfigSource: {
63 0 : const envoy::config::core::v3::ApiConfigSource& api_config_source = config.api_config_source();
64 0 : Utility::checkApiConfigSourceSubscriptionBackingCluster(cm_.primaryClusters(),
65 0 : api_config_source);
66 0 : THROW_IF_NOT_OK(Utility::checkTransportVersion(api_config_source));
67 0 : switch (api_config_source.api_type()) {
68 0 : PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
69 0 : case envoy::config::core::v3::ApiConfigSource::AGGREGATED_GRPC:
70 0 : throwEnvoyExceptionOrPanic("Unsupported config source AGGREGATED_GRPC");
71 0 : case envoy::config::core::v3::ApiConfigSource::AGGREGATED_DELTA_GRPC:
72 0 : throwEnvoyExceptionOrPanic("Unsupported config source AGGREGATED_DELTA_GRPC");
73 0 : case envoy::config::core::v3::ApiConfigSource::DEPRECATED_AND_UNAVAILABLE_DO_NOT_USE:
74 0 : throwEnvoyExceptionOrPanic(
75 0 : "REST_LEGACY no longer a supported ApiConfigSource. "
76 0 : "Please specify an explicit supported api_type in the following config:\n" +
77 0 : config.DebugString());
78 0 : case envoy::config::core::v3::ApiConfigSource::REST:
79 0 : subscription_type = "envoy.config_subscription.rest";
80 0 : break;
81 0 : case envoy::config::core::v3::ApiConfigSource::GRPC:
82 0 : subscription_type = "envoy.config_subscription.grpc";
83 0 : break;
84 0 : case envoy::config::core::v3::ApiConfigSource::DELTA_GRPC:
85 0 : subscription_type = "envoy.config_subscription.delta_grpc";
86 0 : break;
87 0 : }
88 0 : if (subscription_type.empty()) {
89 0 : throwEnvoyExceptionOrPanic("Invalid API config source API type");
90 0 : }
91 0 : break;
92 0 : }
93 135 : case envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kAds: {
94 135 : subscription_type = "envoy.config_subscription.ads";
95 135 : break;
96 0 : }
97 0 : default:
98 0 : throwEnvoyExceptionOrPanic(
99 205 : "Missing config source specifier in envoy::config::core::v3::ConfigSource");
100 205 : }
101 205 : ConfigSubscriptionFactory* factory =
102 205 : Registry::FactoryRegistry<ConfigSubscriptionFactory>::getFactory(subscription_type);
103 205 : if (factory == nullptr) {
104 0 : throwEnvoyExceptionOrPanic(fmt::format(
105 0 : "Didn't find a registered config subscription factory implementation for name: '{}'",
106 0 : subscription_type));
107 0 : }
108 205 : return factory->create(data);
109 205 : }
110 :
111 : SubscriptionPtr createFromFactoryOrThrow(ConfigSubscriptionFactory::SubscriptionData& data,
112 0 : absl::string_view subscription_type) {
113 0 : ConfigSubscriptionFactory* factory =
114 0 : Registry::FactoryRegistry<ConfigSubscriptionFactory>::getFactory(subscription_type);
115 0 : if (factory == nullptr) {
116 0 : throwEnvoyExceptionOrPanic(fmt::format(
117 0 : "Didn't find a registered config subscription factory implementation for name: '{}'",
118 0 : subscription_type));
119 0 : }
120 0 : return factory->create(data);
121 0 : }
122 :
123 : SubscriptionPtr SubscriptionFactoryImpl::collectionSubscriptionFromUrl(
124 : const xds::core::v3::ResourceLocator& collection_locator,
125 : const envoy::config::core::v3::ConfigSource& config, absl::string_view resource_type,
126 : Stats::Scope& scope, SubscriptionCallbacks& callbacks,
127 0 : OpaqueResourceDecoderSharedPtr resource_decoder) {
128 0 : SubscriptionStats stats = Utility::generateStats(scope);
129 0 : SubscriptionOptions options;
130 0 : envoy::config::core::v3::ConfigSource factory_config = config;
131 0 : ConfigSubscriptionFactory::SubscriptionData data{local_info_,
132 0 : dispatcher_,
133 0 : cm_,
134 0 : validation_visitor_,
135 0 : api_,
136 0 : server_,
137 0 : xds_resources_delegate_,
138 0 : xds_config_tracker_,
139 0 : factory_config,
140 0 : "",
141 0 : scope,
142 0 : callbacks,
143 0 : resource_decoder,
144 0 : options,
145 0 : {collection_locator},
146 0 : stats};
147 0 : switch (collection_locator.scheme()) {
148 0 : case xds::core::v3::ResourceLocator::FILE: {
149 0 : const std::string path = Http::Utility::localPathFromFilePath(collection_locator.id());
150 0 : Utility::checkFilesystemSubscriptionBackingPath(path, api_);
151 0 : factory_config.set_path(path);
152 0 : return createFromFactoryOrThrow(data, "envoy.config_subscription.filesystem_collection");
153 0 : }
154 0 : case xds::core::v3::ResourceLocator::XDSTP: {
155 0 : if (resource_type != collection_locator.resource_type()) {
156 0 : throwEnvoyExceptionOrPanic(
157 0 : fmt::format("xdstp:// type does not match {} in {}", resource_type,
158 0 : Config::XdsResourceIdentifier::encodeUrl(collection_locator)));
159 0 : }
160 0 : switch (config.config_source_specifier_case()) {
161 0 : case envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kApiConfigSource: {
162 0 : const envoy::config::core::v3::ApiConfigSource& api_config_source =
163 0 : config.api_config_source();
164 0 : Utility::checkApiConfigSourceSubscriptionBackingCluster(cm_.primaryClusters(),
165 0 : api_config_source);
166 : // All Envoy collections currently are xDS resource graph roots and require node context
167 : // parameters.
168 0 : options.add_xdstp_node_context_params_ = true;
169 0 : switch (api_config_source.api_type()) {
170 0 : case envoy::config::core::v3::ApiConfigSource::DELTA_GRPC: {
171 0 : std::string type_url = TypeUtil::descriptorFullNameToTypeUrl(resource_type);
172 0 : data.type_url_ = type_url;
173 0 : return createFromFactoryOrThrow(data, "envoy.config_subscription.delta_grpc_collection");
174 0 : }
175 0 : case envoy::config::core::v3::ApiConfigSource::AGGREGATED_GRPC:
176 0 : FALLTHRU;
177 0 : case envoy::config::core::v3::ApiConfigSource::AGGREGATED_DELTA_GRPC: {
178 0 : return createFromFactoryOrThrow(data,
179 0 : "envoy.config_subscription.aggregated_grpc_collection");
180 0 : }
181 0 : default:
182 0 : throwEnvoyExceptionOrPanic(fmt::format("Unknown xdstp:// transport API type in {}",
183 0 : api_config_source.DebugString()));
184 0 : }
185 0 : }
186 0 : case envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kAds: {
187 : // TODO(adisuissa): verify that the ADS is set up in delta-xDS mode.
188 : // All Envoy collections currently are xDS resource graph roots and require node context
189 : // parameters.
190 0 : options.add_xdstp_node_context_params_ = true;
191 0 : return createFromFactoryOrThrow(data, "envoy.config_subscription.ads_collection");
192 0 : }
193 0 : default:
194 0 : throwEnvoyExceptionOrPanic(
195 0 : "Missing or not supported config source specifier in "
196 0 : "envoy::config::core::v3::ConfigSource for a collection. Only ADS and "
197 0 : "gRPC in delta-xDS mode are supported.");
198 0 : }
199 0 : }
200 0 : default:
201 : // TODO(htuch): Implement HTTP semantics for collection ResourceLocators.
202 0 : throwEnvoyExceptionOrPanic("Unsupported code path");
203 0 : }
204 0 : }
205 :
206 : } // namespace Config
207 : } // namespace Envoy
|