Coverage Report

Created: 2024-09-19 09:45

/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