Coverage Report

Created: 2023-11-12 09:30

/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