Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/server/config_validation/server.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/server/config_validation/server.h"
2
3
#include <memory>
4
5
#include "envoy/config/bootstrap/v3/bootstrap.pb.h"
6
7
#include "source/common/common/utility.h"
8
#include "source/common/config/utility.h"
9
#include "source/common/config/well_known_names.h"
10
#include "source/common/event/real_time_system.h"
11
#include "source/common/local_info/local_info_impl.h"
12
#include "source/common/protobuf/utility.h"
13
#include "source/common/singleton/manager_impl.h"
14
#include "source/common/version/version.h"
15
#include "source/server/listener_manager_factory.h"
16
#include "source/server/regex_engine.h"
17
#include "source/server/ssl_context_manager.h"
18
#include "source/server/utils.h"
19
20
namespace Envoy {
21
namespace Server {
22
23
bool validateConfig(const Options& options,
24
                    const Network::Address::InstanceConstSharedPtr& local_address,
25
                    ComponentFactory& component_factory, Thread::ThreadFactory& thread_factory,
26
                    Filesystem::Instance& file_system,
27
6.68k
                    const ProcessContextOptRef& process_context) {
28
6.68k
  Thread::MutexBasicLockable access_log_lock;
29
6.68k
  Stats::IsolatedStoreImpl stats_store;
30
31
6.68k
  TRY_ASSERT_MAIN_THREAD {
32
6.68k
    Event::RealTimeSystem time_system;
33
6.68k
    ValidationInstance server(options, time_system, local_address, stats_store, access_log_lock,
34
6.68k
                              component_factory, thread_factory, file_system, process_context);
35
6.68k
    std::cout << "configuration '" << options.configPath() << "' OK" << std::endl;
36
6.68k
    server.shutdown();
37
6.68k
    return true;
38
6.68k
  }
39
6.68k
  END_TRY
40
6.68k
  catch (const EnvoyException& e) {
41
6.68k
    return false;
42
6.68k
  }
43
6.68k
}
44
45
ValidationInstance::ValidationInstance(
46
    const Options& options, Event::TimeSystem& time_system,
47
    const Network::Address::InstanceConstSharedPtr& local_address, Stats::IsolatedStoreImpl& store,
48
    Thread::BasicLockable& access_log_lock, ComponentFactory& component_factory,
49
    Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system,
50
    const ProcessContextOptRef& process_context)
51
    : options_(options), validation_context_(options_.allowUnknownStaticFields(),
52
                                             !options.rejectUnknownDynamicFields(),
53
                                             !options.ignoreUnknownDynamicFields()),
54
      stats_store_(store),
55
      api_(new Api::ValidationImpl(thread_factory, store, time_system, file_system,
56
                                   random_generator_, bootstrap_, process_context)),
57
      dispatcher_(api_->allocateDispatcher("main_thread")),
58
      singleton_manager_(new Singleton::ManagerImpl(api_->threadFactory())),
59
      access_log_manager_(options.fileFlushIntervalMsec(), *api_, *dispatcher_, access_log_lock,
60
                          store),
61
      grpc_context_(stats_store_.symbolTable()), http_context_(stats_store_.symbolTable()),
62
      router_context_(stats_store_.symbolTable()), time_system_(time_system),
63
6.68k
      server_contexts_(*this), quic_stat_names_(stats_store_.symbolTable()) {
64
6.68k
  TRY_ASSERT_MAIN_THREAD { initialize(options, local_address, component_factory); }
65
6.68k
  END_TRY
66
6.68k
  catch (const EnvoyException& e) {
67
6.68k
    ENVOY_LOG(critical, "error initializing configuration '{}': {}", options.configPath(),
68
6.68k
              e.what());
69
6.68k
    shutdown();
70
6.68k
    throw;
71
6.68k
  }
72
6.68k
}
73
74
void ValidationInstance::initialize(const Options& options,
75
                                    const Network::Address::InstanceConstSharedPtr& local_address,
76
6.68k
                                    ComponentFactory& component_factory) {
77
  // See comments on InstanceImpl::initialize() for the overall flow here.
78
  //
79
  // For validation, we only do a subset of normal server initialization: everything that could fail
80
  // on a malformed config (e.g. JSON parsing and all the object construction that follows), but
81
  // more importantly nothing with observable effects (e.g. binding to ports or shutting down any
82
  // other Envoy process).
83
  //
84
  // If we get all the way through that stripped-down initialization flow, to the point where we'd
85
  // be ready to serve, then the config has passed validation.
86
  // Handle configuration that needs to take place prior to the main configuration load.
87
6.68k
  InstanceUtil::loadBootstrapConfig(bootstrap_, options,
88
6.68k
                                    messageValidationContext().staticValidationVisitor(), *api_);
89
90
6.68k
  if (bootstrap_.has_application_log_config()) {
91
2.88k
    THROW_IF_NOT_OK(
92
2.88k
        Utility::assertExclusiveLogFormatMethod(options_, bootstrap_.application_log_config()));
93
2.88k
    THROW_IF_NOT_OK(Utility::maybeSetApplicationLogFormat(bootstrap_.application_log_config()));
94
2.84k
  }
95
96
  // Inject regex engine to singleton.
97
6.65k
  Regex::EnginePtr regex_engine = createRegexEngine(
98
6.65k
      bootstrap_, messageValidationContext().staticValidationVisitor(), serverFactoryContext());
99
100
6.65k
  Config::Utility::createTagProducer(bootstrap_, options_.statsTags());
101
6.65k
  if (!bootstrap_.node().user_agent_build_version().has_version()) {
102
5.16k
    *bootstrap_.mutable_node()->mutable_user_agent_build_version() = VersionInfo::buildVersion();
103
5.16k
  }
104
105
6.65k
  local_info_ = std::make_unique<LocalInfo::LocalInfoImpl>(
106
6.65k
      stats().symbolTable(), bootstrap_.node(), bootstrap_.node_context_params(), local_address,
107
6.65k
      options.serviceZone(), options.serviceClusterName(), options.serviceNodeName());
108
109
6.65k
  overload_manager_ = std::make_unique<OverloadManagerImpl>(
110
6.65k
      dispatcher(), *stats().rootScope(), threadLocal(), bootstrap_.overload_manager(),
111
6.65k
      messageValidationContext().staticValidationVisitor(), *api_, options_);
112
6.65k
  Configuration::InitialImpl initial_config(bootstrap_);
113
6.65k
  initial_config.initAdminAccessLog(bootstrap_, *this);
114
6.65k
  admin_ = std::make_unique<Server::ValidationAdmin>(initial_config.admin().address());
115
6.65k
  listener_manager_ = Config::Utility::getAndCheckFactoryByName<ListenerManagerFactory>(
116
6.65k
                          Config::ServerExtensionValues::get().VALIDATION_LISTENER)
117
6.65k
                          .createListenerManager(*this, nullptr, *this, false, quic_stat_names_);
118
6.65k
  thread_local_.registerThread(*dispatcher_, true);
119
120
6.65k
  runtime_ = component_factory.createRuntime(*this, initial_config);
121
6.65k
  ENVOY_BUG(runtime_ != nullptr,
122
6.65k
            "Component factory should not return nullptr from createRuntime()");
123
6.65k
  drain_manager_ = component_factory.createDrainManager(*this);
124
6.65k
  ENVOY_BUG(drain_manager_ != nullptr,
125
6.65k
            "Component factory should not return nullptr from createDrainManager()");
126
127
6.65k
  secret_manager_ = std::make_unique<Secret::SecretManagerImpl>(admin()->getConfigTracker());
128
6.65k
  ssl_context_manager_ = createContextManager("ssl_context_manager", api_->timeSource());
129
6.65k
  cluster_manager_factory_ = std::make_unique<Upstream::ValidationClusterManagerFactory>(
130
6.65k
      server_contexts_, stats(), threadLocal(), http_context_,
131
6.65k
      [this]() -> Network::DnsResolverSharedPtr { return this->dnsResolver(); },
132
6.65k
      sslContextManager(), *secret_manager_, quic_stat_names_, *this);
133
6.65k
  config_.initialize(bootstrap_, *this, *cluster_manager_factory_);
134
6.65k
  runtime().initialize(clusterManager());
135
6.65k
  clusterManager().setInitializedCb([this]() -> void { init_manager_.initialize(init_watcher_); });
136
6.65k
}
137
138
6.68k
void ValidationInstance::shutdown() {
139
  // This normally happens at the bottom of InstanceImpl::run(), but we don't have a run(). We can
140
  // do an abbreviated shutdown here since there's less to clean up -- for example, no workers to
141
  // exit.
142
6.68k
  thread_local_.shutdownGlobalThreading();
143
6.68k
  if (config_.clusterManager() != nullptr) {
144
0
    config_.clusterManager()->shutdown();
145
0
  }
146
6.68k
  thread_local_.shutdownThread();
147
6.68k
  dispatcher_->shutdown();
148
6.68k
}
149
150
} // namespace Server
151
} // namespace Envoy