/proc/self/cwd/source/server/configuration_impl.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/server/configuration_impl.h" |
2 | | |
3 | | #include <chrono> |
4 | | #include <list> |
5 | | #include <memory> |
6 | | #include <string> |
7 | | #include <vector> |
8 | | |
9 | | #include "envoy/common/exception.h" |
10 | | #include "envoy/config/bootstrap/v3/bootstrap.pb.h" |
11 | | #include "envoy/config/metrics/v3/stats.pb.h" |
12 | | #include "envoy/config/trace/v3/http_tracer.pb.h" |
13 | | #include "envoy/extensions/access_loggers/file/v3/file.pb.h" |
14 | | #include "envoy/network/connection.h" |
15 | | #include "envoy/runtime/runtime.h" |
16 | | #include "envoy/server/instance.h" |
17 | | #include "envoy/server/tracer_config.h" |
18 | | #include "envoy/ssl/context_manager.h" |
19 | | |
20 | | #include "source/common/access_log/access_log_impl.h" |
21 | | #include "source/common/common/assert.h" |
22 | | #include "source/common/common/utility.h" |
23 | | #include "source/common/config/runtime_utility.h" |
24 | | #include "source/common/config/utility.h" |
25 | | #include "source/common/network/socket_option_factory.h" |
26 | | #include "source/common/protobuf/utility.h" |
27 | | |
28 | | namespace Envoy { |
29 | | namespace Server { |
30 | | namespace Configuration { |
31 | | |
32 | | bool FilterChainUtility::buildFilterChain(Network::FilterManager& filter_manager, |
33 | 2.92k | const Filter::NetworkFilterFactoriesList& factories) { |
34 | 2.92k | for (const auto& filter_config_provider : factories) { |
35 | 2.92k | auto config = filter_config_provider->config(); |
36 | 2.92k | if (!config.has_value()) { |
37 | 0 | return false; |
38 | 0 | } |
39 | | |
40 | 2.92k | Network::FilterFactoryCb& factory = config.value(); |
41 | 2.92k | factory(filter_manager); |
42 | 2.92k | } |
43 | | |
44 | 2.92k | return filter_manager.initializeReadFilters(); |
45 | 2.92k | } |
46 | | |
47 | | bool FilterChainUtility::buildFilterChain(Network::ListenerFilterManager& filter_manager, |
48 | 2.92k | const Filter::ListenerFilterFactoriesList& factories) { |
49 | 2.92k | for (const auto& filter_config_provider : factories) { |
50 | 0 | auto config = filter_config_provider->config(); |
51 | 0 | if (!config.has_value()) { |
52 | 0 | return false; |
53 | 0 | } |
54 | 0 | auto config_value = config.value(); |
55 | 0 | config_value(filter_manager); |
56 | 0 | } |
57 | | |
58 | 2.92k | return true; |
59 | 2.92k | } |
60 | | |
61 | | void FilterChainUtility::buildUdpFilterChain( |
62 | | Network::UdpListenerFilterManager& filter_manager, Network::UdpReadFilterCallbacks& callbacks, |
63 | 0 | const std::vector<Network::UdpListenerFilterFactoryCb>& factories) { |
64 | 0 | for (const Network::UdpListenerFilterFactoryCb& factory : factories) { |
65 | 0 | factory(filter_manager, callbacks); |
66 | 0 | } |
67 | 0 | } |
68 | | |
69 | | bool FilterChainUtility::buildQuicFilterChain( |
70 | | Network::QuicListenerFilterManager& filter_manager, |
71 | 0 | const Filter::QuicListenerFilterFactoriesList& factories) { |
72 | 0 | for (const auto& filter_config_provider : factories) { |
73 | 0 | auto config = filter_config_provider->config(); |
74 | 0 | if (!config.has_value()) { |
75 | 0 | return false; |
76 | 0 | } |
77 | 0 | auto config_value = config.value(); |
78 | 0 | config_value(filter_manager); |
79 | 0 | } |
80 | | |
81 | 0 | return true; |
82 | 0 | } |
83 | | |
84 | | StatsConfigImpl::StatsConfigImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
85 | | absl::Status& status) |
86 | 4.38k | : deferred_stat_options_(bootstrap.deferred_stat_options()) { |
87 | 4.38k | status = absl::OkStatus(); |
88 | 4.38k | if (bootstrap.has_stats_flush_interval() && |
89 | 4.38k | bootstrap.stats_flush_case() != |
90 | 69 | envoy::config::bootstrap::v3::Bootstrap::STATS_FLUSH_NOT_SET) { |
91 | 1 | status = absl::InvalidArgumentError( |
92 | 1 | "Only one of stats_flush_interval or stats_flush_on_admin should be set!"); |
93 | 1 | return; |
94 | 1 | } |
95 | | |
96 | 4.38k | flush_interval_ = |
97 | 4.38k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(bootstrap, stats_flush_interval, 5000)); |
98 | | |
99 | 4.38k | if (bootstrap.stats_flush_case() == envoy::config::bootstrap::v3::Bootstrap::kStatsFlushOnAdmin) { |
100 | 82 | flush_on_admin_ = bootstrap.stats_flush_on_admin(); |
101 | 82 | } |
102 | 4.38k | } |
103 | | |
104 | | absl::Status MainImpl::initialize(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
105 | | Instance& server, |
106 | 4.40k | Upstream::ClusterManagerFactory& cluster_manager_factory) { |
107 | | // In order to support dynamic configuration of tracing providers, |
108 | | // a former server-wide Tracer singleton has been replaced by |
109 | | // an Tracer instance per "envoy.filters.network.http_connection_manager" filter. |
110 | | // Tracing configuration as part of bootstrap config is still supported, |
111 | | // however, it's become mandatory to process it prior to static Listeners. |
112 | | // Otherwise, static Listeners will be configured in assumption that |
113 | | // tracing configuration is missing from the bootstrap config. |
114 | 4.40k | initializeTracers(bootstrap.tracing(), server); |
115 | | |
116 | | // stats_config_ should be set before creating the ClusterManagers so that it is available |
117 | | // from the ServerFactoryContext when creating the static clusters and stats sinks, where |
118 | | // stats deferred instantiation setting is read. |
119 | 4.40k | absl::Status status = absl::OkStatus(); |
120 | 4.40k | stats_config_ = std::make_unique<StatsConfigImpl>(bootstrap, status); |
121 | 4.40k | RETURN_IF_NOT_OK(status); |
122 | | |
123 | 4.40k | const auto& secrets = bootstrap.static_resources().secrets(); |
124 | 4.40k | ENVOY_LOG(info, "loading {} static secret(s)", secrets.size()); |
125 | 7.63k | for (ssize_t i = 0; i < secrets.size(); i++) { |
126 | 3.28k | ENVOY_LOG(debug, "static secret #{}: {}", i, secrets[i].name()); |
127 | 3.28k | RETURN_IF_NOT_OK(server.secretManager().addStaticSecret(secrets[i])); |
128 | 3.23k | } |
129 | | |
130 | 4.35k | ENVOY_LOG(info, "loading {} cluster(s)", bootstrap.static_resources().clusters().size()); |
131 | | |
132 | | // clusterManagerFromProto() and init() have to be called consecutively. |
133 | 4.35k | cluster_manager_ = cluster_manager_factory.clusterManagerFromProto(bootstrap); |
134 | 4.35k | status = cluster_manager_->initialize(bootstrap); |
135 | 4.35k | RETURN_IF_NOT_OK(status); |
136 | | |
137 | 4.30k | const auto& listeners = bootstrap.static_resources().listeners(); |
138 | 4.30k | ENVOY_LOG(info, "loading {} listener(s)", listeners.size()); |
139 | 5.97k | for (ssize_t i = 0; i < listeners.size(); i++) { |
140 | 2.56k | ENVOY_LOG(debug, "listener #{}:", i); |
141 | 2.56k | absl::StatusOr<bool> update_or_error = |
142 | 2.56k | server.listenerManager().addOrUpdateListener(listeners[i], "", false); |
143 | 2.56k | RETURN_IF_NOT_OK_REF(update_or_error.status()); |
144 | 1.67k | } |
145 | 3.41k | RETURN_IF_NOT_OK(initializeWatchdogs(bootstrap, server)); |
146 | | // This has to happen after ClusterManager initialization, as it depends on config from |
147 | | // ClusterManager. |
148 | 3.40k | initializeStatsConfig(bootstrap, server); |
149 | 3.40k | return absl::OkStatus(); |
150 | 3.41k | } |
151 | | |
152 | | void MainImpl::initializeStatsConfig(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
153 | 3.34k | Instance& server) { |
154 | 3.34k | ENVOY_LOG(info, "loading stats configuration"); |
155 | | |
156 | 3.34k | for (const envoy::config::metrics::v3::StatsSink& sink_object : bootstrap.stats_sinks()) { |
157 | | // Generate factory and translate stats sink custom config. |
158 | 84 | auto& factory = Config::Utility::getAndCheckFactory<StatsSinkFactory>(sink_object); |
159 | 84 | ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig( |
160 | 84 | sink_object, server.messageValidationContext().staticValidationVisitor(), factory); |
161 | | |
162 | 84 | stats_config_->addSink(factory.createStatsSink(*message, server.serverFactoryContext())); |
163 | 84 | } |
164 | 3.34k | } |
165 | | |
166 | | void MainImpl::initializeTracers(const envoy::config::trace::v3::Tracing& configuration, |
167 | 4.40k | Instance& server) { |
168 | 4.40k | ENVOY_LOG(info, "loading tracing configuration"); |
169 | | |
170 | | // Default tracing configuration must be set prior to processing of static Listeners begins. |
171 | 4.40k | server.setDefaultTracingConfig(configuration); |
172 | | |
173 | 4.40k | if (!configuration.has_http()) { |
174 | 4.38k | return; |
175 | 4.38k | } |
176 | | |
177 | | // Validating tracing configuration (minimally). |
178 | 20 | ENVOY_LOG(info, " validating default server-wide tracing driver: {}", |
179 | 20 | configuration.http().name()); |
180 | | |
181 | | // Now see if there is a factory that will accept the config. |
182 | 20 | auto& factory = Config::Utility::getAndCheckFactory<TracerFactory>(configuration.http()); |
183 | 20 | ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig( |
184 | 20 | configuration.http(), server.messageValidationContext().staticValidationVisitor(), factory); |
185 | | |
186 | | // Notice that the actual Tracer instance will be created on demand |
187 | | // in the context of "envoy.filters.network.http_connection_manager" filter. |
188 | | // The side effect of this is that provider-specific configuration |
189 | | // is no longer validated in this step. |
190 | 20 | } |
191 | | |
192 | | absl::Status MainImpl::initializeWatchdogs(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
193 | 3.35k | Instance& server) { |
194 | 3.35k | if (bootstrap.has_watchdog() && bootstrap.has_watchdogs()) { |
195 | 3 | return absl::InvalidArgumentError("Only one of watchdog or watchdogs should be set!"); |
196 | 3 | } |
197 | | |
198 | 3.34k | if (bootstrap.has_watchdog()) { |
199 | 92 | main_thread_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server); |
200 | 92 | worker_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server); |
201 | 3.25k | } else { |
202 | 3.25k | main_thread_watchdog_ = |
203 | 3.25k | std::make_unique<WatchdogImpl>(bootstrap.watchdogs().main_thread_watchdog(), server); |
204 | 3.25k | worker_watchdog_ = |
205 | 3.25k | std::make_unique<WatchdogImpl>(bootstrap.watchdogs().worker_watchdog(), server); |
206 | 3.25k | } |
207 | 3.34k | return absl::OkStatus(); |
208 | 3.35k | } |
209 | | |
210 | | WatchdogImpl::WatchdogImpl(const envoy::config::bootstrap::v3::Watchdog& watchdog, |
211 | 6.69k | Instance& server) { |
212 | 6.69k | miss_timeout_ = |
213 | 6.69k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, miss_timeout, 200)); |
214 | 6.69k | megamiss_timeout_ = |
215 | 6.69k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, megamiss_timeout, 1000)); |
216 | | |
217 | 6.69k | uint64_t kill_timeout = PROTOBUF_GET_MS_OR_DEFAULT(watchdog, kill_timeout, 0); |
218 | 6.69k | const uint64_t max_kill_timeout_jitter = |
219 | 6.69k | PROTOBUF_GET_MS_OR_DEFAULT(watchdog, max_kill_timeout_jitter, 0); |
220 | | |
221 | | // Adjust kill timeout if we have skew enabled. |
222 | 6.69k | if (kill_timeout > 0 && max_kill_timeout_jitter > 0) { |
223 | | // Increments the kill timeout with a random value in (0, max_skew]. |
224 | | // We shouldn't have overflow issues due to the range of Duration. |
225 | | // This won't be entirely uniform, depending on how large max_skew |
226 | | // is relation to uint64. |
227 | 2 | kill_timeout += (server.api().randomGenerator().random() % max_kill_timeout_jitter) + 1; |
228 | 2 | } |
229 | | |
230 | 6.69k | kill_timeout_ = std::chrono::milliseconds(kill_timeout); |
231 | 6.69k | multikill_timeout_ = |
232 | 6.69k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, multikill_timeout, 0)); |
233 | 6.69k | multikill_threshold_ = PROTOBUF_PERCENT_TO_DOUBLE_OR_DEFAULT(watchdog, multikill_threshold, 0.0); |
234 | 6.69k | actions_ = watchdog.actions(); |
235 | 6.69k | } |
236 | | |
237 | | InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
238 | 8.60k | absl::Status& creation_status) { |
239 | 8.60k | creation_status = absl::OkStatus(); |
240 | 8.60k | const auto& admin = bootstrap.admin(); |
241 | | |
242 | 8.60k | admin_.profile_path_ = |
243 | 8.60k | admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path(); |
244 | 8.60k | if (admin.has_address()) { |
245 | 2.11k | auto address_or_error = Network::Address::resolveProtoAddress(admin.address()); |
246 | 2.11k | if (!address_or_error.status().ok()) { |
247 | 52 | creation_status = address_or_error.status(); |
248 | 52 | return; |
249 | 52 | } |
250 | 2.06k | admin_.address_ = std::move(address_or_error.value()); |
251 | 2.06k | } |
252 | 8.55k | admin_.socket_options_ = std::make_shared<std::vector<Network::Socket::OptionConstSharedPtr>>(); |
253 | 8.55k | if (!admin.socket_options().empty()) { |
254 | 71 | Network::Socket::appendOptions( |
255 | 71 | admin_.socket_options_, |
256 | 71 | Network::SocketOptionFactory::buildLiteralOptions(admin.socket_options())); |
257 | 71 | } |
258 | 8.55k | admin_.ignore_global_conn_limit_ = admin.ignore_global_conn_limit(); |
259 | | |
260 | 8.55k | if (!bootstrap.flags_path().empty()) { |
261 | 805 | flags_path_ = bootstrap.flags_path(); |
262 | 805 | } |
263 | | |
264 | 8.55k | if (bootstrap.has_layered_runtime()) { |
265 | 2.92k | layered_runtime_.MergeFrom(bootstrap.layered_runtime()); |
266 | 2.92k | if (layered_runtime_.layers().empty()) { |
267 | 200 | layered_runtime_.add_layers()->mutable_admin_layer(); |
268 | 200 | } |
269 | 2.92k | } |
270 | 8.55k | } |
271 | | |
272 | | void InitialImpl::initAdminAccessLog(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
273 | 6.06k | FactoryContext& factory_context) { |
274 | 6.06k | const auto& admin = bootstrap.admin(); |
275 | | |
276 | 6.06k | for (const auto& access_log : admin.access_log()) { |
277 | 3.55k | AccessLog::InstanceSharedPtr current_access_log = |
278 | 3.55k | AccessLog::AccessLogFactory::fromProto(access_log, factory_context); |
279 | 3.55k | admin_.access_logs_.emplace_back(current_access_log); |
280 | 3.55k | } |
281 | | |
282 | 6.06k | if (!admin.access_log_path().empty()) { |
283 | 166 | envoy::extensions::access_loggers::file::v3::FileAccessLog config; |
284 | 166 | config.mutable_format(); |
285 | 166 | config.set_path(admin.access_log_path()); |
286 | | |
287 | 166 | auto factory = Config::Utility::getFactoryByName<AccessLog::AccessLogInstanceFactory>( |
288 | 166 | "envoy.file_access_log"); |
289 | 166 | admin_.access_logs_.emplace_back(factory->createAccessLogInstance(config, {}, factory_context)); |
290 | 166 | } |
291 | 6.06k | } |
292 | | |
293 | | } // namespace Configuration |
294 | | } // namespace Server |
295 | | } // namespace Envoy |