diff --git a/DEPRECATED.md b/DEPRECATED.md index e5308f46e43e..3f4daaa2d58f 100644 --- a/DEPRECATED.md +++ b/DEPRECATED.md @@ -23,6 +23,9 @@ A logged warning is expected for each deprecated item that is in deprecation win is deprecated. Please use the new `upgrade_configs` in the [HttpConnectionManager](https://github.com/envoyproxy/envoy/blob/master/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto) instead. +* Use of the integer `percent` field in [FaultDelay](https://github.com/envoyproxy/envoy/blob/master/api/envoy/config/filter/fault/v2/fault.proto) + and in [FaultAbort](https://github.com/envoyproxy/envoy/blob/master/api/envoy/config/filter/http/fault/v2/fault.proto) is deprecated in favor + of the new `FractionalPercent` based `percentage` field. * Setting hosts via `hosts` field in `Cluster` is deprecated. Use `load_assignment` instead. ## Version 1.7.0 diff --git a/api/envoy/config/filter/fault/v2/BUILD b/api/envoy/config/filter/fault/v2/BUILD index 9fba2fbed3e1..c7f8a36eb23f 100644 --- a/api/envoy/config/filter/fault/v2/BUILD +++ b/api/envoy/config/filter/fault/v2/BUILD @@ -9,4 +9,5 @@ api_proto_library_internal( "//envoy/config/filter/http/fault/v2:__pkg__", "//envoy/config/filter/network/mongo_proxy/v2:__pkg__", ], + deps = ["//envoy/type:percent"], ) diff --git a/api/envoy/config/filter/fault/v2/fault.proto b/api/envoy/config/filter/fault/v2/fault.proto index d8f06ceef9e7..8cfd17ed4444 100644 --- a/api/envoy/config/filter/fault/v2/fault.proto +++ b/api/envoy/config/filter/fault/v2/fault.proto @@ -3,6 +3,8 @@ syntax = "proto3"; package envoy.config.filter.fault.v2; option go_package = "v2"; +import "envoy/type/percent.proto"; + import "google/protobuf/duration.proto"; import "validate/validate.proto"; @@ -24,7 +26,11 @@ message FaultDelay { // An integer between 0-100 indicating the percentage of operations/connection requests // on which the delay will be injected. - uint32 percent = 2 [(validate.rules).uint32.lte = 100]; + // + // .. attention:: + // + // Use of integer `percent` value is deprecated. Use fractional `percentage` field instead. + uint32 percent = 2 [(validate.rules).uint32.lte = 100, deprecated = true]; oneof fault_delay_secifier { option (validate.required) = true; @@ -37,4 +43,7 @@ message FaultDelay { google.protobuf.Duration fixed_delay = 3 [(validate.rules).duration.gt = {}, (gogoproto.stdduration) = true]; } + + // The percentage of operations/connection requests on which the delay will be injected. + envoy.type.FractionalPercent percentage = 4; } diff --git a/api/envoy/config/filter/http/fault/v2/BUILD b/api/envoy/config/filter/http/fault/v2/BUILD index 7b414c48af12..d2c935a116b5 100644 --- a/api/envoy/config/filter/http/fault/v2/BUILD +++ b/api/envoy/config/filter/http/fault/v2/BUILD @@ -8,5 +8,6 @@ api_proto_library_internal( deps = [ "//envoy/api/v2/route", "//envoy/config/filter/fault/v2:fault", + "//envoy/type:percent", ], ) diff --git a/api/envoy/config/filter/http/fault/v2/fault.proto b/api/envoy/config/filter/http/fault/v2/fault.proto index 894d2b7846e2..36e1d01a6b86 100644 --- a/api/envoy/config/filter/http/fault/v2/fault.proto +++ b/api/envoy/config/filter/http/fault/v2/fault.proto @@ -3,8 +3,9 @@ syntax = "proto3"; package envoy.config.filter.http.fault.v2; option go_package = "v2"; -import "envoy/config/filter/fault/v2/fault.proto"; import "envoy/api/v2/route/route.proto"; +import "envoy/config/filter/fault/v2/fault.proto"; +import "envoy/type/percent.proto"; import "validate/validate.proto"; @@ -14,7 +15,11 @@ import "validate/validate.proto"; message FaultAbort { // An integer between 0-100 indicating the percentage of requests/operations/connections // that will be aborted with the error code provided. - uint32 percent = 1 [(validate.rules).uint32.lte = 100]; + // + // .. attention:: + // + // Use of integer `percent` value is deprecated. Use fractional `percentage` field instead. + uint32 percent = 1 [(validate.rules).uint32.lte = 100, deprecated = true]; oneof error_type { option (validate.required) = true; @@ -22,6 +27,10 @@ message FaultAbort { // HTTP status code to use to abort the HTTP request. uint32 http_status = 2 [(validate.rules).uint32 = {gte: 200, lt: 600}]; } + + // The percentage of requests/operations/connections that will be aborted with the error code + // provided. + envoy.type.FractionalPercent percentage = 3; } message HTTPFault { diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index 121c40993e0f..4e966e31a4f7 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -11,6 +11,8 @@ Version history `google.api.HttpBody `_. * config: v1 disabled by default. v1 support remains available until October via flipping --v2-config-only=false. * config: v1 disabled by default. v1 support remains available until October via setting :option:`--allow-deprecated-v1-api`. +* fault: added support for fractional percentages in :ref:`FaultDelay ` + and in :ref:`FaultAbort `. * health check: added support for :ref:`custom health check `. * health check: added support for :ref:`specifying jitter as a percentage `. * health_check: added support for :ref:`health check event logging `. diff --git a/include/envoy/runtime/runtime.h b/include/envoy/runtime/runtime.h index 208ea805cd79..eb4719b5f01c 100644 --- a/include/envoy/runtime/runtime.h +++ b/include/envoy/runtime/runtime.h @@ -112,8 +112,8 @@ class Snapshot { * does not exist or it is not an integer. * @param random_value supplies the stable random value to use for determining whether the feature * is enabled. - * @param control max number of buckets for sampling. Sampled value will be in a range of - * [0, num_buckets). + * @param num_buckets control max number of buckets for sampling. Sampled value will be in a range + * of [0, num_buckets). * @return true if the feature is enabled. */ virtual bool featureEnabled(const std::string& key, uint64_t default_value, uint64_t random_value, diff --git a/source/common/protobuf/utility.h b/source/common/protobuf/utility.h index 9229d6eebcce..8804433633fb 100644 --- a/source/common/protobuf/utility.h +++ b/source/common/protobuf/utility.h @@ -48,6 +48,16 @@ ((message).has_##field_name() ? DurationUtil::durationToSeconds((message).field_name()) \ : throw MissingFieldException(#field_name, (message))) +// Set the value of a FractionalPercent field with the value from a protobuf message if present. +// Otherwise, convert the default field value into FractionalPercent and set it. +#define PROTOBUF_SET_FRACTIONAL_PERCENT_OR_DEFAULT(field, message, field_name, default_field_name) \ + if ((message).has_##field_name()) { \ + field = (message).field_name(); \ + } else { \ + field.set_numerator((message).default_field_name()); \ + field.set_denominator(envoy::type::FractionalPercent::HUNDRED); \ + } + namespace Envoy { namespace ProtobufPercentHelper { diff --git a/source/extensions/filters/http/fault/config.cc b/source/extensions/filters/http/fault/config.cc index 4e2fe35453b8..adca17fdade8 100644 --- a/source/extensions/filters/http/fault/config.cc +++ b/source/extensions/filters/http/fault/config.cc @@ -15,8 +15,8 @@ namespace Fault { Http::FilterFactoryCb FaultFilterFactory::createFilterFactoryFromProtoTyped( const envoy::config::filter::http::fault::v2::HTTPFault& config, const std::string& stats_prefix, Server::Configuration::FactoryContext& context) { - FaultFilterConfigSharedPtr filter_config( - new FaultFilterConfig(config, context.runtime(), stats_prefix, context.scope())); + FaultFilterConfigSharedPtr filter_config(new FaultFilterConfig( + config, context.runtime(), stats_prefix, context.scope(), context.random())); return [filter_config](Http::FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(std::make_shared(filter_config)); }; diff --git a/source/extensions/filters/http/fault/fault_filter.cc b/source/extensions/filters/http/fault/fault_filter.cc index 47bfbec25900..1857832505c6 100644 --- a/source/extensions/filters/http/fault/fault_filter.cc +++ b/source/extensions/filters/http/fault/fault_filter.cc @@ -34,12 +34,14 @@ const std::string FaultFilter::ABORT_HTTP_STATUS_KEY = "fault.http.abort.http_st FaultSettings::FaultSettings(const envoy::config::filter::http::fault::v2::HTTPFault& fault) { if (fault.has_abort()) { - abort_percent_ = fault.abort().percent(); + PROTOBUF_SET_FRACTIONAL_PERCENT_OR_DEFAULT(abort_percentage_, fault.abort(), percentage, + percent); http_status_ = fault.abort().http_status(); } if (fault.has_delay()) { - fixed_delay_percent_ = fault.delay().percent(); + PROTOBUF_SET_FRACTIONAL_PERCENT_OR_DEFAULT(fixed_delay_percentage_, fault.delay(), percentage, + percent); const auto& delay = fault.delay(); fixed_duration_ms_ = PROTOBUF_GET_MS_OR_DEFAULT(delay, fixed_delay, 0); } @@ -57,9 +59,9 @@ FaultSettings::FaultSettings(const envoy::config::filter::http::fault::v2::HTTPF FaultFilterConfig::FaultFilterConfig(const envoy::config::filter::http::fault::v2::HTTPFault& fault, Runtime::Loader& runtime, const std::string& stats_prefix, - Stats::Scope& scope) + Stats::Scope& scope, Runtime::RandomGenerator& generator) : settings_(fault), runtime_(runtime), stats_(generateStats(stats_prefix, scope)), - stats_prefix_(stats_prefix), scope_(scope) {} + stats_prefix_(stats_prefix), scope_(scope), generator_(generator) {} FaultFilter::FaultFilter(FaultFilterConfigSharedPtr config) : config_(config) {} @@ -129,26 +131,32 @@ Http::FilterHeadersStatus FaultFilter::decodeHeaders(Http::HeaderMap& headers, b } bool FaultFilter::isDelayEnabled() { - bool enabled = config_->runtime().snapshot().featureEnabled(DELAY_PERCENT_KEY, - fault_settings_->delayPercent()); - + bool enabled = config_->runtime().snapshot().featureEnabled( + DELAY_PERCENT_KEY, fault_settings_->delayPercentage().numerator(), + config_->randomGenerator().random(), + ProtobufPercentHelper::fractionalPercentDenominatorToInt(fault_settings_->delayPercentage())); if (!downstream_cluster_delay_percent_key_.empty()) { - enabled |= config_->runtime().snapshot().featureEnabled(downstream_cluster_delay_percent_key_, - fault_settings_->delayPercent()); + enabled |= config_->runtime().snapshot().featureEnabled( + downstream_cluster_delay_percent_key_, fault_settings_->delayPercentage().numerator(), + config_->randomGenerator().random(), + ProtobufPercentHelper::fractionalPercentDenominatorToInt( + fault_settings_->delayPercentage())); } - return enabled; } bool FaultFilter::isAbortEnabled() { - bool enabled = config_->runtime().snapshot().featureEnabled(ABORT_PERCENT_KEY, - fault_settings_->abortPercent()); - + bool enabled = config_->runtime().snapshot().featureEnabled( + ABORT_PERCENT_KEY, fault_settings_->abortPercentage().numerator(), + config_->randomGenerator().random(), + ProtobufPercentHelper::fractionalPercentDenominatorToInt(fault_settings_->abortPercentage())); if (!downstream_cluster_abort_percent_key_.empty()) { - enabled |= config_->runtime().snapshot().featureEnabled(downstream_cluster_abort_percent_key_, - fault_settings_->abortPercent()); + enabled |= config_->runtime().snapshot().featureEnabled( + downstream_cluster_abort_percent_key_, fault_settings_->abortPercentage().numerator(), + config_->randomGenerator().random(), + ProtobufPercentHelper::fractionalPercentDenominatorToInt( + fault_settings_->abortPercentage())); } - return enabled; } diff --git a/source/extensions/filters/http/fault/fault_filter.h b/source/extensions/filters/http/fault/fault_filter.h index 7559a3003837..d800eb9901f3 100644 --- a/source/extensions/filters/http/fault/fault_filter.h +++ b/source/extensions/filters/http/fault/fault_filter.h @@ -45,19 +45,19 @@ class FaultSettings : public Router::RouteSpecificFilterConfig { const std::vector& filterHeaders() const { return fault_filter_headers_; } - uint64_t abortPercent() const { return abort_percent_; } - uint64_t delayPercent() const { return fixed_delay_percent_; } + envoy::type::FractionalPercent abortPercentage() const { return abort_percentage_; } + envoy::type::FractionalPercent delayPercentage() const { return fixed_delay_percentage_; } uint64_t delayDuration() const { return fixed_duration_ms_; } uint64_t abortCode() const { return http_status_; } const std::string& upstreamCluster() const { return upstream_cluster_; } const std::unordered_set& downstreamNodes() const { return downstream_nodes_; } private: - uint64_t abort_percent_{}; // 0-100 - uint64_t http_status_{}; // HTTP or gRPC return codes - uint64_t fixed_delay_percent_{}; // 0-100 - uint64_t fixed_duration_ms_{}; // in milliseconds - std::string upstream_cluster_; // restrict faults to specific upstream cluster + envoy::type::FractionalPercent abort_percentage_; + uint64_t http_status_{}; // HTTP or gRPC return codes + envoy::type::FractionalPercent fixed_delay_percentage_; + uint64_t fixed_duration_ms_{}; // in milliseconds + std::string upstream_cluster_; // restrict faults to specific upstream cluster std::vector fault_filter_headers_; std::unordered_set downstream_nodes_{}; // Inject failures for specific downstream }; @@ -68,13 +68,15 @@ class FaultSettings : public Router::RouteSpecificFilterConfig { class FaultFilterConfig { public: FaultFilterConfig(const envoy::config::filter::http::fault::v2::HTTPFault& fault, - Runtime::Loader& runtime, const std::string& stats_prefix, Stats::Scope& scope); + Runtime::Loader& runtime, const std::string& stats_prefix, Stats::Scope& scope, + Runtime::RandomGenerator& generator); Runtime::Loader& runtime() { return runtime_; } FaultFilterStats& stats() { return stats_; } const std::string& statsPrefix() { return stats_prefix_; } Stats::Scope& scope() { return scope_; } const FaultSettings* settings() { return &settings_; } + Runtime::RandomGenerator& randomGenerator() { return generator_; } private: static FaultFilterStats generateStats(const std::string& prefix, Stats::Scope& scope); @@ -84,6 +86,7 @@ class FaultFilterConfig { FaultFilterStats stats_; const std::string stats_prefix_; Stats::Scope& scope_; + Runtime::RandomGenerator& generator_; }; typedef std::shared_ptr FaultFilterConfigSharedPtr; diff --git a/source/extensions/filters/network/mongo_proxy/config.cc b/source/extensions/filters/network/mongo_proxy/config.cc index a3d4b8ace349..493b70f286f0 100644 --- a/source/extensions/filters/network/mongo_proxy/config.cc +++ b/source/extensions/filters/network/mongo_proxy/config.cc @@ -35,9 +35,9 @@ Network::FilterFactoryCb MongoProxyFilterConfigFactory::createFilterFactoryFromP return [stat_prefix, &context, access_log, fault_config](Network::FilterManager& filter_manager) -> void { - filter_manager.addFilter( - std::make_shared(stat_prefix, context.scope(), context.runtime(), - access_log, fault_config, context.drainDecision())); + filter_manager.addFilter(std::make_shared( + stat_prefix, context.scope(), context.runtime(), access_log, fault_config, + context.drainDecision(), context.random())); }; } diff --git a/source/extensions/filters/network/mongo_proxy/proxy.cc b/source/extensions/filters/network/mongo_proxy/proxy.cc index 5b1e6eb0c129..4beb2e17f288 100644 --- a/source/extensions/filters/network/mongo_proxy/proxy.cc +++ b/source/extensions/filters/network/mongo_proxy/proxy.cc @@ -41,10 +41,11 @@ void AccessLog::logMessage(const Message& message, bool full, ProxyFilter::ProxyFilter(const std::string& stat_prefix, Stats::Scope& scope, Runtime::Loader& runtime, AccessLogSharedPtr access_log, const FaultConfigSharedPtr& fault_config, - const Network::DrainDecision& drain_decision) + const Network::DrainDecision& drain_decision, + Runtime::RandomGenerator& generator) : stat_prefix_(stat_prefix), scope_(scope), stats_(generateStats(stat_prefix, scope)), - runtime_(runtime), drain_decision_(drain_decision), access_log_(access_log), - fault_config_(fault_config) { + runtime_(runtime), drain_decision_(drain_decision), generator_(generator), + access_log_(access_log), fault_config_(fault_config) { if (!runtime_.snapshot().featureEnabled(MongoRuntimeConfig::get().ConnectionLoggingEnabled, 100)) { // If we are not logging at the connection level, just release the shared pointer so that we @@ -320,7 +321,10 @@ absl::optional ProxyFilter::delayDuration() { } if (!runtime_.snapshot().featureEnabled(MongoRuntimeConfig::get().FixedDelayPercent, - fault_config_->delayPercent())) { + fault_config_->delayPercentage().numerator(), + generator_.random(), + ProtobufPercentHelper::fractionalPercentDenominatorToInt( + fault_config_->delayPercentage()))) { return result; } diff --git a/source/extensions/filters/network/mongo_proxy/proxy.h b/source/extensions/filters/network/mongo_proxy/proxy.h index cb5face62cdc..6122e87bf9c6 100644 --- a/source/extensions/filters/network/mongo_proxy/proxy.h +++ b/source/extensions/filters/network/mongo_proxy/proxy.h @@ -102,13 +102,15 @@ typedef std::shared_ptr AccessLogSharedPtr; class FaultConfig { public: FaultConfig(const envoy::config::filter::fault::v2::FaultDelay& fault_config) - : delay_percent_(fault_config.percent()), - duration_ms_(PROTOBUF_GET_MS_REQUIRED(fault_config, fixed_delay)) {} - uint32_t delayPercent() const { return delay_percent_; } + : duration_ms_(PROTOBUF_GET_MS_REQUIRED(fault_config, fixed_delay)) { + PROTOBUF_SET_FRACTIONAL_PERCENT_OR_DEFAULT(delay_percentage_, fault_config, percentage, + percent); + } + envoy::type::FractionalPercent delayPercentage() const { return delay_percentage_; } uint64_t delayDuration() const { return duration_ms_; } private: - const uint32_t delay_percent_; + envoy::type::FractionalPercent delay_percentage_; const uint64_t duration_ms_; }; @@ -125,7 +127,7 @@ class ProxyFilter : public Network::Filter, public: ProxyFilter(const std::string& stat_prefix, Stats::Scope& scope, Runtime::Loader& runtime, AccessLogSharedPtr access_log, const FaultConfigSharedPtr& fault_config, - const Network::DrainDecision& drain_decision); + const Network::DrainDecision& drain_decision, Runtime::RandomGenerator& generator); ~ProxyFilter(); virtual DecoderPtr createDecoder(DecoderCallbacks& callbacks) PURE; @@ -193,6 +195,7 @@ class ProxyFilter : public Network::Filter, MongoProxyStats stats_; Runtime::Loader& runtime_; const Network::DrainDecision& drain_decision_; + Runtime::RandomGenerator& generator_; Buffer::OwnedImpl read_buffer_; Buffer::OwnedImpl write_buffer_; bool sniffing_{true}; diff --git a/test/extensions/filters/http/fault/fault_filter_test.cc b/test/extensions/filters/http/fault/fault_filter_test.cc index 420c065208b5..37449ac29b7d 100644 --- a/test/extensions/filters/http/fault/fault_filter_test.cc +++ b/test/extensions/filters/http/fault/fault_filter_test.cc @@ -129,13 +129,14 @@ class FaultFilterTest : public testing::Test { return fault; } - void SetUpTest(const std::string json) { - envoy::config::filter::http::fault::v2::HTTPFault fault = convertJsonStrToProtoConfig(json); - config_.reset(new FaultFilterConfig(fault, runtime_, "prefix.", stats_)); + void SetUpTest(const envoy::config::filter::http::fault::v2::HTTPFault fault) { + config_.reset(new FaultFilterConfig(fault, runtime_, "prefix.", stats_, generator_)); filter_.reset(new FaultFilter(config_)); filter_->setDecoderFilterCallbacks(filter_callbacks_); } + void SetUpTest(const std::string json) { SetUpTest(convertJsonStrToProtoConfig(json)); } + void expectDelayTimer(uint64_t duration_ms) { timer_ = new Event::MockTimer(&filter_callbacks_.dispatcher_); EXPECT_CALL(*timer_, enableTimer(std::chrono::milliseconds(duration_ms))); @@ -152,6 +153,7 @@ class FaultFilterTest : public testing::Test { Buffer::OwnedImpl data_; Stats::IsolatedStoreImpl stats_; NiceMock runtime_; + NiceMock generator_; Event::MockTimer* timer_{}; }; @@ -256,10 +258,16 @@ TEST(FaultFilterBadConfigTest, MissingDelayDuration) { } TEST_F(FaultFilterTest, AbortWithHttpStatus) { - SetUpTest(abort_only_json); + envoy::config::filter::http::fault::v2::HTTPFault fault; + fault.mutable_abort()->set_percent(50); + fault.mutable_abort()->mutable_percentage()->set_numerator(100); // should override int percent + fault.mutable_abort()->mutable_percentage()->set_denominator( + envoy::type::FractionalPercent::HUNDRED); + fault.mutable_abort()->set_http_status(429); + SetUpTest(fault); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 0)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 0, _, 100)) .WillOnce(Return(false)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); @@ -269,7 +277,7 @@ TEST_F(FaultFilterTest, AbortWithHttpStatus) { .Times(0); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 429)) @@ -296,7 +304,8 @@ TEST_F(FaultFilterTest, FixedDelayZeroDuration) { SetUpTest(fixed_delay_only_json); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); // Return 0ms delay @@ -304,7 +313,7 @@ TEST_F(FaultFilterTest, FixedDelayZeroDuration) { .WillOnce(Return(0)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0, _, 100)) .WillOnce(Return(false)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); @@ -321,17 +330,25 @@ TEST_F(FaultFilterTest, FixedDelayZeroDuration) { EXPECT_EQ(0UL, config_->stats().aborts_injected_.value()); } -TEST_F(FaultFilterTest, FixedDelayNonZeroDuration) { - SetUpTest(fixed_delay_only_json); +TEST_F(FaultFilterTest, FixedDelayDeprecatedPercentAndNonZeroDuration) { + envoy::config::filter::http::fault::v2::HTTPFault fault; + fault.mutable_delay()->set_type(envoy::config::filter::fault::v2::FaultDelay::FIXED); + fault.mutable_delay()->set_percent(100); + fault.mutable_delay()->mutable_percentage()->set_numerator(50); // should override int percent + fault.mutable_delay()->mutable_percentage()->set_denominator( + envoy::type::FractionalPercent::HUNDRED); + fault.mutable_delay()->mutable_fixed_delay()->set_seconds(5); + SetUpTest(fault); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 50, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); - SCOPED_TRACE("FixedDelayNonZeroDuration"); + SCOPED_TRACE("FixedDelayDeprecatedPercentAndNonZeroDuration"); expectDelayTimer(5000UL); EXPECT_CALL(filter_callbacks_.request_info_, @@ -340,7 +357,7 @@ TEST_F(FaultFilterTest, FixedDelayNonZeroDuration) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0, _, 100)) .WillOnce(Return(false)); // Delay only case @@ -365,10 +382,11 @@ TEST_F(FaultFilterTest, DelayForDownstreamCluster) { request_headers_.addCopy("x-envoy-downstream-service-cluster", "cluster"); // Delay related calls. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(false)); EXPECT_CALL(runtime_.snapshot_, - featureEnabled("fault.http.cluster.delay.fixed_delay_percent", 100)) + featureEnabled("fault.http.cluster.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) @@ -383,9 +401,10 @@ TEST_F(FaultFilterTest, DelayForDownstreamCluster) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0, _, 100)) .WillOnce(Return(false)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.cluster.abort.abort_percent", 0)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.cluster.abort.abort_percent", 0, _, 100)) .WillOnce(Return(false)); // Delay only case, no aborts. @@ -414,10 +433,11 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) { request_headers_.addCopy("x-envoy-downstream-service-cluster", "cluster"); // Delay related calls. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(false)); EXPECT_CALL(runtime_.snapshot_, - featureEnabled("fault.http.cluster.delay.fixed_delay_percent", 100)) + featureEnabled("fault.http.cluster.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) @@ -433,9 +453,10 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstream) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100, _, 100)) .WillOnce(Return(false)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.cluster.abort.abort_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.cluster.abort.abort_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) @@ -468,7 +489,8 @@ TEST_F(FaultFilterTest, FixedDelayAndAbort) { SetUpTest(fixed_delay_and_abort_json); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) @@ -484,7 +506,7 @@ TEST_F(FaultFilterTest, FixedDelayAndAbort) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) @@ -513,7 +535,8 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstreamNodes) { SetUpTest(fixed_delay_and_abort_nodes_json); // Delay related calls. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) .WillOnce(Return(5000UL)); @@ -528,7 +551,7 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortDownstreamNodes) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) .WillOnce(Return(503)); @@ -560,7 +583,8 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortHeaderMatchSuccess) { request_headers_.addCopy("x-foo2", "RandomValue"); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) @@ -576,7 +600,7 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortHeaderMatchSuccess) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", 503)) @@ -605,10 +629,11 @@ TEST_F(FaultFilterTest, FixedDelayAndAbortHeaderMatchFail) { request_headers_.addCopy("x-foo1", "Bar"); request_headers_.addCopy("x-foo3", "Baz"); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", _, _, 100)) .Times(0); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _)).Times(0); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _, _, 100)) + .Times(0); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(filter_callbacks_.request_info_, setResponseFlag(_)).Times(0); @@ -627,7 +652,8 @@ TEST_F(FaultFilterTest, TimerResetAfterStreamReset) { SetUpTest(fixed_delay_only_json); // Prep up with a 5s delay - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) @@ -650,7 +676,8 @@ TEST_F(FaultFilterTest, TimerResetAfterStreamReset) { EXPECT_CALL(*timer_, disableTimer()); // The timer callback should never be called. - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _)).Times(0); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _, _, 100)) + .Times(0); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(filter_callbacks_.request_info_, @@ -672,7 +699,8 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterMatchSuccess) { .WillOnce(ReturnRef(upstream_cluster)); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) @@ -687,7 +715,7 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterMatchSuccess) { filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0, _, 100)) .WillOnce(Return(false)); // Delay only case @@ -712,10 +740,11 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterMatchFail) { EXPECT_CALL(filter_callbacks_.route_->route_entry_, clusterName()) .WillOnce(ReturnRef(upstream_cluster)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", _, _, 100)) .Times(0); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _)).Times(0); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _, _, 100)) + .Times(0); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(filter_callbacks_.request_info_, setResponseFlag(_)).Times(0); @@ -734,10 +763,11 @@ TEST_F(FaultFilterTest, FaultWithTargetClusterNullRoute) { const std::string upstream_cluster("www1"); EXPECT_CALL(*filter_callbacks_.route_, routeEntry()).WillRepeatedly(Return(nullptr)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", _)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", _, _, 100)) .Times(0); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", _)).Times(0); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _)).Times(0); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", _, _, 100)) + .Times(0); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.abort.http_status", _)).Times(0); EXPECT_CALL(filter_callbacks_, encodeHeaders_(_, _)).Times(0); EXPECT_CALL(filter_callbacks_.request_info_, setResponseFlag(_)).Times(0); @@ -768,7 +798,8 @@ void FaultFilterTest::TestPerFilterConfigFault( .WillOnce(ReturnRef(upstream_cluster)); // Delay related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.delay.fixed_delay_percent", 100)) + EXPECT_CALL(runtime_.snapshot_, + featureEnabled("fault.http.delay.fixed_delay_percent", 100, _, 100)) .WillOnce(Return(true)); EXPECT_CALL(runtime_.snapshot_, getInteger("fault.http.delay.fixed_duration_ms", 5000)) @@ -783,7 +814,7 @@ void FaultFilterTest::TestPerFilterConfigFault( filter_->decodeHeaders(request_headers_, false)); // Abort related calls - EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled("fault.http.abort.abort_percent", 0, _, 100)) .WillOnce(Return(false)); EXPECT_CALL(filter_callbacks_, continueDecoding()); diff --git a/test/extensions/filters/network/mongo_proxy/proxy_test.cc b/test/extensions/filters/network/mongo_proxy/proxy_test.cc index 27554fcb4673..d92650072fbf 100644 --- a/test/extensions/filters/network/mongo_proxy/proxy_test.cc +++ b/test/extensions/filters/network/mongo_proxy/proxy_test.cc @@ -76,7 +76,7 @@ class MongoProxyFilterTest : public testing::Test { void initializeFilter() { filter_.reset(new TestProxyFilter("test.", store_, runtime_, access_log_, fault_config_, - drain_decision_)); + drain_decision_, generator_)); filter_->initializeReadFilterCallbacks(read_filter_callbacks_); filter_->onNewConnection(); @@ -87,13 +87,15 @@ class MongoProxyFilterTest : public testing::Test { void setupDelayFault(bool enable_fault) { envoy::config::filter::fault::v2::FaultDelay fault{}; - fault.set_percent(50); + fault.set_percent(100); + fault.mutable_percentage()->set_numerator(50); + fault.mutable_percentage()->set_denominator(envoy::type::FractionalPercent::HUNDRED); fault.mutable_fixed_delay()->CopyFrom(Protobuf::util::TimeUtil::MillisecondsToDuration(10)); fault_config_.reset(new FaultConfig(fault)); - EXPECT_CALL(runtime_.snapshot_, featureEnabled(_, _)).Times(AnyNumber()); - EXPECT_CALL(runtime_.snapshot_, featureEnabled("mongo.fault.fixed_delay.percent", 50)) + EXPECT_CALL(runtime_.snapshot_, featureEnabled(_, _, _, 100)).Times(AnyNumber()); + EXPECT_CALL(runtime_.snapshot_, featureEnabled("mongo.fault.fixed_delay.percent", 50, _, 100)) .WillOnce(Return(enable_fault)); if (enable_fault) { @@ -113,6 +115,7 @@ class MongoProxyFilterTest : public testing::Test { NiceMock read_filter_callbacks_; Envoy::AccessLog::MockAccessLogManager log_manager_; NiceMock drain_decision_; + NiceMock generator_; }; TEST_F(MongoProxyFilterTest, DelayFaults) {