Line data Source code
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/singleton/manager_impl.h"
15 : #include "source/common/version/version.h"
16 : #include "source/server/admin/admin_factory_context.h"
17 : #include "source/server/listener_manager_factory.h"
18 : #include "source/server/overload_manager_impl.h"
19 : #include "source/server/regex_engine.h"
20 : #include "source/server/ssl_context_manager.h"
21 : #include "source/server/utils.h"
22 :
23 : namespace Envoy {
24 : namespace Server {
25 :
26 : bool validateConfig(const Options& options,
27 : const Network::Address::InstanceConstSharedPtr& local_address,
28 : ComponentFactory& component_factory, Thread::ThreadFactory& thread_factory,
29 : Filesystem::Instance& file_system,
30 320 : const ProcessContextOptRef& process_context) {
31 320 : Thread::MutexBasicLockable access_log_lock;
32 320 : Stats::IsolatedStoreImpl stats_store;
33 :
34 320 : TRY_ASSERT_MAIN_THREAD {
35 320 : Event::RealTimeSystem time_system;
36 320 : ValidationInstance server(options, time_system, local_address, stats_store, access_log_lock,
37 320 : component_factory, thread_factory, file_system, process_context);
38 320 : std::cout << "configuration '" << options.configPath() << "' OK" << std::endl;
39 320 : server.shutdown();
40 320 : return true;
41 320 : }
42 320 : END_TRY
43 320 : catch (const EnvoyException& e) {
44 320 : return false;
45 320 : }
46 320 : }
47 :
48 : ValidationInstance::ValidationInstance(
49 : const Options& options, Event::TimeSystem& time_system,
50 : const Network::Address::InstanceConstSharedPtr& local_address, Stats::IsolatedStoreImpl& store,
51 : Thread::BasicLockable& access_log_lock, ComponentFactory& component_factory,
52 : Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system,
53 : const ProcessContextOptRef& process_context)
54 : : options_(options), validation_context_(options_.allowUnknownStaticFields(),
55 : !options.rejectUnknownDynamicFields(),
56 : !options.ignoreUnknownDynamicFields()),
57 : stats_store_(store),
58 : api_(new Api::ValidationImpl(thread_factory, store, time_system, file_system,
59 : random_generator_, bootstrap_, process_context)),
60 : dispatcher_(api_->allocateDispatcher("main_thread")),
61 : singleton_manager_(new Singleton::ManagerImpl(api_->threadFactory())),
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 320 : server_contexts_(*this), quic_stat_names_(stats_store_.symbolTable()) {
67 320 : TRY_ASSERT_MAIN_THREAD { initialize(options, local_address, component_factory); }
68 320 : END_TRY
69 320 : catch (const EnvoyException& e) {
70 320 : ENVOY_LOG(critical, "error initializing configuration '{}': {}", options.configPath(),
71 320 : e.what());
72 320 : shutdown();
73 320 : throw;
74 320 : }
75 320 : }
76 :
77 : void ValidationInstance::initialize(const Options& options,
78 : const Network::Address::InstanceConstSharedPtr& local_address,
79 320 : 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 320 : InstanceUtil::loadBootstrapConfig(bootstrap_, options,
91 320 : messageValidationContext().staticValidationVisitor(), *api_);
92 :
93 320 : if (bootstrap_.has_application_log_config()) {
94 4 : THROW_IF_NOT_OK(
95 4 : Utility::assertExclusiveLogFormatMethod(options_, bootstrap_.application_log_config()));
96 4 : THROW_IF_NOT_OK(Utility::maybeSetApplicationLogFormat(bootstrap_.application_log_config()));
97 4 : }
98 :
99 : // Inject regex engine to singleton.
100 320 : Regex::EnginePtr regex_engine = createRegexEngine(
101 320 : bootstrap_, messageValidationContext().staticValidationVisitor(), serverFactoryContext());
102 :
103 320 : Config::Utility::createTagProducer(bootstrap_, options_.statsTags());
104 320 : if (!bootstrap_.node().user_agent_build_version().has_version()) {
105 114 : *bootstrap_.mutable_node()->mutable_user_agent_build_version() = VersionInfo::buildVersion();
106 114 : }
107 :
108 320 : local_info_ = std::make_unique<LocalInfo::LocalInfoImpl>(
109 320 : stats().symbolTable(), bootstrap_.node(), bootstrap_.node_context_params(), local_address,
110 320 : options.serviceZone(), options.serviceClusterName(), options.serviceNodeName());
111 :
112 320 : overload_manager_ = std::make_unique<OverloadManagerImpl>(
113 320 : dispatcher(), *stats().rootScope(), threadLocal(), bootstrap_.overload_manager(),
114 320 : messageValidationContext().staticValidationVisitor(), *api_, options_);
115 320 : Configuration::InitialImpl initial_config(bootstrap_);
116 320 : AdminFactoryContext factory_context(*this, std::make_shared<ListenerInfoImpl>());
117 320 : initial_config.initAdminAccessLog(bootstrap_, factory_context);
118 320 : admin_ = std::make_unique<Server::ValidationAdmin>(initial_config.admin().address());
119 320 : listener_manager_ = Config::Utility::getAndCheckFactoryByName<ListenerManagerFactory>(
120 320 : Config::ServerExtensionValues::get().VALIDATION_LISTENER)
121 320 : .createListenerManager(*this, nullptr, *this, false, quic_stat_names_);
122 320 : thread_local_.registerThread(*dispatcher_, true);
123 :
124 320 : runtime_ = component_factory.createRuntime(*this, initial_config);
125 320 : ENVOY_BUG(runtime_ != nullptr,
126 320 : "Component factory should not return nullptr from createRuntime()");
127 320 : drain_manager_ = component_factory.createDrainManager(*this);
128 320 : ENVOY_BUG(drain_manager_ != nullptr,
129 320 : "Component factory should not return nullptr from createDrainManager()");
130 :
131 320 : secret_manager_ = std::make_unique<Secret::SecretManagerImpl>(admin()->getConfigTracker());
132 320 : ssl_context_manager_ = createContextManager("ssl_context_manager", api_->timeSource());
133 320 : cluster_manager_factory_ = std::make_unique<Upstream::ValidationClusterManagerFactory>(
134 320 : server_contexts_, stats(), threadLocal(), http_context_,
135 320 : [this]() -> Network::DnsResolverSharedPtr { return this->dnsResolver(); },
136 320 : sslContextManager(), *secret_manager_, quic_stat_names_, *this);
137 320 : config_.initialize(bootstrap_, *this, *cluster_manager_factory_);
138 320 : runtime().initialize(clusterManager());
139 320 : clusterManager().setInitializedCb([this]() -> void { init_manager_.initialize(init_watcher_); });
140 320 : }
141 :
142 320 : void ValidationInstance::shutdown() {
143 : // This normally happens at the bottom of InstanceImpl::run(), but we don't have a run(). We can
144 : // do an abbreviated shutdown here since there's less to clean up -- for example, no workers to
145 : // exit.
146 320 : thread_local_.shutdownGlobalThreading();
147 320 : if (config_.clusterManager() != nullptr) {
148 0 : config_.clusterManager()->shutdown();
149 0 : }
150 320 : thread_local_.shutdownThread();
151 320 : dispatcher_->shutdown();
152 320 : }
153 :
154 : } // namespace Server
155 : } // namespace Envoy
|