/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/network/connection.h" |
14 | | #include "envoy/runtime/runtime.h" |
15 | | #include "envoy/server/instance.h" |
16 | | #include "envoy/server/tracer_config.h" |
17 | | #include "envoy/ssl/context_manager.h" |
18 | | |
19 | | #include "source/common/access_log/access_log_impl.h" |
20 | | #include "source/common/common/assert.h" |
21 | | #include "source/common/common/utility.h" |
22 | | #include "source/common/config/runtime_utility.h" |
23 | | #include "source/common/config/utility.h" |
24 | | #include "source/common/network/socket_option_factory.h" |
25 | | #include "source/common/protobuf/utility.h" |
26 | | #include "source/extensions/access_loggers/common/file_access_log_impl.h" |
27 | | |
28 | | namespace Envoy { |
29 | | namespace Server { |
30 | | namespace Configuration { |
31 | | |
32 | | bool FilterChainUtility::buildFilterChain(Network::FilterManager& filter_manager, |
33 | 3.62k | const Filter::NetworkFilterFactoriesList& factories) { |
34 | 3.62k | for (const auto& filter_config_provider : factories) { |
35 | 3.62k | auto config = filter_config_provider->config(); |
36 | 3.62k | if (!config.has_value()) { |
37 | 0 | return false; |
38 | 0 | } |
39 | | |
40 | 3.62k | Network::FilterFactoryCb& factory = config.value(); |
41 | 3.62k | factory(filter_manager); |
42 | 3.62k | } |
43 | | |
44 | 3.62k | return filter_manager.initializeReadFilters(); |
45 | 3.62k | } |
46 | | |
47 | | bool FilterChainUtility::buildFilterChain(Network::ListenerFilterManager& filter_manager, |
48 | 3.62k | const Filter::ListenerFilterFactoriesList& factories) { |
49 | 3.62k | 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 | 3.62k | return true; |
59 | 3.62k | } |
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 | 5.24k | : deferred_stat_options_(bootstrap.deferred_stat_options()) { |
86 | 5.24k | if (bootstrap.has_stats_flush_interval() && |
87 | 5.24k | bootstrap.stats_flush_case() != |
88 | 48 | envoy::config::bootstrap::v3::Bootstrap::STATS_FLUSH_NOT_SET) { |
89 | 0 | throwEnvoyExceptionOrPanic( |
90 | 0 | "Only one of stats_flush_interval or stats_flush_on_admin should be set!"); |
91 | 0 | } |
92 | | |
93 | 5.24k | flush_interval_ = |
94 | 5.24k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(bootstrap, stats_flush_interval, 5000)); |
95 | | |
96 | 5.24k | if (bootstrap.stats_flush_case() == envoy::config::bootstrap::v3::Bootstrap::kStatsFlushOnAdmin) { |
97 | 108 | flush_on_admin_ = bootstrap.stats_flush_on_admin(); |
98 | 108 | } |
99 | 5.24k | } |
100 | | |
101 | | void MainImpl::initialize(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
102 | | Instance& server, |
103 | 5.27k | Upstream::ClusterManagerFactory& cluster_manager_factory) { |
104 | | // In order to support dynamic configuration of tracing providers, |
105 | | // a former server-wide Tracer singleton has been replaced by |
106 | | // an Tracer instance per "envoy.filters.network.http_connection_manager" filter. |
107 | | // Tracing configuration as part of bootstrap config is still supported, |
108 | | // however, it's become mandatory to process it prior to static Listeners. |
109 | | // Otherwise, static Listeners will be configured in assumption that |
110 | | // tracing configuration is missing from the bootstrap config. |
111 | 5.27k | initializeTracers(bootstrap.tracing(), server); |
112 | | |
113 | | // stats_config_ should be set before creating the ClusterManagers so that it is available |
114 | | // from the ServerFactoryContext when creating the static clusters and stats sinks, where |
115 | | // stats deferred instantiation setting is read. |
116 | 5.27k | stats_config_ = std::make_unique<StatsConfigImpl>(bootstrap); |
117 | | |
118 | 5.27k | const auto& secrets = bootstrap.static_resources().secrets(); |
119 | 5.27k | ENVOY_LOG(info, "loading {} static secret(s)", secrets.size()); |
120 | 9.35k | for (ssize_t i = 0; i < secrets.size(); i++) { |
121 | 4.07k | ENVOY_LOG(debug, "static secret #{}: {}", i, secrets[i].name()); |
122 | 4.07k | server.secretManager().addStaticSecret(secrets[i]); |
123 | 4.07k | } |
124 | | |
125 | 5.27k | ENVOY_LOG(info, "loading {} cluster(s)", bootstrap.static_resources().clusters().size()); |
126 | 5.27k | cluster_manager_ = cluster_manager_factory.clusterManagerFromProto(bootstrap); |
127 | | |
128 | 5.27k | const auto& listeners = bootstrap.static_resources().listeners(); |
129 | 5.27k | ENVOY_LOG(info, "loading {} listener(s)", listeners.size()); |
130 | 7.55k | for (ssize_t i = 0; i < listeners.size(); i++) { |
131 | 3.18k | ENVOY_LOG(debug, "listener #{}:", i); |
132 | 3.18k | absl::StatusOr<bool> update_or_error = |
133 | 3.18k | server.listenerManager().addOrUpdateListener(listeners[i], "", false); |
134 | 3.18k | if (!update_or_error.status().ok()) { |
135 | 911 | throwEnvoyExceptionOrPanic(std::string(update_or_error.status().message())); |
136 | 911 | } |
137 | 3.18k | } |
138 | 4.36k | initializeWatchdogs(bootstrap, server); |
139 | | // This has to happen after ClusterManager initialization, as it depends on config from |
140 | | // ClusterManager. |
141 | 4.36k | initializeStatsConfig(bootstrap, server); |
142 | 4.36k | } |
143 | | |
144 | | void MainImpl::initializeStatsConfig(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
145 | 4.17k | Instance& server) { |
146 | 4.17k | ENVOY_LOG(info, "loading stats configuration"); |
147 | | |
148 | 4.17k | for (const envoy::config::metrics::v3::StatsSink& sink_object : bootstrap.stats_sinks()) { |
149 | | // Generate factory and translate stats sink custom config. |
150 | 98 | auto& factory = Config::Utility::getAndCheckFactory<StatsSinkFactory>(sink_object); |
151 | 98 | ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig( |
152 | 98 | sink_object, server.messageValidationContext().staticValidationVisitor(), factory); |
153 | | |
154 | 98 | stats_config_->addSink(factory.createStatsSink(*message, server.serverFactoryContext())); |
155 | 98 | } |
156 | 4.17k | } |
157 | | |
158 | | void MainImpl::initializeTracers(const envoy::config::trace::v3::Tracing& configuration, |
159 | 5.27k | Instance& server) { |
160 | 5.27k | ENVOY_LOG(info, "loading tracing configuration"); |
161 | | |
162 | | // Default tracing configuration must be set prior to processing of static Listeners begins. |
163 | 5.27k | server.setDefaultTracingConfig(configuration); |
164 | | |
165 | 5.27k | if (!configuration.has_http()) { |
166 | 5.24k | return; |
167 | 5.24k | } |
168 | | |
169 | | // Validating tracing configuration (minimally). |
170 | 35 | ENVOY_LOG(info, " validating default server-wide tracing driver: {}", |
171 | 35 | configuration.http().name()); |
172 | | |
173 | | // Now see if there is a factory that will accept the config. |
174 | 35 | auto& factory = Config::Utility::getAndCheckFactory<TracerFactory>(configuration.http()); |
175 | 35 | ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig( |
176 | 35 | configuration.http(), server.messageValidationContext().staticValidationVisitor(), factory); |
177 | | |
178 | | // Notice that the actual Tracer instance will be created on demand |
179 | | // in the context of "envoy.filters.network.http_connection_manager" filter. |
180 | | // The side effect of this is that provider-specific configuration |
181 | | // is no longer validated in this step. |
182 | 35 | } |
183 | | |
184 | | void MainImpl::initializeWatchdogs(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
185 | 4.17k | Instance& server) { |
186 | 4.17k | if (bootstrap.has_watchdog() && bootstrap.has_watchdogs()) { |
187 | 2 | throwEnvoyExceptionOrPanic("Only one of watchdog or watchdogs should be set!"); |
188 | 2 | } |
189 | | |
190 | 4.17k | if (bootstrap.has_watchdog()) { |
191 | 82 | main_thread_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server); |
192 | 82 | worker_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server); |
193 | 4.09k | } else { |
194 | 4.09k | main_thread_watchdog_ = |
195 | 4.09k | std::make_unique<WatchdogImpl>(bootstrap.watchdogs().main_thread_watchdog(), server); |
196 | 4.09k | worker_watchdog_ = |
197 | 4.09k | std::make_unique<WatchdogImpl>(bootstrap.watchdogs().worker_watchdog(), server); |
198 | 4.09k | } |
199 | 4.17k | } |
200 | | |
201 | | WatchdogImpl::WatchdogImpl(const envoy::config::bootstrap::v3::Watchdog& watchdog, |
202 | 8.35k | Instance& server) { |
203 | 8.35k | miss_timeout_ = |
204 | 8.35k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, miss_timeout, 200)); |
205 | 8.35k | megamiss_timeout_ = |
206 | 8.35k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, megamiss_timeout, 1000)); |
207 | | |
208 | 8.35k | uint64_t kill_timeout = PROTOBUF_GET_MS_OR_DEFAULT(watchdog, kill_timeout, 0); |
209 | 8.35k | const uint64_t max_kill_timeout_jitter = |
210 | 8.35k | PROTOBUF_GET_MS_OR_DEFAULT(watchdog, max_kill_timeout_jitter, 0); |
211 | | |
212 | | // Adjust kill timeout if we have skew enabled. |
213 | 8.35k | if (kill_timeout > 0 && max_kill_timeout_jitter > 0) { |
214 | | // Increments the kill timeout with a random value in (0, max_skew]. |
215 | | // We shouldn't have overflow issues due to the range of Duration. |
216 | | // This won't be entirely uniform, depending on how large max_skew |
217 | | // is relation to uint64. |
218 | 4 | kill_timeout += (server.api().randomGenerator().random() % max_kill_timeout_jitter) + 1; |
219 | 4 | } |
220 | | |
221 | 8.35k | kill_timeout_ = std::chrono::milliseconds(kill_timeout); |
222 | 8.35k | multikill_timeout_ = |
223 | 8.35k | std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, multikill_timeout, 0)); |
224 | 8.35k | multikill_threshold_ = PROTOBUF_PERCENT_TO_DOUBLE_OR_DEFAULT(watchdog, multikill_threshold, 0.0); |
225 | 8.35k | actions_ = watchdog.actions(); |
226 | 8.35k | } |
227 | | |
228 | 10.4k | InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap) { |
229 | 10.4k | const auto& admin = bootstrap.admin(); |
230 | | |
231 | 10.4k | admin_.profile_path_ = |
232 | 10.4k | admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path(); |
233 | 10.4k | if (admin.has_address()) { |
234 | 2.80k | admin_.address_ = Network::Address::resolveProtoAddress(admin.address()); |
235 | 2.80k | } |
236 | 10.4k | admin_.socket_options_ = std::make_shared<std::vector<Network::Socket::OptionConstSharedPtr>>(); |
237 | 10.4k | if (!admin.socket_options().empty()) { |
238 | 74 | Network::Socket::appendOptions( |
239 | 74 | admin_.socket_options_, |
240 | 74 | Network::SocketOptionFactory::buildLiteralOptions(admin.socket_options())); |
241 | 74 | } |
242 | 10.4k | admin_.ignore_global_conn_limit_ = admin.ignore_global_conn_limit(); |
243 | | |
244 | 10.4k | if (!bootstrap.flags_path().empty()) { |
245 | 1.07k | flags_path_ = bootstrap.flags_path(); |
246 | 1.07k | } |
247 | | |
248 | 10.4k | if (bootstrap.has_layered_runtime()) { |
249 | 3.58k | layered_runtime_.MergeFrom(bootstrap.layered_runtime()); |
250 | 3.58k | if (layered_runtime_.layers().empty()) { |
251 | 220 | layered_runtime_.add_layers()->mutable_admin_layer(); |
252 | 220 | } |
253 | 3.58k | } |
254 | 10.4k | } |
255 | | |
256 | | void InitialImpl::initAdminAccessLog(const envoy::config::bootstrap::v3::Bootstrap& bootstrap, |
257 | 10.3k | Instance& server) { |
258 | 10.3k | const auto& admin = bootstrap.admin(); |
259 | | |
260 | 10.3k | for (const auto& access_log : admin.access_log()) { |
261 | 4.12k | AccessLog::InstanceSharedPtr current_access_log = |
262 | 4.12k | AccessLog::AccessLogFactory::fromProto(access_log, server.serverFactoryContext()); |
263 | 4.12k | admin_.access_logs_.emplace_back(current_access_log); |
264 | 4.12k | } |
265 | | |
266 | 10.3k | if (!admin.access_log_path().empty()) { |
267 | 153 | Filesystem::FilePathAndType file_info{Filesystem::DestinationType::File, |
268 | 153 | admin.access_log_path()}; |
269 | 153 | admin_.access_logs_.emplace_back(new Extensions::AccessLoggers::File::FileAccessLog( |
270 | 153 | file_info, {}, Formatter::HttpSubstitutionFormatUtils::defaultSubstitutionFormatter(), |
271 | 153 | server.accessLogManager())); |
272 | 153 | } |
273 | 10.3k | } |
274 | | |
275 | | } // namespace Configuration |
276 | | } // namespace Server |
277 | | } // namespace Envoy |