diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 73728a14d882b..07fe156ae17f5 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -110,7 +110,7 @@ def envoy_api_deps(skip_targets): remote = REPO_LOCATIONS["envoy_api"], commit = "0b35f3efc31621953bc2eb7458d01d8eab984394", ) - bind_targets = ["address", "base", "cds", "eds", "health_check", "protocol", "tls_context"] + bind_targets = ["address", "base", "bootstrap", "cds", "eds", "health_check", "protocol", "tls_context"] for t in bind_targets: native.bind( name = "envoy_" + t, diff --git a/include/envoy/server/options.h b/include/envoy/server/options.h index 3b22b4b797966..c0dfeb15514be 100644 --- a/include/envoy/server/options.h +++ b/include/envoy/server/options.h @@ -64,6 +64,14 @@ class Options { */ virtual const std::string& configPath() PURE; + /** + * @return const std::string& the path to the v2 bootstrap file. + * TODO(htuch): We can eventually consolidate configPath()/bootstrapPath(), but today + * the config fetched from bootstrapPath() acts as an overlay to the config fetched from + * configPath() during v2 API bringup. + */ + virtual const std::string& bootstrapPath() PURE; + /** * @return const std::string& the admin address output file. */ diff --git a/include/envoy/upstream/BUILD b/include/envoy/upstream/BUILD index 2d7f2754d5213..8209528de38fc 100644 --- a/include/envoy/upstream/BUILD +++ b/include/envoy/upstream/BUILD @@ -11,7 +11,10 @@ envoy_package() envoy_cc_library( name = "cluster_manager_interface", hdrs = ["cluster_manager.h"], - external_deps = ["envoy_cds"], + external_deps = [ + "envoy_bootstrap", + "envoy_cds", + ], deps = [ ":load_balancer_interface", ":thread_local_cluster_interface", diff --git a/include/envoy/upstream/cluster_manager.h b/include/envoy/upstream/cluster_manager.h index caa8babd48730..eea2ef9164bde 100644 --- a/include/envoy/upstream/cluster_manager.h +++ b/include/envoy/upstream/cluster_manager.h @@ -16,6 +16,7 @@ #include "envoy/upstream/thread_local_cluster.h" #include "envoy/upstream/upstream.h" +#include "api/bootstrap.pb.h" #include "api/cds.pb.h" namespace Envoy { @@ -148,13 +149,14 @@ class ClusterManagerFactory { /** * Allocate a cluster manager from configuration JSON. + * TODO(htuch): Once bootstrap is sufficiently capable, switch to a translation from the JSON v1 + * cluster manager config -> v2 proto and drop the config parameter. */ - virtual ClusterManagerPtr clusterManagerFromJson(const Json::Object& config, Stats::Store& stats, - ThreadLocal::Instance& tls, - Runtime::Loader& runtime, - Runtime::RandomGenerator& random, - const LocalInfo::LocalInfo& local_info, - AccessLog::AccessLogManager& log_manager) PURE; + virtual ClusterManagerPtr + clusterManagerFromJson(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, + Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::Loader& runtime, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, + AccessLog::AccessLogManager& log_manager) PURE; /** * Allocate an HTTP connection pool. diff --git a/source/common/config/BUILD b/source/common/config/BUILD index a8678fed89055..c87995e81e086 100644 --- a/source/common/config/BUILD +++ b/source/common/config/BUILD @@ -49,8 +49,8 @@ envoy_cc_library( "//include/envoy/filesystem:filesystem_interface", "//source/common/common:logger_lib", "//source/common/config:utility_lib", - "//source/common/filesystem:filesystem_lib", "//source/common/protobuf", + "//source/common/protobuf:utility_lib", ], ) diff --git a/source/common/config/filesystem_subscription_impl.h b/source/common/config/filesystem_subscription_impl.h index 234c611da8cce..c59e7f5c52649 100644 --- a/source/common/config/filesystem_subscription_impl.h +++ b/source/common/config/filesystem_subscription_impl.h @@ -7,8 +7,8 @@ #include "common/common/logger.h" #include "common/common/macros.h" #include "common/config/utility.h" -#include "common/filesystem/filesystem_impl.h" #include "common/protobuf/protobuf.h" +#include "common/protobuf/utility.h" #include "api/base.pb.h" @@ -53,17 +53,8 @@ class FilesystemSubscriptionImpl : public Config::Subscription, stats_.update_attempt_.inc(); bool config_update_available = false; try { - const std::string json = Filesystem::fileReadToEnd(path_); envoy::api::v2::DiscoveryResponse message; - const auto status = - Protobuf::util::JsonStringToMessage(ProtobufTypes::ToString(json), &message); - if (!status.ok()) { - callbacks_->onConfigUpdateFailed(nullptr); - ENVOY_LOG(warn, "Filesystem config JSON conversion error: {}", - ProtobufTypes::FromString(status.ToString())); - stats_.update_failure_.inc(); - return; - } + MessageUtil::loadFromFile(path_, message); const auto typed_resources = Config::Utility::getTypedResources(message); config_update_available = true; callbacks_->onConfigUpdate(typed_resources); diff --git a/source/common/protobuf/BUILD b/source/common/protobuf/BUILD index 188fea724ec5f..da5d5108b20d7 100644 --- a/source/common/protobuf/BUILD +++ b/source/common/protobuf/BUILD @@ -22,5 +22,6 @@ envoy_cc_library( deps = [ ":protobuf", "//source/common/common:utility_lib", + "//source/common/filesystem:filesystem_lib", ], ) diff --git a/source/common/protobuf/utility.cc b/source/common/protobuf/utility.cc index 2cca8d7d80bdc..a012c42058bad 100644 --- a/source/common/protobuf/utility.cc +++ b/source/common/protobuf/utility.cc @@ -1,5 +1,7 @@ #include "common/protobuf/utility.h" +#include "common/filesystem/filesystem_impl.h" + #include "spdlog/spdlog.h" namespace Envoy { @@ -9,4 +11,12 @@ MissingFieldException::MissingFieldException(const std::string& field_name, : EnvoyException(fmt::format("Field '{}' is missing in: {}", field_name, ProtobufTypes::FromString(message.DebugString()))) {} +void MessageUtil::loadFromFile(const std::string& path, Protobuf::Message& message) { + const std::string json = Filesystem::fileReadToEnd(path); + const auto status = Protobuf::util::JsonStringToMessage(ProtobufTypes::ToString(json), &message); + if (!status.ok()) { + throw EnvoyException("Unable to parse JSON as proto: " + json); + } +} + } // namespace Envoy diff --git a/source/common/protobuf/utility.h b/source/common/protobuf/utility.h index 6c62510dc2d93..ac461f243f481 100644 --- a/source/common/protobuf/utility.h +++ b/source/common/protobuf/utility.h @@ -50,6 +50,8 @@ class MessageUtil { static std::size_t hash(const Protobuf::Message& message) { return std::hash{}(message.SerializeAsString()); } + + static void loadFromFile(const std::string& path, Protobuf::Message& message); }; } // namespace Envoy diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index 0e10c67a338ab..af5206d485272 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -154,15 +154,18 @@ void ClusterManagerInitHelper::setInitializedCb(std::function callback) } } -ClusterManagerImpl::ClusterManagerImpl(const Json::Object& config, ClusterManagerFactory& factory, - Stats::Store& stats, ThreadLocal::SlotAllocator& tls, - Runtime::Loader& runtime, Runtime::RandomGenerator& random, +ClusterManagerImpl::ClusterManagerImpl(const Json::Object& config, + const envoy::api::v2::Bootstrap& bootstrap, + ClusterManagerFactory& factory, Stats::Store& stats, + ThreadLocal::SlotAllocator& tls, Runtime::Loader& runtime, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager) : factory_(factory), runtime_(runtime), stats_(stats), tls_(tls.allocateSlot()), random_(random), local_info_(local_info), cm_stats_(generateStats(stats)) { config.validateSchema(Json::Schema::CLUSTER_MANAGER_SCHEMA); + UNREFERENCED_PARAMETER(bootstrap); if (config.hasObject("outlier_detection")) { std::string event_log_file_path = @@ -576,11 +579,11 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::connPool( } ClusterManagerPtr ProdClusterManagerFactory::clusterManagerFromJson( - const Json::Object& config, Stats::Store& stats, ThreadLocal::Instance& tls, - Runtime::Loader& runtime, Runtime::RandomGenerator& random, + const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, Stats::Store& stats, + ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager) { - return ClusterManagerPtr{ - new ClusterManagerImpl(config, *this, stats, tls, runtime, random, local_info, log_manager)}; + return ClusterManagerPtr{new ClusterManagerImpl(config, bootstrap, *this, stats, tls, runtime, + random, local_info, log_manager)}; } Http::ConnectionPool::InstancePtr diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h index 211925f51a72b..ddeccd70de135 100644 --- a/source/common/upstream/cluster_manager_impl.h +++ b/source/common/upstream/cluster_manager_impl.h @@ -39,11 +39,11 @@ class ProdClusterManagerFactory : public ClusterManagerFactory { local_info_(local_info) {} // Upstream::ClusterManagerFactory - ClusterManagerPtr clusterManagerFromJson(const Json::Object& config, Stats::Store& stats, - ThreadLocal::Instance& tls, Runtime::Loader& runtime, - Runtime::RandomGenerator& random, - const LocalInfo::LocalInfo& local_info, - AccessLog::AccessLogManager& log_manager) override; + ClusterManagerPtr + clusterManagerFromJson(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, + Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::Loader& runtime, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, + AccessLog::AccessLogManager& log_manager) override; Http::ConnectionPool::InstancePtr allocateConnPool(Event::Dispatcher& dispatcher, HostConstSharedPtr host, ResourcePriority priority) override; @@ -119,8 +119,9 @@ struct ClusterManagerStats { */ class ClusterManagerImpl : public ClusterManager, Logger::Loggable { public: - ClusterManagerImpl(const Json::Object& config, ClusterManagerFactory& factory, - Stats::Store& stats, ThreadLocal::SlotAllocator& tls, Runtime::Loader& runtime, + ClusterManagerImpl(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, + ClusterManagerFactory& factory, Stats::Store& stats, + ThreadLocal::SlotAllocator& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager); diff --git a/source/server/BUILD b/source/server/BUILD index 9f688fd5fc738..407ad213db5f1 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -20,6 +20,7 @@ envoy_cc_library( name = "configuration_lib", srcs = ["configuration_impl.cc"], hdrs = ["configuration_impl.h"], + external_deps = ["envoy_bootstrap"], deps = [ ":lds_api_lib", "//include/envoy/http:filter_interface", @@ -156,6 +157,7 @@ envoy_cc_library( name = "server_lib", srcs = ["server.cc"], hdrs = ["server.h"], + external_deps = ["envoy_bootstrap"], deps = [ ":configuration_lib", ":connection_handler_lib", @@ -181,6 +183,7 @@ envoy_cc_library( "//source/common/common:utility_lib", "//source/common/common:version_lib", "//source/common/memory:stats_lib", + "//source/common/protobuf:utility_lib", "//source/common/runtime:runtime_lib", "//source/common/stats:statsd_lib", "//source/common/upstream:cluster_manager_lib", diff --git a/source/server/config_validation/BUILD b/source/server/config_validation/BUILD index e40c94aa4f29b..120432eddc5a2 100644 --- a/source/server/config_validation/BUILD +++ b/source/server/config_validation/BUILD @@ -63,6 +63,7 @@ envoy_cc_library( name = "server_lib", srcs = ["server.cc"], hdrs = ["server.h"], + external_deps = ["envoy_bootstrap"], deps = [ ":api_lib", ":cluster_manager_lib", @@ -74,6 +75,7 @@ envoy_cc_library( "//include/envoy/tracing:http_tracer_interface", "//source/common/access_log:access_log_manager_lib", "//source/common/common:assert_lib", + "//source/common/protobuf:utility_lib", "//source/common/runtime:runtime_lib", "//source/common/ssl:context_lib", "//source/common/stats:stats_lib", diff --git a/source/server/config_validation/cluster_manager.cc b/source/server/config_validation/cluster_manager.cc index 29dbcf0935ee6..40aa9148e820f 100644 --- a/source/server/config_validation/cluster_manager.cc +++ b/source/server/config_validation/cluster_manager.cc @@ -12,11 +12,11 @@ ValidationClusterManagerFactory::ValidationClusterManagerFactory( primary_dispatcher, local_info) {} ClusterManagerPtr ValidationClusterManagerFactory::clusterManagerFromJson( - const Json::Object& config, Stats::Store& stats, ThreadLocal::Instance& tls, - Runtime::Loader& runtime, Runtime::RandomGenerator& random, + const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, Stats::Store& stats, + ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager) { - return ClusterManagerPtr{new ValidationClusterManager(config, *this, stats, tls, runtime, random, - local_info, log_manager)}; + return ClusterManagerPtr{new ValidationClusterManager(config, bootstrap, *this, stats, tls, + runtime, random, local_info, log_manager)}; } CdsApiPtr ValidationClusterManagerFactory::createCds(const Json::Object& config, @@ -29,10 +29,12 @@ CdsApiPtr ValidationClusterManagerFactory::createCds(const Json::Object& config, } ValidationClusterManager::ValidationClusterManager( - const Json::Object& config, ClusterManagerFactory& factory, Stats::Store& stats, - ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, + const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, + ClusterManagerFactory& factory, Stats::Store& stats, ThreadLocal::Instance& tls, + Runtime::Loader& runtime, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager) - : ClusterManagerImpl(config, factory, stats, tls, runtime, random, local_info, log_manager) {} + : ClusterManagerImpl(config, bootstrap, factory, stats, tls, runtime, random, local_info, + log_manager) {} Http::ConnectionPool::Instance* ValidationClusterManager::httpConnPoolForCluster(const std::string&, ResourcePriority, diff --git a/source/server/config_validation/cluster_manager.h b/source/server/config_validation/cluster_manager.h index c814ca17e1cca..ff3ebb9037c92 100644 --- a/source/server/config_validation/cluster_manager.h +++ b/source/server/config_validation/cluster_manager.h @@ -22,11 +22,11 @@ class ValidationClusterManagerFactory : public ProdClusterManagerFactory { Event::Dispatcher& primary_dispatcher, const LocalInfo::LocalInfo& local_info); - ClusterManagerPtr clusterManagerFromJson(const Json::Object& config, Stats::Store& stats, - ThreadLocal::Instance& tls, Runtime::Loader& runtime, - Runtime::RandomGenerator& random, - const LocalInfo::LocalInfo& local_info, - AccessLog::AccessLogManager& log_manager) override; + ClusterManagerPtr + clusterManagerFromJson(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, + Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::Loader& runtime, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, + AccessLog::AccessLogManager& log_manager) override; // Delegates to ProdClusterManagerFactory::createCds, but discards the result and returns nullptr // unconditionally. @@ -39,10 +39,10 @@ class ValidationClusterManagerFactory : public ProdClusterManagerFactory { */ class ValidationClusterManager : public ClusterManagerImpl { public: - ValidationClusterManager(const Json::Object& config, ClusterManagerFactory& factory, - Stats::Store& stats, ThreadLocal::Instance& tls, - Runtime::Loader& runtime, Runtime::RandomGenerator& random, - const LocalInfo::LocalInfo& local_info, + ValidationClusterManager(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, + ClusterManagerFactory& factory, Stats::Store& stats, + ThreadLocal::Instance& tls, Runtime::Loader& runtime, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, AccessLog::AccessLogManager& log_manager); Http::ConnectionPool::Instance* httpConnPoolForCluster(const std::string&, ResourcePriority, diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index b362cc2ebac78..b65a24f541bec 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -1,7 +1,11 @@ #include "server/config_validation/server.h" +#include "common/protobuf/utility.h" + #include "server/configuration_impl.h" +#include "api/bootstrap.pb.h" + namespace Envoy { namespace Server { @@ -50,6 +54,11 @@ void ValidationInstance::initialize(Options& options, ComponentFactory& componen // If we get all the way through that stripped-down initialization flow, to the point where we'd // be ready to serve, then the config has passed validation. Json::ObjectSharedPtr config_json = Json::Factory::loadFromFile(options.configPath()); + envoy::api::v2::Bootstrap bootstrap; + if (!options.bootstrapPath().empty()) { + MessageUtil::loadFromFile(options.bootstrapPath(), bootstrap); + } + Configuration::InitialImpl initial_config(*config_json); thread_local_.registerThread(*dispatcher_, true); runtime_loader_ = component_factory.createRuntime(*this, initial_config); @@ -60,7 +69,7 @@ void ValidationInstance::initialize(Options& options, ComponentFactory& componen Configuration::MainImpl* main_config = new Configuration::MainImpl(); config_.reset(main_config); - main_config->initialize(*config_json, *this, *cluster_manager_factory_); + main_config->initialize(*config_json, bootstrap, *this, *cluster_manager_factory_); clusterManager().setInitializedCb( [this]() -> void { init_manager_.initialize([]() -> void {}); }); diff --git a/source/server/configuration_impl.cc b/source/server/configuration_impl.cc index 8cfc21e41009b..e8a35005f4b1a 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -33,11 +33,12 @@ bool FilterChainUtility::buildFilterChain(Network::FilterManager& filter_manager return filter_manager.initializeReadFilters(); } -void MainImpl::initialize(const Json::Object& json, Instance& server, +void MainImpl::initialize(const Json::Object& json, const envoy::api::v2::Bootstrap& bootstrap, + Instance& server, Upstream::ClusterManagerFactory& cluster_manager_factory) { cluster_manager_ = cluster_manager_factory.clusterManagerFromJson( - *json.getObject("cluster_manager"), server.stats(), server.threadLocal(), server.runtime(), - server.random(), server.localInfo(), server.accessLogManager()); + *json.getObject("cluster_manager"), bootstrap, server.stats(), server.threadLocal(), + server.runtime(), server.random(), server.localInfo(), server.accessLogManager()); std::vector listeners = json.getObjectArray("listeners"); ENVOY_LOG(info, "loading {} listener(s)", listeners.size()); diff --git a/source/server/configuration_impl.h b/source/server/configuration_impl.h index 591f4f3edc84a..2fb18f6ba4614 100644 --- a/source/server/configuration_impl.h +++ b/source/server/configuration_impl.h @@ -22,6 +22,8 @@ #include "server/lds_api.h" +#include "api/bootstrap.pb.h" + namespace Envoy { namespace Server { namespace Configuration { @@ -106,11 +108,12 @@ class MainImpl : Logger::Loggable, public Main { * will call through the server into the config to get the cluster manager so the config object * must be created already. * @param json supplies the configuration JSON. + * @param bootstrap v2 bootstrap proto. * @param server supplies the owning server. * @param cluster_manager_factory supplies the cluster manager creation factory. */ - void initialize(const Json::Object& json, Instance& server, - Upstream::ClusterManagerFactory& cluster_manager_factory); + void initialize(const Json::Object& json, const envoy::api::v2::Bootstrap& bootstrap, + Instance& server, Upstream::ClusterManagerFactory& cluster_manager_factory); // Server::Configuration::Main Upstream::ClusterManager& clusterManager() override { return *cluster_manager_; } diff --git a/source/server/options_impl.cc b/source/server/options_impl.cc index a313b58d488b9..19e05aec244af 100644 --- a/source/server/options_impl.cc +++ b/source/server/options_impl.cc @@ -30,6 +30,8 @@ OptionsImpl::OptionsImpl(int argc, char** argv, const std::string& hot_restart_v std::thread::hardware_concurrency(), "uint32_t", cmd); TCLAP::ValueArg config_path("c", "config-path", "Path to configuration file", false, "", "string", cmd); + TCLAP::ValueArg bootstrap_path("b", "bootstrap-path", "Path to v2 bootstrap file", + false, "", "string", cmd); TCLAP::ValueArg admin_address_path("", "admin-address-path", "Admin address path", false, "", "string", cmd); TCLAP::ValueArg local_address_ip_version("", "local-address-ip-version", @@ -104,6 +106,7 @@ OptionsImpl::OptionsImpl(int argc, char** argv, const std::string& hot_restart_v base_id_ = base_id.getValue() * 10; concurrency_ = concurrency.getValue(); config_path_ = config_path.getValue(); + bootstrap_path_ = bootstrap_path.getValue(); admin_address_path_ = admin_address_path.getValue(); restart_epoch_ = restart_epoch.getValue(); service_cluster_ = service_cluster.getValue(); diff --git a/source/server/options_impl.h b/source/server/options_impl.h index 15be994d829fc..8aa25b3f2a132 100644 --- a/source/server/options_impl.h +++ b/source/server/options_impl.h @@ -25,6 +25,7 @@ class OptionsImpl : public Server::Options { uint64_t baseId() override { return base_id_; } uint32_t concurrency() override { return concurrency_; } const std::string& configPath() override { return config_path_; } + const std::string& bootstrapPath() override { return bootstrap_path_; } const std::string& adminAddressPath() override { return admin_address_path_; } Network::Address::IpVersion localAddressIpVersion() override { return local_address_ip_version_; } std::chrono::seconds drainTime() override { return drain_time_; } @@ -38,6 +39,7 @@ class OptionsImpl : public Server::Options { uint64_t base_id_; uint32_t concurrency_; std::string config_path_; + std::string bootstrap_path_; std::string admin_address_path_; Network::Address::IpVersion local_address_ip_version_; spdlog::level::level_enum log_level_; diff --git a/source/server/server.cc b/source/server/server.cc index d3e3cc2f00bef..9a28fed7f9f9f 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -18,6 +18,7 @@ #include "common/common/version.h" #include "common/memory/stats.h" #include "common/network/address_impl.h" +#include "common/protobuf/utility.h" #include "common/runtime/runtime_impl.h" #include "common/stats/statsd.h" #include "common/upstream/cluster_manager_impl.h" @@ -27,6 +28,8 @@ #include "server/guarddog_impl.h" #include "server/test_hooks.h" +#include "api/bootstrap.pb.h" + namespace Envoy { namespace Server { @@ -59,7 +62,9 @@ InstanceImpl::InstanceImpl(Options& options, TestHooks& hooks, HotRestart& resta try { initialize(options, component_factory); } catch (const EnvoyException& e) { - ENVOY_LOG(critical, "error initializing configuration '{}': {}", options.configPath(), + ENVOY_LOG(critical, "error initializing configuration '{}': {}", + options.configPath() + + (options.bootstrapPath().empty() ? "" : (";" + options.bootstrapPath())), e.what()); thread_local_.shutdownThread(); exit(1); @@ -141,6 +146,11 @@ void InstanceImpl::initialize(Options& options, ComponentFactory& component_fact // Handle configuration that needs to take place prior to the main configuration load. Json::ObjectSharedPtr config_json = Json::Factory::loadFromFile(options.configPath()); + envoy::api::v2::Bootstrap bootstrap; + if (!options.bootstrapPath().empty()) { + MessageUtil::loadFromFile(options.bootstrapPath(), bootstrap); + } + Configuration::InitialImpl initial_config(*config_json); ENVOY_LOG(info, "admin address: {}", initial_config.admin().address()->asString()); @@ -184,7 +194,7 @@ void InstanceImpl::initialize(Options& options, ComponentFactory& component_fact // per above. See MainImpl::initialize() for why we do this pointer dance. Configuration::MainImpl* main_config = new Configuration::MainImpl(); config_.reset(main_config); - main_config->initialize(*config_json, *this, *cluster_manager_factory_); + main_config->initialize(*config_json, bootstrap, *this, *cluster_manager_factory_); // Setup signals. sigterm_ = dispatcher_->listenForSignal(SIGTERM, [this]() -> void { diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index d416521c3c02f..4448fcfaa1c34 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -70,7 +70,8 @@ class TestClusterManagerFactory : public ClusterManagerFactory { return CdsApiPtr{createCds_()}; } - ClusterManagerPtr clusterManagerFromJson(const Json::Object& config, Stats::Store& stats, + ClusterManagerPtr clusterManagerFromJson(const Json::Object& config, + const envoy::api::v2::Bootstrap&, Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, @@ -105,9 +106,10 @@ class TestClusterManagerFactory : public ClusterManagerFactory { class ClusterManagerImplTest : public testing::Test { public: void create(const Json::Object& config) { - cluster_manager_.reset(new ClusterManagerImpl(config, factory_, factory_.stats_, factory_.tls_, - factory_.runtime_, factory_.random_, - factory_.local_info_, log_manager_)); + envoy::api::v2::Bootstrap bootstrap; + cluster_manager_.reset(new ClusterManagerImpl( + config, bootstrap, factory_, factory_.stats_, factory_.tls_, factory_.runtime_, + factory_.random_, factory_.local_info_, log_manager_)); } NiceMock factory_; diff --git a/test/config_test/config_test.cc b/test/config_test/config_test.cc index c00981f1965a8..7e340344f6113 100644 --- a/test/config_test/config_test.cc +++ b/test/config_test/config_test.cc @@ -33,6 +33,7 @@ class ConfigTest { .WillByDefault(Return("access_token")); Json::ObjectSharedPtr config_json = Json::Factory::loadFromFile(file_path); + envoy::api::v2::Bootstrap bootstrap; Server::Configuration::InitialImpl initial_config(*config_json); Server::Configuration::MainImpl main_config; @@ -53,7 +54,7 @@ class ConfigTest { })); try { - main_config.initialize(*config_json, server_, *cluster_manager_factory_); + main_config.initialize(*config_json, bootstrap, server_, *cluster_manager_factory_); } catch (const EnvoyException& ex) { ADD_FAILURE() << fmt::format("'{}' config failed. Error: {}", file_path, ex.what()); } diff --git a/test/integration/server.h b/test/integration/server.h index e4d776789d501..8db610b274969 100644 --- a/test/integration/server.h +++ b/test/integration/server.h @@ -33,6 +33,7 @@ class TestOptionsImpl : public Options { uint64_t baseId() override { return 0; } uint32_t concurrency() override { return 1; } const std::string& configPath() override { return config_path_; } + const std::string& bootstrapPath() override { return bootstrap_path_; } const std::string& adminAddressPath() override { return admin_address_path_; } Network::Address::IpVersion localAddressIpVersion() override { return local_address_ip_version_; } std::chrono::seconds drainTime() override { return std::chrono::seconds(1); } @@ -46,6 +47,7 @@ class TestOptionsImpl : public Options { private: const std::string config_path_; + const std::string bootstrap_path_; const std::string admin_address_path_; Network::Address::IpVersion local_address_ip_version_; }; diff --git a/test/mocks/server/mocks.cc b/test/mocks/server/mocks.cc index 3a36b8a72a0e8..ea11424ee2768 100644 --- a/test/mocks/server/mocks.cc +++ b/test/mocks/server/mocks.cc @@ -15,9 +15,10 @@ using testing::_; namespace Envoy { namespace Server { -MockOptions::MockOptions(const std::string& config_path) - : config_path_(config_path), admin_address_path_("") { +MockOptions::MockOptions(const std::string& config_path, const std::string& bootstrap_path) + : config_path_(config_path), bootstrap_path_(bootstrap_path), admin_address_path_("") { ON_CALL(*this, configPath()).WillByDefault(ReturnRef(config_path_)); + ON_CALL(*this, bootstrapPath()).WillByDefault(ReturnRef(bootstrap_path_)); ON_CALL(*this, adminAddressPath()).WillByDefault(ReturnRef(admin_address_path_)); } MockOptions::~MockOptions() {} diff --git a/test/mocks/server/mocks.h b/test/mocks/server/mocks.h index 55826fd3e0987..de0cc7d827c54 100644 --- a/test/mocks/server/mocks.h +++ b/test/mocks/server/mocks.h @@ -39,12 +39,14 @@ namespace Server { class MockOptions : public Options { public: MockOptions() : MockOptions(std::string()) {} - MockOptions(const std::string& path); + MockOptions(const std::string& config_path) : MockOptions(config_path, std::string()) {} + MockOptions(const std::string& config_path, const std::string& boostrap_path); ~MockOptions(); MOCK_METHOD0(baseId, uint64_t()); MOCK_METHOD0(concurrency, uint32_t()); MOCK_METHOD0(configPath, const std::string&()); + MOCK_METHOD0(bootstrapPath, const std::string&()); MOCK_METHOD0(adminAddressPath, const std::string&()); MOCK_METHOD0(localAddressIpVersion, Network::Address::IpVersion()); MOCK_METHOD0(drainTime, std::chrono::seconds()); @@ -55,6 +57,7 @@ class MockOptions : public Options { MOCK_CONST_METHOD0(mode, Mode()); std::string config_path_; + std::string bootstrap_path_; std::string admin_address_path_; }; diff --git a/test/server/BUILD b/test/server/BUILD index 768117b65d5a5..cb97081996c31 100644 --- a/test/server/BUILD +++ b/test/server/BUILD @@ -109,6 +109,7 @@ envoy_cc_test( name = "server_test", srcs = ["server_test.cc"], data = [ + ":empty_bootstrap.json", "//test/config/integration:server.json", "//test/config/integration:server_config_files", ], diff --git a/test/server/config_validation/cluster_manager_test.cc b/test/server/config_validation/cluster_manager_test.cc index dc51d19157c58..ea08a1a6c76f3 100644 --- a/test/server/config_validation/cluster_manager_test.cc +++ b/test/server/config_validation/cluster_manager_test.cc @@ -40,9 +40,9 @@ TEST(ValidationClusterManagerTest, MockedMethods) { )EOF"; Json::ObjectSharedPtr config = Json::Factory::loadFromString(json); AccessLog::MockAccessLogManager log_manager; - - ClusterManagerPtr cluster_manager = - factory.clusterManagerFromJson(*config, stats, tls, runtime, random, local_info, log_manager); + envoy::api::v2::Bootstrap bootstrap; + ClusterManagerPtr cluster_manager = factory.clusterManagerFromJson( + *config, bootstrap, stats, tls, runtime, random, local_info, log_manager); EXPECT_EQ(nullptr, cluster_manager->httpConnPoolForCluster("cluster", ResourcePriority::Default, nullptr)); Host::CreateConnectionData data = cluster_manager->tcpConnForCluster("cluster"); diff --git a/test/server/configuration_impl_test.cc b/test/server/configuration_impl_test.cc index 9abd6518693f8..e57014a16fe3d 100644 --- a/test/server/configuration_impl_test.cc +++ b/test/server/configuration_impl_test.cc @@ -66,9 +66,10 @@ TEST_F(ConfigurationImplTest, DefaultStatsFlushInterval) { )EOF"; Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); + envoy::api::v2::Bootstrap bootstrap; MainImpl config; - config.initialize(*loader, server_, cluster_manager_factory_); + config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); EXPECT_EQ(std::chrono::milliseconds(5000), config.statsFlushInterval()); } @@ -87,9 +88,10 @@ TEST_F(ConfigurationImplTest, CustomStatsFlushInterval) { )EOF"; Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); + envoy::api::v2::Bootstrap bootstrap; MainImpl config; - config.initialize(*loader, server_, cluster_manager_factory_); + config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); EXPECT_EQ(std::chrono::milliseconds(500), config.statsFlushInterval()); } @@ -116,9 +118,10 @@ TEST_F(ConfigurationImplTest, SetUpstreamClusterPerConnectionBufferLimit) { )EOF"; Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); + envoy::api::v2::Bootstrap bootstrap; MainImpl config; - config.initialize(*loader, server_, cluster_manager_factory_); + config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); ASSERT_EQ(1U, config.clusterManager().clusters().count("test_cluster")); EXPECT_EQ(8192U, config.clusterManager() @@ -156,10 +159,12 @@ TEST_F(ConfigurationImplTest, ServiceClusterNotSetWhenLSTracing) { )EOF"; Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); + envoy::api::v2::Bootstrap bootstrap; server_.local_info_.cluster_name_ = ""; MainImpl config; - EXPECT_THROW(config.initialize(*loader, server_, cluster_manager_factory_), EnvoyException); + EXPECT_THROW(config.initialize(*loader, bootstrap, server_, cluster_manager_factory_), + EnvoyException); } TEST_F(ConfigurationImplTest, NullTracerSetWhenTracingConfigurationAbsent) { @@ -178,10 +183,11 @@ TEST_F(ConfigurationImplTest, NullTracerSetWhenTracingConfigurationAbsent) { )EOF"; Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); + envoy::api::v2::Bootstrap bootstrap; server_.local_info_.cluster_name_ = ""; MainImpl config; - config.initialize(*loader, server_, cluster_manager_factory_); + config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); EXPECT_NE(nullptr, dynamic_cast(&config.httpTracer())); } @@ -212,10 +218,11 @@ TEST_F(ConfigurationImplTest, NullTracerSetWhenHttpKeyAbsentFromTracerConfigurat )EOF"; Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); + envoy::api::v2::Bootstrap bootstrap; server_.local_info_.cluster_name_ = ""; MainImpl config; - config.initialize(*loader, server_, cluster_manager_factory_); + config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); EXPECT_NE(nullptr, dynamic_cast(&config.httpTracer())); } @@ -246,9 +253,11 @@ TEST_F(ConfigurationImplTest, ConfigurationFailsWhenInvalidTracerSpecified) { )EOF"; Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); + envoy::api::v2::Bootstrap bootstrap; MainImpl config; - EXPECT_THROW_WITH_MESSAGE(config.initialize(*loader, server_, cluster_manager_factory_), - EnvoyException, "No HttpTracerFactory found for type: invalid"); + EXPECT_THROW_WITH_MESSAGE( + config.initialize(*loader, bootstrap, server_, cluster_manager_factory_), EnvoyException, + "No HttpTracerFactory found for type: invalid"); } } // namespace Configuration diff --git a/test/server/empty_bootstrap.json b/test/server/empty_bootstrap.json new file mode 100644 index 0000000000000..0967ef424bce6 --- /dev/null +++ b/test/server/empty_bootstrap.json @@ -0,0 +1 @@ +{} diff --git a/test/server/server_test.cc b/test/server/server_test.cc index ed552470389db..e5c8a5f81b5dc 100644 --- a/test/server/server_test.cc +++ b/test/server/server_test.cc @@ -39,7 +39,8 @@ class ServerInstanceImplTest : public testing::TestWithParam