Coverage Report

Created: 2024-09-19 09:45

/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/listener_manager/listener_info_impl.h"
12
#include "source/common/local_info/local_info_impl.h"
13
#include "source/common/protobuf/utility.h"
14
#include "source/common/stats/tag_producer_impl.h"
15
#include "source/common/tls/context_manager_impl.h"
16
#include "source/common/version/version.h"
17
#include "source/server/admin/admin_factory_context.h"
18
#include "source/server/listener_manager_factory.h"
19
#include "source/server/null_overload_manager.h"
20
#include "source/server/overload_manager_impl.h"
21
#include "source/server/regex_engine.h"
22
#include "source/server/utils.h"
23
24
namespace Envoy {
25
namespace Server {
26
27
bool validateConfig(const Options& options,
28
                    const Network::Address::InstanceConstSharedPtr& local_address,
29
                    ComponentFactory& component_factory, Thread::ThreadFactory& thread_factory,
30
                    Filesystem::Instance& file_system,
31
5.52k
                    const ProcessContextOptRef& process_context) {
32
5.52k
  Thread::MutexBasicLockable access_log_lock;
33
5.52k
  Stats::IsolatedStoreImpl stats_store;
34
35
5.52k
  TRY_ASSERT_MAIN_THREAD {
36
5.52k
    Event::RealTimeSystem time_system;
37
5.52k
    ValidationInstance server(options, time_system, local_address, stats_store, access_log_lock,
38
5.52k
                              component_factory, thread_factory, file_system, process_context);
39
5.52k
    std::cout << "configuration '" << options.configPath() << "' OK" << std::endl;
40
5.52k
    server.shutdown();
41
5.52k
    return true;
42
5.52k
  }
43
5.52k
  END_TRY
44
5.52k
  catch (const EnvoyException& e) {
45
5.52k
    return false;
46
5.52k
  }
47
5.52k
}
48
49
ValidationInstance::ValidationInstance(
50
    const Options& options, Event::TimeSystem& time_system,
51
    const Network::Address::InstanceConstSharedPtr& local_address, Stats::IsolatedStoreImpl& store,
52
    Thread::BasicLockable& access_log_lock, ComponentFactory& component_factory,
53
    Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system,
54
    const ProcessContextOptRef& process_context)
55
    : options_(options), validation_context_(options_.allowUnknownStaticFields(),
56
                                             !options.rejectUnknownDynamicFields(),
57
                                             !options.ignoreUnknownDynamicFields()),
58
      stats_store_(store),
59
      api_(new Api::ValidationImpl(thread_factory, store, time_system, file_system,
60
                                   random_generator_, bootstrap_, process_context)),
61
      dispatcher_(api_->allocateDispatcher("main_thread")),
62
      access_log_manager_(options.fileFlushIntervalMsec(), *api_, *dispatcher_, access_log_lock,
63
                          store),
64
      grpc_context_(stats_store_.symbolTable()), http_context_(stats_store_.symbolTable()),
65
      router_context_(stats_store_.symbolTable()), time_system_(time_system),
66
5.52k
      server_contexts_(*this), quic_stat_names_(stats_store_.symbolTable()) {
67
5.52k
  TRY_ASSERT_MAIN_THREAD { initialize(options, local_address, component_factory); }
68
5.52k
  END_TRY
69
5.52k
  catch (const EnvoyException& e) {
70
5.52k
    ENVOY_LOG(critical, "error initializing configuration '{}': {}", options.configPath(),
71
5.52k
              e.what());
72
5.52k
    shutdown();
73
5.52k
    throw;
74
5.52k
  }
75
5.52k
}
76
77
void ValidationInstance::initialize(const Options& options,
78
                                    const Network::Address::InstanceConstSharedPtr& local_address,
79
5.52k
                                    ComponentFactory& component_factory) {
80
  // See comments on InstanceImpl::initialize() for the overall flow here.
81
  //
82
  // For validation, we only do a subset of normal server initialization: everything that could fail
83
  // on a malformed config (e.g. JSON parsing and all the object construction that follows), but
84
  // more importantly nothing with observable effects (e.g. binding to ports or shutting down any
85
  // other Envoy process).
86
  //
87
  // If we get all the way through that stripped-down initialization flow, to the point where we'd
88
  // be ready to serve, then the config has passed validation.
89
  // Handle configuration that needs to take place prior to the main configuration load.
90
5.52k
  THROW_IF_NOT_OK(InstanceUtil::loadBootstrapConfig(
91
5.52k
      bootstrap_, options, messageValidationContext().staticValidationVisitor(), *api_));
92
93
5.52k
  if (bootstrap_.has_application_log_config()) {
94
2.05k
    THROW_IF_NOT_OK(
95
2.05k
        Utility::assertExclusiveLogFormatMethod(options_, bootstrap_.application_log_config()));
96
2.05k
    THROW_IF_NOT_OK(Utility::maybeSetApplicationLogFormat(bootstrap_.application_log_config()));
97
2.05k
  }
98
99
  // Inject regex engine to singleton.
100
5.49k
  regex_engine_ = createRegexEngine(
101
5.49k
      bootstrap_, messageValidationContext().staticValidationVisitor(), serverFactoryContext());
102
103
5.49k
  auto producer_or_error =
104
5.49k
      Stats::TagProducerImpl::createTagProducer(bootstrap_.stats_config(), options_.statsTags());
105
5.49k
  THROW_IF_NOT_OK_REF(producer_or_error.status());
106
5.23k
  if (!bootstrap_.node().user_agent_build_version().has_version()) {
107
4.15k
    *bootstrap_.mutable_node()->mutable_user_agent_build_version() = VersionInfo::buildVersion();
108
4.15k
  }
109
110
5.23k
  local_info_ = std::make_unique<LocalInfo::LocalInfoImpl>(
111
5.23k
      stats().symbolTable(), bootstrap_.node(), bootstrap_.node_context_params(), local_address,
112
5.23k
      options.serviceZone(), options.serviceClusterName(), options.serviceNodeName());
113
114
5.23k
  overload_manager_ = THROW_OR_RETURN_VALUE(
115
5.23k
      OverloadManagerImpl::create(
116
5.23k
          dispatcher(), *stats().rootScope(), threadLocal(), bootstrap_.overload_manager(),
117
5.23k
          messageValidationContext().staticValidationVisitor(), *api_, options_),
118
5.23k
      std::unique_ptr<OverloadManagerImpl>);
119
5.23k
  null_overload_manager_ = std::make_unique<NullOverloadManager>(threadLocal(), false);
120
5.23k
  absl::Status creation_status = absl::OkStatus();
121
5.23k
  Configuration::InitialImpl initial_config(bootstrap_, creation_status);
122
5.23k
  THROW_IF_NOT_OK_REF(creation_status);
123
5.18k
  AdminFactoryContext factory_context(*this, std::make_shared<ListenerInfoImpl>());
124
5.18k
  initial_config.initAdminAccessLog(bootstrap_, factory_context);
125
5.18k
  admin_ = std::make_unique<Server::ValidationAdmin>(initial_config.admin().address());
126
5.18k
  listener_manager_ = Config::Utility::getAndCheckFactoryByName<ListenerManagerFactory>(
127
5.18k
                          Config::ServerExtensionValues::get().VALIDATION_LISTENER)
128
5.18k
                          .createListenerManager(*this, nullptr, *this, false, quic_stat_names_);
129
5.18k
  thread_local_.registerThread(*dispatcher_, true);
130
131
5.18k
  runtime_ = component_factory.createRuntime(*this, initial_config);
132
5.18k
  ENVOY_BUG(runtime_ != nullptr,
133
5.18k
            "Component factory should not return nullptr from createRuntime()");
134
5.18k
  drain_manager_ = component_factory.createDrainManager(*this);
135
5.18k
  ENVOY_BUG(drain_manager_ != nullptr,
136
5.18k
            "Component factory should not return nullptr from createDrainManager()");
137
138
5.18k
  secret_manager_ = std::make_unique<Secret::SecretManagerImpl>(admin()->getConfigTracker());
139
5.18k
  ssl_context_manager_ =
140
5.18k
      std::make_unique<Extensions::TransportSockets::Tls::ContextManagerImpl>(server_contexts_);
141
142
5.18k
  http_server_properties_cache_manager_ =
143
5.18k
      std::make_unique<Http::HttpServerPropertiesCacheManagerImpl>(
144
5.18k
          serverFactoryContext(), messageValidationContext().staticValidationVisitor(),
145
5.18k
          thread_local_);
146
147
5.18k
  cluster_manager_factory_ = std::make_unique<Upstream::ValidationClusterManagerFactory>(
148
5.18k
      server_contexts_, stats(), threadLocal(), http_context_,
149
5.18k
      [this]() -> Network::DnsResolverSharedPtr { return this->dnsResolver(); },
150
5.18k
      sslContextManager(), *secret_manager_, quic_stat_names_, *this);
151
5.18k
  THROW_IF_NOT_OK(config_.initialize(bootstrap_, *this, *cluster_manager_factory_));
152
5.18k
  THROW_IF_NOT_OK(runtime().initialize(clusterManager()));
153
5.18k
  clusterManager().setInitializedCb([this]() -> void { init_manager_.initialize(init_watcher_); });
154
5.18k
}
155
156
5.52k
void ValidationInstance::shutdown() {
157
  // This normally happens at the bottom of InstanceImpl::run(), but we don't have a run(). We can
158
  // do an abbreviated shutdown here since there's less to clean up -- for example, no workers to
159
  // exit.
160
5.52k
  thread_local_.shutdownGlobalThreading();
161
5.52k
  if (config_.clusterManager() != nullptr) {
162
0
    config_.clusterManager()->shutdown();
163
0
  }
164
5.52k
  thread_local_.shutdownThread();
165
5.52k
  dispatcher_->shutdown();
166
5.52k
}
167
168
0
Network::DnsResolverSharedPtr ValidationInstance::dnsResolver() {
169
0
  envoy::config::core::v3::TypedExtensionConfig typed_dns_resolver_config;
170
0
  Network::DnsResolverFactory& dns_resolver_factory =
171
0
      Network::createDefaultDnsResolverFactory(typed_dns_resolver_config);
172
0
  return THROW_OR_RETURN_VALUE(
173
0
      dns_resolver_factory.createDnsResolver(dispatcher(), api(), typed_dns_resolver_config),
174
0
      Network::DnsResolverSharedPtr);
175
0
}
176
177
} // namespace Server
178
} // namespace Envoy