diff --git a/source/common/config/BUILD b/source/common/config/BUILD index 47d515d5dfb8..669172558ffb 100644 --- a/source/common/config/BUILD +++ b/source/common/config/BUILD @@ -91,6 +91,7 @@ envoy_cc_library( "envoy_filter_http_http_connection_manager", "envoy_filter_http_buffer", "envoy_filter_http_fault", + "envoy_filter_http_health_check", "envoy_filter_http_router", "envoy_filter_network_mongo_proxy", ], diff --git a/source/common/config/filter_json.cc b/source/common/config/filter_json.cc index e299b1f1a0cf..07f5bcbf7ecf 100644 --- a/source/common/config/filter_json.cc +++ b/source/common/config/filter_json.cc @@ -266,6 +266,16 @@ void FilterJson::translateFaultFilter(const Json::Object& json_fault, } } +void FilterJson::translateHealthCheckFilter( + const Json::Object& json_health_check, + envoy::api::v2::filter::http::HealthCheck& health_check) { + json_health_check.validateSchema(Json::Schema::HEALTH_CHECK_HTTP_FILTER_SCHEMA); + + JSON_UTIL_SET_BOOL(json_health_check, health_check, pass_through_mode); + JSON_UTIL_SET_DURATION(json_health_check, health_check, cache_time); + JSON_UTIL_SET_STRING(json_health_check, health_check, endpoint); +} + void FilterJson::translateRouter(const Json::Object& json_router, envoy::api::v2::filter::http::Router& router) { json_router.validateSchema(Json::Schema::ROUTER_HTTP_FILTER_SCHEMA); diff --git a/source/common/config/filter_json.h b/source/common/config/filter_json.h index 7fb8acc56292..663c03b2f184 100644 --- a/source/common/config/filter_json.h +++ b/source/common/config/filter_json.h @@ -4,6 +4,7 @@ #include "api/filter/http/buffer.pb.h" #include "api/filter/http/fault.pb.h" +#include "api/filter/http/health_check.pb.h" #include "api/filter/http/http_connection_manager.pb.h" #include "api/filter/http/router.pb.h" #include "api/filter/network/mongo_proxy.pb.h" @@ -59,6 +60,15 @@ class FilterJson { static void translateFaultFilter(const Json::Object& json_fault, envoy::api::v2::filter::http::HTTPFault& fault); + /** + * Translate a v1 JSON Health Check filter object to v2 envoy::api::v2::filter::http::HealthCheck. + * @param config source v1 JSON Health Check Filter object. + * @param health_check destination v2 + * envoy::api::v2::filter::http::HealthCheck. + */ + static void translateHealthCheckFilter(const Json::Object& config, + envoy::api::v2::filter::http::HealthCheck& health_check); + /* * Translate a v1 JSON Router object to v2 envoy::api::v2::filter::http::Router. * @param json_router source v1 JSON HTTP router object. diff --git a/source/server/http/BUILD b/source/server/http/BUILD index b01bfae09eff..b902a5c168fa 100644 --- a/source/server/http/BUILD +++ b/source/server/http/BUILD @@ -52,6 +52,7 @@ envoy_cc_library( name = "health_check_lib", srcs = ["health_check.cc"], hdrs = ["health_check.h"], + external_deps = ["envoy_filter_http_health_check"], deps = [ "//include/envoy/event:dispatcher_interface", "//include/envoy/event:timer_interface", @@ -60,12 +61,13 @@ envoy_cc_library( "//include/envoy/http:header_map_interface", "//source/common/common:assert_lib", "//source/common/common:enum_to_int", + "//source/common/config:filter_json_lib", + "//source/common/config:well_known_names", "//source/common/http:codes_lib", "//source/common/http:header_map_lib", "//source/common/http:headers_lib", "//source/common/http:utility_lib", - "//source/common/json:config_schemas_lib", - "//source/common/json:json_loader_lib", + "//source/common/protobuf:utility_lib", "//source/server/config/network:http_connection_manager_lib", ], ) diff --git a/source/server/http/health_check.cc b/source/server/http/health_check.cc index 8c2df6b18484..805029e60861 100644 --- a/source/server/http/health_check.cc +++ b/source/server/http/health_check.cc @@ -10,12 +10,12 @@ #include "common/common/assert.h" #include "common/common/enum_to_int.h" +#include "common/config/filter_json.h" #include "common/http/codes.h" #include "common/http/header_map_impl.h" #include "common/http/headers.h" #include "common/http/utility.h" -#include "common/json/config_schemas.h" -#include "common/json/json_loader.h" +#include "common/protobuf/utility.h" #include "server/config/network/http_connection_manager.h" @@ -23,17 +23,15 @@ namespace Envoy { namespace Server { namespace Configuration { -/** - * Config registration for the health check filter. @see NamedHttpFilterConfigFactory. - */ -HttpFilterFactoryCb HealthCheckFilterConfig::createFilterFactory(const Json::Object& config, - const std::string&, - FactoryContext& context) { - config.validateSchema(Json::Schema::HEALTH_CHECK_HTTP_FILTER_SCHEMA); +HttpFilterFactoryCb HealthCheckFilterConfig::createHealthCheckFilter( + const envoy::api::v2::filter::http::HealthCheck& health_check, const std::string&, + FactoryContext& context) { + ASSERT(health_check.has_pass_through_mode()); + ASSERT(!health_check.endpoint().empty()); - bool pass_through_mode = config.getBoolean("pass_through_mode"); - int64_t cache_time_ms = config.getInteger("cache_time_ms", 0); - std::string hc_endpoint = config.getString("endpoint"); + bool pass_through_mode = health_check.pass_through_mode().value(); + int64_t cache_time_ms = PROTOBUF_GET_MS_OR_DEFAULT(health_check, cache_time, 0); + std::string hc_endpoint = health_check.endpoint(); if (!pass_through_mode && cache_time_ms) { throw EnvoyException("cache_time_ms must not be set when path_through_mode is disabled"); @@ -52,6 +50,24 @@ HttpFilterFactoryCb HealthCheckFilterConfig::createFilterFactory(const Json::Obj }; } +/** + * Config registration for the health check filter. @see NamedHttpFilterConfigFactory. + */ +HttpFilterFactoryCb HealthCheckFilterConfig::createFilterFactory(const Json::Object& json_config, + const std::string& stats_prefix, + FactoryContext& context) { + envoy::api::v2::filter::http::HealthCheck health_check; + Config::FilterJson::translateHealthCheckFilter(json_config, health_check); + return createHealthCheckFilter(health_check, stats_prefix, context); +} + +HttpFilterFactoryCb HealthCheckFilterConfig::createFilterFactoryFromProto( + const Protobuf::Message& config, const std::string& stats_prefix, FactoryContext& context) { + return createHealthCheckFilter( + dynamic_cast(config), stats_prefix, + context); +} + /** * Static registration for the health check filter. @see RegisterFactory. */ diff --git a/source/server/http/health_check.h b/source/server/http/health_check.h index d36e5ea097dd..4214d9aceb83 100644 --- a/source/server/http/health_check.h +++ b/source/server/http/health_check.h @@ -9,6 +9,10 @@ #include "envoy/http/filter.h" #include "envoy/server/filter_config.h" +#include "common/config/well_known_names.h" + +#include "api/filter/http/health_check.pb.h" + namespace Envoy { namespace Server { namespace Configuration { @@ -17,7 +21,20 @@ class HealthCheckFilterConfig : public NamedHttpFilterConfigFactory { public: HttpFilterFactoryCb createFilterFactory(const Json::Object& config, const std::string&, FactoryContext& context) override; - std::string name() override { return "envoy.health_check"; } + HttpFilterFactoryCb createFilterFactoryFromProto(const Protobuf::Message& config, + const std::string& stats_prefix, + FactoryContext& context) override; + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return ProtobufTypes::MessagePtr{new envoy::api::v2::filter::http::HealthCheck()}; + } + + std::string name() override { return Config::HttpFilterNames::get().HEALTH_CHECK; } + +private: + HttpFilterFactoryCb + createHealthCheckFilter(const envoy::api::v2::filter::http::HealthCheck& health_check, + const std::string& stats_prefix, FactoryContext& context); }; } // namespace Configuration diff --git a/test/server/http/health_check_test.cc b/test/server/http/health_check_test.cc index 07c1a2acb6e4..ba5c86d5f42e 100644 --- a/test/server/http/health_check_test.cc +++ b/test/server/http/health_check_test.cc @@ -208,7 +208,7 @@ TEST_F(HealthCheckFilterCachingTest, NotHcRequest) { filter_->decodeHeaders(request_headers_no_hc_, true)); } -TEST(HealthCheckFilterConfig, failsWhenNotPassThroughButTimeoutSet) { +TEST(HealthCheckFilterConfig, failsWhenNotPassThroughButTimeoutSetJson) { Server::Configuration::HealthCheckFilterConfig healthCheckFilterConfig; Json::ObjectSharedPtr config = Json::Factory::loadFromString( "{\"pass_through_mode\":false, \"cache_time_ms\":234, \"endpoint\":\"foo\"}"); @@ -218,7 +218,7 @@ TEST(HealthCheckFilterConfig, failsWhenNotPassThroughButTimeoutSet) { EnvoyException); } -TEST(HealthCheckFilterConfig, notFailingWhenNotPassThroughAndTimeoutNotSet) { +TEST(HealthCheckFilterConfig, notFailingWhenNotPassThroughAndTimeoutNotSetJson) { Server::Configuration::HealthCheckFilterConfig healthCheckFilterConfig; Json::ObjectSharedPtr config = Json::Factory::loadFromString("{\"pass_through_mode\":false, \"endpoint\":\"foo\"}"); @@ -226,4 +226,40 @@ TEST(HealthCheckFilterConfig, notFailingWhenNotPassThroughAndTimeoutNotSet) { healthCheckFilterConfig.createFilterFactory(*config, "dummy_stats_prefix", context); } + +TEST(HealthCheckFilterConfig, failsWhenNotPassThroughButTimeoutSetProto) { + Server::Configuration::HealthCheckFilterConfig healthCheckFilterConfig; + envoy::api::v2::filter::http::HealthCheck config{}; + NiceMock context; + + config.mutable_pass_through_mode()->set_value(false); + config.set_endpoint("foo"); + config.mutable_cache_time()->set_seconds(10); + + EXPECT_THROW( + healthCheckFilterConfig.createFilterFactoryFromProto(config, "dummy_stats_prefix", context), + EnvoyException); +} + +TEST(HealthCheckFilterConfig, notFailingWhenNotPassThroughAndTimeoutNotSetProto) { + Server::Configuration::HealthCheckFilterConfig healthCheckFilterConfig; + envoy::api::v2::filter::http::HealthCheck config{}; + NiceMock context; + + config.mutable_pass_through_mode()->set_value(false); + config.set_endpoint("foo"); + healthCheckFilterConfig.createFilterFactoryFromProto(config, "dummy_stats_prefix", context); +} + +TEST(HealthCheckFilterConfig, HealthCheckFilterWithEmptyProto) { + Server::Configuration::HealthCheckFilterConfig healthCheckFilterConfig; + NiceMock context; + envoy::api::v2::filter::http::HealthCheck config = + *dynamic_cast( + healthCheckFilterConfig.createEmptyConfigProto().get()); + + config.mutable_pass_through_mode()->set_value(false); + config.set_endpoint("foo"); + healthCheckFilterConfig.createFilterFactoryFromProto(config, "dummy_stats_prefix", context); +} } // namespace Envoy