diff --git a/include/envoy/server/BUILD b/include/envoy/server/BUILD index f45f2f2c6f84..c43dba589d91 100644 --- a/include/envoy/server/BUILD +++ b/include/envoy/server/BUILD @@ -105,6 +105,7 @@ envoy_cc_library( "//include/envoy/access_log:access_log_interface", "//include/envoy/http:filter_interface", "//include/envoy/init:init_interface", + "//include/envoy/json:json_object_interface", "//include/envoy/local_info:local_info_interface", "//include/envoy/network:drain_decision_interface", "//include/envoy/ratelimit:ratelimit_interface", diff --git a/include/envoy/server/configuration.h b/include/envoy/server/configuration.h index 8a005a7dc926..1c91da638828 100644 --- a/include/envoy/server/configuration.h +++ b/include/envoy/server/configuration.h @@ -69,9 +69,9 @@ class Main { virtual Optional statsdTcpClusterName() PURE; /** - * @return Optional the optional UDP statsd address to write to. + * @return Network::Address::InstanceConstSharedPtr the optional UDP statsd address to write to. */ - virtual Optional statsdUdpIpAddress() PURE; + virtual Network::Address::InstanceConstSharedPtr statsdUdpIpAddress() PURE; /** * @return std::chrono::milliseconds the time interval between flushing to configured stat sinks. diff --git a/include/envoy/server/options.h b/include/envoy/server/options.h index f0d45aeef2fd..a655bb9e1a41 100644 --- a/include/envoy/server/options.h +++ b/include/envoy/server/options.h @@ -64,14 +64,6 @@ 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 a27a80a27cb6..96355723fcb8 100644 --- a/include/envoy/upstream/BUILD +++ b/include/envoy/upstream/BUILD @@ -22,7 +22,6 @@ envoy_cc_library( "//include/envoy/access_log:access_log_interface", "//include/envoy/http:async_client_interface", "//include/envoy/http:conn_pool_interface", - "//include/envoy/json:json_object_interface", "//include/envoy/local_info:local_info_interface", "//include/envoy/runtime:runtime_interface", ], diff --git a/include/envoy/upstream/cluster_manager.h b/include/envoy/upstream/cluster_manager.h index 29c6248e3916..a3e47e13ed0b 100644 --- a/include/envoy/upstream/cluster_manager.h +++ b/include/envoy/upstream/cluster_manager.h @@ -9,7 +9,6 @@ #include "envoy/access_log/access_log.h" #include "envoy/http/async_client.h" #include "envoy/http/conn_pool.h" -#include "envoy/json/json_object.h" #include "envoy/local_info/local_info.h" #include "envoy/runtime/runtime.h" #include "envoy/upstream/load_balancer.h" @@ -120,14 +119,6 @@ class ClusterManager { typedef std::unique_ptr ClusterManagerPtr; -/** - * Global configuration for any SDS clusters. - */ -struct SdsConfig { - std::string sds_cluster_name_; - std::chrono::milliseconds refresh_delay_; -}; - /** * Abstract interface for a CDS API provider. */ @@ -157,15 +148,14 @@ class ClusterManagerFactory { virtual ~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. + * Allocate a cluster manager from configuration proto. */ - 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; + virtual ClusterManagerPtr clusterManagerFromProto(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. @@ -186,7 +176,8 @@ class ClusterManagerFactory { * Create a CDS API provider from configuration proto. */ virtual CdsApiPtr createCds(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm) PURE; + const Optional& eds_config, + ClusterManager& cm) PURE; }; } // namespace Upstream diff --git a/include/envoy/upstream/resource_manager.h b/include/envoy/upstream/resource_manager.h index 839ddfab34d7..2bb474560ccf 100644 --- a/include/envoy/upstream/resource_manager.h +++ b/include/envoy/upstream/resource_manager.h @@ -12,7 +12,7 @@ namespace Upstream { * arrays for each priority, but does not pollute the enum. */ enum class ResourcePriority { Default, High }; -const size_t NumResourcePriorities = 2; +const std::size_t NumResourcePriorities = 2; /** * An individual resource tracked by the resource manager. diff --git a/source/common/config/BUILD b/source/common/config/BUILD index 0674d7cfe0c6..8955c6cd16a6 100644 --- a/source/common/config/BUILD +++ b/source/common/config/BUILD @@ -20,6 +20,24 @@ envoy_cc_library( ], ) +envoy_cc_library( + name = "bootstrap_json_lib", + srcs = ["bootstrap_json.cc"], + hdrs = ["bootstrap_json.h"], + external_deps = ["envoy_bootstrap"], + deps = [ + ":address_json_lib", + ":cds_json_lib", + ":json_utility_lib", + ":lds_json_lib", + ":utility_lib", + "//include/envoy/json:json_object_interface", + "//source/common/common:assert_lib", + "//source/common/json:config_schemas_lib", + "//source/common/protobuf:utility_lib", + ], +) + envoy_cc_library( name = "base_json_lib", srcs = ["base_json.cc"], diff --git a/source/common/config/bootstrap_json.cc b/source/common/config/bootstrap_json.cc new file mode 100644 index 000000000000..a7280834a504 --- /dev/null +++ b/source/common/config/bootstrap_json.cc @@ -0,0 +1,131 @@ +#include "common/config/bootstrap_json.h" + +#include "common/common/assert.h" +#include "common/config/address_json.h" +#include "common/config/cds_json.h" +#include "common/config/json_utility.h" +#include "common/config/lds_json.h" +#include "common/config/utility.h" +#include "common/json/config_schemas.h" +#include "common/protobuf/utility.h" + +namespace Envoy { +namespace Config { + +void BootstrapJson::translateClusterManagerBootstrap(const Json::Object& json_cluster_manager, + envoy::api::v2::Bootstrap& bootstrap) { + json_cluster_manager.validateSchema(Json::Schema::CLUSTER_MANAGER_SCHEMA); + + Optional eds_config; + if (json_cluster_manager.hasObject("sds")) { + const auto json_sds = json_cluster_manager.getObject("sds"); + auto* cluster = bootstrap.mutable_static_resources()->mutable_clusters()->Add(); + Config::CdsJson::translateCluster(*json_sds->getObject("cluster"), + Optional(), *cluster); + Config::Utility::translateEdsConfig( + *json_sds, + *bootstrap.mutable_dynamic_resources()->mutable_deprecated_v1()->mutable_sds_config()); + eds_config.value(bootstrap.dynamic_resources().deprecated_v1().sds_config()); + } + + if (json_cluster_manager.hasObject("cds")) { + const auto json_cds = json_cluster_manager.getObject("cds"); + auto* cluster = bootstrap.mutable_static_resources()->mutable_clusters()->Add(); + Config::CdsJson::translateCluster(*json_cds->getObject("cluster"), eds_config, *cluster); + Config::Utility::translateCdsConfig( + *json_cds, *bootstrap.mutable_dynamic_resources()->mutable_cds_config()); + } + + for (const Json::ObjectSharedPtr& json_cluster : + json_cluster_manager.getObjectArray("clusters")) { + auto* cluster = bootstrap.mutable_static_resources()->mutable_clusters()->Add(); + Config::CdsJson::translateCluster(*json_cluster, eds_config, *cluster); + } + + auto* cluster_manager = bootstrap.mutable_cluster_manager(); + JSON_UTIL_SET_STRING(json_cluster_manager, *cluster_manager, local_cluster_name); + if (json_cluster_manager.hasObject("outlier_detection")) { + JSON_UTIL_SET_STRING(*json_cluster_manager.getObject("outlier_detection"), + *cluster_manager->mutable_outlier_detection(), event_log_path); + } +} + +void BootstrapJson::translateBootstrap(const Json::Object& json_config, + envoy::api::v2::Bootstrap& bootstrap) { + json_config.validateSchema(Json::Schema::TOP_LEVEL_CONFIG_SCHEMA); + + translateClusterManagerBootstrap(*json_config.getObject("cluster_manager"), bootstrap); + + if (json_config.hasObject("lds")) { + auto* lds_config = bootstrap.mutable_dynamic_resources()->mutable_lds_config(); + Config::Utility::translateLdsConfig(*json_config.getObject("lds"), *lds_config); + } + + for (const auto json_listener : json_config.getObjectArray("listeners")) { + auto* listener = bootstrap.mutable_static_resources()->mutable_listeners()->Add(); + Config::LdsJson::translateListener(*json_listener, *listener); + } + + JSON_UTIL_SET_STRING(json_config, bootstrap, flags_path); + + auto* stats_sinks = bootstrap.mutable_stats_sinks(); + if (json_config.hasObject("statsd_udp_ip_address")) { + auto* stats_sink = stats_sinks->Add(); + stats_sink->set_name("envoy.statsd"); + envoy::api::v2::StatsdSink statsd_sink; + AddressJson::translateAddress(json_config.getString("statsd_udp_ip_address"), false, true, + *statsd_sink.mutable_address()); + MessageUtil::jsonConvert(statsd_sink, *stats_sink->mutable_config()); + } + + if (json_config.hasObject("statsd_tcp_cluster_name")) { + auto* stats_sink = stats_sinks->Add(); + stats_sink->set_name("envoy.statsd"); + envoy::api::v2::StatsdSink statsd_sink; + statsd_sink.set_tcp_cluster_name(json_config.getString("statsd_tcp_cluster_name")); + MessageUtil::jsonConvert(statsd_sink, *stats_sink->mutable_config()); + } + + JSON_UTIL_SET_DURATION(json_config, bootstrap, stats_flush_interval); + + auto* watchdog = bootstrap.mutable_watchdog(); + JSON_UTIL_SET_DURATION(json_config, *watchdog, miss_timeout); + JSON_UTIL_SET_DURATION(json_config, *watchdog, megamiss_timeout); + JSON_UTIL_SET_DURATION(json_config, *watchdog, kill_timeout); + JSON_UTIL_SET_DURATION(json_config, *watchdog, multikill_timeout); + + const auto http = json_config.getObject("tracing", true)->getObject("http", true); + if (http->hasObject("driver")) { + const auto driver = http->getObject("driver"); + auto* http_tracing = bootstrap.mutable_tracing()->mutable_http(); + http_tracing->set_name("envoy." + driver->getString("type")); + MessageUtil::loadFromJson(driver->getObject("config")->asJsonString(), + *http_tracing->mutable_config()); + } + + if (json_config.hasObject("rate_limit_service")) { + const auto json_rate_limit_service = json_config.getObject("rate_limit_service"); + auto* rate_limit_service = bootstrap.mutable_rate_limit_service(); + ASSERT(json_rate_limit_service->getString("type") == "grpc_service"); + JSON_UTIL_SET_STRING(*json_rate_limit_service->getObject("config"), *rate_limit_service, + cluster_name); + } + + const auto json_admin = json_config.getObject("admin"); + auto* admin = bootstrap.mutable_admin(); + JSON_UTIL_SET_STRING(*json_admin, *admin, access_log_path); + JSON_UTIL_SET_STRING(*json_admin, *admin, profile_path); + AddressJson::translateAddress(json_admin->getString("address"), true, true, + *admin->mutable_address()); + + if (json_config.hasObject("runtime")) { + const auto json_runtime = json_config.getObject("runtime"); + auto* runtime = bootstrap.mutable_runtime(); + JSON_UTIL_SET_STRING(*json_runtime, *runtime, symlink_root); + JSON_UTIL_SET_STRING(*json_runtime, *runtime, subdirectory); + JSON_UTIL_SET_STRING(*json_runtime, *runtime, override_subdirectory); + } +} + +} // namespace Config +} // namespace Envoy diff --git a/source/common/config/bootstrap_json.h b/source/common/config/bootstrap_json.h new file mode 100644 index 000000000000..114f6c3a646f --- /dev/null +++ b/source/common/config/bootstrap_json.h @@ -0,0 +1,30 @@ +#pragma once + +#include "envoy/json/json_object.h" + +#include "api/bootstrap.pb.h" + +namespace Envoy { +namespace Config { + +class BootstrapJson { +public: + /** + * Translate a v1 JSON cluster manager object to v2 envoy::api::v2::Bootstrap. + * @param json_cluster_manager source v1 JSON cluster manager object. + * @param bootstrap destination v2 envoy::api::v2::Bootstrap. + */ + static void translateClusterManagerBootstrap(const Json::Object& json_cluster_manager, + envoy::api::v2::Bootstrap& bootstrap); + + /** + * Translate a v1 JSON static config object to v2 envoy::api::v2::Bootstrap. + * @param json_config source v1 JSON static config object. + * @param bootstrap destination v2 envoy::api::v2::Bootstrap. + */ + static void translateBootstrap(const Json::Object& json_config, + envoy::api::v2::Bootstrap& bootstrap); +}; + +} // namespace Config +} // namespace Envoy diff --git a/source/common/config/cds_json.cc b/source/common/config/cds_json.cc index b3d30a116f15..40935b0cdebd 100644 --- a/source/common/config/cds_json.cc +++ b/source/common/config/cds_json.cc @@ -81,7 +81,7 @@ void CdsJson::translateOutlierDetection( } void CdsJson::translateCluster(const Json::Object& json_cluster, - const Optional& sds_config, + const Optional& eds_config, envoy::api::v2::Cluster& cluster) { json_cluster.validateSchema(Json::Schema::CLUSTER_SCHEMA); cluster.set_name(json_cluster.getString("name")); @@ -120,9 +120,8 @@ void CdsJson::translateCluster(const Json::Object& json_cluster, } else { ASSERT(string_type == "sds"); cluster.set_type(envoy::api::v2::Cluster::EDS); - auto* eds_cluster_config = cluster.mutable_eds_cluster_config(); - Utility::sdsConfigToEdsConfig(sds_config.value(), *eds_cluster_config->mutable_eds_config()); - eds_cluster_config->set_service_name(json_cluster.getString("service_name", "")); + cluster.mutable_eds_cluster_config()->mutable_eds_config()->CopyFrom(eds_config.value()); + JSON_UTIL_SET_STRING(json_cluster, *cluster.mutable_eds_cluster_config(), service_name); } JSON_UTIL_SET_DURATION(json_cluster, cluster, cleanup_interval); diff --git a/source/common/config/cds_json.h b/source/common/config/cds_json.h index b29883d8bf94..a3c16bd632d3 100644 --- a/source/common/config/cds_json.h +++ b/source/common/config/cds_json.h @@ -49,11 +49,11 @@ class CdsJson { /** * Translate a v1 JSON Cluster to v2 envoy::api::v2::Cluster. * @param json_cluster source v1 JSON Cluster object. - * @param sds_config SDS config if 'sds' discovery type. + * @param eds_config SDS config if 'sds' discovery type. * @param cluster destination v2 envoy::api::v2::Cluster. */ static void translateCluster(const Json::Object& json_cluster, - const Optional& sds_config, + const Optional& eds_config, envoy::api::v2::Cluster& cluster); }; diff --git a/source/common/config/utility.cc b/source/common/config/utility.cc index f7974ff00c9e..ea42a6532860 100644 --- a/source/common/config/utility.cc +++ b/source/common/config/utility.cc @@ -59,13 +59,11 @@ Utility::apiConfigSourceRefreshDelay(const envoy::api::v2::ApiConfigSource& api_ Protobuf::util::TimeUtil::DurationToMilliseconds(api_config_source.refresh_delay())); } -void Utility::sdsConfigToEdsConfig(const Upstream::SdsConfig& sds_config, - envoy::api::v2::ConfigSource& eds_config) { - auto* api_config_source = eds_config.mutable_api_config_source(); - api_config_source->set_api_type(envoy::api::v2::ApiConfigSource::REST_LEGACY); - api_config_source->add_cluster_name(sds_config.sds_cluster_name_); - api_config_source->mutable_refresh_delay()->CopyFrom( - Protobuf::util::TimeUtil::MillisecondsToDuration(sds_config.refresh_delay_.count())); +void Utility::translateEdsConfig(const Json::Object& json_config, + envoy::api::v2::ConfigSource& eds_config) { + translateApiConfigSource(json_config.getObject("cluster")->getString("name"), + json_config.getInteger("refresh_delay_ms", 30000), + *eds_config.mutable_api_config_source()); } void Utility::translateCdsConfig(const Json::Object& json_config, diff --git a/source/common/config/utility.h b/source/common/config/utility.h index 557521c29505..57c65472f12d 100644 --- a/source/common/config/utility.h +++ b/source/common/config/utility.h @@ -1,6 +1,7 @@ #pragma once #include "envoy/config/subscription.h" +#include "envoy/json/json_object.h" #include "envoy/local_info/local_info.h" #include "envoy/upstream/cluster_manager.h" @@ -69,12 +70,12 @@ class Utility { const LocalInfo::LocalInfo& local_info); /** - * Convert a v1 SdsConfig to v2 EDS envoy::api::v2::ConfigSource. - * @param sds_config source v1 SdsConfig. + * Convert a v1 SDS JSON config to v2 EDS envoy::api::v2::ConfigSource. + * @param json_config source v1 SDS JSON config. * @param eds_config destination v2 EDS envoy::api::v2::ConfigSource. */ - static void sdsConfigToEdsConfig(const Upstream::SdsConfig& sds_config, - envoy::api::v2::ConfigSource& eds_config); + static void translateEdsConfig(const Json::Object& json_config, + envoy::api::v2::ConfigSource& eds_config); /** * Convert a v1 CDS JSON config to v2 CDS envoy::api::v2::ConfigSource. diff --git a/source/common/network/utility.cc b/source/common/network/utility.cc index cdc0c72ef424..137b3a9a2a29 100644 --- a/source/common/network/utility.cc +++ b/source/common/network/utility.cc @@ -153,7 +153,7 @@ Address::InstanceConstSharedPtr Utility::fromProtoAddress(const envoy::api::v2:: case envoy::api::v2::Address::kPipe: return Address::InstanceConstSharedPtr{new Address::PipeInstance(address.pipe().path())}; default: - NOT_REACHED; + throw EnvoyException("Address must be a socket or pipe: " + address.DebugString()); } } diff --git a/source/common/protobuf/utility.cc b/source/common/protobuf/utility.cc index 695262a134f3..a7f12abe36df 100644 --- a/source/common/protobuf/utility.cc +++ b/source/common/protobuf/utility.cc @@ -52,4 +52,14 @@ std::string MessageUtil::getJsonStringFromMessage(const Protobuf::Message& messa return json; } +void MessageUtil::jsonConvert(const Protobuf::Message& source, Protobuf::Message& dest) { + // TODO(htuch): Consolidate with the inflight cleanups here. + Protobuf::util::JsonOptions json_options; + ProtobufTypes::String json; + const auto status = Protobuf::util::MessageToJsonString(source, &json, json_options); + // This should always succeed unless something crash-worthy such as out-of-memory. + RELEASE_ASSERT(status.ok()); + MessageUtil::loadFromJson(json, dest); +} + } // namespace Envoy diff --git a/source/common/protobuf/utility.h b/source/common/protobuf/utility.h index 9be6f1ea13e8..d7f8ead9d9fe 100644 --- a/source/common/protobuf/utility.h +++ b/source/common/protobuf/utility.h @@ -67,6 +67,16 @@ class MessageUtil { static void loadFromJson(const std::string& json, Protobuf::Message& message); static void loadFromFile(const std::string& path, Protobuf::Message& message); + /** + * Convert between two protobufs via a JSON round-trip. This is used to translate arbitrary + * messages to/from google.protobuf.Struct. + * TODO(htuch): Avoid round-tripping via JSON strings by doing whatever + * Protobuf::util::MessageToJsonString does but generating a google.protobuf.Struct instead. + * @param source message. + * @param dest message. + */ + static void jsonConvert(const Protobuf::Message& source, Protobuf::Message& dest); + /** * Extract JSON as string from a google.protobuf.Message. * @param message message of type type.googleapis.com/google.protobuf.Message. diff --git a/source/common/ratelimit/BUILD b/source/common/ratelimit/BUILD index 11f38e47f3a2..93d1d4f46440 100644 --- a/source/common/ratelimit/BUILD +++ b/source/common/ratelimit/BUILD @@ -13,6 +13,7 @@ envoy_cc_library( name = "ratelimit_lib", srcs = ["ratelimit_impl.cc"], hdrs = ["ratelimit_impl.h"], + external_deps = ["envoy_bootstrap"], deps = [ ":ratelimit_proto", "//include/envoy/grpc:async_client_interface", @@ -23,7 +24,6 @@ envoy_cc_library( "//source/common/common:empty_string", "//source/common/grpc:async_client_lib", "//source/common/http:headers_lib", - "//source/common/json:json_loader_lib", ], ) diff --git a/source/common/ratelimit/ratelimit_impl.cc b/source/common/ratelimit/ratelimit_impl.cc index b0a52b5eb7b5..c95faef60af8 100644 --- a/source/common/ratelimit/ratelimit_impl.cc +++ b/source/common/ratelimit/ratelimit_impl.cc @@ -85,8 +85,9 @@ void GrpcClientImpl::onFailure(Grpc::Status::GrpcStatus status, const std::strin callbacks_ = nullptr; } -GrpcFactoryImpl::GrpcFactoryImpl(const Json::Object& config, Upstream::ClusterManager& cm) - : cluster_name_(config.getString("cluster_name")), cm_(cm) { +GrpcFactoryImpl::GrpcFactoryImpl(const envoy::api::v2::RateLimitServiceConfig& config, + Upstream::ClusterManager& cm) + : cluster_name_(config.cluster_name()), cm_(cm) { if (!cm_.get(cluster_name_)) { throw EnvoyException(fmt::format("unknown rate limit service cluster '{}'", cluster_name_)); } diff --git a/source/common/ratelimit/ratelimit_impl.h b/source/common/ratelimit/ratelimit_impl.h index adf8ab2923a0..4bb4d969edaa 100644 --- a/source/common/ratelimit/ratelimit_impl.h +++ b/source/common/ratelimit/ratelimit_impl.h @@ -10,9 +10,10 @@ #include "envoy/tracing/context.h" #include "envoy/upstream/cluster_manager.h" -#include "common/json/json_loader.h" #include "common/ratelimit/ratelimit.pb.h" +#include "api/bootstrap.pb.h" + namespace Envoy { namespace RateLimit { @@ -57,7 +58,8 @@ class GrpcClientImpl : public Client, public RateLimitAsyncCallbacks { class GrpcFactoryImpl : public ClientFactory { public: - GrpcFactoryImpl(const Json::Object& config, Upstream::ClusterManager& cm); + GrpcFactoryImpl(const envoy::api::v2::RateLimitServiceConfig& config, + Upstream::ClusterManager& cm); // RateLimit::ClientFactory ClientPtr create(const Optional& timeout) override; diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index 1185eb61bde2..96af02d72da1 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -69,8 +69,6 @@ envoy_cc_library( "//source/common/http:async_client_lib", "//source/common/http/http1:conn_pool_lib", "//source/common/http/http2:conn_pool_lib", - "//source/common/json:config_schemas_lib", - "//source/common/json:json_loader_lib", "//source/common/network:utility_lib", "//source/common/protobuf:utility_lib", "//source/common/router:shadow_writer_lib", diff --git a/source/common/upstream/cds_api_impl.cc b/source/common/upstream/cds_api_impl.cc index b00eb828dcb7..ce121f237686 100644 --- a/source/common/upstream/cds_api_impl.cc +++ b/source/common/upstream/cds_api_impl.cc @@ -10,15 +10,16 @@ namespace Envoy { namespace Upstream { CdsApiPtr CdsApiImpl::create(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm, - Event::Dispatcher& dispatcher, Runtime::RandomGenerator& random, + const Optional& eds_config, + ClusterManager& cm, Event::Dispatcher& dispatcher, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, Stats::Scope& scope) { return CdsApiPtr{ - new CdsApiImpl(cds_config, sds_config, cm, dispatcher, random, local_info, scope)}; + new CdsApiImpl(cds_config, eds_config, cm, dispatcher, random, local_info, scope)}; } CdsApiImpl::CdsApiImpl(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm, + const Optional& eds_config, ClusterManager& cm, Event::Dispatcher& dispatcher, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, Stats::Scope& scope) : cm_(cm), scope_(scope.createScope("cluster_manager.cds.")) { @@ -26,10 +27,10 @@ CdsApiImpl::CdsApiImpl(const envoy::api::v2::ConfigSource& cds_config, subscription_ = Config::SubscriptionFactory::subscriptionFromConfigSource( cds_config, local_info.node(), dispatcher, cm, random, *scope_, - [this, &cds_config, &sds_config, &cm, &dispatcher, &random, + [this, &cds_config, &eds_config, &cm, &dispatcher, &random, &local_info]() -> Config::Subscription* { return new CdsSubscription(Config::Utility::generateStats(*scope_), cds_config, - sds_config, cm, dispatcher, random, local_info); + eds_config, cm, dispatcher, random, local_info); }, "envoy.api.v2.ClusterDiscoveryService.FetchClusters", "envoy.api.v2.ClusterDiscoveryService.StreamClusters"); diff --git a/source/common/upstream/cds_api_impl.h b/source/common/upstream/cds_api_impl.h index e4b6c3749369..2456f750b03f 100644 --- a/source/common/upstream/cds_api_impl.h +++ b/source/common/upstream/cds_api_impl.h @@ -22,9 +22,10 @@ class CdsApiImpl : public CdsApi, Logger::Loggable { public: static CdsApiPtr create(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm, - Event::Dispatcher& dispatcher, Runtime::RandomGenerator& random, - const LocalInfo::LocalInfo& local_info, Stats::Scope& scope); + const Optional& eds_config, + ClusterManager& cm, Event::Dispatcher& dispatcher, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, + Stats::Scope& scope); // Upstream::CdsApi void initialize() override { subscription_->start({}, *this); } @@ -33,8 +34,9 @@ class CdsApiImpl : public CdsApi, } private: - CdsApiImpl(const envoy::api::v2::ConfigSource& cds_config, const Optional& sds_config, - ClusterManager& cm, Event::Dispatcher& dispatcher, Runtime::RandomGenerator& random, + CdsApiImpl(const envoy::api::v2::ConfigSource& cds_config, + const Optional& eds_config, ClusterManager& cm, + Event::Dispatcher& dispatcher, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, Stats::Scope& scope); void runInitializeCallbackIfAny(); diff --git a/source/common/upstream/cds_subscription.cc b/source/common/upstream/cds_subscription.cc index 7622b13ba312..7e47d371b83c 100644 --- a/source/common/upstream/cds_subscription.cc +++ b/source/common/upstream/cds_subscription.cc @@ -15,12 +15,13 @@ namespace Upstream { CdsSubscription::CdsSubscription(Config::SubscriptionStats stats, const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm, - Event::Dispatcher& dispatcher, Runtime::RandomGenerator& random, + const Optional& eds_config, + ClusterManager& cm, Event::Dispatcher& dispatcher, + Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info) : RestApiFetcher(cm, cds_config.api_config_source().cluster_name()[0], dispatcher, random, Config::Utility::apiConfigSourceRefreshDelay(cds_config.api_config_source())), - local_info_(local_info), stats_(stats), sds_config_(sds_config) { + local_info_(local_info), stats_(stats), eds_config_(eds_config) { const auto& api_config_source = cds_config.api_config_source(); UNREFERENCED_PARAMETER(api_config_source); // If we are building an CdsSubscription, the ConfigSource should be REST_LEGACY. @@ -46,7 +47,7 @@ void CdsSubscription::parseResponse(const Http::Message& response) { Protobuf::RepeatedPtrField resources; for (const Json::ObjectSharedPtr& cluster : clusters) { - Config::CdsJson::translateCluster(*cluster, sds_config_, *resources.Add()); + Config::CdsJson::translateCluster(*cluster, eds_config_, *resources.Add()); } callbacks_->onConfigUpdate(resources); diff --git a/source/common/upstream/cds_subscription.h b/source/common/upstream/cds_subscription.h index 751c9c51df29..375df253f34e 100644 --- a/source/common/upstream/cds_subscription.h +++ b/source/common/upstream/cds_subscription.h @@ -24,7 +24,7 @@ class CdsSubscription : public Http::RestApiFetcher, Logger::Loggable { public: CdsSubscription(Config::SubscriptionStats stats, const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm, + const Optional& eds_config, ClusterManager& cm, Event::Dispatcher& dispatcher, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info); @@ -55,7 +55,7 @@ class CdsSubscription : public Http::RestApiFetcher, const LocalInfo::LocalInfo& local_info_; Config::SubscriptionCallbacks* callbacks_; Config::SubscriptionStats stats_; - const Optional& sds_config_; + const Optional& eds_config_; }; } // namespace Upstream diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index e05965cc249b..8c98c5486370 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -156,44 +156,7 @@ void ClusterManagerInitHelper::setInitializedCb(std::function callback) } } -void ClusterManagerImpl::initializeClustersFromV1Json(const Json::Object& config) { - envoy::api::v2::ConfigSource cds_config; - if (config.hasObject("cds")) { - envoy::api::v2::Cluster cds_cluster; - Config::CdsJson::translateCluster(*config.getObject("cds")->getObject("cluster"), sds_config_, - cds_cluster); - loadCluster(cds_cluster, false); - Config::Utility::translateCdsConfig(*config.getObject("cds"), cds_config); - // We can now potentially create the CDS API once the backing cluster exists. - cds_api_ = factory_.createCds(cds_config, sds_config_, *this); - init_helper_.setCds(cds_api_.get()); - } else { - init_helper_.setCds(nullptr); - } - - for (const Json::ObjectSharedPtr& cluster_config : config.getObjectArray("clusters")) { - envoy::api::v2::Cluster cluster; - Config::CdsJson::translateCluster(*cluster_config, sds_config_, cluster); - loadCluster(cluster, false); - } -} - -void ClusterManagerImpl::initializeClustersFromV2Proto(const envoy::api::v2::Bootstrap& bootstrap) { - for (const auto& cluster : bootstrap.static_resources().clusters()) { - loadCluster(cluster, false); - } - - // We can now potentially create the CDS API once the backing cluster exists. - if (bootstrap.dynamic_resources().has_cds_config()) { - cds_api_ = factory_.createCds(bootstrap.dynamic_resources().cds_config(), sds_config_, *this); - init_helper_.setCds(cds_api_.get()); - } else { - init_helper_.setCds(nullptr); - } -} - -ClusterManagerImpl::ClusterManagerImpl(const Json::Object& config, - const envoy::api::v2::Bootstrap& bootstrap, +ClusterManagerImpl::ClusterManagerImpl(const envoy::api::v2::Bootstrap& bootstrap, ClusterManagerFactory& factory, Stats::Store& stats, ThreadLocal::SlotAllocator& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, @@ -201,12 +164,9 @@ ClusterManagerImpl::ClusterManagerImpl(const Json::Object& config, 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); - - if (config.hasObject("outlier_detection")) { - std::string event_log_file_path = - config.getObject("outlier_detection")->getString("event_log_path", ""); + const auto& cm_config = bootstrap.cluster_manager(); + if (cm_config.has_outlier_detection()) { + const std::string event_log_file_path = cm_config.outlier_detection().event_log_path(); if (!event_log_file_path.empty()) { outlier_event_logger_.reset(new Outlier::EventLoggerImpl(log_manager, event_log_file_path, ProdSystemTimeSource::instance_, @@ -214,17 +174,8 @@ ClusterManagerImpl::ClusterManagerImpl(const Json::Object& config, } } - if (config.hasObject("sds")) { - envoy::api::v2::Cluster sds_cluster; - Config::CdsJson::translateCluster(*config.getObject("sds")->getObject("cluster"), sds_config_, - sds_cluster); - loadCluster(sds_cluster, false); - - SdsConfig sds_config{ - config.getObject("sds")->getObject("cluster")->getString("name"), - std::chrono::milliseconds(config.getObject("sds")->getInteger("refresh_delay_ms"))}; - - sds_config_.value(sds_config); + if (bootstrap.dynamic_resources().deprecated_v1().has_sds_config()) { + eds_config_.value(bootstrap.dynamic_resources().deprecated_v1().sds_config()); } if (bootstrap.cluster_manager().upstream_bind_config().has_source_address()) { @@ -232,19 +183,21 @@ ClusterManagerImpl::ClusterManagerImpl(const Json::Object& config, bootstrap.cluster_manager().upstream_bind_config().source_address()); } - if (bootstrap.dynamic_resources().has_cds_config() || - !bootstrap.static_resources().clusters().empty()) { - initializeClustersFromV2Proto(bootstrap); + for (const auto& cluster : bootstrap.static_resources().clusters()) { + loadCluster(cluster, false); + } + + // We can now potentially create the CDS API once the backing cluster exists. + if (bootstrap.dynamic_resources().has_cds_config()) { + cds_api_ = factory_.createCds(bootstrap.dynamic_resources().cds_config(), eds_config_, *this); + init_helper_.setCds(cds_api_.get()); } else { - // TODO(htuch): Make this similar to the v1 -> v2 translation elsewhere, - // convert the JSON to envoy::api::v2::Bootstrap and use initializeClustersFromV2Proto() - // instead. - initializeClustersFromV1Json(config); + init_helper_.setCds(nullptr); } Optional local_cluster_name; - if (config.hasObject("local_cluster_name")) { - local_cluster_name.value(config.getString("local_cluster_name")); + if (!cm_config.local_cluster_name().empty()) { + local_cluster_name.value(cm_config.local_cluster_name()); if (primary_clusters_.find(local_cluster_name.value()) == primary_clusters_.end()) { throw EnvoyException( fmt::format("local cluster '{}' must be defined", local_cluster_name.value())); @@ -619,12 +572,12 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::connPool( return container.pools_[enumToInt(priority)].get(); } -ClusterManagerPtr ProdClusterManagerFactory::clusterManagerFromJson( - const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, Stats::Store& stats, - ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, +ClusterManagerPtr ProdClusterManagerFactory::clusterManagerFromProto( + 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, bootstrap, *this, stats, tls, runtime, - random, local_info, log_manager)}; + return ClusterManagerPtr{new ClusterManagerImpl(bootstrap, *this, stats, tls, runtime, random, + local_info, log_manager)}; } Http::ConnectionPool::InstancePtr @@ -648,10 +601,11 @@ ClusterSharedPtr ProdClusterManagerFactory::clusterFromProto( outlier_event_logger, added_via_api); } -CdsApiPtr ProdClusterManagerFactory::createCds(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, - ClusterManager& cm) { - return CdsApiImpl::create(cds_config, sds_config, cm, primary_dispatcher_, random_, local_info_, +CdsApiPtr +ProdClusterManagerFactory::createCds(const envoy::api::v2::ConfigSource& cds_config, + const Optional& eds_config, + ClusterManager& cm) { + return CdsApiImpl::create(cds_config, eds_config, cm, primary_dispatcher_, random_, local_info_, stats_); } diff --git a/source/common/upstream/cluster_manager_impl.h b/source/common/upstream/cluster_manager_impl.h index 60fa4d2df527..015c237978e4 100644 --- a/source/common/upstream/cluster_manager_impl.h +++ b/source/common/upstream/cluster_manager_impl.h @@ -17,7 +17,6 @@ #include "envoy/upstream/cluster_manager.h" #include "common/http/async_client_impl.h" -#include "common/json/json_loader.h" #include "common/upstream/upstream_impl.h" #include "api/bootstrap.pb.h" @@ -41,11 +40,12 @@ class ProdClusterManagerFactory : public ClusterManagerFactory { local_info_(local_info) {} // Upstream::ClusterManagerFactory - 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; + ClusterManagerPtr clusterManagerFromProto(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; @@ -53,7 +53,8 @@ class ProdClusterManagerFactory : public ClusterManagerFactory { Outlier::EventLoggerSharedPtr outlier_event_logger, bool added_via_api) override; CdsApiPtr createCds(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm) override; + const Optional& eds_config, + ClusterManager& cm) override; private: Runtime::Loader& runtime_; @@ -116,14 +117,13 @@ struct ClusterManagerStats { }; /** - * Implementation of ClusterManager that reads from a JSON configuration, maintains a central + * Implementation of ClusterManager that reads from a proto configuration, maintains a central * cluster list, as well as thread local caches of each cluster and associated connection pools. */ class ClusterManagerImpl : public ClusterManager, Logger::Loggable { public: - ClusterManagerImpl(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, - ClusterManagerFactory& factory, Stats::Store& stats, - ThreadLocal::SlotAllocator& tls, Runtime::Loader& runtime, + ClusterManagerImpl(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); @@ -222,8 +222,6 @@ class ClusterManagerImpl : public ClusterManager, Logger::Loggable primary_clusters_; - Optional sds_config_; + Optional eds_config_; Network::Address::InstanceConstSharedPtr source_address_; Outlier::EventLoggerSharedPtr outlier_event_logger_; const LocalInfo::LocalInfo& local_info_; diff --git a/source/server/BUILD b/source/server/BUILD index ee6f7deaf972..2c3d97c7001a 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -41,8 +41,8 @@ envoy_cc_library( "//source/common/common:utility_lib", "//source/common/config:lds_json_lib", "//source/common/config:utility_lib", - "//source/common/json:config_schemas_lib", "//source/common/network:utility_lib", + "//source/common/protobuf:utility_lib", "//source/common/ratelimit:ratelimit_lib", "//source/common/tracing:http_tracer_lib", ], @@ -229,6 +229,7 @@ envoy_cc_library( "//source/common/api:api_lib", "//source/common/common:utility_lib", "//source/common/common:version_lib", + "//source/common/config:bootstrap_json_lib", "//source/common/local_info:local_info_lib", "//source/common/memory:stats_lib", "//source/common/protobuf:utility_lib", diff --git a/source/server/config/http/lightstep_http_tracer.cc b/source/server/config/http/lightstep_http_tracer.cc index 363c08339cc5..d6535d0b5b3b 100644 --- a/source/server/config/http/lightstep_http_tracer.cc +++ b/source/server/config/http/lightstep_http_tracer.cc @@ -36,7 +36,7 @@ LightstepHttpTracerFactory::createHttpTracer(const Json::Object& json_config, new Tracing::HttpTracerImpl(std::move(lightstep_driver), server.localInfo())); } -std::string LightstepHttpTracerFactory::name() { return "lightstep"; } +std::string LightstepHttpTracerFactory::name() { return "envoy.lightstep"; } /** * Static registration for the lightstep http tracer. @see RegisterFactory. diff --git a/source/server/config/http/zipkin_http_tracer.cc b/source/server/config/http/zipkin_http_tracer.cc index 817cf377c653..501ca6d8d882 100644 --- a/source/server/config/http/zipkin_http_tracer.cc +++ b/source/server/config/http/zipkin_http_tracer.cc @@ -26,7 +26,7 @@ ZipkinHttpTracerFactory::createHttpTracer(const Json::Object& json_config, Serve new Tracing::HttpTracerImpl(std::move(zipkin_driver), server.localInfo())); } -std::string ZipkinHttpTracerFactory::name() { return "zipkin"; } +std::string ZipkinHttpTracerFactory::name() { return "envoy.zipkin"; } /** * Static registration for the lightstep http tracer. @see RegisterFactory. diff --git a/source/server/config/network/http_connection_manager.cc b/source/server/config/network/http_connection_manager.cc index 0976d40a3ed0..111d0359466e 100644 --- a/source/server/config/network/http_connection_manager.cc +++ b/source/server/config/network/http_connection_manager.cc @@ -242,7 +242,7 @@ HttpConnectionManagerConfig::HttpConnectionManagerConfig( throw EnvoyException( fmt::format("Filter factory for '{}' has unexpected proto config", string_name)); } - MessageUtil::loadFromJson(filter_config->asJsonString(), *message); + MessageUtil::jsonConvert(proto_config, *message); callback = factory->createFilterFactoryFromProto(*message, stats_prefix_, context); } filter_factories_.push_back(callback); diff --git a/source/server/config_validation/BUILD b/source/server/config_validation/BUILD index 0786306bce80..3e674c2a948e 100644 --- a/source/server/config_validation/BUILD +++ b/source/server/config_validation/BUILD @@ -86,6 +86,8 @@ envoy_cc_library( "//include/envoy/tracing:http_tracer_interface", "//source/common/access_log:access_log_manager_lib", "//source/common/common:assert_lib", + "//source/common/common:version_lib", + "//source/common/config:bootstrap_json_lib", "//source/common/local_info:local_info_lib", "//source/common/protobuf:utility_lib", "//source/common/router:rds_lib", diff --git a/source/server/config_validation/cluster_manager.cc b/source/server/config_validation/cluster_manager.cc index 0e86d7a2af1b..b6ed64d6c01c 100644 --- a/source/server/config_validation/cluster_manager.cc +++ b/source/server/config_validation/cluster_manager.cc @@ -11,30 +11,30 @@ ValidationClusterManagerFactory::ValidationClusterManagerFactory( : ProdClusterManagerFactory(runtime, stats, tls, random, dns_resolver, ssl_context_manager, primary_dispatcher, local_info) {} -ClusterManagerPtr ValidationClusterManagerFactory::clusterManagerFromJson( - const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, Stats::Store& stats, - ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, +ClusterManagerPtr ValidationClusterManagerFactory::clusterManagerFromProto( + 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, bootstrap, *this, stats, tls, - runtime, random, local_info, log_manager)}; + return ClusterManagerPtr{new ValidationClusterManager(bootstrap, *this, stats, tls, runtime, + random, local_info, log_manager)}; } -CdsApiPtr ValidationClusterManagerFactory::createCds(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, - ClusterManager& cm) { +CdsApiPtr +ValidationClusterManagerFactory::createCds(const envoy::api::v2::ConfigSource& cds_config, + const Optional& eds_config, + ClusterManager& cm) { // Create the CdsApiImpl... - ProdClusterManagerFactory::createCds(cds_config, sds_config, cm); + ProdClusterManagerFactory::createCds(cds_config, eds_config, cm); // ... and then throw it away, so that we don't actually connect to it. return nullptr; } ValidationClusterManager::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 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, bootstrap, factory, stats, tls, runtime, random, local_info, - log_manager) {} + : ClusterManagerImpl(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 de0233da8b62..f36cc0c09e67 100644 --- a/source/server/config_validation/cluster_manager.h +++ b/source/server/config_validation/cluster_manager.h @@ -22,16 +22,18 @@ class ValidationClusterManagerFactory : public ProdClusterManagerFactory { Event::Dispatcher& primary_dispatcher, const LocalInfo::LocalInfo& local_info); - 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; + ClusterManagerPtr clusterManagerFromProto(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. CdsApiPtr createCds(const envoy::api::v2::ConfigSource& cds_config, - const Optional& sds_config, ClusterManager& cm) override; + const Optional& eds_config, + ClusterManager& cm) override; }; /** @@ -39,7 +41,7 @@ class ValidationClusterManagerFactory : public ProdClusterManagerFactory { */ class ValidationClusterManager : public ClusterManagerImpl { public: - ValidationClusterManager(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap, + ValidationClusterManager(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, diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index bb1c3086ebff..6c295a7e3687 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -1,5 +1,7 @@ #include "server/config_validation/server.h" +#include "common/common/version.h" +#include "common/config/bootstrap_json.h" #include "common/local_info/local_info_impl.h" #include "common/protobuf/utility.h" #include "common/singleton/manager_impl.h" @@ -59,17 +61,25 @@ void ValidationInstance::initialize(Options& options, // // 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()); + // Handle configuration that needs to take place prior to the main configuration load. envoy::api::v2::Bootstrap bootstrap; - if (!options.bootstrapPath().empty()) { - MessageUtil::loadFromFile(options.bootstrapPath(), bootstrap); + try { + MessageUtil::loadFromFile(options.configPath(), bootstrap); + } catch (const EnvoyException& e) { + // TODO(htuch): When v1 is deprecated, make this a warning encouraging config upgrade. + ENVOY_LOG(debug, "Unable to initialize config as v2, will retry as v1: {}", e.what()); + } + if (!bootstrap.has_admin()) { + Json::ObjectSharedPtr config_json = Json::Factory::loadFromFile(options.configPath()); + Config::BootstrapJson::translateBootstrap(*config_json, bootstrap); } + bootstrap.mutable_node()->set_build_version(VersionInfo::version()); local_info_.reset( new LocalInfo::LocalInfoImpl(bootstrap.node(), local_address, options.serviceZone(), options.serviceClusterName(), options.serviceNodeName())); - Configuration::InitialImpl initial_config(*config_json); + Configuration::InitialImpl initial_config(bootstrap); thread_local_.registerThread(*dispatcher_, true); runtime_loader_ = component_factory.createRuntime(*this, initial_config); ssl_context_manager_.reset(new Ssl::ContextManagerImpl(*runtime_loader_)); @@ -79,7 +89,7 @@ void ValidationInstance::initialize(Options& options, Configuration::MainImpl* main_config = new Configuration::MainImpl(); config_.reset(main_config); - main_config->initialize(*config_json, bootstrap, *this, *cluster_manager_factory_); + main_config->initialize(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 84455a018296..20cee769231b 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -16,7 +16,7 @@ #include "common/common/utility.h" #include "common/config/lds_json.h" #include "common/config/utility.h" -#include "common/json/config_schemas.h" +#include "common/protobuf/utility.h" #include "common/ratelimit/ratelimit_impl.h" #include "common/tracing/http_tracer_impl.h" @@ -36,78 +36,71 @@ bool FilterChainUtility::buildFilterChain(Network::FilterManager& filter_manager return filter_manager.initializeReadFilters(); } -void MainImpl::initialize(const Json::Object& json, const envoy::api::v2::Bootstrap& bootstrap, - Instance& server, +void MainImpl::initialize(const envoy::api::v2::Bootstrap& bootstrap, Instance& server, Upstream::ClusterManagerFactory& cluster_manager_factory) { - cluster_manager_ = cluster_manager_factory.clusterManagerFromJson( - *json.getObject("cluster_manager"), bootstrap, server.stats(), server.threadLocal(), - server.runtime(), server.random(), server.localInfo(), server.accessLogManager()); + cluster_manager_ = cluster_manager_factory.clusterManagerFromProto( + bootstrap, server.stats(), server.threadLocal(), server.runtime(), server.random(), + server.localInfo(), server.accessLogManager()); - std::vector listeners = json.getObjectArray("listeners"); + const auto& listeners = bootstrap.static_resources().listeners(); ENVOY_LOG(info, "loading {} listener(s)", listeners.size()); - for (size_t i = 0; i < listeners.size(); i++) { + for (ssize_t i = 0; i < listeners.size(); i++) { ENVOY_LOG(info, "listener #{}:", i); - envoy::api::v2::Listener listener; - Config::LdsJson::translateListener(*listeners[i], listener); - server.listenerManager().addOrUpdateListener(listener); + server.listenerManager().addOrUpdateListener(listeners[i]); } if (bootstrap.dynamic_resources().has_lds_config()) { lds_api_.reset(new LdsApi(bootstrap.dynamic_resources().lds_config(), *cluster_manager_, server.dispatcher(), server.random(), server.initManager(), server.localInfo(), server.stats(), server.listenerManager())); - } else if (json.hasObject("lds")) { - envoy::api::v2::ConfigSource lds_config; - Config::Utility::translateLdsConfig(*json.getObject("lds"), lds_config); - lds_api_.reset(new LdsApi(lds_config, *cluster_manager_, server.dispatcher(), server.random(), - server.initManager(), server.localInfo(), server.stats(), - server.listenerManager())); } - if (json.hasObject("statsd_udp_ip_address")) { - statsd_udp_ip_address_.value(json.getString("statsd_udp_ip_address")); - } - - if (json.hasObject("statsd_tcp_cluster_name")) { - statsd_tcp_cluster_name_.value(json.getString("statsd_tcp_cluster_name")); + for (const auto& stats_sink : bootstrap.stats_sinks()) { + // TODO(mrice32): Add support for pluggable stats sinks. + ASSERT(stats_sink.name() == "envoy.statsd"); + envoy::api::v2::StatsdSink statsd_sink; + MessageUtil::jsonConvert(stats_sink.config(), statsd_sink); + + switch (statsd_sink.statsd_specifier_case()) { + case envoy::api::v2::StatsdSink::kAddress: { + statsd_udp_ip_address_ = Network::Utility::fromProtoAddress(statsd_sink.address()); + break; + } + case envoy::api::v2::StatsdSink::kTcpClusterName: + statsd_tcp_cluster_name_.value(statsd_sink.tcp_cluster_name()); + break; + default: + NOT_REACHED; + } } stats_flush_interval_ = - std::chrono::milliseconds(json.getInteger("stats_flush_interval_ms", 5000)); + std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(bootstrap, stats_flush_interval, 5000)); + const auto& watchdog = bootstrap.watchdog(); watchdog_miss_timeout_ = - std::chrono::milliseconds(json.getInteger("watchdog_miss_timeout_ms", 200)); + std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, miss_timeout, 200)); watchdog_megamiss_timeout_ = - std::chrono::milliseconds(json.getInteger("watchdog_megamiss_timeout_ms", 1000)); + std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, megamiss_timeout, 1000)); watchdog_kill_timeout_ = - std::chrono::milliseconds(json.getInteger("watchdog_kill_timeout_ms", 0)); + std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, kill_timeout, 0)); watchdog_multikill_timeout_ = - std::chrono::milliseconds(json.getInteger("watchdog_multikill_timeout_ms", 0)); + std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, multikill_timeout, 0)); - initializeTracers(json, server); + initializeTracers(bootstrap.tracing(), server); - if (json.hasObject("rate_limit_service")) { - Json::ObjectSharedPtr rate_limit_service_config = json.getObject("rate_limit_service"); - std::string type = rate_limit_service_config->getString("type"); - ASSERT(type == "grpc_service"); - UNREFERENCED_PARAMETER(type); - ratelimit_client_factory_.reset(new RateLimit::GrpcFactoryImpl( - *rate_limit_service_config->getObject("config"), *cluster_manager_)); + if (bootstrap.has_rate_limit_service()) { + ratelimit_client_factory_.reset( + new RateLimit::GrpcFactoryImpl(bootstrap.rate_limit_service(), *cluster_manager_)); } else { ratelimit_client_factory_.reset(new RateLimit::NullFactoryImpl()); } } -void MainImpl::initializeTracers(const Json::Object& configuration, Instance& server) { +void MainImpl::initializeTracers(const envoy::api::v2::Tracing& configuration, Instance& server) { ENVOY_LOG(info, "loading tracing configuration"); - if (!configuration.hasObject("tracing")) { - http_tracer_.reset(new Tracing::HttpNullTracer()); - return; - } - - Json::ObjectSharedPtr tracing_configuration = configuration.getObject("tracing"); - if (!tracing_configuration->hasObject("http")) { + if (!configuration.has_http()) { http_tracer_.reset(new Tracing::HttpNullTracer()); return; } @@ -118,13 +111,12 @@ void MainImpl::initializeTracers(const Json::Object& configuration, Instance& se } // Initialize tracing driver. - Json::ObjectSharedPtr http_tracer_config = tracing_configuration->getObject("http"); - Json::ObjectSharedPtr driver = http_tracer_config->getObject("driver"); - - std::string type = driver->getString("type"); + std::string type = configuration.http().name(); ENVOY_LOG(info, " loading tracing driver: {}", type); - Json::ObjectSharedPtr driver_config = driver->getObject("config"); + // TODO(htuch): Make this dynamically pluggable one day. + Json::ObjectSharedPtr driver_config = + MessageUtil::getJsonObjectFromMessage(configuration.http().config()); // Now see if there is a factory that will accept the config. HttpTracerFactory* factory = Registry::FactoryRegistry::getFactory(type); @@ -135,23 +127,22 @@ void MainImpl::initializeTracers(const Json::Object& configuration, Instance& se } } -InitialImpl::InitialImpl(const Json::Object& json) { - json.validateSchema(Json::Schema::TOP_LEVEL_CONFIG_SCHEMA); - Json::ObjectSharedPtr admin = json.getObject("admin"); - admin_.access_log_path_ = admin->getString("access_log_path"); - admin_.profile_path_ = admin->getString("profile_path", "/var/log/envoy/envoy.prof"); - admin_.address_ = Network::Utility::resolveUrl(admin->getString("address")); +InitialImpl::InitialImpl(const envoy::api::v2::Bootstrap& bootstrap) { + const auto& admin = bootstrap.admin(); + admin_.access_log_path_ = admin.access_log_path(); + admin_.profile_path_ = + admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path(); + admin_.address_ = Network::Utility::fromProtoAddress(admin.address()); - if (json.hasObject("flags_path")) { - flags_path_.value(json.getString("flags_path")); + if (!bootstrap.flags_path().empty()) { + flags_path_.value(bootstrap.flags_path()); } - if (json.hasObject("runtime")) { + if (bootstrap.has_runtime()) { runtime_.reset(new RuntimeImpl()); - runtime_->symlink_root_ = json.getObject("runtime")->getString("symlink_root"); - runtime_->subdirectory_ = json.getObject("runtime")->getString("subdirectory"); - runtime_->override_subdirectory_ = - json.getObject("runtime")->getString("override_subdirectory", ""); + runtime_->symlink_root_ = bootstrap.runtime().symlink_root(); + runtime_->subdirectory_ = bootstrap.runtime().subdirectory(); + runtime_->override_subdirectory_ = bootstrap.runtime().override_subdirectory(); } } diff --git a/source/server/configuration_impl.h b/source/server/configuration_impl.h index fc759d8300c6..a7b4817a5026 100644 --- a/source/server/configuration_impl.h +++ b/source/server/configuration_impl.h @@ -77,20 +77,21 @@ class MainImpl : Logger::Loggable, public Main { * Initialize the configuration. This happens here vs. the constructor because the initialization * 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, const envoy::api::v2::Bootstrap& bootstrap, - Instance& server, Upstream::ClusterManagerFactory& cluster_manager_factory); + void initialize(const envoy::api::v2::Bootstrap& bootstrap, Instance& server, + Upstream::ClusterManagerFactory& cluster_manager_factory); // Server::Configuration::Main Upstream::ClusterManager& clusterManager() override { return *cluster_manager_; } Tracing::HttpTracer& httpTracer() override { return *http_tracer_; } RateLimit::ClientFactory& rateLimitClientFactory() override { return *ratelimit_client_factory_; } Optional statsdTcpClusterName() override { return statsd_tcp_cluster_name_; } - Optional statsdUdpIpAddress() override { return statsd_udp_ip_address_; } + Network::Address::InstanceConstSharedPtr statsdUdpIpAddress() override { + return statsd_udp_ip_address_; + } std::chrono::milliseconds statsFlushInterval() override { return stats_flush_interval_; } std::chrono::milliseconds wdMissTimeout() const override { return watchdog_miss_timeout_; } std::chrono::milliseconds wdMegaMissTimeout() const override { @@ -105,13 +106,13 @@ class MainImpl : Logger::Loggable, public Main { /** * Initialize tracers and corresponding sinks. */ - void initializeTracers(const Json::Object& tracing_configuration, Instance& server); + void initializeTracers(const envoy::api::v2::Tracing& configuration, Instance& server); std::unique_ptr cluster_manager_; std::unique_ptr lds_api_; Tracing::HttpTracerPtr http_tracer_; Optional statsd_tcp_cluster_name_; - Optional statsd_udp_ip_address_; + Network::Address::InstanceConstSharedPtr statsd_udp_ip_address_; RateLimit::ClientFactoryPtr ratelimit_client_factory_; std::chrono::milliseconds stats_flush_interval_; std::chrono::milliseconds watchdog_miss_timeout_; @@ -125,7 +126,7 @@ class MainImpl : Logger::Loggable, public Main { */ class InitialImpl : public Initial { public: - InitialImpl(const Json::Object& json); + InitialImpl(const envoy::api::v2::Bootstrap& bootstrap); // Server::Configuration::Initial Admin& admin() override { return admin_; } diff --git a/source/server/listener_manager_impl.cc b/source/server/listener_manager_impl.cc index 50e93b5325c9..07af3fb07c25 100644 --- a/source/server/listener_manager_impl.cc +++ b/source/server/listener_manager_impl.cc @@ -41,7 +41,7 @@ ProdListenerComponentFactory::createFilterFactoryList_( throw EnvoyException( fmt::format("Filter factory for '{}' has unexpected proto config", string_name)); } - MessageUtil::loadFromJson(filter_config->asJsonString(), *message); + MessageUtil::jsonConvert(proto_config, *message); callback = factory->createFilterFactoryFromProto(*message, context); } ret.push_back(callback); diff --git a/source/server/options_impl.cc b/source/server/options_impl.cc index 19e05aec244a..a313b58d488b 100644 --- a/source/server/options_impl.cc +++ b/source/server/options_impl.cc @@ -30,8 +30,6 @@ 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", @@ -106,7 +104,6 @@ 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 21b4fcc1a5d6..b72a791b02b1 100644 --- a/source/server/options_impl.h +++ b/source/server/options_impl.h @@ -21,7 +21,6 @@ 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,7 +37,6 @@ 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 e105718dacf6..981565055029 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -16,6 +16,7 @@ #include "common/api/api_impl.h" #include "common/common/utility.h" #include "common/common/version.h" +#include "common/config/bootstrap_json.h" #include "common/local_info/local_info_impl.h" #include "common/memory/stats.h" #include "common/network/address_impl.h" @@ -65,9 +66,7 @@ InstanceImpl::InstanceImpl(Options& options, Network::Address::InstanceConstShar try { initialize(options, local_address, component_factory); } catch (const EnvoyException& e) { - ENVOY_LOG(critical, "error initializing configuration '{}': {}", - options.configPath() + - (options.bootstrapPath().empty() ? "" : (";" + options.bootstrapPath())), + ENVOY_LOG(critical, "error initializing configuration '{}': {}", options.configPath(), e.what()); thread_local_.shutdownGlobalThreading(); thread_local_.shutdownThread(); @@ -151,10 +150,16 @@ void InstanceImpl::initialize(Options& options, restarter_.version()); // 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); + try { + MessageUtil::loadFromFile(options.configPath(), bootstrap); + } catch (const EnvoyException& e) { + // TODO(htuch): When v1 is deprecated, make this a warning encouraging config upgrade. + ENVOY_LOG(debug, "Unable to initialize config as v2, will retry as v1: {}", e.what()); + } + if (!bootstrap.has_admin()) { + Json::ObjectSharedPtr config_json = Json::Factory::loadFromFile(options.configPath()); + Config::BootstrapJson::translateBootstrap(*config_json, bootstrap); } bootstrap.mutable_node()->set_build_version(VersionInfo::version()); @@ -162,7 +167,7 @@ void InstanceImpl::initialize(Options& options, new LocalInfo::LocalInfoImpl(bootstrap.node(), local_address, options.serviceZone(), options.serviceClusterName(), options.serviceNodeName())); - Configuration::InitialImpl initial_config(*config_json); + Configuration::InitialImpl initial_config(bootstrap); ENVOY_LOG(info, "admin address: {}", initial_config.admin().address()->asString()); HotRestart::ShutdownParentAdminInfo info; @@ -205,7 +210,7 @@ void InstanceImpl::initialize(Options& options, // 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, bootstrap, *this, *cluster_manager_factory_); + main_config->initialize(bootstrap, *this, *cluster_manager_factory_); // Setup signals. sigterm_ = dispatcher_->listenForSignal(SIGTERM, [this]() -> void { @@ -264,11 +269,10 @@ Runtime::LoaderPtr InstanceUtil::createRuntime(Instance& server, } void InstanceImpl::initializeStatSinks() { - if (config_->statsdUdpIpAddress().valid()) { - ENVOY_LOG(info, "statsd UDP ip address: {}", config_->statsdUdpIpAddress().value()); - stat_sinks_.emplace_back(new Stats::Statsd::UdpStatsdSink( - thread_local_, - Network::Utility::parseInternetAddressAndPort(config_->statsdUdpIpAddress().value()))); + if (config_->statsdUdpIpAddress()) { + ENVOY_LOG(info, "statsd UDP ip address: {}", config_->statsdUdpIpAddress()->asString()); + stat_sinks_.emplace_back( + new Stats::Statsd::UdpStatsdSink(thread_local_, config_->statsdUdpIpAddress())); stats_store_.addSink(*stat_sinks_.back()); } diff --git a/test/common/config/utility_test.cc b/test/common/config/utility_test.cc index 93d33789c869..72b6415c23b0 100644 --- a/test/common/config/utility_test.cc +++ b/test/common/config/utility_test.cc @@ -38,17 +38,5 @@ TEST(UtilityTest, ApiConfigSourceRefreshDelay) { EXPECT_EQ(1234, Utility::apiConfigSourceRefreshDelay(api_config_source).count()); } -TEST(UtilityTest, SdsConfigToEdsConfig) { - Upstream::SdsConfig sds_config{"sds", std::chrono::milliseconds(30000)}; - envoy::api::v2::ConfigSource config; - Utility::sdsConfigToEdsConfig(sds_config, config); - EXPECT_TRUE(config.has_api_config_source()); - const auto& api_config_source = config.api_config_source(); - EXPECT_EQ(envoy::api::v2::ApiConfigSource::REST_LEGACY, api_config_source.api_type()); - EXPECT_EQ(1, api_config_source.cluster_name().size()); - EXPECT_EQ("sds", api_config_source.cluster_name()[0]); - EXPECT_EQ(30000, Utility::apiConfigSourceRefreshDelay(api_config_source).count()); -} - } // namespace Config } // namespace Envoy diff --git a/test/common/ratelimit/ratelimit_impl_test.cc b/test/common/ratelimit/ratelimit_impl_test.cc index bc6160250420..285146fd0fd5 100644 --- a/test/common/ratelimit/ratelimit_impl_test.cc +++ b/test/common/ratelimit/ratelimit_impl_test.cc @@ -120,31 +120,21 @@ TEST_F(RateLimitGrpcClientTest, Cancel) { } TEST(RateLimitGrpcFactoryTest, NoCluster) { - std::string json = R"EOF( - { - "cluster_name": "foo" - } - )EOF"; - - Json::ObjectSharedPtr config = Json::Factory::loadFromString(json); + envoy::api::v2::RateLimitServiceConfig config; + config.set_cluster_name("foo"); Upstream::MockClusterManager cm; EXPECT_CALL(cm, get("foo")).WillOnce(Return(nullptr)); - EXPECT_THROW(GrpcFactoryImpl(*config, cm), EnvoyException); + EXPECT_THROW(GrpcFactoryImpl(config, cm), EnvoyException); } TEST(RateLimitGrpcFactoryTest, Create) { - std::string json = R"EOF( - { - "cluster_name": "foo" - } - )EOF"; - - Json::ObjectSharedPtr config = Json::Factory::loadFromString(json); + envoy::api::v2::RateLimitServiceConfig config; + config.set_cluster_name("foo"); Upstream::MockClusterManager cm; EXPECT_CALL(cm, get("foo")).Times(AtLeast(1)); - GrpcFactoryImpl factory(*config, cm); + GrpcFactoryImpl factory(config, cm); factory.create(Optional()); } diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index f549b435f695..ea555484b456 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -30,6 +30,7 @@ envoy_cc_test( deps = [ ":utility_lib", "//include/envoy/upstream:upstream_interface", + "//source/common/config:bootstrap_json_lib", "//source/common/config:utility_lib", "//source/common/event:dispatcher_lib", "//source/common/network:utility_lib", diff --git a/test/common/upstream/cds_api_impl_test.cc b/test/common/upstream/cds_api_impl_test.cc index 50ab5c702f5a..ad410d844095 100644 --- a/test/common/upstream/cds_api_impl_test.cc +++ b/test/common/upstream/cds_api_impl_test.cc @@ -42,7 +42,7 @@ class CdsApiImplTest : public testing::Test { envoy::api::v2::ConfigSource cds_config; Config::Utility::translateCdsConfig(*config, cds_config); cds_ = - CdsApiImpl::create(cds_config, sds_config_, cm_, dispatcher_, random_, local_info_, store_); + CdsApiImpl::create(cds_config, eds_config_, cm_, dispatcher_, random_, local_info_, store_); cds_->setInitializedCb([this]() -> void { initialized_.ready(); }); expectRequest(); @@ -90,7 +90,7 @@ class CdsApiImplTest : public testing::Test { Event::MockTimer* interval_timer_; Http::AsyncClient::Callbacks* callbacks_{}; ReadyWatcher initialized_; - Optional sds_config_; + Optional eds_config_; }; TEST_F(CdsApiImplTest, InvalidOptions) { @@ -108,7 +108,7 @@ TEST_F(CdsApiImplTest, InvalidOptions) { envoy::api::v2::ConfigSource cds_config; Config::Utility::translateCdsConfig(*config, cds_config); EXPECT_THROW( - CdsApiImpl::create(cds_config, sds_config_, cm_, dispatcher_, random_, local_info_, store_), + CdsApiImpl::create(cds_config, eds_config_, cm_, dispatcher_, random_, local_info_, store_), EnvoyException); } diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index 0bf3b4825102..66eceddc31e9 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -3,6 +3,7 @@ #include "envoy/upstream/upstream.h" +#include "common/config/bootstrap_json.h" #include "common/config/utility.h" #include "common/network/utility.h" #include "common/ssl/context_manager_impl.h" @@ -64,23 +65,23 @@ class TestClusterManagerFactory : public ClusterManagerFactory { return clusterFromProto_(cluster, cm, outlier_event_logger, added_via_api); } - CdsApiPtr createCds(const envoy::api::v2::ConfigSource&, const Optional&, - ClusterManager&) override { + CdsApiPtr createCds(const envoy::api::v2::ConfigSource&, + const Optional&, ClusterManager&) override { return CdsApiPtr{createCds_()}; } - 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, - AccessLog::AccessLogManager& log_manager) override { + ClusterManagerPtr clusterManagerFromProto(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 { return ClusterManagerPtr{ - clusterManagerFromJson_(config, stats, tls, runtime, random, local_info, log_manager)}; + clusterManagerFromProto_(bootstrap, stats, tls, runtime, random, local_info, log_manager)}; } - MOCK_METHOD7(clusterManagerFromJson_, - ClusterManager*(const Json::Object& config, Stats::Store& stats, + MOCK_METHOD7(clusterManagerFromProto_, + ClusterManager*(const envoy::api::v2::Bootstrap& bootstrap, Stats::Store& stats, ThreadLocal::Instance& tls, Runtime::Loader& runtime, Runtime::RandomGenerator& random, const LocalInfo::LocalInfo& local_info, @@ -105,14 +106,10 @@ class TestClusterManagerFactory : public ClusterManagerFactory { class ClusterManagerImplTest : public testing::Test { public: - void createWithBootstrap(const Json::Object& config, const envoy::api::v2::Bootstrap& bootstrap) { + void create(const 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_)); - } - - void create(const Json::Object& config) { - createWithBootstrap(config, envoy::api::v2::Bootstrap()); + bootstrap, factory_, factory_.stats_, factory_.tls_, factory_.runtime_, factory_.random_, + factory_.local_info_, log_manager_)); } NiceMock factory_; @@ -120,6 +117,13 @@ class ClusterManagerImplTest : public testing::Test { AccessLog::MockAccessLogManager log_manager_; }; +envoy::api::v2::Bootstrap parseBootstrapFromJson(const std::string& json_string) { + envoy::api::v2::Bootstrap bootstrap; + auto json_object_ptr = Json::Factory::loadFromString(json_string); + Config::BootstrapJson::translateClusterManagerBootstrap(*json_object_ptr, bootstrap); + return bootstrap; +} + TEST_F(ClusterManagerImplTest, OutlierEventLog) { const std::string json = R"EOF( { @@ -130,15 +134,13 @@ TEST_F(ClusterManagerImplTest, OutlierEventLog) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); EXPECT_CALL(log_manager_, createAccessLog("foo")); - create(*loader); + create(parseBootstrapFromJson(json)); } TEST_F(ClusterManagerImplTest, NoSdsConfig) { const std::string json = fmt::sprintf("{%s}", clustersJson({defaultSdsClusterJson("cluster_1")})); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW(create(*loader), EnvoyException); + EXPECT_THROW(create(parseBootstrapFromJson(json)), EnvoyException); } TEST_F(ClusterManagerImplTest, UnknownClusterType) { @@ -154,8 +156,7 @@ TEST_F(ClusterManagerImplTest, UnknownClusterType) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW(create(*loader), EnvoyException); + EXPECT_THROW(create(parseBootstrapFromJson(json)), EnvoyException); } TEST_F(ClusterManagerImplTest, LocalClusterNotDefined) { @@ -168,8 +169,7 @@ TEST_F(ClusterManagerImplTest, LocalClusterNotDefined) { )EOF", clustersJson({defaultStaticClusterJson("cluster_1"), defaultStaticClusterJson("cluster_2")})); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW(create(*loader), EnvoyException); + EXPECT_THROW(create(parseBootstrapFromJson(json)), EnvoyException); } TEST_F(ClusterManagerImplTest, BadClusterManagerConfig) { @@ -183,8 +183,7 @@ TEST_F(ClusterManagerImplTest, BadClusterManagerConfig) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW(create(*loader), Json::Exception); + EXPECT_THROW(create(parseBootstrapFromJson(json)), Json::Exception); } TEST_F(ClusterManagerImplTest, LocalClusterDefined) { @@ -198,8 +197,7 @@ TEST_F(ClusterManagerImplTest, LocalClusterDefined) { clustersJson({defaultStaticClusterJson("cluster_1"), defaultStaticClusterJson("cluster_2"), defaultStaticClusterJson("new_cluster")})); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); EXPECT_EQ(3UL, factory_.stats_.counter("cluster_manager.cluster_added").value()); EXPECT_EQ(3UL, factory_.stats_.gauge("cluster_manager.total_clusters").value()); @@ -211,8 +209,7 @@ TEST_F(ClusterManagerImplTest, DuplicateCluster) { const std::string json = fmt::sprintf( "{%s}", clustersJson({defaultStaticClusterJson("cluster_1"), defaultStaticClusterJson("cluster_1")})); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW(create(*loader), EnvoyException); + EXPECT_THROW(create(parseBootstrapFromJson(json)), EnvoyException); } TEST_F(ClusterManagerImplTest, UnknownHcType) { @@ -232,8 +229,7 @@ TEST_F(ClusterManagerImplTest, UnknownHcType) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW(create(*loader), EnvoyException); + EXPECT_THROW(create(parseBootstrapFromJson(json)), EnvoyException); } TEST_F(ClusterManagerImplTest, MaxClusterName) { @@ -246,8 +242,7 @@ TEST_F(ClusterManagerImplTest, MaxClusterName) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW_WITH_MESSAGE(create(*loader), Json::Exception, + EXPECT_THROW_WITH_MESSAGE(create(parseBootstrapFromJson(json)), Json::Exception, "JSON at lines 4-6 does not conform to schema.\n Invalid schema: " "#/properties/name\n Schema violation: maxLength\n Offending " "document key: #/name"); @@ -263,8 +258,7 @@ TEST_F(ClusterManagerImplTest, InvalidClusterNameChars) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW_WITH_MESSAGE(create(*loader), Json::Exception, + EXPECT_THROW_WITH_MESSAGE(create(parseBootstrapFromJson(json)), Json::Exception, "JSON at lines 4-6 does not conform to schema.\n Invalid schema: " "#/properties/name\n Schema violation: pattern\n Offending document " "key: #/name"); @@ -283,9 +277,8 @@ TEST_F(ClusterManagerImplTest, OriginalDstLbRestriction) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); EXPECT_THROW_WITH_MESSAGE( - create(*loader), EnvoyException, + create(parseBootstrapFromJson(json)), EnvoyException, "cluster: cluster type 'original_dst' may only be used with LB type 'original_dst_lb'"); } @@ -303,9 +296,8 @@ TEST_F(ClusterManagerImplTest, OriginalDstLbRestriction2) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); EXPECT_THROW_WITH_MESSAGE( - create(*loader), EnvoyException, + create(parseBootstrapFromJson(json)), EnvoyException, "cluster: LB type 'original_dst_lb' may only be used with cluser type 'original_dst'"); } @@ -336,13 +328,12 @@ TEST_F(ClusterManagerImplTest, TcpHealthChecker) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); Network::MockClientConnection* connection = new NiceMock(); EXPECT_CALL( factory_.dispatcher_, createClientConnection_(PointeesEq(Network::Utility::resolveUrl("tcp://127.0.0.1:11001")), _)) .WillOnce(Return(connection)); - create(*loader); + create(parseBootstrapFromJson(json)); factory_.tls_.shutdownThread(); } @@ -382,8 +373,7 @@ TEST_F(ClusterManagerImplTest, UnknownCluster) { const std::string json = fmt::sprintf("{%s}", clustersJson({defaultStaticClusterJson("cluster_1")})); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); EXPECT_EQ(nullptr, cluster_manager_->get("hello")); EXPECT_EQ(nullptr, cluster_manager_->httpConnPoolForCluster("hello", ResourcePriority::Default, nullptr)); @@ -410,8 +400,7 @@ TEST_F(ClusterManagerImplTest, VerifyBufferLimits) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); Network::MockClientConnection* connection = new NiceMock(); EXPECT_CALL(*connection, setBufferLimits(8192)); EXPECT_CALL(factory_.tls_.dispatcher_, createClientConnection_(_, _)) @@ -425,8 +414,7 @@ TEST_F(ClusterManagerImplTest, ShutdownOrder) { const std::string json = fmt::sprintf("{%s}", clustersJson({defaultStaticClusterJson("cluster_1")})); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); const Cluster& cluster = cluster_manager_->clusters().begin()->second; EXPECT_EQ("cluster_1", cluster.info()->name()); EXPECT_EQ(cluster.info(), cluster_manager_->get("cluster_1")->info()); @@ -442,33 +430,6 @@ TEST_F(ClusterManagerImplTest, ShutdownOrder) { EXPECT_EQ(3U, cluster.info().use_count()); } -// Validate that the v2 envoy::api::v2::Bootstrap overrides JSON config. -TEST_F(ClusterManagerImplTest, CdsBootstrap) { - const std::string json = R"EOF( - { - "clusters": [ - { - "name": "clusterwithareallyreallylongnamemorethanmaxcharsallowedbyschema" - }] - } - )EOF"; - - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - EXPECT_THROW_WITH_MESSAGE(create(*loader), Json::Exception, - "JSON at lines 4-6 does not conform to schema.\n Invalid schema: " - "#/properties/name\n Schema violation: maxLength\n Offending " - "document key: #/name"); - - envoy::api::v2::Bootstrap cds_config_bootstrap; - cds_config_bootstrap.mutable_dynamic_resources()->mutable_cds_config(); - createWithBootstrap(*loader, cds_config_bootstrap); - - envoy::api::v2::Bootstrap clusters_bootstrap; - clusters_bootstrap.mutable_static_resources()->mutable_clusters()->Add()->CopyFrom( - defaultStaticCluster("foo")); - createWithBootstrap(*loader, clusters_bootstrap); -} - TEST_F(ClusterManagerImplTest, InitializeOrder) { const std::string json = fmt::sprintf( R"EOF( @@ -490,19 +451,18 @@ TEST_F(ClusterManagerImplTest, InitializeOrder) { // This part tests static init. InSequence s; - EXPECT_CALL(factory_, clusterFromProto_(_, _, _, _)).WillOnce(Return(cds_cluster)); - ON_CALL(*cds_cluster, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); - EXPECT_CALL(*cds_cluster, initialize()); - EXPECT_CALL(factory_, createCds_()).WillOnce(Return(cds)); - EXPECT_CALL(*cds, setInitializedCb(_)); EXPECT_CALL(factory_, clusterFromProto_(_, _, _, _)).WillOnce(Return(cluster1)); ON_CALL(*cluster1, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); EXPECT_CALL(*cluster1, initialize()); EXPECT_CALL(factory_, clusterFromProto_(_, _, _, _)).WillOnce(Return(cluster2)); ON_CALL(*cluster2, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Secondary)); + EXPECT_CALL(factory_, clusterFromProto_(_, _, _, _)).WillOnce(Return(cds_cluster)); + ON_CALL(*cds_cluster, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); + EXPECT_CALL(*cds_cluster, initialize()); + EXPECT_CALL(factory_, createCds_()).WillOnce(Return(cds)); + EXPECT_CALL(*cds, setInitializedCb(_)); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); ReadyWatcher initialized; cluster_manager_->setInitializedCb([&]() -> void { initialized.ready(); }); @@ -574,8 +534,7 @@ TEST_F(ClusterManagerImplTest, DynamicRemoveWithLocalCluster) { ON_CALL(*foo, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); EXPECT_CALL(*foo, initialize()); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); foo->initialize_callback_(); // Now add a dynamic cluster. This cluster will have a member update callback from the local @@ -617,8 +576,7 @@ TEST_F(ClusterManagerImplTest, DynamicAddRemove) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); InSequence s; ReadyWatcher initialized; @@ -686,8 +644,7 @@ TEST_F(ClusterManagerImplTest, AddOrUpdatePrimaryClusterStaticExists) { ON_CALL(*cluster1, initializePhase()).WillByDefault(Return(Cluster::InitializePhase::Primary)); EXPECT_CALL(*cluster1, initialize()); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); ReadyWatcher initialized; cluster_manager_->setInitializedCb([&]() -> void { initialized.ready(); }); @@ -720,8 +677,6 @@ TEST_F(ClusterManagerImplTest, DynamicHostRemove) { } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - std::shared_ptr dns_resolver(new Network::MockDnsResolver()); EXPECT_CALL(factory_.dispatcher_, createDnsResolver(_)).WillOnce(Return(dns_resolver)); @@ -730,7 +685,7 @@ TEST_F(ClusterManagerImplTest, DynamicHostRemove) { Network::MockActiveDnsQuery active_dns_query; EXPECT_CALL(*dns_resolver, resolve(_, _, _)) .WillRepeatedly(DoAll(SaveArg<2>(&dns_callback), Return(&active_dns_query))); - create(*loader); + create(parseBootstrapFromJson(json)); EXPECT_FALSE(cluster_manager_->get("cluster_1")->info()->addedViaApi()); // Test for no hosts returning the correct values before we have hosts. @@ -817,8 +772,7 @@ TEST_F(ClusterManagerImplTest, OriginalDstInitialization) { ReadyWatcher initialized; EXPECT_CALL(initialized, ready()); - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - create(*loader); + create(parseBootstrapFromJson(json)); // Set up for an initialize callback. cluster_manager_->setInitializedCb([&]() -> void { initialized.ready(); }); diff --git a/test/common/upstream/eds_test.cc b/test/common/upstream/eds_test.cc index 6ac694e7a8cd..288b2ae1d4de 100644 --- a/test/common/upstream/eds_test.cc +++ b/test/common/upstream/eds_test.cc @@ -29,9 +29,11 @@ class EdsTest : public testing::Test { } void resetCluster(const std::string& json_config) { - SdsConfig sds_config{"eds", std::chrono::milliseconds(30000)}; + envoy::api::v2::ConfigSource eds_config; + eds_config.mutable_api_config_source()->add_cluster_name("eds"); + eds_config.mutable_api_config_source()->mutable_refresh_delay()->set_seconds(1); local_info_.zone_name_ = "us-east-1a"; - eds_cluster_ = parseSdsClusterFromJson(json_config, sds_config); + eds_cluster_ = parseSdsClusterFromJson(json_config, eds_config); cluster_.reset(new EdsClusterImpl(eds_cluster_, runtime_, stats_, ssl_context_manager_, local_info_, cm_, dispatcher_, random_, false)); EXPECT_EQ(Cluster::InitializePhase::Secondary, cluster_->initializePhase()); diff --git a/test/common/upstream/sds_test.cc b/test/common/upstream/sds_test.cc index a9d92b2026e9..00ac0faddf3e 100644 --- a/test/common/upstream/sds_test.cc +++ b/test/common/upstream/sds_test.cc @@ -51,8 +51,10 @@ class SdsTest : public testing::Test { timer_ = new Event::MockTimer(&dispatcher_); local_info_.zone_name_ = "us-east-1a"; - const SdsConfig sds_config{"sds", std::chrono::milliseconds(30000)}; - sds_cluster_ = parseSdsClusterFromJson(raw_config, sds_config); + envoy::api::v2::ConfigSource eds_config; + eds_config.mutable_api_config_source()->add_cluster_name("sds"); + eds_config.mutable_api_config_source()->mutable_refresh_delay()->set_seconds(1); + sds_cluster_ = parseSdsClusterFromJson(raw_config, eds_config); cluster_.reset(new EdsClusterImpl(sds_cluster_, runtime_, stats_, ssl_context_manager_, local_info_, cm_, dispatcher_, random_, false)); EXPECT_EQ(Cluster::InitializePhase::Secondary, cluster_->initializePhase()); diff --git a/test/common/upstream/utility.h b/test/common/upstream/utility.h index 6e307ce93fb0..6d9d04661b33 100644 --- a/test/common/upstream/utility.h +++ b/test/common/upstream/utility.h @@ -42,7 +42,8 @@ inline std::string clustersJson(const std::vector& clusters) { inline envoy::api::v2::Cluster parseClusterFromJson(const std::string& json_string) { envoy::api::v2::Cluster cluster; auto json_object_ptr = Json::Factory::loadFromString(json_string); - Config::CdsJson::translateCluster(*json_object_ptr, Optional(), cluster); + Config::CdsJson::translateCluster(*json_object_ptr, Optional(), + cluster); return cluster; } @@ -50,11 +51,12 @@ inline envoy::api::v2::Cluster defaultStaticCluster(const std::string& name) { return parseClusterFromJson(defaultStaticClusterJson(name)); } -inline envoy::api::v2::Cluster parseSdsClusterFromJson(const std::string& json_string, - const SdsConfig sds_config) { +inline envoy::api::v2::Cluster +parseSdsClusterFromJson(const std::string& json_string, + const envoy::api::v2::ConfigSource eds_config) { envoy::api::v2::Cluster cluster; auto json_object_ptr = Json::Factory::loadFromString(json_string); - Config::CdsJson::translateCluster(*json_object_ptr, sds_config, cluster); + Config::CdsJson::translateCluster(*json_object_ptr, eds_config, cluster); return cluster; } diff --git a/test/config/integration/BUILD b/test/config/integration/BUILD index 51bdc3b92d71..d94a60daf92e 100644 --- a/test/config/integration/BUILD +++ b/test/config/integration/BUILD @@ -27,7 +27,6 @@ filegroup( "server_xds.bootstrap.yaml", "server_xds.cds.yaml", "server_xds.eds.yaml", - "server_xds.json", "server_xds.lds.yaml", "server_xds.rds.yaml", ], diff --git a/test/config/integration/server_xds.bootstrap.yaml b/test/config/integration/server_xds.bootstrap.yaml index fdd63c2c3a1a..26eafc3e79d6 100644 --- a/test/config/integration/server_xds.bootstrap.yaml +++ b/test/config/integration/server_xds.bootstrap.yaml @@ -3,3 +3,9 @@ dynamic_resources: path: {{ lds_json_path }} cds_config: path: {{ cds_json_path }} +admin: + access_log_path: /dev/null + address: + socket_address: + address: {{ ntop_ip_loopback_address }} + port_value: 0 diff --git a/test/config/integration/server_xds.json b/test/config/integration/server_xds.json deleted file mode 100644 index 111bc3b9d12d..000000000000 --- a/test/config/integration/server_xds.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "listeners": [], - "admin": { "access_log_path": "/dev/null", "address": "tcp://{{ ip_loopback_address }}:0" }, - "cluster_manager": { - "clusters": [] - } -} diff --git a/test/config_test/config_test.cc b/test/config_test/config_test.cc index e8940383bada..8cd50a66bc39 100644 --- a/test/config_test/config_test.cc +++ b/test/config_test/config_test.cc @@ -25,8 +25,7 @@ namespace ConfigTest { class ConfigTest { public: - ConfigTest(const std::string& file_path) - : options_(file_path, std::string(), Network::Address::IpVersion::v6) { + ConfigTest(const std::string& file_path) : options_(file_path, Network::Address::IpVersion::v6) { ON_CALL(server_, options()).WillByDefault(ReturnRef(options_)); ON_CALL(server_, random()).WillByDefault(ReturnRef(random_)); ON_CALL(server_, sslContextManager()).WillByDefault(ReturnRef(ssl_context_manager_)); @@ -34,8 +33,9 @@ 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); + envoy::api::v2::Bootstrap bootstrap = + TestUtility::parseBootstrapFromJson(config_json->asJsonString()); + Server::Configuration::InitialImpl initial_config(bootstrap); Server::Configuration::MainImpl main_config; cluster_manager_factory_.reset(new Upstream::ProdClusterManagerFactory( @@ -54,7 +54,7 @@ class ConfigTest { })); try { - main_config.initialize(*config_json, bootstrap, server_, *cluster_manager_factory_); + main_config.initialize(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/BUILD b/test/integration/BUILD index 041e60321d6c..6571fdbaf3bd 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -11,6 +11,18 @@ load( envoy_package() +envoy_cc_test( + name = "proto_integration_test", + srcs = ["proto_integration_test.cc"], + deps = [ + ":integration_lib", + "//source/common/http:header_map_lib", + "//source/common/protobuf:utility_lib", + "//test/test_common:network_utility_lib", + "//test/test_common:utility_lib", + ], +) + envoy_sh_test( name = "hotrestart_test", srcs = envoy_select_hot_restart(["hotrestart_test.sh"]), diff --git a/test/integration/integration.cc b/test/integration/integration.cc index 689707a5eb02..15e0870a5d90 100644 --- a/test/integration/integration.cc +++ b/test/integration/integration.cc @@ -324,38 +324,37 @@ void BaseIntegrationTest::registerTestServerPorts(const std::vector registerPort("admin", test_server_->server().admin().socket().localAddress()->ip()->port()); } -void BaseIntegrationTest::createApiTestServer(const std::string& json_path, - const ApiFilesystemConfig& api_filesystem_config, - const std::vector& port_names) { - if (api_filesystem_config.bootstrap_path_.empty()) { - test_server_ = IntegrationTestServer::create( - TestEnvironment::temporaryFileSubstitute(json_path, port_map_, version_), std::string(), - version_); - } else { - const std::string eds_path = TestEnvironment::temporaryFileSubstitute( - api_filesystem_config.eds_path_, port_map_, version_); - const std::string cds_path = TestEnvironment::temporaryFileSubstitute( - api_filesystem_config.cds_path_, {{"eds_json_path", eds_path}}, port_map_, version_); - const std::string rds_path = TestEnvironment::temporaryFileSubstitute( - api_filesystem_config.rds_path_, port_map_, version_); - const std::string lds_path = TestEnvironment::temporaryFileSubstitute( - api_filesystem_config.lds_path_, {{"rds_json_path", rds_path}}, port_map_, version_); - test_server_ = IntegrationTestServer::create( - TestEnvironment::temporaryFileSubstitute(json_path, port_map_, version_), - TestEnvironment::temporaryFileSubstitute( - api_filesystem_config.bootstrap_path_, - {{"cds_json_path", cds_path}, {"lds_json_path", lds_path}}, port_map_, version_), - version_); - // Need to ensure we have an LDS update before invoking registerTestServerPorts() below that - // needs to know about the bound listener ports. - test_server_->waitForCounterGe("listener_manager.listener_create_success", 1); - } +void BaseIntegrationTest::createGeneratedApiTestServer(const std::string& bootstrap_path, + const std::vector& port_names) { + test_server_ = IntegrationTestServer::create(bootstrap_path, version_); + // Need to ensure we have an LDS update before invoking registerTestServerPorts() below that + // needs to know about the bound listener ports. + test_server_->waitForCounterGe("listener_manager.listener_create_success", 1); registerTestServerPorts(port_names); } +void BaseIntegrationTest::createApiTestServer(const ApiFilesystemConfig& api_filesystem_config, + const std::vector& port_names) { + const std::string eds_path = TestEnvironment::temporaryFileSubstitute( + api_filesystem_config.eds_path_, port_map_, version_); + const std::string cds_path = TestEnvironment::temporaryFileSubstitute( + api_filesystem_config.cds_path_, {{"eds_json_path", eds_path}}, port_map_, version_); + const std::string rds_path = TestEnvironment::temporaryFileSubstitute( + api_filesystem_config.rds_path_, port_map_, version_); + const std::string lds_path = TestEnvironment::temporaryFileSubstitute( + api_filesystem_config.lds_path_, {{"rds_json_path", rds_path}}, port_map_, version_); + createGeneratedApiTestServer(TestEnvironment::temporaryFileSubstitute( + api_filesystem_config.bootstrap_path_, + {{"cds_json_path", cds_path}, {"lds_json_path", lds_path}}, + port_map_, version_), + port_names); +} + void BaseIntegrationTest::createTestServer(const std::string& json_path, const std::vector& port_names) { - createApiTestServer(json_path, ApiFilesystemConfig(), port_names); + test_server_ = IntegrationTestServer::create( + TestEnvironment::temporaryFileSubstitute(json_path, port_map_, version_), version_); + registerTestServerPorts(port_names); } void BaseIntegrationTest::sendRequestAndWaitForResponse(Http::TestHeaderMapImpl& request_headers, diff --git a/test/integration/integration.h b/test/integration/integration.h index 1c40120496ae..407f6019b097 100644 --- a/test/integration/integration.h +++ b/test/integration/integration.h @@ -188,8 +188,9 @@ class BaseIntegrationTest : Logger::Loggable { void sendRawHttpAndWaitForResponse(const char* http, std::string* response); void registerTestServerPorts(const std::vector& port_names); void createTestServer(const std::string& json_path, const std::vector& port_names); - void createApiTestServer(const std::string& json_path, - const ApiFilesystemConfig& api_filesystem_config, + void createGeneratedApiTestServer(const std::string& bootstrap_path, + const std::vector& port_names); + void createApiTestServer(const ApiFilesystemConfig& api_filesystem_config, const std::vector& port_names); Api::ApiPtr api_; diff --git a/test/integration/integration_test.cc b/test/integration/integration_test.cc index 7b2991995b7a..7e06eac3f84a 100644 --- a/test/integration/integration_test.cc +++ b/test/integration/integration_test.cc @@ -3,8 +3,10 @@ #include #include "common/http/header_map_impl.h" +#include "common/protobuf/utility.h" #include "test/integration/utility.h" +#include "test/test_common/network_utility.h" #include "test/test_common/printers.h" #include "test/test_common/utility.h" @@ -218,53 +220,4 @@ TEST_P(IntegrationTest, WebSocketConnectionUpstreamDisconnect) { EXPECT_EQ(upgrade_resp_str + "world", tcp_client->data()); } -class BindIntegrationTest : public IntegrationTest { -public: - void SetUp() override { - envoy::api::v2::Bootstrap bootstrap; - if (GetParam() == Network::Address::IpVersion::v4) { - address_string_ = TestUtility::getIpv4Loopback(); - } - bootstrap.mutable_cluster_manager() - ->mutable_upstream_bind_config() - ->mutable_source_address() - ->set_address(address_string_); - - api_filesystem_config_.bootstrap_path_ = - TestEnvironment::writeStringToFileForTest("bootstrap.pb", bootstrap.SerializeAsString()); - IntegrationTest::SetUp(); - } - - std::string address_string_ = "::1"; -}; - -TEST_P(BindIntegrationTest, TestBind) { - executeActions( - {[&]() -> void { - codec_client_ = makeHttpConnection(lookupPort("http"), Http::CodecClient::Type::HTTP1); - }, - // Request 1. - [&]() -> void { - codec_client_->makeRequestWithBody(Http::TestHeaderMapImpl{{":method", "GET"}, - {":path", "/test/long/url"}, - {":scheme", "http"}, - {":authority", "host"}}, - 1024, *response_); - }, - [&]() -> void { - fake_upstream_connection_ = fake_upstreams_[0]->waitForHttpConnection(*dispatcher_); - std::string address = - fake_upstream_connection_->connection().remoteAddress().ip()->addressAsString(); - EXPECT_EQ(address, address_string_); - }, - [&]() -> void { upstream_request_ = fake_upstream_connection_->waitForNewStream(); }, - [&]() -> void { upstream_request_->waitForEndStream(*dispatcher_); }, - // Cleanup both downstream and upstream - [&]() -> void { codec_client_->close(); }, - [&]() -> void { fake_upstream_connection_->close(); }, - [&]() -> void { fake_upstream_connection_->waitForDisconnect(); }}); -} - -INSTANTIATE_TEST_CASE_P(IpVersions, BindIntegrationTest, - testing::ValuesIn(TestEnvironment::getIpVersionsForTest())); } // namespace Envoy diff --git a/test/integration/integration_test.h b/test/integration/integration_test.h index c6310727bb88..5efcdd9f850f 100644 --- a/test/integration/integration_test.h +++ b/test/integration/integration_test.h @@ -17,8 +17,8 @@ class IntegrationTest : public BaseIntegrationTest, registerPort("upstream_0", fake_upstreams_.back()->localAddress()->ip()->port()); fake_upstreams_.emplace_back(new FakeUpstream(0, FakeHttpConnection::Type::HTTP1, version_)); registerPort("upstream_1", fake_upstreams_.back()->localAddress()->ip()->port()); - createApiTestServer("test/config/integration/server.json", api_filesystem_config_, - {"http", "http_forward", "http_buffer", "rds"}); + createTestServer("test/config/integration/server.json", + {"http", "http_forward", "http_buffer", "rds"}); } /** @@ -28,7 +28,5 @@ class IntegrationTest : public BaseIntegrationTest, test_server_.reset(); fake_upstreams_.clear(); } - - ApiFilesystemConfig api_filesystem_config_; }; } // namespace Envoy diff --git a/test/integration/proto_integration_test.cc b/test/integration/proto_integration_test.cc new file mode 100644 index 000000000000..5114f0904784 --- /dev/null +++ b/test/integration/proto_integration_test.cc @@ -0,0 +1,126 @@ +#include + +#include "common/http/header_map_impl.h" +#include "common/protobuf/utility.h" + +#include "test/integration/integration.h" +#include "test/integration/utility.h" +#include "test/test_common/network_utility.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace { + +class ProtoIntegrationTest : public BaseIntegrationTest, + public testing::TestWithParam { +public: + ProtoIntegrationTest() : BaseIntegrationTest(GetParam()) {} + + void SetUp() override { + // Fake upstream. + fake_upstreams_.emplace_back(new FakeUpstream(0, FakeHttpConnection::Type::HTTP1, version_)); + + // Below we build up the config completely dynamically. + // TODO(alyssawilk): Make some of this a static config as appropriate, i.e. the bits that won't + // change. + envoy::api::v2::Bootstrap bootstrap; + + // Admin access log path and address. + auto* admin = bootstrap.mutable_admin(); + admin->set_access_log_path("/dev/null"); + auto* admin_socket_addr = admin->mutable_address()->mutable_socket_address(); + admin_socket_addr->set_address(Network::Test::getLoopbackAddressString(GetParam())); + admin_socket_addr->set_port_value(0); + + // HTTP/1.1 Listener with HTTP connection manager filter. + auto* static_resources = bootstrap.mutable_static_resources(); + auto* listener = static_resources->mutable_listeners()->Add(); + listener->set_name("listener_0"); + auto* listener_socket_addr = listener->mutable_address()->mutable_socket_address(); + listener_socket_addr->set_address(Network::Test::getLoopbackAddressString(GetParam())); + listener_socket_addr->set_port_value(0); + auto* hcm_filter = listener->mutable_filter_chains()->Add()->mutable_filters()->Add(); + hcm_filter->set_name("http_connection_manager"); + envoy::api::v2::filter::HttpConnectionManager hcm_config; + hcm_config.set_codec_type(envoy::api::v2::filter::HttpConnectionManager::HTTP1); + auto* router_filter = hcm_config.mutable_http_filters()->Add(); + router_filter->set_name("router"); + (*router_filter->mutable_config()->mutable_fields())["deprecated_v1"].set_bool_value(true); + // Route configuration. + auto* route_config = hcm_config.mutable_route_config(); + route_config->set_name("route_config_0"); + auto* virtual_host = route_config->mutable_virtual_hosts()->Add(); + virtual_host->set_name("integration"); + virtual_host->add_domains("*"); + auto* route = virtual_host->mutable_routes()->Add(); + route->mutable_match()->set_prefix("/"); + route->mutable_route()->set_cluster("cluster_0"); + MessageUtil::jsonConvert(hcm_config, *hcm_filter->mutable_config()); + + // Cluster for fake upstream. + auto* cluster = static_resources->mutable_clusters()->Add(); + cluster->set_name("cluster_0"); + cluster->mutable_connect_timeout()->set_seconds(5); + cluster->set_type(envoy::api::v2::Cluster::STATIC); + cluster->set_lb_policy(envoy::api::v2::Cluster::ROUND_ROBIN); + auto* host_socket_addr = cluster->mutable_hosts()->Add()->mutable_socket_address(); + host_socket_addr->set_address(Network::Test::getLoopbackAddressString(GetParam())); + host_socket_addr->set_port_value(fake_upstreams_.back()->localAddress()->ip()->port()); + + // Cluster manager. + // TODO(alyssawilk): Refactor to separate the bind-specific from generic v2 proto config setup. + if (GetParam() == Network::Address::IpVersion::v4) { + address_string_ = TestUtility::getIpv4Loopback(); + } + bootstrap.mutable_cluster_manager() + ->mutable_upstream_bind_config() + ->mutable_source_address() + ->set_address(address_string_); + + // Generate bootstrap JSON. + const std::string bootstrap_path = TestEnvironment::writeStringToFileForTest( + "bootstrap.json", MessageUtil::getJsonStringFromMessage(bootstrap)); + createGeneratedApiTestServer(bootstrap_path, {"http"}); + } + + void TearDown() override { + test_server_.reset(); + fake_upstreams_.clear(); + } + + std::string address_string_ = "::1"; +}; + +TEST_P(ProtoIntegrationTest, TestBind) { + executeActions( + {[&]() -> void { + codec_client_ = makeHttpConnection(lookupPort("http"), Http::CodecClient::Type::HTTP1); + }, + // Request 1. + [&]() -> void { + codec_client_->makeRequestWithBody(Http::TestHeaderMapImpl{{":method", "GET"}, + {":path", "/test/long/url"}, + {":scheme", "http"}, + {":authority", "host"}}, + 1024, *response_); + }, + [&]() -> void { + fake_upstream_connection_ = fake_upstreams_[0]->waitForHttpConnection(*dispatcher_); + std::string address = + fake_upstream_connection_->connection().remoteAddress().ip()->addressAsString(); + EXPECT_EQ(address, address_string_); + }, + [&]() -> void { upstream_request_ = fake_upstream_connection_->waitForNewStream(); }, + [&]() -> void { upstream_request_->waitForEndStream(*dispatcher_); }, + // Cleanup both downstream and upstream + [&]() -> void { codec_client_->close(); }, + [&]() -> void { fake_upstream_connection_->close(); }, + [&]() -> void { fake_upstream_connection_->waitForDisconnect(); }}); +} + +INSTANTIATE_TEST_CASE_P(IpVersions, ProtoIntegrationTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest())); +} // namespace +} // namespace Envoy diff --git a/test/integration/server.cc b/test/integration/server.cc index e3fd5c7f3cc7..e15cfb003de5 100644 --- a/test/integration/server.cc +++ b/test/integration/server.cc @@ -20,9 +20,8 @@ namespace Envoy { IntegrationTestServerPtr IntegrationTestServer::create(const std::string& config_path, - const std::string& bootstrap_path, const Network::Address::IpVersion version) { - IntegrationTestServerPtr server{new IntegrationTestServer(config_path, bootstrap_path)}; + IntegrationTestServerPtr server{new IntegrationTestServer(config_path)}; server->start(version); return server; } @@ -75,7 +74,7 @@ void IntegrationTestServer::onWorkerListenerRemoved() { } void IntegrationTestServer::threadRoutine(const Network::Address::IpVersion version) { - Server::TestOptionsImpl options(config_path_, bootstrap_path_, version); + Server::TestOptionsImpl options(config_path_, version); Server::HotRestartNopImpl restarter; Thread::MutexBasicLockable lock; diff --git a/test/integration/server.h b/test/integration/server.h index 5f063443f436..7f342562af45 100644 --- a/test/integration/server.h +++ b/test/integration/server.h @@ -27,17 +27,15 @@ namespace Server { */ class TestOptionsImpl : public Options { public: - TestOptionsImpl(const std::string& config_path, const std::string& bootstrap_path, - Network::Address::IpVersion ip_version) - : config_path_(config_path), bootstrap_path_(bootstrap_path), - local_address_ip_version_(ip_version), service_cluster_name_("cluster_name"), - service_node_name_("node_name"), service_zone_("zone_name") {} + TestOptionsImpl(const std::string& config_path, Network::Address::IpVersion ip_version) + : config_path_(config_path), local_address_ip_version_(ip_version), + service_cluster_name_("cluster_name"), service_node_name_("node_name"), + service_zone_("zone_name") {} // Server::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); } @@ -54,7 +52,6 @@ class TestOptionsImpl : public Options { private: const std::string config_path_; - const std::string bootstrap_path_; const std::string admin_address_path_; const Network::Address::IpVersion local_address_ip_version_; const std::string service_cluster_name_; @@ -190,7 +187,6 @@ class IntegrationTestServer : Logger::Loggable, public Server::ComponentFactory { public: static IntegrationTestServerPtr create(const std::string& config_path, - const std::string& bootstrap_path, const Network::Address::IpVersion version); ~IntegrationTestServer(); @@ -247,8 +243,7 @@ class IntegrationTestServer : Logger::Loggable, } protected: - IntegrationTestServer(const std::string& config_path, const std::string& bootstrap_path) - : config_path_(config_path), bootstrap_path_(bootstrap_path) {} + IntegrationTestServer(const std::string& config_path) : config_path_(config_path) {} private: /** @@ -257,7 +252,6 @@ class IntegrationTestServer : Logger::Loggable, void threadRoutine(const Network::Address::IpVersion version); const std::string config_path_; - const std::string bootstrap_path_; Thread::ThreadPtr thread_; std::condition_variable listeners_cv_; std::mutex listeners_mutex_; diff --git a/test/integration/ssl_integration_test.h b/test/integration/ssl_integration_test.h index 2867fd7e918c..7f892363a946 100644 --- a/test/integration/ssl_integration_test.h +++ b/test/integration/ssl_integration_test.h @@ -34,7 +34,7 @@ class MockRuntimeIntegrationTestServer : public IntegrationTestServer { private: MockRuntimeIntegrationTestServer(const std::string& config_path) - : IntegrationTestServer(config_path, std::string()) {} + : IntegrationTestServer(config_path) {} }; class SslIntegrationTest : public BaseIntegrationTest, diff --git a/test/integration/xds_integration_test.cc b/test/integration/xds_integration_test.cc index 0fbb05bd9d9e..d866ef54eac7 100644 --- a/test/integration/xds_integration_test.cc +++ b/test/integration/xds_integration_test.cc @@ -15,15 +15,15 @@ class XdsIntegrationTest : public BaseIntegrationTest, void SetUp() override { fake_upstreams_.emplace_back(new FakeUpstream(0, FakeHttpConnection::Type::HTTP2, version_)); registerPort("upstream_0", fake_upstreams_.back()->localAddress()->ip()->port()); - createApiTestServer("test/config/integration/server_xds.json", - { - .bootstrap_path_ = "test/config/integration/server_xds.bootstrap.yaml", - .cds_path_ = "test/config/integration/server_xds.cds.yaml", - .eds_path_ = "test/config/integration/server_xds.eds.yaml", - .lds_path_ = "test/config/integration/server_xds.lds.yaml", - .rds_path_ = "test/config/integration/server_xds.rds.yaml", - }, - {"http"}); + createApiTestServer( + { + .bootstrap_path_ = "test/config/integration/server_xds.bootstrap.yaml", + .cds_path_ = "test/config/integration/server_xds.cds.yaml", + .eds_path_ = "test/config/integration/server_xds.eds.yaml", + .lds_path_ = "test/config/integration/server_xds.lds.yaml", + .rds_path_ = "test/config/integration/server_xds.rds.yaml", + }, + {"http"}); } void TearDown() override { diff --git a/test/mocks/server/mocks.cc b/test/mocks/server/mocks.cc index 9900030060e2..fcb502b20324 100644 --- a/test/mocks/server/mocks.cc +++ b/test/mocks/server/mocks.cc @@ -17,10 +17,9 @@ using testing::_; namespace Envoy { namespace Server { -MockOptions::MockOptions(const std::string& config_path, const std::string& bootstrap_path) - : config_path_(config_path), bootstrap_path_(bootstrap_path), admin_address_path_("") { +MockOptions::MockOptions(const std::string& config_path) + : config_path_(config_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_)); ON_CALL(*this, serviceClusterName()).WillByDefault(ReturnRef(service_cluster_name_)); ON_CALL(*this, serviceNodeName()).WillByDefault(ReturnRef(service_node_name_)); diff --git a/test/mocks/server/mocks.h b/test/mocks/server/mocks.h index e05cf8afe672..8c35b04c110b 100644 --- a/test/mocks/server/mocks.h +++ b/test/mocks/server/mocks.h @@ -40,14 +40,12 @@ namespace Server { class MockOptions : public Options { public: MockOptions() : MockOptions(std::string()) {} - MockOptions(const std::string& config_path) : MockOptions(config_path, std::string()) {} - MockOptions(const std::string& config_path, const std::string& boostrap_path); + MockOptions(const std::string& config_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()); @@ -61,7 +59,6 @@ class MockOptions : public Options { MOCK_METHOD0(serviceZone, const std::string&()); std::string config_path_; - std::string bootstrap_path_; std::string admin_address_path_; std::string service_cluster_name_; std::string service_node_name_; @@ -303,7 +300,7 @@ class MockMain : public Main { MOCK_METHOD0(httpTracer, Tracing::HttpTracer&()); MOCK_METHOD0(rateLimitClientFactory, RateLimit::ClientFactory&()); MOCK_METHOD0(statsdTcpClusterName, Optional()); - MOCK_METHOD0(statsdUdpIpAddress, Optional()); + MOCK_METHOD0(statsdUdpIpAddress, Network::Address::InstanceConstSharedPtr()); MOCK_METHOD0(statsFlushInterval, std::chrono::milliseconds()); MOCK_CONST_METHOD0(wdMissTimeout, std::chrono::milliseconds()); MOCK_CONST_METHOD0(wdMegaMissTimeout, std::chrono::milliseconds()); diff --git a/test/server/BUILD b/test/server/BUILD index 1a51558c2e2d..bcbb5e74631c 100644 --- a/test/server/BUILD +++ b/test/server/BUILD @@ -112,8 +112,7 @@ envoy_cc_test( name = "server_test", srcs = ["server_test.cc"], data = [ - ":empty_bootstrap.json", - ":node_bootstrap.json", + ":node_bootstrap.yaml", "//test/config/integration:server.json", "//test/config/integration:server_config_files", ], diff --git a/test/server/config/http/config_test.cc b/test/server/config/http/config_test.cc index 2104b5f778de..c91f404e7efa 100644 --- a/test/server/config/http/config_test.cc +++ b/test/server/config/http/config_test.cc @@ -281,7 +281,7 @@ TEST(HttpTracerConfigTest, ZipkinHttpTracer) { TEST(HttpTracerConfigTest, DoubleRegistrationTest) { EXPECT_THROW_WITH_MESSAGE( (Registry::RegisterFactory()), EnvoyException, - "Double registration for name: 'zipkin'"); + "Double registration for name: 'envoy.zipkin'"); } } // namespace Configuration diff --git a/test/server/config_validation/BUILD b/test/server/config_validation/BUILD index 83a95026e824..26300c601a10 100644 --- a/test/server/config_validation/BUILD +++ b/test/server/config_validation/BUILD @@ -20,10 +20,8 @@ envoy_cc_test( name = "cluster_manager_test", srcs = ["cluster_manager_test.cc"], deps = [ - "//include/envoy/json:json_object_interface", "//include/envoy/upstream:resource_manager_interface", "//include/envoy/upstream:upstream_interface", - "//source/common/json:json_loader_lib", "//source/common/ssl:context_lib", "//source/common/stats:stats_lib", "//source/server/config_validation:cluster_manager_lib", @@ -35,6 +33,7 @@ envoy_cc_test( "//test/mocks/runtime:runtime_mocks", "//test/mocks/thread_local:thread_local_mocks", "//test/mocks/upstream:upstream_mocks", + "//test/test_common:utility_lib", ], ) diff --git a/test/server/config_validation/cluster_manager_test.cc b/test/server/config_validation/cluster_manager_test.cc index 1ec20df8dc8b..9664ba490773 100644 --- a/test/server/config_validation/cluster_manager_test.cc +++ b/test/server/config_validation/cluster_manager_test.cc @@ -1,8 +1,6 @@ -#include "envoy/json/json_object.h" #include "envoy/upstream/resource_manager.h" #include "envoy/upstream/upstream.h" -#include "common/json/json_loader.h" #include "common/ssl/context_manager_impl.h" #include "common/stats/stats_impl.h" @@ -16,6 +14,7 @@ #include "test/mocks/runtime/mocks.h" #include "test/mocks/thread_local/mocks.h" #include "test/mocks/upstream/mocks.h" +#include "test/test_common/utility.h" namespace Envoy { namespace Upstream { @@ -33,16 +32,10 @@ TEST(ValidationClusterManagerTest, MockedMethods) { ValidationClusterManagerFactory factory(runtime, stats, tls, random, dns_resolver, ssl_context_manager, dispatcher, local_info); - std::string json = R"EOF( - { - "clusters": [] - } - )EOF"; - Json::ObjectSharedPtr config = Json::Factory::loadFromString(json); AccessLog::MockAccessLogManager log_manager; - envoy::api::v2::Bootstrap bootstrap; - ClusterManagerPtr cluster_manager = factory.clusterManagerFromJson( - *config, bootstrap, stats, tls, runtime, random, local_info, log_manager); + const envoy::api::v2::Bootstrap bootstrap; + ClusterManagerPtr cluster_manager = factory.clusterManagerFromProto( + 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", nullptr); diff --git a/test/server/configuration_impl_test.cc b/test/server/configuration_impl_test.cc index e57014a16fe3..971a9ea9ce5f 100644 --- a/test/server/configuration_impl_test.cc +++ b/test/server/configuration_impl_test.cc @@ -55,21 +55,10 @@ class ConfigurationImplTest : public testing::Test { }; TEST_F(ConfigurationImplTest, DefaultStatsFlushInterval) { - std::string json = R"EOF( - { - "listeners": [], - - "cluster_manager": { - "clusters": [] - } - } - )EOF"; - - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); envoy::api::v2::Bootstrap bootstrap; MainImpl config; - config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); + config.initialize(bootstrap, server_, cluster_manager_factory_); EXPECT_EQ(std::chrono::milliseconds(5000), config.statsFlushInterval()); } @@ -83,21 +72,22 @@ TEST_F(ConfigurationImplTest, CustomStatsFlushInterval) { "cluster_manager": { "clusters": [] - } + }, + + "admin": {"access_log_path": "/dev/null", "address": "tcp://1.2.3.4:5678"} } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - envoy::api::v2::Bootstrap bootstrap; + envoy::api::v2::Bootstrap bootstrap = TestUtility::parseBootstrapFromJson(json); MainImpl config; - config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); + config.initialize(bootstrap, server_, cluster_manager_factory_); EXPECT_EQ(std::chrono::milliseconds(500), config.statsFlushInterval()); } TEST_F(ConfigurationImplTest, SetUpstreamClusterPerConnectionBufferLimit) { - std::string json = R"EOF( + const std::string json = R"EOF( { "listeners" : [], "cluster_manager": { @@ -113,15 +103,15 @@ TEST_F(ConfigurationImplTest, SetUpstreamClusterPerConnectionBufferLimit) { ] } ] - } + }, + "admin": {"access_log_path": "/dev/null", "address": "tcp://1.2.3.4:5678"} } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - envoy::api::v2::Bootstrap bootstrap; + envoy::api::v2::Bootstrap bootstrap = TestUtility::parseBootstrapFromJson(json); MainImpl config; - config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); + config.initialize(bootstrap, server_, cluster_manager_factory_); ASSERT_EQ(1U, config.clusterManager().clusters().count("test_cluster")); EXPECT_EQ(8192U, config.clusterManager() @@ -150,21 +140,21 @@ TEST_F(ConfigurationImplTest, ServiceClusterNotSetWhenLSTracing) { "driver": { "type": "lightstep", "config": { + "collector_cluster": "cluster_0", "access_token_file": "/etc/envoy/envoy.cfg" } } } - } + }, + "admin": {"access_log_path": "/dev/null", "address": "tcp://1.2.3.4:5678"} } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - envoy::api::v2::Bootstrap bootstrap; + envoy::api::v2::Bootstrap bootstrap = TestUtility::parseBootstrapFromJson(json); server_.local_info_.cluster_name_ = ""; MainImpl config; - EXPECT_THROW(config.initialize(*loader, bootstrap, server_, cluster_manager_factory_), - EnvoyException); + EXPECT_THROW(config.initialize(bootstrap, server_, cluster_manager_factory_), EnvoyException); } TEST_F(ConfigurationImplTest, NullTracerSetWhenTracingConfigurationAbsent) { @@ -178,16 +168,16 @@ TEST_F(ConfigurationImplTest, NullTracerSetWhenTracingConfigurationAbsent) { ], "cluster_manager": { "clusters": [] - } + }, + "admin": {"access_log_path": "/dev/null", "address": "tcp://1.2.3.4:5678"} } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - envoy::api::v2::Bootstrap bootstrap; + envoy::api::v2::Bootstrap bootstrap = TestUtility::parseBootstrapFromJson(json); server_.local_info_.cluster_name_ = ""; MainImpl config; - config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); + config.initialize(bootstrap, server_, cluster_manager_factory_); EXPECT_NE(nullptr, dynamic_cast(&config.httpTracer())); } @@ -209,20 +199,21 @@ TEST_F(ConfigurationImplTest, NullTracerSetWhenHttpKeyAbsentFromTracerConfigurat "driver": { "type": "lightstep", "config": { + "collector_cluster": "cluster_0", "access_token_file": "/etc/envoy/envoy.cfg" } } } - } + }, + "admin": {"access_log_path": "/dev/null", "address": "tcp://1.2.3.4:5678"} } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - envoy::api::v2::Bootstrap bootstrap; + envoy::api::v2::Bootstrap bootstrap = TestUtility::parseBootstrapFromJson(json); server_.local_info_.cluster_name_ = ""; MainImpl config; - config.initialize(*loader, bootstrap, server_, cluster_manager_factory_); + config.initialize(bootstrap, server_, cluster_manager_factory_); EXPECT_NE(nullptr, dynamic_cast(&config.httpTracer())); } @@ -242,22 +233,23 @@ TEST_F(ConfigurationImplTest, ConfigurationFailsWhenInvalidTracerSpecified) { "tracing": { "http": { "driver": { - "type": "invalid", + "type": "lightstep", "config": { + "collector_cluster": "cluster_0", "access_token_file": "/etc/envoy/envoy.cfg" } } } - } + }, + "admin": {"access_log_path": "/dev/null", "address": "tcp://1.2.3.4:5678"} } )EOF"; - Json::ObjectSharedPtr loader = Json::Factory::loadFromString(json); - envoy::api::v2::Bootstrap bootstrap; + envoy::api::v2::Bootstrap bootstrap = TestUtility::parseBootstrapFromJson(json); + bootstrap.mutable_tracing()->mutable_http()->set_name("invalid"); MainImpl config; - EXPECT_THROW_WITH_MESSAGE( - config.initialize(*loader, bootstrap, server_, cluster_manager_factory_), EnvoyException, - "No HttpTracerFactory found for type: invalid"); + EXPECT_THROW_WITH_MESSAGE(config.initialize(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 deleted file mode 100644 index 0967ef424bce..000000000000 --- a/test/server/empty_bootstrap.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/server/node_bootstrap.json b/test/server/node_bootstrap.json deleted file mode 100644 index 475f24894a34..000000000000 --- a/test/server/node_bootstrap.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "node": { - "id": "bootstrap_id", - "cluster": "bootstrap_cluster", - "locality": { - "zone": "bootstrap_zone", - "sub_zone": "bootstrap_sub_zone" - }, - "build_version": "should_be_ignored" - } -} diff --git a/test/server/node_bootstrap.yaml b/test/server/node_bootstrap.yaml new file mode 100644 index 000000000000..ece2eb50df7a --- /dev/null +++ b/test/server/node_bootstrap.yaml @@ -0,0 +1,13 @@ +node: + id: bootstrap_id + cluster: bootstrap_cluster + locality: + zone: bootstrap_zone + sub_zone: bootstrap_sub_zone + build_version: should_be_ignored +admin: + access_log_path: /dev/null + address: + socket_address: + address: {{ ntop_ip_loopback_address }} + port_value: 0 diff --git a/test/server/server_test.cc b/test/server/server_test.cc index 96d0377da5e3..a1744e391fac 100644 --- a/test/server/server_test.cc +++ b/test/server/server_test.cc @@ -40,9 +40,13 @@ class ServerInstanceImplTest : public testing::TestWithParamlocalInfo().zoneName()); EXPECT_EQ("bootstrap_cluster", server_->localInfo().clusterName()); EXPECT_EQ("bootstrap_id", server_->localInfo().nodeName()); @@ -91,7 +95,7 @@ TEST_P(ServerInstanceImplTest, BootstrapNodeWithOptionsOverride) { options_.service_cluster_name_ = "some_cluster_name"; options_.service_node_name_ = "some_node_name"; options_.service_zone_name_ = "some_zone_name"; - initialize("test/server/node_bootstrap.json"); + initialize("test/server/node_bootstrap.yaml"); EXPECT_EQ("some_zone_name", server_->localInfo().zoneName()); EXPECT_EQ("some_cluster_name", server_->localInfo().clusterName()); EXPECT_EQ("some_node_name", server_->localInfo().nodeName()); diff --git a/test/test_common/BUILD b/test/test_common/BUILD index 4a7a8eac2e23..9b73e4a0ccc3 100644 --- a/test/test_common/BUILD +++ b/test/test_common/BUILD @@ -59,12 +59,15 @@ envoy_cc_test_library( name = "utility_lib", srcs = ["utility.cc"], hdrs = ["utility.h"], + external_deps = ["envoy_bootstrap"], deps = [ "//include/envoy/buffer:buffer_interface", "//include/envoy/http:codec_interface", "//include/envoy/network:address_interface", "//source/common/common:empty_string", + "//source/common/config:bootstrap_json_lib", "//source/common/http:header_map_lib", + "//source/common/json:json_loader_lib", "//source/common/network:address_lib", "//source/common/network:utility_lib", ], diff --git a/test/test_common/environment.cc b/test/test_common/environment.cc index ee8d4dc450b6..e9694e68faf1 100644 --- a/test/test_common/environment.cc +++ b/test/test_common/environment.cc @@ -151,11 +151,6 @@ std::string TestEnvironment::temporaryFileSubstitute(const std::string& path, const ParamMap& param_map, const PortMap& port_map, Network::Address::IpVersion version) { - // Protobufs should be generated dynamically so not need port substitution. - if (path.size() > 3 && path.substr(path.size() - 3) == ".pb") { - return path; - } - // Load the entire file as a string, regex replace one at a time and write it back out. Proper // templating might be better one day, but this works for now. const std::string json_path = TestEnvironment::runfilesPath(path); diff --git a/test/test_common/utility.cc b/test/test_common/utility.cc index 403519e3de20..c182c30f7b86 100644 --- a/test/test_common/utility.cc +++ b/test/test_common/utility.cc @@ -15,6 +15,8 @@ #include "envoy/http/codec.h" #include "common/common/empty_string.h" +#include "common/config/bootstrap_json.h" +#include "common/json/json_loader.h" #include "common/network/address_impl.h" #include "common/network/utility.h" @@ -131,6 +133,13 @@ std::vector TestUtility::listFiles(const std::string& path, bool re return file_names; } +envoy::api::v2::Bootstrap TestUtility::parseBootstrapFromJson(const std::string& json_string) { + envoy::api::v2::Bootstrap bootstrap; + auto json_object_ptr = Json::Factory::loadFromString(json_string); + Config::BootstrapJson::translateBootstrap(*json_object_ptr, bootstrap); + return bootstrap; +} + void ConditionalInitializer::setReady() { std::unique_lock lock(mutex_); EXPECT_FALSE(ready_); diff --git a/test/test_common/utility.h b/test/test_common/utility.h index 20bf0fb07bb8..f3adbcdb0948 100644 --- a/test/test_common/utility.h +++ b/test/test_common/utility.h @@ -17,6 +17,7 @@ #include "test/test_common/printers.h" +#include "api/bootstrap.pb.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -104,6 +105,13 @@ class TestUtility { lhs.SerializeAsString() == rhs.SerializeAsString(); } + /** + * Parse bootstrap config from v1 JSON static config string. + * @param json_string source v1 JSON static config string. + * @return envoy::api::v2::Bootstrap. + */ + static envoy::api::v2::Bootstrap parseBootstrapFromJson(const std::string& json_string); + /** * Returns a "novel" IPv4 loopback address, if available. * For many tests, we want a loopback address other than 127.0.0.1 where possible. For some