LCOV - code coverage report
Current view: top level - source/server - configuration_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 119 166 71.7 %
Date: 2024-01-05 06:35:25 Functions: 10 12 83.3 %

          Line data    Source code
       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         784 :                                           const Filter::NetworkFilterFactoriesList& factories) {
      34         784 :   for (const auto& filter_config_provider : factories) {
      35         784 :     auto config = filter_config_provider->config();
      36         784 :     if (!config.has_value()) {
      37           0 :       return false;
      38           0 :     }
      39             : 
      40         784 :     Network::FilterFactoryCb& factory = config.value();
      41         784 :     factory(filter_manager);
      42         784 :   }
      43             : 
      44         784 :   return filter_manager.initializeReadFilters();
      45         784 : }
      46             : 
      47             : bool FilterChainUtility::buildFilterChain(Network::ListenerFilterManager& filter_manager,
      48         784 :                                           const Filter::ListenerFilterFactoriesList& factories) {
      49         784 :   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         784 :   return true;
      59         784 : }
      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         131 :     : deferred_stat_options_(bootstrap.deferred_stat_options()) {
      86         131 :   if (bootstrap.has_stats_flush_interval() &&
      87         131 :       bootstrap.stats_flush_case() !=
      88           0 :           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         131 :   flush_interval_ =
      94         131 :       std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(bootstrap, stats_flush_interval, 5000));
      95             : 
      96         131 :   if (bootstrap.stats_flush_case() == envoy::config::bootstrap::v3::Bootstrap::kStatsFlushOnAdmin) {
      97           0 :     flush_on_admin_ = bootstrap.stats_flush_on_admin();
      98           0 :   }
      99         131 : }
     100             : 
     101             : void MainImpl::initialize(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
     102             :                           Instance& server,
     103         131 :                           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         131 :   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         131 :   stats_config_ = std::make_unique<StatsConfigImpl>(bootstrap);
     117             : 
     118         131 :   const auto& secrets = bootstrap.static_resources().secrets();
     119         131 :   ENVOY_LOG(info, "loading {} static secret(s)", secrets.size());
     120         201 :   for (ssize_t i = 0; i < secrets.size(); i++) {
     121          70 :     ENVOY_LOG(debug, "static secret #{}: {}", i, secrets[i].name());
     122          70 :     THROW_IF_NOT_OK(server.secretManager().addStaticSecret(secrets[i]));
     123          70 :   }
     124             : 
     125         131 :   ENVOY_LOG(info, "loading {} cluster(s)", bootstrap.static_resources().clusters().size());
     126         131 :   cluster_manager_ = cluster_manager_factory.clusterManagerFromProto(bootstrap);
     127             : 
     128         131 :   const auto& listeners = bootstrap.static_resources().listeners();
     129         131 :   ENVOY_LOG(info, "loading {} listener(s)", listeners.size());
     130         137 :   for (ssize_t i = 0; i < listeners.size(); i++) {
     131          19 :     ENVOY_LOG(debug, "listener #{}:", i);
     132          19 :     absl::StatusOr<bool> update_or_error =
     133          19 :         server.listenerManager().addOrUpdateListener(listeners[i], "", false);
     134          19 :     if (!update_or_error.status().ok()) {
     135          13 :       throwEnvoyExceptionOrPanic(std::string(update_or_error.status().message()));
     136          13 :     }
     137          19 :   }
     138         118 :   initializeWatchdogs(bootstrap, server);
     139             :   // This has to happen after ClusterManager initialization, as it depends on config from
     140             :   // ClusterManager.
     141         118 :   initializeStatsConfig(bootstrap, server);
     142         118 : }
     143             : 
     144             : void MainImpl::initializeStatsConfig(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
     145         113 :                                      Instance& server) {
     146         113 :   ENVOY_LOG(info, "loading stats configuration");
     147             : 
     148         113 :   for (const envoy::config::metrics::v3::StatsSink& sink_object : bootstrap.stats_sinks()) {
     149             :     // Generate factory and translate stats sink custom config.
     150           2 :     auto& factory = Config::Utility::getAndCheckFactory<StatsSinkFactory>(sink_object);
     151           2 :     ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig(
     152           2 :         sink_object, server.messageValidationContext().staticValidationVisitor(), factory);
     153             : 
     154           2 :     stats_config_->addSink(factory.createStatsSink(*message, server.serverFactoryContext()));
     155           2 :   }
     156         113 : }
     157             : 
     158             : void MainImpl::initializeTracers(const envoy::config::trace::v3::Tracing& configuration,
     159         131 :                                  Instance& server) {
     160         131 :   ENVOY_LOG(info, "loading tracing configuration");
     161             : 
     162             :   // Default tracing configuration must be set prior to processing of static Listeners begins.
     163         131 :   server.setDefaultTracingConfig(configuration);
     164             : 
     165         131 :   if (!configuration.has_http()) {
     166         131 :     return;
     167         131 :   }
     168             : 
     169             :   // Validating tracing configuration (minimally).
     170           0 :   ENVOY_LOG(info, "  validating default server-wide tracing driver: {}",
     171           0 :             configuration.http().name());
     172             : 
     173             :   // Now see if there is a factory that will accept the config.
     174           0 :   auto& factory = Config::Utility::getAndCheckFactory<TracerFactory>(configuration.http());
     175           0 :   ProtobufTypes::MessagePtr message = Config::Utility::translateToFactoryConfig(
     176           0 :       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           0 : }
     183             : 
     184             : void MainImpl::initializeWatchdogs(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
     185         115 :                                    Instance& server) {
     186         115 :   if (bootstrap.has_watchdog() && bootstrap.has_watchdogs()) {
     187           0 :     throwEnvoyExceptionOrPanic("Only one of watchdog or watchdogs should be set!");
     188           0 :   }
     189             : 
     190         115 :   if (bootstrap.has_watchdog()) {
     191           0 :     main_thread_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server);
     192           0 :     worker_watchdog_ = std::make_unique<WatchdogImpl>(bootstrap.watchdog(), server);
     193         115 :   } else {
     194         115 :     main_thread_watchdog_ =
     195         115 :         std::make_unique<WatchdogImpl>(bootstrap.watchdogs().main_thread_watchdog(), server);
     196         115 :     worker_watchdog_ =
     197         115 :         std::make_unique<WatchdogImpl>(bootstrap.watchdogs().worker_watchdog(), server);
     198         115 :   }
     199         115 : }
     200             : 
     201             : WatchdogImpl::WatchdogImpl(const envoy::config::bootstrap::v3::Watchdog& watchdog,
     202         228 :                            Instance& server) {
     203         228 :   miss_timeout_ =
     204         228 :       std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, miss_timeout, 200));
     205         228 :   megamiss_timeout_ =
     206         228 :       std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, megamiss_timeout, 1000));
     207             : 
     208         228 :   uint64_t kill_timeout = PROTOBUF_GET_MS_OR_DEFAULT(watchdog, kill_timeout, 0);
     209         228 :   const uint64_t max_kill_timeout_jitter =
     210         228 :       PROTOBUF_GET_MS_OR_DEFAULT(watchdog, max_kill_timeout_jitter, 0);
     211             : 
     212             :   // Adjust kill timeout if we have skew enabled.
     213         228 :   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           0 :     kill_timeout += (server.api().randomGenerator().random() % max_kill_timeout_jitter) + 1;
     219           0 :   }
     220             : 
     221         228 :   kill_timeout_ = std::chrono::milliseconds(kill_timeout);
     222         228 :   multikill_timeout_ =
     223         228 :       std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, multikill_timeout, 0));
     224         228 :   multikill_threshold_ = PROTOBUF_PERCENT_TO_DOUBLE_OR_DEFAULT(watchdog, multikill_threshold, 0.0);
     225         228 :   actions_ = watchdog.actions();
     226         228 : }
     227             : 
     228         244 : InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap) {
     229         244 :   const auto& admin = bootstrap.admin();
     230             : 
     231         244 :   admin_.profile_path_ =
     232         244 :       admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path();
     233         244 :   if (admin.has_address()) {
     234         139 :     admin_.address_ = Network::Address::resolveProtoAddress(admin.address());
     235         139 :   }
     236         244 :   admin_.socket_options_ = std::make_shared<std::vector<Network::Socket::OptionConstSharedPtr>>();
     237         244 :   if (!admin.socket_options().empty()) {
     238           0 :     Network::Socket::appendOptions(
     239           0 :         admin_.socket_options_,
     240           0 :         Network::SocketOptionFactory::buildLiteralOptions(admin.socket_options()));
     241           0 :   }
     242         244 :   admin_.ignore_global_conn_limit_ = admin.ignore_global_conn_limit();
     243             : 
     244         244 :   if (!bootstrap.flags_path().empty()) {
     245          14 :     flags_path_ = bootstrap.flags_path();
     246          14 :   }
     247             : 
     248         244 :   if (bootstrap.has_layered_runtime()) {
     249         103 :     layered_runtime_.MergeFrom(bootstrap.layered_runtime());
     250         103 :     if (layered_runtime_.layers().empty()) {
     251           1 :       layered_runtime_.add_layers()->mutable_admin_layer();
     252           1 :     }
     253         103 :   }
     254         244 : }
     255             : 
     256             : void InitialImpl::initAdminAccessLog(const envoy::config::bootstrap::v3::Bootstrap& bootstrap,
     257         208 :                                      FactoryContext& factory_context) {
     258         208 :   const auto& admin = bootstrap.admin();
     259             : 
     260         208 :   for (const auto& access_log : admin.access_log()) {
     261          98 :     AccessLog::InstanceSharedPtr current_access_log =
     262          98 :         AccessLog::AccessLogFactory::fromProto(access_log, factory_context);
     263          98 :     admin_.access_logs_.emplace_back(current_access_log);
     264          98 :   }
     265             : 
     266         208 :   if (!admin.access_log_path().empty()) {
     267           3 :     Filesystem::FilePathAndType file_info{Filesystem::DestinationType::File,
     268           3 :                                           admin.access_log_path()};
     269           3 :     admin_.access_logs_.emplace_back(new Extensions::AccessLoggers::File::FileAccessLog(
     270           3 :         file_info, {}, Formatter::HttpSubstitutionFormatUtils::defaultSubstitutionFormatter(),
     271           3 :         factory_context.serverFactoryContext().accessLogManager()));
     272           3 :   }
     273         208 : }
     274             : 
     275             : } // namespace Configuration
     276             : } // namespace Server
     277             : } // namespace Envoy

Generated by: LCOV version 1.15