From b916786755867f01ec36c8165b4d8b0708b6075e Mon Sep 17 00:00:00 2001 From: code Date: Tue, 10 Sep 2024 00:03:21 +0800 Subject: [PATCH 01/21] route: get all per filter config directly (#36028) Commit Message: route: get all per filter config directly Additional Description: 1. used absl::string_view rather than `const std::string&` as input parameter type. This allow the `mostSpecificPerFilterConfig()` and `perFilterConfigs()` to take a string view as input parameter. 2. replace the `traversePerFilterConfig()` with `perFilterConfigs()`. The `perFilterConfigs()` will return a vector (inlined) of configs directly and needn't the caller to provide a callback function to collect them. The new method is more straight forward and easier to use. The new method didn't effect any exist logic, but reduce ~150 lines code. Risk Level: low. Testing: n/a. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping --- .../filters/http/source/golang_filter.cc | 8 +-- envoy/http/filter.h | 10 ++-- envoy/router/router.h | 28 ++++------ source/common/http/async_client_impl.h | 3 +- source/common/http/filter_manager.cc | 9 +-- source/common/http/filter_manager.h | 3 +- source/common/http/null_route_impl.h | 16 +++--- source/common/http/utility.h | 55 +++---------------- source/common/router/config_impl.cc | 40 +++++++------- source/common/router/config_impl.h | 37 +++++-------- source/common/router/delegating_route_impl.h | 8 +-- source/common/tcp_proxy/tcp_proxy.h | 3 +- source/extensions/filters/http/cors/BUILD | 1 + .../filters/http/cors/cors_filter.cc | 10 +--- .../filters/http/cors/cors_filter.h | 6 +- .../custom_response/custom_response_filter.cc | 24 ++++---- .../filters/http/ext_authz/ext_authz.cc | 16 ++++-- .../filters/http/ext_proc/ext_proc.cc | 13 ++--- .../filters/http/file_system_buffer/filter.cc | 14 +++-- .../http/header_mutation/header_mutation.h | 2 +- test/common/http/filter_manager_test.cc | 27 ++++----- test/common/http/utility_test.cc | 52 ------------------ test/common/router/config_impl_test.cc | 19 +++---- .../router/delegating_route_impl_test.cc | 3 +- .../filters/http/cors/cors_filter_test.cc | 49 +++++++---------- .../filters/http/ext_authz/ext_authz_test.cc | 8 +-- .../filters/http/ext_proc/filter_test.cc | 24 +++----- .../http/file_system_buffer/filter_test.cc | 12 ++-- .../header_mutation/header_mutation_test.cc | 14 ++--- test/mocks/http/mocks.cc | 34 ++++++------ test/mocks/http/mocks.h | 6 +- test/mocks/router/mocks.h | 14 ++--- 32 files changed, 204 insertions(+), 364 deletions(-) diff --git a/contrib/golang/filters/http/source/golang_filter.cc b/contrib/golang/filters/http/source/golang_filter.cc index fa4a6ef35fa6..226a6656ec6f 100644 --- a/contrib/golang/filters/http/source/golang_filter.cc +++ b/contrib/golang/filters/http/source/golang_filter.cc @@ -19,6 +19,7 @@ #include "source/common/grpc/status.h" #include "source/common/http/headers.h" #include "source/common/http/http1/codec_impl.h" +#include "source/common/http/utility.h" #include "source/common/router/string_accessor_impl.h" #include "source/extensions/filters/common/expr/context.h" @@ -1377,16 +1378,13 @@ uint64_t Filter::getMergedConfigId() { Http::StreamFilterCallbacks* callbacks = decoding_state_.getFilterCallbacks(); // get all of the per route config - std::list route_config_list; - callbacks->traversePerFilterConfig( - [&route_config_list](const Router::RouteSpecificFilterConfig& cfg) { - route_config_list.push_back(dynamic_cast(&cfg)); - }); + auto route_config_list = Http::Utility::getAllPerFilterConfig(callbacks); ENVOY_LOG(debug, "golang filter route config list length: {}.", route_config_list.size()); auto id = config_->getConfigId(); for (auto it : route_config_list) { + ASSERT(it != nullptr, "route config should not be null"); auto route_config = *it; id = route_config.getPluginConfigId(id, config_->pluginName()); } diff --git a/envoy/http/filter.h b/envoy/http/filter.h index f9cc5450c87b..749c5b0a4078 100644 --- a/envoy/http/filter.h +++ b/envoy/http/filter.h @@ -463,13 +463,11 @@ class StreamFilterCallbacks { virtual const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const PURE; /** - * Find all the available per route filter configs, invoking the callback with each config (if - * it is present). Iteration of the configs is in order of specificity. That means that the - * callback will be called first for a config on a Virtual host, then a route, and finally a route - * entry (weighted cluster). If a config is not present, the callback will not be invoked. + * Return all the available per route filter configs. The configs is in order of specificity. + * That means that the config from a route configuration will be first, then the config from a + * virtual host, then the config from a route. */ - virtual void traversePerFilterConfig( - std::function cb) const PURE; + virtual Router::RouteSpecificFilterConfigs perFilterConfigs() const PURE; /** * Return the HTTP/1 stream encoder options if applicable. If the stream is not HTTP/1 returns diff --git a/envoy/router/router.h b/envoy/router/router.h index 48ed169bcd40..09632aa82a0f 100644 --- a/envoy/router/router.h +++ b/envoy/router/router.h @@ -122,6 +122,7 @@ class RouteSpecificFilterConfig { virtual ~RouteSpecificFilterConfig() = default; }; using RouteSpecificFilterConfigConstSharedPtr = std::shared_ptr; +using RouteSpecificFilterConfigs = absl::InlinedVector; /** * CorsPolicy for Route and VirtualHost. @@ -686,18 +687,14 @@ class VirtualHost { * hierarchy (Route --> VirtualHost --> RouteConfiguration). Or nullptr if none of them exist. */ virtual const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const PURE; + mostSpecificPerFilterConfig(absl::string_view name) const PURE; /** - * Find all the available per route filter configs, invoking the callback with - * each config (if it is present). Iteration of the configs is in order of - * specificity. That means that the callback will be called first for a config on - * a route configuration, virtual host, route, and finally a route entry (weighted cluster). If - * a config is not present, the callback will not be invoked. + * Return all the available per route filter configs. The configs is in order of specificity. + * That means that the config from a route configuration will be first, then the config from a + * virtual host, then the config from a route. */ - virtual void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const PURE; + virtual Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view name) const PURE; /** * @return const envoy::config::core::v3::Metadata& return the metadata provided in the config for @@ -1248,17 +1245,14 @@ class Route { * hierarchy(Route --> VirtualHost --> RouteConfiguration). Or nullptr if none of them exist. */ virtual const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const PURE; + mostSpecificPerFilterConfig(absl::string_view name) const PURE; /** - * Find all the available per route filter configs, invoking the callback with each config (if - * it is present). Iteration of the configs is in order of specificity. That means that the - * callback will be called first for a config on a Virtual host, then a route, and finally a route - * entry (weighted cluster). If a config is not present, the callback will not be invoked. + * Return all the available per route filter configs. The configs is in order of specificity. + * That means that the config from a route configuration will be first, then the config from a + * virtual host, then the config from a route. */ - virtual void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const PURE; + virtual Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view name) const PURE; /** * @return const envoy::config::core::v3::Metadata& return the metadata provided in the config for diff --git a/source/common/http/async_client_impl.h b/source/common/http/async_client_impl.h index efbceb7e93d7..e0dc6562b37e 100644 --- a/source/common/http/async_client_impl.h +++ b/source/common/http/async_client_impl.h @@ -257,8 +257,7 @@ class AsyncStreamImpl : public virtual AsyncClient::Stream, const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const override { return nullptr; } - void traversePerFilterConfig( - std::function) const override {} + Router::RouteSpecificFilterConfigs perFilterConfigs() const override { return {}; } Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override { return {}; } OptRef downstreamCallbacks() override { return {}; } OptRef upstreamCallbacks() override { return {}; } diff --git a/source/common/http/filter_manager.cc b/source/common/http/filter_manager.cc index be2c9b7af44f..35066ddb8806 100644 --- a/source/common/http/filter_manager.cc +++ b/source/common/http/filter_manager.cc @@ -284,16 +284,13 @@ ActiveStreamFilterBase::mostSpecificPerFilterConfig() const { return current_route->mostSpecificPerFilterConfig(filter_context_.config_name); } -void ActiveStreamFilterBase::traversePerFilterConfig( - std::function cb) const { +Router::RouteSpecificFilterConfigs ActiveStreamFilterBase::perFilterConfigs() const { Router::RouteConstSharedPtr current_route = getRoute(); if (current_route == nullptr) { - return; + return {}; } - current_route->traversePerFilterConfig( - filter_context_.config_name, - [&cb](const Router::RouteSpecificFilterConfig& config) { cb(config); }); + return current_route->perFilterConfigs(filter_context_.config_name); } Http1StreamEncoderOptionsOptRef ActiveStreamFilterBase::http1StreamEncoderOptions() { diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index 82405f0cc4b2..0a3d593b8b95 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -119,8 +119,7 @@ struct ActiveStreamFilterBase : public virtual StreamFilterCallbacks, void restoreContextOnContinue(ScopeTrackedObjectStack& tracked_object_stack) override; void resetIdleTimer() override; const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const override; - void traversePerFilterConfig( - std::function cb) const override; + Router::RouteSpecificFilterConfigs perFilterConfigs() const override; Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override; OptRef downstreamCallbacks() override; OptRef upstreamCallbacks() override; diff --git a/source/common/http/null_route_impl.h b/source/common/http/null_route_impl.h index 672dcc207d9a..5da6b8789f77 100644 --- a/source/common/http/null_route_impl.h +++ b/source/common/http/null_route_impl.h @@ -64,12 +64,12 @@ struct NullVirtualHost : public Router::VirtualHost { bool includeIsTimeoutRetryHeader() const override { return false; } uint32_t retryShadowBufferLimit() const override { return std::numeric_limits::max(); } const Router::RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string&) const override { + mostSpecificPerFilterConfig(absl::string_view) const override { return nullptr; } - void traversePerFilterConfig( - const std::string&, - std::function) const override {} + Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override { + return {}; + } const envoy::config::core::v3::Metadata& metadata() const override { return Router::DefaultRouteMetadataPack::get().proto_metadata_; } @@ -225,12 +225,12 @@ struct NullRouteImpl : public Router::Route { const Router::Decorator* decorator() const override { return nullptr; } const Router::RouteTracing* tracingConfig() const override { return nullptr; } const Router::RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string&) const override { + mostSpecificPerFilterConfig(absl::string_view) const override { return nullptr; } - void traversePerFilterConfig( - const std::string&, - std::function) const override {} + Router::RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override { + return {}; + } const envoy::config::core::v3::Metadata& metadata() const override { return Router::DefaultRouteMetadataPack::get().proto_metadata_; } diff --git a/source/common/http/utility.h b/source/common/http/utility.h index 57cd2ebad0a5..d1b2d0d09376 100644 --- a/source/common/http/utility.h +++ b/source/common/http/utility.h @@ -563,43 +563,6 @@ const ConfigType* resolveMostSpecificPerFilterConfig(const Http::StreamFilterCal return dynamic_cast(callbacks->mostSpecificPerFilterConfig()); } -/** - * Merge all the available per route filter configs into one. To perform the merge, - * the reduce function will be called on each two configs until a single merged config is left. - * - * @param reduce The first argument for this function will be the config from the previous level - * and the second argument is the config from the current level (the more specific one). The - * function should merge the second argument into the first argument. - * - * @return The merged config. - */ -template -absl::optional -getMergedPerFilterConfig(const Http::StreamFilterCallbacks* callbacks, - std::function reduce) { - static_assert(std::is_copy_constructible::value, - "ConfigType must be copy constructible"); - ASSERT(callbacks != nullptr); - - absl::optional merged; - - callbacks->traversePerFilterConfig([&reduce, - &merged](const Router::RouteSpecificFilterConfig& cfg) { - const ConfigType* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg == nullptr) { - ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); - return; - } - if (!merged) { - merged.emplace(*typed_cfg); - } else { - reduce(merged.value(), *typed_cfg); - } - }); - - return merged; -} - /** * Return all the available per route filter configs. * @@ -609,20 +572,20 @@ getMergedPerFilterConfig(const Http::StreamFilterCallbacks* callbacks, * and their lifetime is the same as the matched route. */ template -absl::InlinedVector +absl::InlinedVector getAllPerFilterConfig(const Http::StreamFilterCallbacks* callbacks) { ASSERT(callbacks != nullptr); - absl::InlinedVector all_configs; - callbacks->traversePerFilterConfig([&all_configs](const Router::RouteSpecificFilterConfig& cfg) { - const ConfigType* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg == nullptr) { + absl::InlinedVector all_configs; + + for (const auto* config : callbacks->perFilterConfigs()) { + const ConfigType* typed_config = dynamic_cast(config); + if (typed_config == nullptr) { ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); - return; + continue; } - - all_configs.push_back(typed_cfg); - }); + all_configs.push_back(typed_config); + } return all_configs; } diff --git a/source/common/router/config_impl.cc b/source/common/router/config_impl.cc index 0d4b12862985..7c70a5f42e54 100644 --- a/source/common/router/config_impl.cc +++ b/source/common/router/config_impl.cc @@ -1510,15 +1510,15 @@ absl::optional RouteEntryImplBase::filterDisabled(absl::string_view config return vhost_->filterDisabled(config_name); } -void RouteEntryImplBase::traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const { - vhost_->traversePerFilterConfig(filter_name, cb); +RouteSpecificFilterConfigs +RouteEntryImplBase::perFilterConfigs(absl::string_view filter_name) const { + auto result = vhost_->perFilterConfigs(filter_name); - auto maybe_route_config = per_filter_configs_->get(filter_name); + const auto* maybe_route_config = per_filter_configs_->get(filter_name); if (maybe_route_config != nullptr) { - cb(*maybe_route_config); + result.push_back(maybe_route_config); } + return result; } const envoy::config::core::v3::Metadata& RouteEntryImplBase::metadata() const { @@ -1598,15 +1598,15 @@ Http::HeaderTransforms RouteEntryImplBase::WeightedClusterEntry::responseHeaderT return transforms; } -void RouteEntryImplBase::WeightedClusterEntry::traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const { - DynamicRouteEntry::traversePerFilterConfig(filter_name, cb); +RouteSpecificFilterConfigs +RouteEntryImplBase::WeightedClusterEntry::perFilterConfigs(absl::string_view filter_name) const { + auto result = DynamicRouteEntry::perFilterConfigs(filter_name); const auto* cfg = per_filter_configs_->get(filter_name); - if (cfg) { - cb(*cfg); + if (cfg != nullptr) { + result.push_back(cfg); } + return result; } UriTemplateMatcherRouteEntryImpl::UriTemplateMatcherRouteEntryImpl( @@ -1910,23 +1910,25 @@ absl::optional CommonVirtualHostImpl::filterDisabled(absl::string_view con } const RouteSpecificFilterConfig* -CommonVirtualHostImpl::mostSpecificPerFilterConfig(const std::string& name) const { +CommonVirtualHostImpl::mostSpecificPerFilterConfig(absl::string_view name) const { auto* per_filter_config = per_filter_configs_->get(name); return per_filter_config != nullptr ? per_filter_config : global_route_config_->perFilterConfig(name); } -void CommonVirtualHostImpl::traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const { +RouteSpecificFilterConfigs +CommonVirtualHostImpl::perFilterConfigs(absl::string_view filter_name) const { + RouteSpecificFilterConfigs result; + // Parent first. if (auto* maybe_rc_config = global_route_config_->perFilterConfig(filter_name); maybe_rc_config != nullptr) { - cb(*maybe_rc_config); + result.push_back(maybe_rc_config); } if (auto* maybe_vhost_config = per_filter_configs_->get(filter_name); maybe_vhost_config != nullptr) { - cb(*maybe_vhost_config); + result.push_back(maybe_vhost_config); } + return result; } const envoy::config::core::v3::Metadata& CommonVirtualHostImpl::metadata() const { @@ -2491,7 +2493,7 @@ PerFilterConfigs::PerFilterConfigs( } } -const RouteSpecificFilterConfig* PerFilterConfigs::get(const std::string& name) const { +const RouteSpecificFilterConfig* PerFilterConfigs::get(absl::string_view name) const { auto it = configs_.find(name); return it == configs_.end() ? nullptr : it->second.config_.get(); } diff --git a/source/common/router/config_impl.h b/source/common/router/config_impl.h index 36b0e26dc6f4..c8dce5ceec36 100644 --- a/source/common/router/config_impl.h +++ b/source/common/router/config_impl.h @@ -93,7 +93,7 @@ class PerFilterConfigs : public Logger::Loggable { bool disabled_{}; }; - const RouteSpecificFilterConfig* get(const std::string& name) const; + const RouteSpecificFilterConfig* get(absl::string_view name) const; /** * @return true if the filter is explicitly disabled for this route or virtual host, false @@ -148,13 +148,11 @@ class SslRedirectRoute : public Route { const RouteEntry* routeEntry() const override { return nullptr; } const Decorator* decorator() const override { return nullptr; } const RouteTracing* tracingConfig() const override { return nullptr; } - const RouteSpecificFilterConfig* mostSpecificPerFilterConfig(const std::string&) const override { + const RouteSpecificFilterConfig* mostSpecificPerFilterConfig(absl::string_view) const override { return nullptr; } absl::optional filterDisabled(absl::string_view) const override { return {}; } - void traversePerFilterConfig( - const std::string&, - std::function) const override {} + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override { return {}; } const envoy::config::core::v3::Metadata& metadata() const override { return metadata_; } const Envoy::Config::TypedMetadata& typedMetadata() const override { return typed_metadata_; } const std::string& routeName() const override { return EMPTY_STRING; } @@ -290,7 +288,7 @@ class CommonVirtualHostImpl : public VirtualHost, Logger::Loggable cb) const override; + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override; const envoy::config::core::v3::Metadata& metadata() const override; const Envoy::Config::TypedMetadata& typedMetadata() const override; const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const override { @@ -831,13 +827,11 @@ class RouteEntryImplBase : public RouteEntryAndRoute, const RouteTracing* tracingConfig() const override { return route_tracing_.get(); } absl::optional filterDisabled(absl::string_view config_name) const override; const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { auto* config = per_filter_configs_->get(name); return config ? config : vhost_->mostSpecificPerFilterConfig(name); } - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override; + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override; const std::string& routeName() const override { return route_name_; } // Sanitizes the |path| before passing it to PathMatcher, if configured, this method makes the @@ -965,13 +959,11 @@ class RouteEntryImplBase : public RouteEntryAndRoute, return parent_->filterDisabled(config_name); } const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { return parent_->mostSpecificPerFilterConfig(name); } - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override { - parent_->traversePerFilterConfig(filter_name, cb); + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view filter_name) const override { + return parent_->perFilterConfigs(filter_name); }; const std::string& routeName() const override { return parent_->routeName(); } @@ -1058,14 +1050,11 @@ class RouteEntryImplBase : public RouteEntryAndRoute, return DynamicRouteEntry::filterDisabled(config_name); } const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { auto* config = per_filter_configs_->get(name); return config ? config : DynamicRouteEntry::mostSpecificPerFilterConfig(name); } - - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override; + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view) const override; const Http::LowerCaseString& clusterHeaderName() const { return cluster_header_name_; } @@ -1613,7 +1602,7 @@ class CommonConfigImpl : public CommonConfig { return HeaderParser::defaultParser(); } - const RouteSpecificFilterConfig* perFilterConfig(const std::string& name) const { + const RouteSpecificFilterConfig* perFilterConfig(absl::string_view name) const { return per_filter_configs_->get(name); } absl::optional filterDisabled(absl::string_view config_name) const { diff --git a/source/common/router/delegating_route_impl.h b/source/common/router/delegating_route_impl.h index 36deb173c7f9..a0218a636310 100644 --- a/source/common/router/delegating_route_impl.h +++ b/source/common/router/delegating_route_impl.h @@ -28,13 +28,11 @@ class DelegatingRoute : public Router::Route { const Router::RouteTracing* tracingConfig() const override; const RouteSpecificFilterConfig* - mostSpecificPerFilterConfig(const std::string& name) const override { + mostSpecificPerFilterConfig(absl::string_view name) const override { return base_route_->mostSpecificPerFilterConfig(name); } - void traversePerFilterConfig( - const std::string& filter_name, - std::function cb) const override { - base_route_->traversePerFilterConfig(filter_name, cb); + RouteSpecificFilterConfigs perFilterConfigs(absl::string_view filter_name) const override { + return base_route_->perFilterConfigs(filter_name); } const envoy::config::core::v3::Metadata& metadata() const override { diff --git a/source/common/tcp_proxy/tcp_proxy.h b/source/common/tcp_proxy/tcp_proxy.h index 66a53e64aec3..b528b87cf164 100644 --- a/source/common/tcp_proxy/tcp_proxy.h +++ b/source/common/tcp_proxy/tcp_proxy.h @@ -545,6 +545,7 @@ class Filter : public Network::ReadFilter, const Router::RouteSpecificFilterConfig* mostSpecificPerFilterConfig() const override { return nullptr; } + Router::RouteSpecificFilterConfigs perFilterConfigs() const override { return {}; } Buffer::BufferMemoryAccountSharedPtr account() const override { return nullptr; } void setUpstreamOverrideHost(Upstream::LoadBalancerContext::OverrideHost) override {} absl::optional @@ -555,8 +556,6 @@ class Filter : public Network::ReadFilter, void restoreContextOnContinue(ScopeTrackedObjectStack& tracked_object_stack) override { tracked_object_stack.add(*this); } - void traversePerFilterConfig( - std::function) const override {} Http::Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override { return {}; } OptRef downstreamCallbacks() override { return {}; } OptRef upstreamCallbacks() override { return {}; } diff --git a/source/extensions/filters/http/cors/BUILD b/source/extensions/filters/http/cors/BUILD index 1896cc73c5d9..60b5e0d42aae 100644 --- a/source/extensions/filters/http/cors/BUILD +++ b/source/extensions/filters/http/cors/BUILD @@ -27,6 +27,7 @@ envoy_cc_library( "//source/common/common:enum_to_int", "//source/common/http:header_map_lib", "//source/common/http:headers_lib", + "//source/common/http:utility_lib", ], ) diff --git a/source/extensions/filters/http/cors/cors_filter.cc b/source/extensions/filters/http/cors/cors_filter.cc index 4cc33d7d116e..98ecb2a17c02 100644 --- a/source/extensions/filters/http/cors/cors_filter.cc +++ b/source/extensions/filters/http/cors/cors_filter.cc @@ -10,6 +10,7 @@ #include "source/common/common/enum_to_int.h" #include "source/common/http/header_map_impl.h" #include "source/common/http/headers.h" +#include "source/common/http/utility.h" namespace Envoy { namespace Extensions { @@ -53,14 +54,9 @@ CorsFilterConfig::CorsFilterConfig(const std::string& stats_prefix, Stats::Scope CorsFilter::CorsFilter(CorsFilterConfigSharedPtr config) : config_(std::move(config)) {} void CorsFilter::initializeCorsPolicies() { - decoder_callbacks_->traversePerFilterConfig([this](const Router::RouteSpecificFilterConfig& cfg) { - const auto* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg != nullptr) { - policies_.push_back(typed_cfg); - } - }); + policies_ = Http::Utility::getAllPerFilterConfig(decoder_callbacks_); - // The 'traversePerFilterConfig' will handle cors policy of virtual host first. So, we need + // The 'perFilterConfigs' will handle cors policy of virtual host first. So, we need // reverse the 'policies_' to make sure the cors policy of route entry to be first item in the // 'policies_'. if (policies_.size() >= 2) { diff --git a/source/extensions/filters/http/cors/cors_filter.h b/source/extensions/filters/http/cors/cors_filter.h index 4e0187a5e902..0c8cf535a9c6 100644 --- a/source/extensions/filters/http/cors/cors_filter.h +++ b/source/extensions/filters/http/cors/cors_filter.h @@ -83,9 +83,7 @@ class CorsFilter : public Http::StreamFilter { encoder_callbacks_ = &callbacks; }; - const absl::InlinedVector& policiesForTest() const { - return policies_; - } + const auto& policiesForTest() const { return policies_; } private: friend class CorsFilterTest; @@ -104,7 +102,7 @@ class CorsFilter : public Http::StreamFilter { Http::StreamDecoderFilterCallbacks* decoder_callbacks_{}; Http::StreamEncoderFilterCallbacks* encoder_callbacks_{}; - absl::InlinedVector policies_; + absl::InlinedVector policies_; bool is_cors_request_{}; std::string latched_origin_; diff --git a/source/extensions/filters/http/custom_response/custom_response_filter.cc b/source/extensions/filters/http/custom_response/custom_response_filter.cc index 7e58ad4bbfc4..d133c8b75315 100644 --- a/source/extensions/filters/http/custom_response/custom_response_filter.cc +++ b/source/extensions/filters/http/custom_response/custom_response_filter.cc @@ -48,18 +48,18 @@ Http::FilterHeadersStatus CustomResponseFilter::encodeHeaders(Http::ResponseHead // policy. Note that since the traversal is least to most specific, we can't // return early when a match is found. PolicySharedPtr policy; - decoder_callbacks_->traversePerFilterConfig( - [&policy, &headers, this](const Router::RouteSpecificFilterConfig& config) { - const FilterConfig* typed_config = dynamic_cast(&config); - if (typed_config) { - // Check if a match is found first to avoid overwriting policy with an - // empty shared_ptr. - auto maybe_policy = typed_config->getPolicy(headers, encoder_callbacks_->streamInfo()); - if (maybe_policy) { - policy = maybe_policy; - } - } - }); + for (const auto* typed_config : + Http::Utility::getAllPerFilterConfig(encoder_callbacks_)) { + ASSERT(typed_config != nullptr); + + // Check if a match is found first to avoid overwriting policy with an + // empty shared_ptr. + auto maybe_policy = typed_config->getPolicy(headers, encoder_callbacks_->streamInfo()); + if (maybe_policy) { + policy = maybe_policy; + } + } + if (!policy) { policy = config_->getPolicy(headers, encoder_callbacks_->streamInfo()); } diff --git a/source/extensions/filters/http/ext_authz/ext_authz.cc b/source/extensions/filters/http/ext_authz/ext_authz.cc index d301d12689c8..92bde93d3758 100644 --- a/source/extensions/filters/http/ext_authz/ext_authz.cc +++ b/source/extensions/filters/http/ext_authz/ext_authz.cc @@ -1,3 +1,4 @@ +#include "ext_authz.h" #include "source/extensions/filters/http/ext_authz/ext_authz.h" #include @@ -175,11 +176,16 @@ void Filter::initiateCall(const Http::RequestHeaderMap& headers) { return; } - auto&& maybe_merged_per_route_config = - Http::Utility::getMergedPerFilterConfig( - decoder_callbacks_, [](FilterConfigPerRoute& cfg_base, const FilterConfigPerRoute& cfg) { - cfg_base.merge(cfg); - }); + absl::optional maybe_merged_per_route_config; + for (const auto* cfg : + Http::Utility::getAllPerFilterConfig(decoder_callbacks_)) { + ASSERT(cfg != nullptr); + if (maybe_merged_per_route_config.has_value()) { + maybe_merged_per_route_config.value().merge(*cfg); + } else { + maybe_merged_per_route_config = *cfg; + } + } Protobuf::Map context_extensions; if (maybe_merged_per_route_config) { diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 7e8f4f138652..8af46dc4da98 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -1279,20 +1279,15 @@ void Filter::mergePerRouteConfig() { route_config_merged_ = true; absl::optional merged_config; - - decoder_callbacks_->traversePerFilterConfig([&merged_config]( - const Router::RouteSpecificFilterConfig& cfg) { - const FilterConfigPerRoute* typed_cfg = dynamic_cast(&cfg); - if (typed_cfg == nullptr) { - ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); - return; - } + for (const auto* typed_cfg : + Http::Utility::getAllPerFilterConfig(decoder_callbacks_)) { + ASSERT(typed_cfg != nullptr); if (!merged_config.has_value()) { merged_config.emplace(*typed_cfg); } else { merged_config.emplace(FilterConfigPerRoute(merged_config.value(), *typed_cfg)); } - }); + } if (!merged_config.has_value()) { return; diff --git a/source/extensions/filters/http/file_system_buffer/filter.cc b/source/extensions/filters/http/file_system_buffer/filter.cc index a4e5e38f4295..56764975b057 100644 --- a/source/extensions/filters/http/file_system_buffer/filter.cc +++ b/source/extensions/filters/http/file_system_buffer/filter.cc @@ -1,3 +1,4 @@ +#include "filter.h" #include "source/extensions/filters/http/file_system_buffer/filter.h" namespace Envoy { @@ -20,12 +21,13 @@ bool FileSystemBufferFilter::initPerRouteConfig() { auto route = request_callbacks_->route(); FilterConfigVector config_chain; if (route) { - route->traversePerFilterConfig( - FileSystemBufferFilter::filterName(), - [&config_chain](const Router::RouteSpecificFilterConfig& route_cfg) { - auto cfg = dynamic_cast(&route_cfg); - config_chain.emplace_back(*cfg); - }); + // TODO(wbpcode): fix this to use the callbacks to get the route specific configs. + for (const auto* cfg : route->perFilterConfigs(FileSystemBufferFilter::filterName())) { + auto typed_cfg = dynamic_cast(cfg); + if (typed_cfg) { + config_chain.emplace_back(*typed_cfg); + } + } } config_chain.emplace_back(*base_config_); config_.emplace(config_chain); diff --git a/source/extensions/filters/http/header_mutation/header_mutation.h b/source/extensions/filters/http/header_mutation/header_mutation.h index 6701a4b219d1..5286d8340471 100644 --- a/source/extensions/filters/http/header_mutation/header_mutation.h +++ b/source/extensions/filters/http/header_mutation/header_mutation.h @@ -82,7 +82,7 @@ class HeaderMutation : public Http::PassThroughFilter, public Logger::Loggable route_configs_{}; + absl::InlinedVector route_configs_{}; }; } // namespace HeaderMutation diff --git a/test/common/http/filter_manager_test.cc b/test/common/http/filter_manager_test.cc index d310d73873db..417de64780df 100644 --- a/test/common/http/filter_manager_test.cc +++ b/test/common/http/filter_manager_test.cc @@ -461,24 +461,18 @@ TEST_F(FilterManagerTest, GetRouteLevelFilterConfig) { EXPECT_EQ(nullptr, decoder_filter->callbacks_->mostSpecificPerFilterConfig()); // Get a valid config by the custom filter name. - EXPECT_CALL(*route, traversePerFilterConfig(testing::Eq("custom-name"), _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(*route_config); + EXPECT_CALL(*route, perFilterConfigs(testing::Eq("custom-name"))) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {route_config.get()}; })); - decoder_filter->callbacks_->traversePerFilterConfig( - [&](const Router::RouteSpecificFilterConfig& config) { - EXPECT_EQ(route_config.get(), &config); - }); + auto route_config_result = decoder_filter->callbacks_->perFilterConfigs(); + EXPECT_EQ(route_config.get(), route_config_result[0]); // Get nothing by the custom filter name. - EXPECT_CALL(*route, traversePerFilterConfig(testing::Eq("custom-name"), _)) - .WillOnce(Invoke([&](const std::string&, - std::function) {})); - decoder_filter->callbacks_->traversePerFilterConfig( - [&](const Router::RouteSpecificFilterConfig& config) { - EXPECT_EQ(route_config.get(), &config); - }); + EXPECT_CALL(*route, perFilterConfigs(testing::Eq("custom-name"))) + .WillOnce(Invoke([](absl::string_view) -> Router::RouteSpecificFilterConfigs { return {}; })); + route_config_result = decoder_filter->callbacks_->perFilterConfigs(); + EXPECT_TRUE(route_config_result.empty()); filter_manager_->destroyFilters(); }; @@ -507,8 +501,7 @@ TEST_F(FilterManagerTest, GetRouteLevelFilterConfigForNullRoute) { decoder_filter->callbacks_->mostSpecificPerFilterConfig(); EXPECT_CALL(downstream_callbacks, route(_)).WillOnce(Return(nullptr)); - decoder_filter->callbacks_->traversePerFilterConfig( - [](const Router::RouteSpecificFilterConfig&) {}); + decoder_filter->callbacks_->perFilterConfigs(); filter_manager_->destroyFilters(); } diff --git a/test/common/http/utility_test.cc b/test/common/http/utility_test.cc index 74a5f963a697..69e63853b79e 100644 --- a/test/common/http/utility_test.cc +++ b/test/common/http/utility_test.cc @@ -1237,58 +1237,6 @@ TEST(HttpUtility, ResolveMostSpecificPerFilterConfigNilRoute) { EXPECT_EQ(nullptr, Utility::resolveMostSpecificPerFilterConfig(&filter_callbacks)); } -// Verify that merging works as expected and we get back the merged result. -TEST(HttpUtility, GetMergedPerFilterConfig) { - TestConfig baseTestConfig, routeTestConfig; - - baseTestConfig.state_ = 1; - routeTestConfig.state_ = 1; - - NiceMock filter_callbacks; - - EXPECT_CALL(*filter_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(baseTestConfig); - cb(routeTestConfig); - })); - - // merge the configs - auto merged_cfg = Utility::getMergedPerFilterConfig( - &filter_callbacks, - [&](TestConfig& base_cfg, const TestConfig& route_cfg) { base_cfg.merge(route_cfg); }); - - // make sure that the callback was called (which means that the dynamic_cast worked.) - ASSERT_TRUE(merged_cfg.has_value()); - EXPECT_EQ(2, merged_cfg.value().state_); -} - -class BadConfig { -public: - int state_; - void merge(const BadConfig& other) { state_ += other.state_; } -}; - -// Verify that merging result is empty as expected when the bad config is provided. -TEST(HttpUtility, GetMergedPerFilterBadConfig) { - TestConfig testConfig; - NiceMock filter_callbacks; - - EXPECT_CALL(*filter_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(testConfig); - })); - - EXPECT_LOG_CONTAINS( - "debug", "Failed to retrieve the correct type of route specific filter config", - auto merged_cfg = Utility::getMergedPerFilterConfig( - &filter_callbacks, - [&](BadConfig& base_cfg, const BadConfig& route_cfg) { base_cfg.merge(route_cfg); }); - // Dynamic_cast failed, so merged_cfg is not set. - ASSERT_FALSE(merged_cfg.has_value());); -} - TEST(HttpUtility, CheckIsIpAddress) { std::array>, 15> patterns{ std::make_tuple(true, "1.2.3.4", "1.2.3.4", absl::nullopt), diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index 8cc2795e4613..b400e04b62f5 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -10644,11 +10644,11 @@ class PerFilterConfigsTest : public testing::Test, public ConfigImplTestBase { check(dynamic_cast( route->mostSpecificPerFilterConfig(route_config_name)), expected_most_specific_config, "most specific config"); - route->traversePerFilterConfig( - route_config_name, [&](const Router::RouteSpecificFilterConfig& cfg) { - auto* typed_cfg = dynamic_cast(&cfg); - traveled_cfg.push_back(typed_cfg->config_.seconds()); - }); + for (const auto* cfg : route->perFilterConfigs(route_config_name)) { + auto* typed_cfg = dynamic_cast(cfg); + traveled_cfg.push_back(typed_cfg->config_.seconds()); + } + ASSERT_EQ(expected_traveled_config, traveled_cfg); } @@ -10666,11 +10666,10 @@ class PerFilterConfigsTest : public testing::Test, public ConfigImplTestBase { absl::InlinedVector traveled_cfg; EXPECT_EQ(nullptr, route->mostSpecificPerFilterConfig(route_config_name)); - route->traversePerFilterConfig( - route_config_name, [&](const Router::RouteSpecificFilterConfig& cfg) { - auto* typed_cfg = dynamic_cast(&cfg); - traveled_cfg.push_back(typed_cfg->config_.seconds()); - }); + for (const auto* cfg : route->perFilterConfigs(route_config_name)) { + auto* typed_cfg = dynamic_cast(cfg); + traveled_cfg.push_back(typed_cfg->config_.seconds()); + } EXPECT_EQ(0, traveled_cfg.size()); } diff --git a/test/common/router/delegating_route_impl_test.cc b/test/common/router/delegating_route_impl_test.cc index 5bd579dfa874..c717c4a96a16 100644 --- a/test/common/router/delegating_route_impl_test.cc +++ b/test/common/router/delegating_route_impl_test.cc @@ -34,8 +34,7 @@ TEST(DelegatingRoute, DelegatingRouteTest) { std::string name; TEST_METHOD(mostSpecificPerFilterConfig, name); - std::function cb; - TEST_METHOD(traversePerFilterConfig, name, cb); + TEST_METHOD(perFilterConfigs, name); } // Verify that DelegatingRouteEntry class forwards all calls to internal base route. diff --git a/test/extensions/filters/http/cors/cors_filter_test.cc b/test/extensions/filters/http/cors/cors_filter_test.cc index 3206df3017c1..c699fe543e68 100644 --- a/test/extensions/filters/http/cors/cors_filter_test.cc +++ b/test/extensions/filters/http/cors/cors_filter_test.cc @@ -55,12 +55,10 @@ class CorsFilterTest : public testing::Test { cors_policy_->allow_private_network_access_ = true; cors_policy_->max_age_ = "0"; - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of virtual host. - cb(*cors_policy_); // Cors policy of route entry. - })); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([this]() -> Router::RouteSpecificFilterConfigs { + return {cors_policy_.get(), cors_policy_.get()}; + })); filter_.setDecoderFilterCallbacks(decoder_callbacks_); filter_.setEncoderFilterCallbacks(encoder_callbacks_); @@ -99,11 +97,9 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { filter_.setDecoderFilterCallbacks(decoder_callbacks_); filter_.setEncoderFilterCallbacks(encoder_callbacks_); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of virtual host. - })); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke( + [this]() -> Router::RouteSpecificFilterConfigs { return {cors_policy_.get()}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); @@ -120,9 +116,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_CALL(decoder_callbacks_.route_->route_entry_, corsPolicy()).WillOnce(Return(nullptr)); EXPECT_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()).WillOnce(Return(nullptr)); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); @@ -139,9 +134,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { .WillOnce(Return(cors_policy_.get())); EXPECT_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()).WillOnce(Return(nullptr)); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, true)); EXPECT_EQ(false, isCorsRequest()); @@ -158,9 +152,8 @@ TEST_F(CorsFilterTest, InitializeCorsPoliciesTest) { EXPECT_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()) .WillOnce(Return(cors_policy_.get())); - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false)); EXPECT_EQ(false, isCorsRequest()); @@ -715,8 +708,8 @@ TEST_F(CorsFilterTest, NoCorsEntry) { {":method", "OPTIONS"}, {"origin", "localhost"}, {"access-control-request-method", "GET"}}; // No cors policy in the 'typed_per_filter_config'. - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) - .WillByDefault(Invoke([](std::function) {})); + ON_CALL(decoder_callbacks_, perFilterConfigs()) + .WillByDefault(Invoke([]() -> Router::RouteSpecificFilterConfigs { return {}; })); // No cors policy in route entry or virtual host. ON_CALL(decoder_callbacks_.route_->route_entry_, corsPolicy()).WillByDefault(Return(nullptr)); ON_CALL(decoder_callbacks_.route_->virtual_host_, corsPolicy()).WillByDefault(Return(nullptr)); @@ -741,11 +734,9 @@ TEST_F(CorsFilterTest, NoRouteCorsEntry) { Http::TestRequestHeaderMapImpl request_headers{ {":method", "OPTIONS"}, {"origin", "localhost"}, {"access-control-request-method", "GET"}}; - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + ON_CALL(decoder_callbacks_, perFilterConfigs()) .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of route entry. - })); + Invoke([this]() -> Router::RouteSpecificFilterConfigs { return {cors_policy_.get()}; })); Http::TestResponseHeaderMapImpl response_headers{ {":status", "200"}, @@ -775,11 +766,9 @@ TEST_F(CorsFilterTest, NoVHostCorsEntry) { cors_policy_->allow_methods_ = ""; - ON_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + ON_CALL(decoder_callbacks_, perFilterConfigs()) .WillByDefault( - Invoke([this](std::function cb) { - cb(*cors_policy_); // Cors policy of route entry. - })); + Invoke([this]() -> Router::RouteSpecificFilterConfigs { return {cors_policy_.get()}; })); Http::TestResponseHeaderMapImpl response_headers{ {":status", "200"}, diff --git a/test/extensions/filters/http/ext_authz/ext_authz_test.cc b/test/extensions/filters/http/ext_authz/ext_authz_test.cc index 7559128d07cf..fab44855d8aa 100644 --- a/test/extensions/filters/http/ext_authz/ext_authz_test.cc +++ b/test/extensions/filters/http/ext_authz/ext_authz_test.cc @@ -2605,11 +2605,9 @@ TEST_P(HttpFilterTestParam, ContextExtensions) { EXPECT_CALL(*decoder_filter_callbacks_.route_, mostSpecificPerFilterConfig(_)) .WillOnce(Return(&auth_per_route)); - EXPECT_CALL(*decoder_filter_callbacks_.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(auth_per_vhost); - cb(auth_per_route); + EXPECT_CALL(*decoder_filter_callbacks_.route_, perFilterConfigs(_)) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {&auth_per_vhost, &auth_per_route}; })); prepareCheck(); diff --git a/test/extensions/filters/http/ext_proc/filter_test.cc b/test/extensions/filters/http/ext_proc/filter_test.cc index 6fd45bff4495..008974567edc 100644 --- a/test/extensions/filters/http/ext_proc/filter_test.cc +++ b/test/extensions/filters/http/ext_proc/filter_test.cc @@ -2675,11 +2675,9 @@ TEST_F(HttpFilterTest, ProcessingModeResponseHeadersOnlyWithoutCallingDecodeHead route_proto.mutable_overrides()->mutable_grpc_service()->mutable_envoy_grpc()->set_cluster_name( "cluster_1"); FilterConfigPerRoute route_config(route_proto); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); final_expected_grpc_service_.emplace(route_proto.overrides().grpc_service()); config_with_hash_key_.setConfig(route_proto.overrides().grpc_service()); @@ -3473,11 +3471,9 @@ TEST_F(HttpFilterTest, MetadataOptionsOverride) { FilterConfigPerRoute route_config(override_cfg); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); response_headers_.addCopy(LowerCaseString(":status"), "200"); response_headers_.addCopy(LowerCaseString("content-type"), "text/plain"); @@ -3537,11 +3533,9 @@ TEST_F(HttpFilterTest, MetadataOptionsNoOverride) { FilterConfigPerRoute route_config(override_cfg); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); response_headers_.addCopy(LowerCaseString(":status"), "200"); response_headers_.addCopy(LowerCaseString("content-type"), "text/plain"); @@ -4469,11 +4463,9 @@ TEST_F(HttpFilterTest, GrpcServiceMetadataOverride) { *route_proto.mutable_overrides()->mutable_grpc_initial_metadata()->Add() = makeHeaderValue("c", "c"); FilterConfigPerRoute route_config(route_proto); - EXPECT_CALL(decoder_callbacks_, traversePerFilterConfig(_)) + EXPECT_CALL(decoder_callbacks_, perFilterConfigs()) .WillOnce( - testing::Invoke([&](std::function cb) { - cb(route_config); - })); + testing::Invoke([&]() -> Router::RouteSpecificFilterConfigs { return {&route_config}; })); // Build expected merged grpc_service configuration. { diff --git a/test/extensions/filters/http/file_system_buffer/filter_test.cc b/test/extensions/filters/http/file_system_buffer/filter_test.cc index 846b912ebfef..78541b92b314 100644 --- a/test/extensions/filters/http/file_system_buffer/filter_test.cc +++ b/test/extensions/filters/http/file_system_buffer/filter_test.cc @@ -774,13 +774,11 @@ TEST_F(FileSystemBufferFilterTest, MergesRouteConfig) { )"); auto mock_route = std::make_shared(); EXPECT_CALL(decoder_callbacks_, route()).WillOnce(Return(mock_route)); - EXPECT_CALL(*mock_route, traversePerFilterConfig(_, _)) - .WillOnce([vhost_config, route_config]( - const std::string&, - std::function add_config) { - add_config(*vhost_config); - add_config(*route_config); - }); + EXPECT_CALL(*mock_route, perFilterConfigs(_)) + .WillOnce( + [vhost_config, route_config](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {vhost_config.get(), route_config.get()}; + }); // The default config would return Continue, so these returning StopIteration shows that // both route_configs were applied. EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, diff --git a/test/extensions/filters/http/header_mutation/header_mutation_test.cc b/test/extensions/filters/http/header_mutation/header_mutation_test.cc index 3b5ede576915..318f05d6c204 100644 --- a/test/extensions/filters/http/header_mutation/header_mutation_test.cc +++ b/test/extensions/filters/http/header_mutation/header_mutation_test.cc @@ -113,10 +113,9 @@ TEST(HeaderMutationFilterTest, HeaderMutationFilterTest) { filter.setDecoderFilterCallbacks(decoder_callbacks); filter.setEncoderFilterCallbacks(encoder_callbacks); - EXPECT_CALL(*decoder_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(*config); + EXPECT_CALL(*decoder_callbacks.route_, perFilterConfigs(_)) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {config.get()}; })); { @@ -238,10 +237,9 @@ TEST(HeaderMutationFilterTest, HeaderMutationFilterTest) { }; // If the decoding phase is not performed then try to get the config from the encoding phase. - EXPECT_CALL(*encoder_callbacks.route_, traversePerFilterConfig(_, _)) - .WillOnce(Invoke([&](const std::string&, - std::function cb) { - cb(*config); + EXPECT_CALL(*encoder_callbacks.route_, perFilterConfigs(_)) + .WillOnce(Invoke([&](absl::string_view) -> Router::RouteSpecificFilterConfigs { + return {config.get()}; })); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter.encodeHeaders(headers, true)); diff --git a/test/mocks/http/mocks.cc b/test/mocks/http/mocks.cc index a7f12edb2e4d..7406cfa3446a 100644 --- a/test/mocks/http/mocks.cc +++ b/test/mocks/http/mocks.cc @@ -109,15 +109,14 @@ MockStreamDecoderFilterCallbacks::MockStreamDecoderFilterCallbacks() { } return route->mostSpecificPerFilterConfig("envoy.filter"); })); - ON_CALL(*this, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - auto route = this->route(); - if (route == nullptr) { - return; - } - route->traversePerFilterConfig("envoy.filter", cb); - })); + ON_CALL(*this, perFilterConfigs()) + .WillByDefault(Invoke([this]() -> Router::RouteSpecificFilterConfigs { + auto route = this->route(); + if (route == nullptr) { + return {}; + } + return route->perFilterConfigs("envoy.filter"); + })); } MockStreamDecoderFilterCallbacks::~MockStreamDecoderFilterCallbacks() = default; @@ -158,15 +157,14 @@ MockStreamEncoderFilterCallbacks::MockStreamEncoderFilterCallbacks() { } return route->mostSpecificPerFilterConfig("envoy.filter"); })); - ON_CALL(*this, traversePerFilterConfig(_)) - .WillByDefault( - Invoke([this](std::function cb) { - auto route = this->route(); - if (route == nullptr) { - return; - } - route->traversePerFilterConfig("envoy.filter", cb); - })); + ON_CALL(*this, perFilterConfigs()) + .WillByDefault(Invoke([this]() -> Router::RouteSpecificFilterConfigs { + auto route = this->route(); + if (route == nullptr) { + return {}; + } + return route->perFilterConfigs("envoy.filter"); + })); } MockStreamEncoderFilterCallbacks::~MockStreamEncoderFilterCallbacks() = default; diff --git a/test/mocks/http/mocks.h b/test/mocks/http/mocks.h index cdf2690c2a1c..7dcf37ca998b 100644 --- a/test/mocks/http/mocks.h +++ b/test/mocks/http/mocks.h @@ -272,8 +272,7 @@ class MockStreamDecoderFilterCallbacks : public StreamDecoderFilterCallbacks, MOCK_METHOD(void, addUpstreamSocketOptions, (const Network::Socket::OptionsSharedPtr& options)); MOCK_METHOD(Network::Socket::OptionsSharedPtr, getUpstreamSocketOptions, (), (const)); MOCK_METHOD(const Router::RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (), (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (std::function cb), (const)); + MOCK_METHOD(Router::RouteSpecificFilterConfigs, perFilterConfigs, (), (const)); MOCK_METHOD(Http1StreamEncoderOptionsOptRef, http1StreamEncoderOptions, ()); MOCK_METHOD(OptRef, downstreamCallbacks, ()); MOCK_METHOD(OptRef, upstreamCallbacks, ()); @@ -369,8 +368,7 @@ class MockStreamEncoderFilterCallbacks : public StreamEncoderFilterCallbacks, MOCK_METHOD(uint32_t, encoderBufferLimit, ()); MOCK_METHOD(void, restoreContextOnContinue, (ScopeTrackedObjectStack&)); MOCK_METHOD(const Router::RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (), (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (std::function cb), (const)); + MOCK_METHOD(Router::RouteSpecificFilterConfigs, perFilterConfigs, (), (const)); MOCK_METHOD(Http1StreamEncoderOptionsOptRef, http1StreamEncoderOptions, ()); MOCK_METHOD(OptRef, downstreamCallbacks, ()); MOCK_METHOD(OptRef, upstreamCallbacks, ()); diff --git a/test/mocks/router/mocks.h b/test/mocks/router/mocks.h index 1fcadf99f811..2a8ee2c4c01d 100644 --- a/test/mocks/router/mocks.h +++ b/test/mocks/router/mocks.h @@ -319,7 +319,7 @@ class MockVirtualHost : public VirtualHost { MOCK_METHOD(const RateLimitPolicy&, rateLimitPolicy, (), (const)); MOCK_METHOD(const CorsPolicy*, corsPolicy, (), (const)); MOCK_METHOD(const CommonConfig&, routeConfig, (), (const)); - MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (const std::string&), + MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (absl::string_view), (const)); MOCK_METHOD(bool, includeAttemptCountInRequest, (), (const)); MOCK_METHOD(bool, includeAttemptCountInResponse, (), (const)); @@ -327,9 +327,7 @@ class MockVirtualHost : public VirtualHost { MOCK_METHOD(Upstream::RetryPrioritySharedPtr, retryPriority, ()); MOCK_METHOD(Upstream::RetryHostPredicateSharedPtr, retryHostPredicate, ()); MOCK_METHOD(uint32_t, retryShadowBufferLimit, (), (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (const std::string&, std::function), - (const)); + MOCK_METHOD(RouteSpecificFilterConfigs, perFilterConfigs, (absl::string_view), (const)); MOCK_METHOD(const envoy::config::core::v3::Metadata&, metadata, (), (const)); MOCK_METHOD(const Envoy::Config::TypedMetadata&, typedMetadata, (), (const)); MOCK_METHOD(const VirtualCluster*, virtualCluster, (const Http::HeaderMap& headers), (const)); @@ -516,12 +514,10 @@ class MockRoute : public Route { MOCK_METHOD(const Decorator*, decorator, (), (const)); MOCK_METHOD(const RouteTracing*, tracingConfig, (), (const)); MOCK_METHOD(absl::optional, filterDisabled, (absl::string_view), (const)); - MOCK_METHOD(const RouteSpecificFilterConfig*, perFilterConfig, (const std::string&), (const)); - MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (const std::string&), - (const)); - MOCK_METHOD(void, traversePerFilterConfig, - (const std::string&, std::function), + MOCK_METHOD(const RouteSpecificFilterConfig*, perFilterConfig, (absl::string_view), (const)); + MOCK_METHOD(const RouteSpecificFilterConfig*, mostSpecificPerFilterConfig, (absl::string_view), (const)); + MOCK_METHOD(RouteSpecificFilterConfigs, perFilterConfigs, (absl::string_view), (const)); MOCK_METHOD(const envoy::config::core::v3::Metadata&, metadata, (), (const)); MOCK_METHOD(const Envoy::Config::TypedMetadata&, typedMetadata, (), (const)); MOCK_METHOD(const std::string&, routeName, (), (const)); From 64bd53530cdbb9d5ac053fcca0f5cbb342a941bd Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 9 Sep 2024 17:35:11 +0100 Subject: [PATCH 02/21] ci/codeql: Fix build setup (#36021) This fixes the recent issues with codeql caused by removing some of the setup in setup_clang.sh this is a partial revert of that, essentially for containerless local builds it also prevents this codepath from being used in RBE, which was a main goal of the previous changes Signed-off-by: Ryan Northey --- .bazelrc | 3 +-- .github/workflows/codeql-daily.yml | 9 +++++++-- .github/workflows/codeql-push.yml | 5 ++--- bazel/setup_clang.sh | 3 +++ ci/build_setup.sh | 10 ++++++---- ci/do_ci.sh | 7 ++++++- ci/filter_example_setup.sh | 2 +- 7 files changed, 26 insertions(+), 13 deletions(-) diff --git a/.bazelrc b/.bazelrc index fdf86fa2a91b..0b7b3b892115 100644 --- a/.bazelrc +++ b/.bazelrc @@ -272,8 +272,7 @@ build:rbe-toolchain-clang-libc++ --action_env=CXXFLAGS=-stdlib=libc++ build:rbe-toolchain-clang-libc++ --action_env=LDFLAGS=-stdlib=libc++ build:rbe-toolchain-clang-libc++ --define force_libcpp=enabled -# Do not inherit from "clang-asan" to avoid picking up flags from local clang.bazelrc. -build:rbe-toolchain-asan --config=asan +build:rbe-toolchain-asan --config=clang-asan build:rbe-toolchain-asan --linkopt -fuse-ld=lld build:rbe-toolchain-asan --action_env=ENVOY_UBSAN_VPTR=1 build:rbe-toolchain-asan --copt=-fsanitize=vptr,function diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 29bf47cb5683..af8a14f0b4f2 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -54,13 +54,18 @@ jobs: cd bin/clang14 wget https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz tar -xf clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz --strip-components 1 - export PATH=bin/clang14/bin:$PATH - name: Build run: | bazel/setup_clang.sh bin/clang14 bazelisk shutdown - bazelisk build -c fastbuild --spawn_strategy=local --discard_analysis_cache --nouse_action_cache --config clang --config libc++ \ + bazel build \ + -c fastbuild \ + --spawn_strategy=local \ + --discard_analysis_cache \ + --nouse_action_cache \ + --config=clang-libc++ \ + --config=ci \ //source/common/http/... - name: Clean Artifacts diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index db6aa77f37a5..b2b1209cc0ed 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -85,7 +85,6 @@ jobs: cd bin/clang14 wget https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz tar -xf clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz --strip-components 1 - export PATH=bin/clang14/bin:$PATH - name: Build if: ${{ env.BUILD_TARGETS != '' }} @@ -97,8 +96,8 @@ jobs: --spawn_strategy=local \ --discard_analysis_cache \ --nouse_action_cache \ - --config clang \ - --config libc++ \ + --config=clang-libc++ \ + --config=ci \ $BUILD_TARGETS echo -e "Built targets...\n$BUILD_TARGETS" diff --git a/bazel/setup_clang.sh b/bazel/setup_clang.sh index 1b49ad94861d..ba17049fd060 100755 --- a/bazel/setup_clang.sh +++ b/bazel/setup_clang.sh @@ -15,11 +15,14 @@ fi LLVM_VERSION="$("${LLVM_CONFIG}" --version)" LLVM_LIBDIR="$("${LLVM_CONFIG}" --libdir)" LLVM_TARGET="$("${LLVM_CONFIG}" --host-target)" +PATH="$("${LLVM_CONFIG}" --bindir):${PATH}" RT_LIBRARY_PATH="${LLVM_LIBDIR}/clang/${LLVM_VERSION}/lib/${LLVM_TARGET}" cat < "${BAZELRC_FILE}" # Generated file, do not edit. If you want to disable clang, just delete this file. +build:clang --host_action_env=PATH=${PATH} --action_env=PATH=${PATH} + build:clang --action_env=LLVM_CONFIG=${LLVM_CONFIG} --host_action_env=LLVM_CONFIG=${LLVM_CONFIG} build:clang --repo_env=LLVM_CONFIG=${LLVM_CONFIG} build:clang --linkopt=-L${LLVM_LIBDIR} diff --git a/ci/build_setup.sh b/ci/build_setup.sh index abdbea03859b..68282ac7c06f 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -119,10 +119,12 @@ export BAZEL_STARTUP_OPTION_LIST export BAZEL_BUILD_OPTION_LIST export BAZEL_GLOBAL_OPTION_LIST -if [[ -e "${LLVM_ROOT}" ]]; then - "${CURRENT_SCRIPT_DIR}/../bazel/setup_clang.sh" "${LLVM_ROOT}" -else - echo "LLVM_ROOT not found, not setting up llvm." +if [[ -z "${ENVOY_RBE}" ]]; then + if [[ -e "${LLVM_ROOT}" ]]; then + "${CURRENT_SCRIPT_DIR}/../bazel/setup_clang.sh" "${LLVM_ROOT}" + else + echo "LLVM_ROOT not found, not setting up llvm." + fi fi [[ "${BAZEL_EXPUNGE}" == "1" ]] && bazel clean "${BAZEL_BUILD_OPTIONS[@]}" --expunge diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 43aa3f7a1ffd..c6a19f24ca8d 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -351,9 +351,14 @@ case $CI_TARGET in asan) setup_clang_toolchain + if [[ -n "$ENVOY_RBE" ]]; then + ASAN_CONFIG="--config=rbe-toolchain-asan" + else + ASAN_CONFIG="--config=clang-asan" + fi BAZEL_BUILD_OPTIONS+=( -c dbg - "--config=clang-asan" + "${ASAN_CONFIG}" "--build_tests_only" "--remote_download_minimal") echo "bazel ASAN/UBSAN debug build with tests" diff --git a/ci/filter_example_setup.sh b/ci/filter_example_setup.sh index be529e6f82d9..e2d6e1b434a9 100644 --- a/ci/filter_example_setup.sh +++ b/ci/filter_example_setup.sh @@ -29,6 +29,6 @@ cp -a "${ENVOY_SRCDIR}"/bazel/protoc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/bazel/ cp -f "${ENVOY_SRCDIR}"/.bazelrc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ rm -f "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/.bazelversion cp -f "${ENVOY_SRCDIR}"/.bazelversion "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ -cp -f "${ENVOY_SRCDIR}"/*.bazelrc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ +cp -f "${ENVOY_SRCDIR}"/*.bazelrc "${ENVOY_FILTER_EXAMPLE_SRCDIR}"/ || : export FILTER_WORKSPACE_SET=1 From ccccc115b42e5083a573dff1fbd9f3dfb9db9b9b Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 9 Sep 2024 17:36:13 +0100 Subject: [PATCH 03/21] ci/example: Dont build/test the filter example in Envoy CI (#36038) Currently the compile-time-options/msan/asan tests are run in the context of the filter-example This adds a lot of complexity to the build and messes up our test artefacts. The example is not well maintained - it has circle CI configured which hasnt passed in years. Ideally we close that repo and add it instead to the examples repo Signed-off-by: Ryan Northey --- .azure-pipelines/ci.yml | 5 ----- .azure-pipelines/stage/checks.yml | 4 ---- ci/build_setup.sh | 9 --------- ci/do_ci.sh | 19 ------------------- 4 files changed, 37 deletions(-) diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index d4454b618ba3..8f80098026a6 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -64,9 +64,6 @@ parameters: displayName: "Upload bazel run data to BES" type: boolean default: true -- name: envoyBuildFilterExample - type: string - default: "" - name: cacheTestResults displayName: "Cache test results" type: boolean @@ -224,7 +221,6 @@ steps: echo "##vso[task.setvariable variable=BAZEL_FAKE_SCM_REVISION]${BAZEL_FAKE_SCM_REVISION}" echo "##vso[task.setvariable variable=BAZEL_STARTUP_EXTRA_OPTIONS]${{ parameters.bazelStartupExtraOptions }}" echo "##vso[task.setvariable variable=CI_TARGET_BRANCH]${CI_TARGET_BRANCH}" - echo "##vso[task.setvariable variable=ENVOY_BUILD_FILTER_EXAMPLE]${{ parameters.envoyBuildFilterExample }}" echo "##vso[task.setvariable variable=ENVOY_DOCKER_BUILD_DIR]$(Build.StagingDirectory)" echo "##vso[task.setvariable variable=ENVOY_RBE]${ENVOY_RBE}" echo "##vso[task.setvariable variable=ENVOY_SHARED_TMP_DIR]${ENVOY_SHARED_TMP_DIR}" @@ -275,7 +271,6 @@ steps: - script: ci/run_envoy_docker.sh 'ci/do_ci.sh ${{ parameters.ciTarget }}' workingDirectory: $(Build.SourcesDirectory) env: - ENVOY_BUILD_FILTER_EXAMPLE: ${{ parameters.envoyBuildFilterExample }} ${{ each var in parameters.env }}: ${{ var.key }}: ${{ var.value }} displayName: "Run CI script ${{ parameters.ciTarget }}" diff --git a/.azure-pipelines/stage/checks.yml b/.azure-pipelines/stage/checks.yml index b4e650287a23..c5d7e22f58e2 100644 --- a/.azure-pipelines/stage/checks.yml +++ b/.azure-pipelines/stage/checks.yml @@ -47,12 +47,10 @@ jobs: CI_TARGET: "fuzz_coverage" compile_time_options: CI_TARGET: "compile_time_options" - ENVOY_FILTER_EXAMPLE: true tsan: CI_TARGET: "tsan" asan: CI_TARGET: "asan" - ENVOY_FILTER_EXAMPLE: true # Disabled due to https://github.com/envoyproxy/envoy/pull/18218 # api_compat: # CI_TARGET: "api_compat" @@ -60,7 +58,6 @@ jobs: CI_TARGET: "gcc" msan: CI_TARGET: "msan" - ENVOY_FILTER_EXAMPLE: true # # Temporarily disabled to facilitate release CI, should be resolved # as part of https://github.com/envoyproxy/envoy/issues/28566 @@ -81,7 +78,6 @@ jobs: parameters: ciTarget: $(CI_TARGET) cacheName: $(CI_TARGET) - envoyBuildFilterExample: $(ENVOY_FILTER_EXAMPLE) cacheTestResults: ${{ parameters.cacheTestResults }} diskspaceHack: true managedAgent: false diff --git a/ci/build_setup.sh b/ci/build_setup.sh index 68282ac7c06f..1ef213757975 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -33,8 +33,6 @@ fi export ENVOY_BUILD_ARCH } -export ENVOY_BUILD_FILTER_EXAMPLE="${ENVOY_BUILD_FILTER_EXAMPLE:-0}" - read -ra BAZEL_BUILD_EXTRA_OPTIONS <<< "${BAZEL_BUILD_EXTRA_OPTIONS:-}" read -ra BAZEL_EXTRA_TEST_OPTIONS <<< "${BAZEL_EXTRA_TEST_OPTIONS:-}" read -ra BAZEL_STARTUP_EXTRA_OPTIONS <<< "${BAZEL_STARTUP_EXTRA_OPTIONS:-}" @@ -157,11 +155,4 @@ mkdir -p "${ENVOY_FAILED_TEST_LOGS}" export ENVOY_BUILD_PROFILE="${ENVOY_BUILD_DIR}"/generated/build-profile mkdir -p "${ENVOY_BUILD_PROFILE}" -if [[ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "true" ]]; then - # shellcheck source=ci/filter_example_setup.sh - . "${CURRENT_SCRIPT_DIR}"/filter_example_setup.sh -else - echo "Skip setting up Envoy Filter Example." -fi - export NO_BUILD_SETUP=1 diff --git a/ci/do_ci.sh b/ci/do_ci.sh index c6a19f24ca8d..2581a479c299 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -364,14 +364,6 @@ case $CI_TARGET in echo "bazel ASAN/UBSAN debug build with tests" echo "Building and testing envoy tests ${TEST_TARGETS[*]}" bazel_with_collection test "${BAZEL_BUILD_OPTIONS[@]}" "${TEST_TARGETS[@]}" - if [ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "1" ]; then - echo "Building and testing envoy-filter-example tests..." - pushd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" - bazel_with_collection \ - test "${BAZEL_BUILD_OPTIONS[@]}" \ - "${ENVOY_FILTER_EXAMPLE_TESTS[@]}" - popd - fi # TODO(mattklein123): This part of the test is now flaky in CI and it's unclear why, possibly # due to sandboxing issue. Debug and enable it again. # if [ "${CI_SKIP_INTEGRATION_TEST_TRAFFIC_TAPPING}" != "1" ] ; then @@ -429,7 +421,6 @@ case $CI_TARGET in setup_clang_toolchain # This doesn't go into CI but is available for developer convenience. echo "bazel with different compiletime options build with tests..." - cd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" TEST_TARGETS=("${TEST_TARGETS[@]/#\/\//@envoy\/\/}") # Building all the dependencies from scratch to link them against libc++. echo "Building and testing with wasm=wamr: ${TEST_TARGETS[*]}" @@ -977,16 +968,6 @@ case $CI_TARGET in --build_tests_only \ --remote_download_minimal \ "${TEST_TARGETS[@]}" - if [ "${ENVOY_BUILD_FILTER_EXAMPLE}" == "1" ]; then - echo "Building and testing envoy-filter-example tests..." - pushd "${ENVOY_FILTER_EXAMPLE_SRCDIR}" - bazel_with_collection \ - test "${BAZEL_BUILD_OPTIONS[@]}" \ - -c dbg \ - --config=clang-tsan \ - "${ENVOY_FILTER_EXAMPLE_TESTS[@]}" - popd - fi ;; verify_distro) From c57ddb6933e9b9966d6a5d88c78bb55412affa03 Mon Sep 17 00:00:00 2001 From: code Date: Tue, 10 Sep 2024 01:07:16 +0800 Subject: [PATCH 04/21] http: minor code clean up to the http filter manager (#36027) 1. simplify the code and remove unnecessary flag. 2. resolve clang tidy warning. Signed-off-by: wangbaiping --- source/common/http/filter_manager.h | 96 +++++++------------ .../http/conn_manager_impl_test_base.cc | 14 +-- 2 files changed, 39 insertions(+), 71 deletions(-) diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index 0a3d593b8b95..105168585190 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -64,12 +64,9 @@ class LocalReplyOwnerObject : public StreamInfo::FilterState::Object { */ struct ActiveStreamFilterBase : public virtual StreamFilterCallbacks, Logger::Loggable { - ActiveStreamFilterBase(FilterManager& parent, bool is_encoder_decoder_filter, - FilterContext filter_context) + ActiveStreamFilterBase(FilterManager& parent, FilterContext filter_context) : parent_(parent), iteration_state_(IterationState::Continue), - filter_context_(std::move(filter_context)), iterate_from_current_filter_(false), - headers_continued_(false), continued_1xx_headers_(false), end_stream_(false), - is_encoder_decoder_filter_(is_encoder_decoder_filter), processed_headers_(false) {} + filter_context_(std::move(filter_context)) {} // Functions in the following block are called after the filter finishes processing // corresponding data. Those functions handle state updates and data storage (if needed) @@ -184,14 +181,13 @@ struct ActiveStreamFilterBase : public virtual StreamFilterCallbacks, // hasn't parsed data and trailers. As a result, the filter iteration should start with the // current filter instead of the next one. If true, filter iteration starts with the current // filter. Otherwise, starts with the next filter in the chain. - bool iterate_from_current_filter_ : 1; - bool headers_continued_ : 1; - bool continued_1xx_headers_ : 1; + bool iterate_from_current_filter_{}; + bool headers_continued_{}; + bool continued_1xx_headers_{}; // If true, end_stream is called for this filter. - bool end_stream_ : 1; - const bool is_encoder_decoder_filter_ : 1; + bool end_stream_{}; // If true, the filter has processed headers. - bool processed_headers_ : 1; + bool processed_headers_{}; }; /** @@ -201,9 +197,8 @@ struct ActiveStreamDecoderFilter : public ActiveStreamFilterBase, public StreamDecoderFilterCallbacks, LinkedObject { ActiveStreamDecoderFilter(FilterManager& parent, StreamDecoderFilterSharedPtr filter, - bool is_encoder_decoder_filter, FilterContext filter_context) - : ActiveStreamFilterBase(parent, is_encoder_decoder_filter, std::move(filter_context)), - handle_(std::move(filter)) { + FilterContext filter_context) + : ActiveStreamFilterBase(parent, std::move(filter_context)), handle_(std::move(filter)) { handle_->setDecoderFilterCallbacks(*this); } @@ -297,9 +292,8 @@ struct ActiveStreamEncoderFilter : public ActiveStreamFilterBase, public StreamEncoderFilterCallbacks, LinkedObject { ActiveStreamEncoderFilter(FilterManager& parent, StreamEncoderFilterSharedPtr filter, - bool is_encoder_decoder_filter, FilterContext filter_context) - : ActiveStreamFilterBase(parent, is_encoder_decoder_filter, std::move(filter_context)), - handle_(std::move(filter)) { + FilterContext filter_context) + : ActiveStreamFilterBase(parent, std::move(filter_context)), handle_(std::move(filter)) { handle_->setEncoderFilterCallbacks(*this); } @@ -719,30 +713,16 @@ class FilterManager : public ScopeTrackedObject, std::list accessLogHandlers() { return access_log_handlers_; } void onStreamComplete() { - for (auto& filter : decoder_filters_) { - filter->handle_->onStreamComplete(); - } - - for (auto& filter : encoder_filters_) { - // Do not call onStreamComplete twice for dual registered filters. - if (!filter->is_encoder_decoder_filter_) { - filter->handle_->onStreamComplete(); - } + for (auto filter : filters_) { + filter->onStreamComplete(); } } void destroyFilters() { state_.destroyed_ = true; - for (auto& filter : decoder_filters_) { - filter->handle_->onDestroy(); - } - - for (auto& filter : encoder_filters_) { - // Do not call on destroy twice for dual registered filters. - if (!filter->is_encoder_decoder_filter_) { - filter->handle_->onDestroy(); - } + for (auto filter : filters_) { + filter->onDestroy(); } } @@ -883,50 +863,44 @@ class FilterManager : public ScopeTrackedObject, protected: struct State { - State() - : decoder_filter_chain_complete_(false), encoder_filter_chain_complete_(false), - observed_decode_end_stream_(false), observed_encode_end_stream_(false), - has_1xx_headers_(false), created_filter_chain_(false), is_head_request_(false), - is_grpc_request_(false), non_100_response_headers_encoded_(false), - under_on_local_reply_(false), decoder_filter_chain_aborted_(false), - encoder_filter_chain_aborted_(false), saw_downstream_reset_(false) {} + State() = default; uint32_t filter_call_state_{0}; // Set after decoder filter chain has completed iteration. Prevents further calls to decoder // filters. This flag is used to determine stream completion when the independent half-close is // enabled. - bool decoder_filter_chain_complete_ : 1; + bool decoder_filter_chain_complete_{}; // Set after encoder filter chain has completed iteration. Prevents further calls to encoder // filters. This flag is used to determine stream completion when the independent half-close is // enabled. - bool encoder_filter_chain_complete_ : 1; + bool encoder_filter_chain_complete_{}; // Set `true` when the filter manager observes end stream on the decoder path (from downstream // client) before iteration of the decoder filter chain begins. This flag is used for setting // end_stream value when resuming decoder filter chain iteration. - bool observed_decode_end_stream_ : 1; + bool observed_decode_end_stream_{}; // Set `true` when the filter manager observes end stream on the encoder path (from upstream // server or Envoy's local reply) before iteration of the encoder filter chain begins. This flag // is used for setting end_stream value when resuming encoder filter chain iteration. - bool observed_encode_end_stream_ : 1; + bool observed_encode_end_stream_{}; // By default, we will assume there are no 1xx. If encode1xxHeaders // is ever called, this is set to true so commonContinue resumes processing the 1xx. - bool has_1xx_headers_ : 1; - bool created_filter_chain_ : 1; + bool has_1xx_headers_{}; + bool created_filter_chain_{}; // These two are latched on initial header read, to determine if the original headers // constituted a HEAD or gRPC request, respectively. - bool is_head_request_ : 1; - bool is_grpc_request_ : 1; + bool is_head_request_{}; + bool is_grpc_request_{}; // Tracks if headers other than 100-Continue have been encoded to the codec. - bool non_100_response_headers_encoded_ : 1; + bool non_100_response_headers_encoded_{}; // True under the stack of onLocalReply, false otherwise. - bool under_on_local_reply_ : 1; + bool under_on_local_reply_{}; // True when the filter chain iteration was aborted with local reply. - bool decoder_filter_chain_aborted_ : 1; - bool encoder_filter_chain_aborted_ : 1; - bool saw_downstream_reset_ : 1; + bool decoder_filter_chain_aborted_{}; + bool encoder_filter_chain_aborted_{}; + bool saw_downstream_reset_{}; // The following 3 members are booleans rather than part of the space-saving bitfield as they // are passed as arguments to functions expecting bools. Extend State using the bitfield @@ -951,14 +925,14 @@ class FilterManager : public ScopeTrackedObject, void addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr filter) override { manager_.addStreamFilterBase(filter.get()); - manager_.addStreamDecoderFilter(std::make_unique( - manager_, std::move(filter), false, context_)); + manager_.addStreamDecoderFilter( + std::make_unique(manager_, std::move(filter), context_)); } void addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr filter) override { manager_.addStreamFilterBase(filter.get()); - manager_.addStreamEncoderFilter(std::make_unique( - manager_, std::move(filter), false, context_)); + manager_.addStreamEncoderFilter( + std::make_unique(manager_, std::move(filter), context_)); } void addStreamFilter(Http::StreamFilterSharedPtr filter) override { @@ -966,9 +940,9 @@ class FilterManager : public ScopeTrackedObject, manager_.addStreamFilterBase(decoder_filter); manager_.addStreamDecoderFilter( - std::make_unique(manager_, filter, true, context_)); + std::make_unique(manager_, filter, context_)); manager_.addStreamEncoderFilter( - std::make_unique(manager_, std::move(filter), true, context_)); + std::make_unique(manager_, std::move(filter), context_)); } void addAccessLogHandler(AccessLog::InstanceSharedPtr handler) override { diff --git a/test/common/http/conn_manager_impl_test_base.cc b/test/common/http/conn_manager_impl_test_base.cc index daa753103766..0b70e2057938 100644 --- a/test/common/http/conn_manager_impl_test_base.cc +++ b/test/common/http/conn_manager_impl_test_base.cc @@ -394,21 +394,15 @@ void HttpConnectionManagerImplMixin::expectOnDestroy(bool deferred) { for (auto filter : decoder_filters_) { EXPECT_CALL(*filter, onStreamComplete()); } - { - auto setup_filter_expect = [](MockStreamEncoderFilter* filter) { - EXPECT_CALL(*filter, onStreamComplete()); - }; - std::for_each(encoder_filters_.rbegin(), encoder_filters_.rend(), setup_filter_expect); + for (auto filter : encoder_filters_) { + EXPECT_CALL(*filter, onStreamComplete()); } for (auto filter : decoder_filters_) { EXPECT_CALL(*filter, onDestroy()); } - { - auto setup_filter_expect = [](MockStreamEncoderFilter* filter) { - EXPECT_CALL(*filter, onDestroy()); - }; - std::for_each(encoder_filters_.rbegin(), encoder_filters_.rend(), setup_filter_expect); + for (auto filter : encoder_filters_) { + EXPECT_CALL(*filter, onDestroy()); } if (deferred) { From e41fb7185da2fef25f1a64a36d856c7c14bb28c8 Mon Sep 17 00:00:00 2001 From: Fredy Wijaya Date: Mon, 9 Sep 2024 12:44:31 -0500 Subject: [PATCH 05/21] mobile: Fix missing logging output in Swift integration tests (#36040) In Swift, `print` goes to stdout buffering. The fix is to flush the `stdout` and `stderr` before the end of the test. See https://github.com/swiftlang/swift-corelibs-xctest/issues/422#issuecomment-1310952437 Risk Level: low (tests only) Testing: CI Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a --------- Signed-off-by: Fredy Wijaya --- .../swift/integration/CancelGRPCStreamTest.swift | 7 +++++++ .../test/swift/integration/CancelStreamTest.swift | 7 +++++++ .../integration/EndToEndNetworkingTest.swift | 7 +++++++ mobile/test/swift/integration/EngineApiTest.swift | 7 +++++++ .../swift/integration/FilterResetIdleTest.swift | 7 +++++++ .../swift/integration/GRPCReceiveErrorTest.swift | 7 +++++++ .../test/swift/integration/IdleTimeoutTest.swift | 7 +++++++ .../swift/integration/KeyValueStoreTest.swift | 7 +++++++ .../test/swift/integration/ReceiveDataTest.swift | 7 +++++++ .../test/swift/integration/ReceiveErrorTest.swift | 10 +++++++--- .../integration/ResetConnectivityStateTest.swift | 7 +++++++ mobile/test/swift/integration/SendDataTest.swift | 7 +++++++ .../test/swift/integration/SendHeadersTest.swift | 7 +++++++ .../test/swift/integration/SendTrailersTest.swift | 7 +++++++ .../swift/integration/SetEventTrackerTest.swift | 7 +++++++ .../SetEventTrackerTestNoTracker.swift | 7 +++++++ mobile/test/swift/integration/SetLoggerTest.swift | 15 ++++++++++----- .../proxying/HTTPRequestUsingProxyTest.swift | 7 +++++++ 18 files changed, 129 insertions(+), 8 deletions(-) diff --git a/mobile/test/swift/integration/CancelGRPCStreamTest.swift b/mobile/test/swift/integration/CancelGRPCStreamTest.swift index b878490af6ff..6b35c002f08c 100644 --- a/mobile/test/swift/integration/CancelGRPCStreamTest.swift +++ b/mobile/test/swift/integration/CancelGRPCStreamTest.swift @@ -11,6 +11,13 @@ final class CancelGRPCStreamTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testCancelGRPCStream() { let filterName = "cancel_validation_filter" diff --git a/mobile/test/swift/integration/CancelStreamTest.swift b/mobile/test/swift/integration/CancelStreamTest.swift index e6dd2dec4e16..a53f165b2c4b 100644 --- a/mobile/test/swift/integration/CancelStreamTest.swift +++ b/mobile/test/swift/integration/CancelStreamTest.swift @@ -11,6 +11,13 @@ final class CancelStreamTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testCancelStream() { let filterName = "cancel_validation_filter" diff --git a/mobile/test/swift/integration/EndToEndNetworkingTest.swift b/mobile/test/swift/integration/EndToEndNetworkingTest.swift index 18c1e5684e62..638eefc62333 100644 --- a/mobile/test/swift/integration/EndToEndNetworkingTest.swift +++ b/mobile/test/swift/integration/EndToEndNetworkingTest.swift @@ -10,6 +10,13 @@ final class EndToEndNetworkingTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testNetworkRequestReturnsHeadersAndData() { EnvoyTestServer.startHttp1PlaintextServer() EnvoyTestServer.setHeadersAndData( diff --git a/mobile/test/swift/integration/EngineApiTest.swift b/mobile/test/swift/integration/EngineApiTest.swift index 669269526817..22c8a5b68868 100644 --- a/mobile/test/swift/integration/EngineApiTest.swift +++ b/mobile/test/swift/integration/EngineApiTest.swift @@ -9,6 +9,13 @@ final class EngineApiTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testEngineApis() throws { let engineExpectation = self.expectation(description: "Engine Running") diff --git a/mobile/test/swift/integration/FilterResetIdleTest.swift b/mobile/test/swift/integration/FilterResetIdleTest.swift index b9ed4755ba9f..da7f5a528829 100644 --- a/mobile/test/swift/integration/FilterResetIdleTest.swift +++ b/mobile/test/swift/integration/FilterResetIdleTest.swift @@ -11,6 +11,13 @@ final class FilterResetIdleTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testFilterResetIdle() { let filterName = "reset_idle_test_filter" diff --git a/mobile/test/swift/integration/GRPCReceiveErrorTest.swift b/mobile/test/swift/integration/GRPCReceiveErrorTest.swift index 6713b185eb8b..a1266db281c7 100644 --- a/mobile/test/swift/integration/GRPCReceiveErrorTest.swift +++ b/mobile/test/swift/integration/GRPCReceiveErrorTest.swift @@ -11,6 +11,13 @@ final class GRPCReceiveErrorTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testReceiveError() { let filterName = "error_validation_filter" diff --git a/mobile/test/swift/integration/IdleTimeoutTest.swift b/mobile/test/swift/integration/IdleTimeoutTest.swift index 4f3d18440f28..95324f9195cd 100644 --- a/mobile/test/swift/integration/IdleTimeoutTest.swift +++ b/mobile/test/swift/integration/IdleTimeoutTest.swift @@ -11,6 +11,13 @@ final class IdleTimeoutTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testIdleTimeout() { let filterName = "reset_idle_test_filter" diff --git a/mobile/test/swift/integration/KeyValueStoreTest.swift b/mobile/test/swift/integration/KeyValueStoreTest.swift index b33204b2c52b..595bae134513 100644 --- a/mobile/test/swift/integration/KeyValueStoreTest.swift +++ b/mobile/test/swift/integration/KeyValueStoreTest.swift @@ -11,6 +11,13 @@ final class KeyValueStoreTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testKeyValueStore() { // swiftlint:disable:next line_length let kvStoreType = "type.googleapis.com/envoymobile.extensions.filters.http.test_kv_store.TestKeyValueStore" diff --git a/mobile/test/swift/integration/ReceiveDataTest.swift b/mobile/test/swift/integration/ReceiveDataTest.swift index 2e2855535508..483c947e7261 100644 --- a/mobile/test/swift/integration/ReceiveDataTest.swift +++ b/mobile/test/swift/integration/ReceiveDataTest.swift @@ -11,6 +11,13 @@ final class ReceiveDataTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testReceiveData() { let directResponseBody = "response_body" EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/ReceiveErrorTest.swift b/mobile/test/swift/integration/ReceiveErrorTest.swift index 24d9a2b0b194..cb8b408adcc6 100644 --- a/mobile/test/swift/integration/ReceiveErrorTest.swift +++ b/mobile/test/swift/integration/ReceiveErrorTest.swift @@ -10,6 +10,13 @@ final class ReceiveErrorTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testReceiveError() { let filterName = "error_validation_filter" @@ -59,9 +66,6 @@ final class ReceiveErrorTests: XCTestCase { .setLogger { _, msg in print(msg, terminator: "") } - .setLogger { _, msg in - print(msg, terminator: "") - } .addPlatformFilter( name: filterName, factory: { diff --git a/mobile/test/swift/integration/ResetConnectivityStateTest.swift b/mobile/test/swift/integration/ResetConnectivityStateTest.swift index e0c260feb690..ddeb5bb0590e 100644 --- a/mobile/test/swift/integration/ResetConnectivityStateTest.swift +++ b/mobile/test/swift/integration/ResetConnectivityStateTest.swift @@ -11,6 +11,13 @@ final class ResetConnectivityStateTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testResetConnectivityState() { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SendDataTest.swift b/mobile/test/swift/integration/SendDataTest.swift index 25c096e61a94..4a7b736b6f1a 100644 --- a/mobile/test/swift/integration/SendDataTest.swift +++ b/mobile/test/swift/integration/SendDataTest.swift @@ -11,6 +11,13 @@ final class SendDataTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSendData() throws { EnvoyTestServer.startHttp1PlaintextServer() EnvoyTestServer.setHeadersAndData("x-response-foo", header_value: "aaa", response_body: "data") diff --git a/mobile/test/swift/integration/SendHeadersTest.swift b/mobile/test/swift/integration/SendHeadersTest.swift index 6b5bc67fce73..46de840b92ef 100644 --- a/mobile/test/swift/integration/SendHeadersTest.swift +++ b/mobile/test/swift/integration/SendHeadersTest.swift @@ -11,6 +11,13 @@ final class SendHeadersTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSendHeaders() { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SendTrailersTest.swift b/mobile/test/swift/integration/SendTrailersTest.swift index e557756c0edb..5f1caa7a2404 100644 --- a/mobile/test/swift/integration/SendTrailersTest.swift +++ b/mobile/test/swift/integration/SendTrailersTest.swift @@ -11,6 +11,13 @@ final class SendTrailersTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSendTrailers() throws { // swiftlint:disable:next line_length let assertionFilterType = "type.googleapis.com/envoymobile.extensions.filters.http.assertion.Assertion" diff --git a/mobile/test/swift/integration/SetEventTrackerTest.swift b/mobile/test/swift/integration/SetEventTrackerTest.swift index a13e0ddfed56..beec655a1717 100644 --- a/mobile/test/swift/integration/SetEventTrackerTest.swift +++ b/mobile/test/swift/integration/SetEventTrackerTest.swift @@ -11,6 +11,13 @@ final class SetEventTrackerTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSetEventTracker() throws { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift b/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift index 78449f41f1e0..33f5035191e0 100644 --- a/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift +++ b/mobile/test/swift/integration/SetEventTrackerTestNoTracker.swift @@ -11,6 +11,13 @@ final class SetEventTrackerTestNoTracker: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testEmitEventWithoutSettingEventTracker() throws { EnvoyTestServer.startHttp1PlaintextServer() diff --git a/mobile/test/swift/integration/SetLoggerTest.swift b/mobile/test/swift/integration/SetLoggerTest.swift index afe3a8a1654c..96836ebf9dd0 100644 --- a/mobile/test/swift/integration/SetLoggerTest.swift +++ b/mobile/test/swift/integration/SetLoggerTest.swift @@ -11,6 +11,13 @@ final class LoggerTests: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + func testSetLogger() throws { let engineExpectation = self.expectation(description: "Run started engine") let loggingExpectation = self.expectation(description: "Run used platform logger") @@ -24,16 +31,14 @@ final class LoggerTests: XCTestCase { .setLogLevel(.debug) .setLogger { _, msg in print(msg, terminator: "") + if msg.contains("starting main dispatch loop") { + loggingExpectation.fulfill() + } } .addNativeFilter( name: "test_logger", // swiftlint:disable:next line_length typedConfig: "[type.googleapis.com/envoymobile.extensions.filters.http.test_logger.TestLogger]{}") - .setLogger { _, msg in - if msg.contains("starting main dispatch loop") { - loggingExpectation.fulfill() - } - } .setOnEngineRunning { engineExpectation.fulfill() } diff --git a/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift b/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift index da80194d2ff3..67f3e215bb3f 100644 --- a/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift +++ b/mobile/test/swift/integration/proxying/HTTPRequestUsingProxyTest.swift @@ -12,6 +12,13 @@ final class HTTPRequestUsingProxyTest: XCTestCase { register_test_extensions() } + override static func tearDown() { + super.tearDown() + // Flush the stdout and stderror to show the print output. + fflush(stdout) + fflush(stderr) + } + private func executeRequest(engine: Engine, scheme: String, authority: String) -> String? { let responseHeadersExpectation = self.expectation(description: "Successful response headers received") From 97b2408a186602f12e0a475bd5812de1bac9c275 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 9 Sep 2024 21:46:02 +0200 Subject: [PATCH 06/21] Geoip fix asan failure (#36043) Fixing asan failures: ``` ==16==ERROR: LeakSanitizer: detected memory leaks Direct leak of 48 byte(s) in 1 object(s) allocated from: #0 0x323ecbe in malloc /local/mnt/workspace/bcain_clang_hu-bcain-lv_22036/final/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3 #1 0xa58a194 in operator new(unsigned long) (/b/f/w/bazel-out/k8-dbg/bin/test/extensions/geoip_providers/maxmind/geoip_provider_test.runfiles/envoy/test/extensions/geoip_providers/maxmind/geoip_provider_test+0xa58a194) #2 0x3348d04 in void std::__1::vector, std::__1::allocator > >::__emplace_back_slow_path >(std::__1::function&&) /opt/llvm/bin/../include/c++/v1/vector:1558:49 #3 0x3348883 in std::__1::function& std::__1::vector, std::__1::allocator > >::emplace_back >(std::__1::function&&) /opt/llvm/bin/../include/c++/v1/vector:1580:9 #4 0x3348554 in Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::initializeProvider(std::__1::basic_string, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)::operator()(std::__1::basic_string_view >, unsigned int, std::__1::function) const /proc/self/cwd/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc:118:35 #5 0x334830e in decltype(static_cast, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)&>(fp)(static_cast >>(fp0), static_cast(fp0), static_cast>(fp0))) std::__1::__invoke, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)&, std::__1::basic_string_view >, unsigned int, std::__1::function >(Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::initializeProvider(std::__1::basic_string, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)&, std::__1::basic_string_view >&&, unsigned int&&, std::__1::function&&) /opt/llvm/bin/../include/c++/v1/type_traits:3640:23 #6 0x33481c5 in absl::lts_20230802::Status std::__1::__invoke_void_return_wrapper::__call, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)&, std::__1::basic_string_view >, unsigned int, std::__1::function >(Envoy::Extensions::GeoipProviders::Maxmind::GeoipProviderTestBase::initializeProvider(std::__1::basic_string, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)&, std::__1::basic_string_view >&&, unsigned int&&, std::__1::function&&) /opt/llvm/bin/../include/c++/v1/__functional/invoke.h:30:16 #7 0x334819d in std::__1::__function::__alloc_func, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function), std::__1::allocator, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)>, absl::lts_20230802::Status (std::__1::basic_string_view >, unsigned int, std::__1::function)>::operator()(std::__1::basic_string_view >&&, unsigned int&&, std::__1::function&&) /opt/llvm/bin/../include/c++/v1/__functional/function.h:180:16 #8 0x3347993 in std::__1::__function::__func, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function), std::__1::allocator, std::__1::allocator > const&, std::__1::optional&)::'lambda'()::operator()() const::'lambda'(std::__1::basic_string_view >, unsigned int, std::__1::function)>, absl::lts_20230802::Status (std::__1::basic_string_view >, unsigned int, std::__1::function)>::operator()(std::__1::basic_string_view >&&, unsigned int&&, std::__1::function&&) /opt/llvm/bin/../include/c++/v1/__functional/function.h:354:12 #9 0x71758dd in std::__1::__function::__value_func >, unsigned int, std::__1::function)>::operator()(std::__1::basic_string_view >&&, unsigned int&&, std::__1::function&&) const /opt/llvm/bin/../include/c++/v1/__functional/function.h:507:16 #10 0x7175738 in std::__1::function >, unsigned int, std::__1::function)>::operator()(std::__1::basic_string_view >, unsigned int, std::__1::function) const /opt/llvm/bin/../include/c++/v1/__functional/function.h:1184:12 #11 0x71754e8 in decltype(std::forward >, unsigned int, std::__1::function)> const&>(fp)(std::get<0ul>(std::forward >, unsigned int, std::__1::function > >(fp0)), std::get<1ul>(std::forward >, unsigned int, std::__1::function > >(fp0)), std::get<2ul>(std::forward >, unsigned int, std::__1::function > >(fp0)))) testing::internal::ApplyImpl >, unsigned int, std::__1::function)> const&, std::__1::tuple >, unsigned int, std::__1::function >, 0ul, 1ul, 2ul>(std::__1::function >, unsigned int, std::__1::function)> const&, std::__1::tuple >, unsigned int, std::__1::function >&&, testing::internal::IndexSequence<0ul, 1ul, 2ul>) /proc/self/cwd/external/com_google_googletest/googlemock/include/gmock/internal/gmock-internal-utils.h:420:10 #12 0x7175395 in decltype(ApplyImpl(std::forward >, unsigned int, std::__1::function)> const&>(fp), std::forward >, unsigned int, std::__1::function > >(fp0), (testing::internal::MakeIndexSequence >, unsigned int, std::__1::function > >::type>::value>)())) testing::internal::Apply >, unsigned int, std::__1::function)> const&, std::__1::tuple >, unsigned int, std::__1::function > >(std::__1::function >, unsigned int, std::__1::function)> const&, std::__1::tuple >, unsigned int, std::__1::function >&&) /proc/self/cwd/external/com_google_googletest/googlemock/include/gmock/internal/gmock-internal-utils.h:429:10 #13 0x7174d47 in testing::Action >, unsigned int, std::__1::function)>::Perform(std::__1::tuple >, unsigned int, std::__1::function >) const /proc/self/cwd/external/com_google_googletest/googlemock/include/gmock/gmock-actions.h:497:12 #14 0x7175afd in testing::internal::ActionResultHolder* testing::internal::ActionResultHolder::PerformAction >, unsigned int, std::__1::function)>(testing::Action >, unsigned int, std::__1::function)> const&, testing::internal::Function >, unsigned int, std::__1::function)>::ArgumentTuple&&) /proc/self/cwd/external/com_google_googletest/googlemock/include/gmock/gmock-spec-builders.h:1402:24 #15 0x7173651 in testing::internal::FunctionMocker >, unsigned int, std::__1::function)>::UntypedPerformAction(void const*, void*) const /proc/self/cwd/external/com_google_googletest/googlemock/include/gmock/gmock-spec-builders.h:1556:12 #16 0xa3e9535 in testing::internal::UntypedFunctionMockerBase::UntypedInvokeWith(void*) /proc/self/cwd/external/com_google_googletest/googlemock/src/gmock-spec-builders.cc:452:24 #17 0x333e5b2 in testing::internal::FunctionMocker >, unsigned int, std::__1::function)>::Invoke(std::__1::basic_string_view >, unsigned int, std::__1::function) /proc/self/cwd/external/com_google_googletest/googlemock/include/gmock/gmock-spec-builders.h:1593:15 #18 0x333e24c in Envoy::Filesystem::MockWatcher::addWatch(std::__1::basic_string_view >, unsigned int, std::__1::function) /proc/self/cwd/./test/mocks/filesystem/mocks.h:78:3 #19 0x3405db9 in decltype(static_cast, std::__1::shared_ptr)::$_0&>(fp)()) std::__1::__invoke, std::__1::shared_ptr)::$_0&>(Envoy::Extensions::GeoipProviders::Maxmind::GeoipProvider::GeoipProvider(Envoy::Event::Dispatcher&, Envoy::Api::Api&, std::__1::shared_ptr, std::__1::shared_ptr)::$_0&) /proc/self/cwd/source/extensions/geoip_providers/maxmind/geoip_provider.cc:126:11 #20 0x3404a63 in std::__1::__function::__func, std::__1::shared_ptr)::$_0, std::__1::allocator, std::__1::shared_ptr)::$_0>, void ()>::operator()() /opt/llvm/bin/../include/c++/v1/__functional/invoke.h:61:9 #21 0x34f0239 in std::__1::__function::__value_func::operator()() const /opt/llvm/bin/../include/c++/v1/__functional/function.h:507:16 #22 0x91dbf37 in Envoy::Thread::PosixThreadFactory::createPthread(Envoy::Thread::ThreadHandle*)::$_6::__invoke(void*) /opt/llvm/bin/../include/c++/v1/__functional/function.h:1184:12 #23 0x7fb0ecf9f608 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x8608) (BuildId: 0c044ba611aeeeaebb8374e660061f341ebc0bac) ``` Commit Message: Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] Fixes #35829 [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] Signed-off-by: Kateryna Nezdolii --- test/extensions/geoip_providers/maxmind/geoip_provider_test.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index b8d1cc93b647..6d3e8961d82a 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -94,6 +94,7 @@ class GeoipProviderTestBase { Registry::FactoryRegistry::getFactory( "envoy.geoip_providers.maxmind")); ASSERT(provider_factory_); + on_changed_cbs_.reserve(1); } ~GeoipProviderTestBase() { From 627187b5b8da45c8cc028c44f41b70a12c67b2b7 Mon Sep 17 00:00:00 2001 From: Greg Greenway Date: Mon, 9 Sep 2024 21:54:04 -0700 Subject: [PATCH 07/21] quic: enable certificate compression/decompression (#35999) QUIC servers are limited in how much data they can send to clients in the ServerHello before the client is validated (see https://www.rfc-editor.org/rfc/rfc9000.html#section-8). If too much data needs to be sent, an extra network round trip is needed. One way to reduce the size of the ServerHello data is to compress the certificates. This can, in some situations, remove an extra round trip. Risk Level: Low Testing: Added unit and integration tests Docs Changes: Release Notes: Added Platform Specific Features: Runtime guard: `envoy.reloadable_features.quic_support_certificate_compression` --------- Signed-off-by: Greg Greenway --- changelogs/current.yaml | 5 + source/common/quic/BUILD | 21 ++- source/common/quic/cert_compression.cc | 122 ++++++++++++++++++ source/common/quic/cert_compression.h | 31 +++++ source/common/quic/envoy_quic_proof_source.cc | 5 + source/common/quic/envoy_quic_proof_source.h | 1 + .../quic_client_transport_socket_factory.cc | 3 + source/common/runtime/runtime_features.cc | 1 + test/common/quic/BUILD | 9 ++ test/common/quic/cert_compression_test.cc | 46 +++++++ .../integration/quic_http_integration_test.cc | 20 +++ test/per_file_coverage.sh | 2 +- 12 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 source/common/quic/cert_compression.cc create mode 100644 source/common/quic/cert_compression.h create mode 100644 test/common/quic/cert_compression_test.cc diff --git a/changelogs/current.yaml b/changelogs/current.yaml index fcf4a1c034e4..d46e53b6071e 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -230,6 +230,11 @@ new_features: Added socket ``type`` field for specifying a socket type to apply the socket option to under :ref:`SocketOption `. If not specified, the socket option will be applied to all socket types. +- area: quic + change: | + QUIC server and client support certificate compression, which can in some cases reduce the number of round trips + required to setup a connection. This change temporarily disabled by setting the runtime flag + ``envoy.reloadable_features.quic_support_certificate_compression`` to ``false``. - area: tls change: | Added an extension point :ref:`custom_tls_certificate_selector diff --git a/source/common/quic/BUILD b/source/common/quic/BUILD index 884ce2714010..8a91e57052e4 100644 --- a/source/common/quic/BUILD +++ b/source/common/quic/BUILD @@ -116,7 +116,9 @@ envoy_cc_library( name = "envoy_quic_proof_source_lib", srcs = ["envoy_quic_proof_source.cc"], hdrs = ["envoy_quic_proof_source.h"], - external_deps = ["ssl"], + external_deps = [ + "ssl", + ], tags = ["nofips"], deps = [ ":envoy_quic_proof_source_base_lib", @@ -124,6 +126,7 @@ envoy_cc_library( ":quic_io_handle_wrapper_lib", ":quic_transport_socket_factory_lib", "//envoy/ssl:tls_certificate_config_interface", + "//source/common/quic:cert_compression_lib", "//source/common/quic:quic_server_transport_socket_factory_lib", "//source/common/stream_info:stream_info_lib", "//source/server:listener_stats", @@ -500,6 +503,7 @@ envoy_cc_library( "//envoy/ssl:context_config_interface", "//source/common/common:assert_lib", "//source/common/network:transport_socket_options_lib", + "//source/common/quic:cert_compression_lib", "//source/common/tls:client_ssl_socket_lib", "//source/common/tls:context_config_lib", "@com_github_google_quiche//:quic_core_crypto_crypto_handshake_lib", @@ -714,3 +718,18 @@ envoy_cc_library( "@com_github_google_quiche//:quic_core_types_lib", ], ) + +envoy_cc_library( + name = "cert_compression_lib", + srcs = ["cert_compression.cc"], + hdrs = ["cert_compression.h"], + external_deps = [ + "ssl", + "zlib", + ], + deps = [ + "//source/common/common:assert_lib", + "//source/common/common:logger_lib", + "//source/common/runtime:runtime_lib", + ], +) diff --git a/source/common/quic/cert_compression.cc b/source/common/quic/cert_compression.cc new file mode 100644 index 000000000000..90acde1e2694 --- /dev/null +++ b/source/common/quic/cert_compression.cc @@ -0,0 +1,122 @@ +#include "source/common/quic/cert_compression.h" + +#include "source/common/common/assert.h" +#include "source/common/runtime/runtime_features.h" + +#include "openssl/tls1.h" + +#define ZLIB_CONST +#include "zlib.h" + +namespace Envoy { +namespace Quic { + +namespace { + +class ScopedZStream { +public: + using CleanupFunc = int (*)(z_stream*); + + ScopedZStream(z_stream& z, CleanupFunc cleanup) : z_(z), cleanup_(cleanup) {} + ~ScopedZStream() { cleanup_(&z_); } + +private: + z_stream& z_; + CleanupFunc cleanup_; +}; + +} // namespace + +void CertCompression::registerSslContext(SSL_CTX* ssl_ctx) { + if (Runtime::runtimeFeatureEnabled( + "envoy.reloadable_features.quic_support_certificate_compression")) { + auto ret = SSL_CTX_add_cert_compression_alg(ssl_ctx, TLSEXT_cert_compression_zlib, compressZlib, + decompressZlib); + ASSERT(ret == 1); + } +} + +int CertCompression::compressZlib(SSL*, CBB* out, const uint8_t* in, size_t in_len) { + + z_stream z = {}; + int rv = deflateInit(&z, Z_DEFAULT_COMPRESSION); + if (rv != Z_OK) { + IS_ENVOY_BUG(fmt::format("Cert compression failure in deflateInit: {}", rv)); + return FAILURE; + } + + ScopedZStream deleter(z, deflateEnd); + + const auto upper_bound = deflateBound(&z, in_len); + + uint8_t* out_buf = nullptr; + if (!CBB_reserve(out, &out_buf, upper_bound)) { + IS_ENVOY_BUG(fmt::format("Cert compression failure in allocating output CBB buffer of size {}", + upper_bound)); + return FAILURE; + } + + z.next_in = in; + z.avail_in = in_len; + z.next_out = out_buf; + z.avail_out = upper_bound; + + rv = deflate(&z, Z_FINISH); + if (rv != Z_STREAM_END) { + IS_ENVOY_BUG(fmt::format( + "Cert compression failure in deflate: {}, z.total_out {}, in_len {}, z.avail_in {}", rv, + z.avail_in, in_len, z.avail_in)); + return FAILURE; + } + + if (!CBB_did_write(out, z.total_out)) { + IS_ENVOY_BUG("CBB_did_write failed"); + return FAILURE; + } + + ENVOY_LOG(trace, "Cert compression successful"); + + return SUCCESS; +} + +int CertCompression::decompressZlib(SSL*, CRYPTO_BUFFER** out, size_t uncompressed_len, + const uint8_t* in, size_t in_len) { + z_stream z = {}; + int rv = inflateInit(&z); + if (rv != Z_OK) { + IS_ENVOY_BUG(fmt::format("Cert decompression failure in inflateInit: {}", rv)); + return FAILURE; + } + + ScopedZStream deleter(z, inflateEnd); + + z.next_in = in; + z.avail_in = in_len; + bssl::UniquePtr decompressed_data( + CRYPTO_BUFFER_alloc(&z.next_out, uncompressed_len)); + z.avail_out = uncompressed_len; + + rv = inflate(&z, Z_FINISH); + if (rv != Z_STREAM_END) { + ENVOY_LOG_PERIODIC(error, std::chrono::seconds(10), + "Cert decompression failure in inflate, possibly caused by invalid " + "compressed cert from peer: {}, z.total_out {}, uncompressed_len {}", + rv, z.total_out, uncompressed_len); + return FAILURE; + } + + if (z.total_out != uncompressed_len) { + ENVOY_LOG_PERIODIC(error, std::chrono::seconds(10), + "Decompression length did not match peer provided uncompressed length, " + "caused by either invalid peer handshake data or decompression error."); + return FAILURE; + } + + ENVOY_LOG(trace, "Cert decompression successful"); + + *out = decompressed_data.release(); + return SUCCESS; +} + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/cert_compression.h b/source/common/quic/cert_compression.h new file mode 100644 index 000000000000..65be63cb8fde --- /dev/null +++ b/source/common/quic/cert_compression.h @@ -0,0 +1,31 @@ +#pragma once + +#include "source/common/common/logger.h" + +#include "openssl/ssl.h" + +namespace Envoy { +namespace Quic { + +/** + * Support for certificate compression and decompression in QUIC TLS handshakes. This often + * needed for the ServerHello to fit in the initial response and not need an additional round trip + * between client and server. + */ +class CertCompression : protected Logger::Loggable { +public: + // Registers compression and decompression functions on `ssl_ctx` if enabled. + static void registerSslContext(SSL_CTX* ssl_ctx); + + // Callbacks for `SSL_CTX_add_cert_compression_alg`. + static int compressZlib(SSL* ssl, CBB* out, const uint8_t* in, size_t in_len); + static int decompressZlib(SSL*, CRYPTO_BUFFER** out, size_t uncompressed_len, const uint8_t* in, + size_t in_len); + + // Defined return values for callbacks from `SSL_CTX_add_cert_compression_alg`. + static constexpr int SUCCESS = 1; + static constexpr int FAILURE = 0; +}; + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/envoy_quic_proof_source.cc b/source/common/quic/envoy_quic_proof_source.cc index e5457e953ad9..4d696753e013 100644 --- a/source/common/quic/envoy_quic_proof_source.cc +++ b/source/common/quic/envoy_quic_proof_source.cc @@ -4,6 +4,7 @@ #include "envoy/ssl/tls_certificate_config.h" +#include "source/common/quic/cert_compression.h" #include "source/common/quic/envoy_quic_utils.h" #include "source/common/quic/quic_io_handle_wrapper.h" #include "source/common/runtime/runtime_features.h" @@ -211,5 +212,9 @@ void EnvoyQuicProofSource::updateFilterChainManager( filter_chain_manager_ = &filter_chain_manager; } +void EnvoyQuicProofSource::OnNewSslCtx(SSL_CTX* ssl_ctx) { + CertCompression::registerSslContext(ssl_ctx); +} + } // namespace Quic } // namespace Envoy diff --git a/source/common/quic/envoy_quic_proof_source.h b/source/common/quic/envoy_quic_proof_source.h index e950b982445b..1d8bf461f948 100644 --- a/source/common/quic/envoy_quic_proof_source.h +++ b/source/common/quic/envoy_quic_proof_source.h @@ -19,6 +19,7 @@ class EnvoyQuicProofSource : public EnvoyQuicProofSourceBase { ~EnvoyQuicProofSource() override = default; // quic::ProofSource + void OnNewSslCtx(SSL_CTX* ssl_ctx) override; quiche::QuicheReferenceCountedPointer GetCertChain(const quic::QuicSocketAddress& server_address, const quic::QuicSocketAddress& client_address, const std::string& hostname, diff --git a/source/common/quic/quic_client_transport_socket_factory.cc b/source/common/quic/quic_client_transport_socket_factory.cc index e7b2febc8f75..0ec580f830b0 100644 --- a/source/common/quic/quic_client_transport_socket_factory.cc +++ b/source/common/quic/quic_client_transport_socket_factory.cc @@ -4,6 +4,7 @@ #include "envoy/extensions/transport_sockets/quic/v3/quic_transport.pb.validate.h" +#include "source/common/quic/cert_compression.h" #include "source/common/quic/envoy_quic_proof_verifier.h" #include "source/common/runtime/runtime_features.h" #include "source/common/tls/context_config_impl.h" @@ -86,6 +87,8 @@ std::shared_ptr QuicClientTransportSocketFactory:: tls_config.crypto_config_ = std::make_shared( std::make_unique(std::move(context), accept_untrusted), std::make_unique()); + + CertCompression::registerSslContext(tls_config.crypto_config_->ssl_ctx()); } // Return the latest crypto config. return tls_config.crypto_config_; diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 7f0378342a27..1411ac47f991 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -80,6 +80,7 @@ RUNTIME_GUARD(envoy_reloadable_features_quic_receive_ecn); // Ignore the automated "remove this flag" issue: we should keep this for 1 year. Confirm with // @danzh2010 or @RyanTheOptimist before removing. RUNTIME_GUARD(envoy_reloadable_features_quic_send_server_preferred_address_to_all_clients); +RUNTIME_GUARD(envoy_reloadable_features_quic_support_certificate_compression); RUNTIME_GUARD(envoy_reloadable_features_quic_upstream_reads_fixed_number_packets); RUNTIME_GUARD(envoy_reloadable_features_quic_upstream_socket_use_address_cache_for_read); RUNTIME_GUARD(envoy_reloadable_features_reject_invalid_yaml); diff --git a/test/common/quic/BUILD b/test/common/quic/BUILD index dc2df66c3174..938238aafdf4 100644 --- a/test/common/quic/BUILD +++ b/test/common/quic/BUILD @@ -395,6 +395,15 @@ envoy_cc_test( ]), ) +envoy_cc_test( + name = "cert_compression_test", + srcs = ["cert_compression_test.cc"], + deps = [ + "//source/common/quic:cert_compression_lib", + "//test/test_common:logging_lib", + ], +) + envoy_proto_library( name = "envoy_quic_h3_fuzz_proto", srcs = ["envoy_quic_h3_fuzz.proto"], diff --git a/test/common/quic/cert_compression_test.cc b/test/common/quic/cert_compression_test.cc new file mode 100644 index 000000000000..767b13df1bf3 --- /dev/null +++ b/test/common/quic/cert_compression_test.cc @@ -0,0 +1,46 @@ +#include "source/common/quic/cert_compression.h" + +#include "test/test_common/logging.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Quic { + +TEST(CertCompressionZlibTest, DecompressBadData) { + EXPECT_LOG_CONTAINS( + "error", + "Cert decompression failure in inflate, possibly caused by invalid compressed cert from peer", + { + CRYPTO_BUFFER* out = nullptr; + const uint8_t bad_compressed_data = 1; + EXPECT_EQ(CertCompression::FAILURE, + CertCompression::decompressZlib(nullptr, &out, 100, &bad_compressed_data, + sizeof(bad_compressed_data))); + }); +} + +TEST(CertCompressionZlibTest, DecompressBadLength) { + constexpr uint8_t the_data[] = {1, 2, 3, 4, 5, 6}; + constexpr size_t uncompressed_len = 6; + bssl::ScopedCBB compressed; + ASSERT_EQ(1, CBB_init(compressed.get(), 0)); + ASSERT_EQ(CertCompression::SUCCESS, + CertCompression::compressZlib(nullptr, compressed.get(), the_data, uncompressed_len)); + const auto compressed_len = CBB_len(compressed.get()); + EXPECT_NE(0, compressed_len); + + EXPECT_LOG_CONTAINS("error", + "Decompression length did not match peer provided uncompressed length, " + "caused by either invalid peer handshake data or decompression error.", + { + CRYPTO_BUFFER* out = nullptr; + EXPECT_EQ(CertCompression::FAILURE, + CertCompression::decompressZlib( + nullptr, &out, + uncompressed_len + 1 /* intentionally incorrect */, + CBB_data(compressed.get()), compressed_len)); + }); +} +} // namespace Quic +} // namespace Envoy diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index e431aa45828e..b2dc7b4fa18a 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -671,6 +671,26 @@ TEST_P(QuicHttpIntegrationTest, RuntimeEnableDraft29) { test_server_->waitForCounterEq("http3.quic_version_h3_29", 1u); } +TEST_P(QuicHttpIntegrationTest, CertCompressionEnabled) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.quic_support_certificate_compression", "true"); + initialize(); + + EXPECT_LOG_CONTAINS_ALL_OF( + Envoy::ExpectedLogMessages( + {{"trace", "Cert compression successful"}, {"trace", "Cert decompression successful"}}), + { testRouterHeaderOnlyRequestAndResponse(); }); +} + +TEST_P(QuicHttpIntegrationTest, CertCompressionDisabled) { + config_helper_.addRuntimeOverride( + "envoy.reloadable_features.quic_support_certificate_compression", "false"); + initialize(); + + EXPECT_LOG_NOT_CONTAINS("trace", "Cert compression successful", + { testRouterHeaderOnlyRequestAndResponse(); }); +} + TEST_P(QuicHttpIntegrationTest, ZeroRtt) { // Make sure all connections use the same PersistentQuicInfoImpl. concurrency_ = 1; diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index 8138b1e56ebc..5b5f6d472a7a 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -16,7 +16,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/memory:74.5" # tcmalloc code path is not enabled in coverage build, only gperf tcmalloc, see PR#32589 "source/common/network:94.4" # Flaky, `activateFileEvents`, `startSecureTransport` and `ioctl`, listener_socket do not always report LCOV "source/common/network/dns_resolver:91.4" # A few lines of MacOS code not tested in linux scripts. Tested in MacOS scripts -"source/common/quic:93.7" +"source/common/quic:93.5" "source/common/secret:95.4" "source/common/signal:87.2" # Death tests don't report LCOV "source/common/thread:0.0" # Death tests don't report LCOV From 7549bbc798904a0b485a661712c6da14904d1fc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:03:59 +0100 Subject: [PATCH 08/21] build(deps): bump multidict from 6.0.5 to 6.1.0 in /tools/base (#36048) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 184 ++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 91 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 2b04f6be9239..088fdc49c291 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -868,97 +868,99 @@ monotonic==1.6 \ --hash=sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7 \ --hash=sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c # via gsutil -multidict==6.0.5 \ - --hash=sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556 \ - --hash=sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c \ - --hash=sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29 \ - --hash=sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b \ - --hash=sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8 \ - --hash=sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7 \ - --hash=sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd \ - --hash=sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40 \ - --hash=sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6 \ - --hash=sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3 \ - --hash=sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c \ - --hash=sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9 \ - --hash=sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5 \ - --hash=sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae \ - --hash=sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442 \ - --hash=sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9 \ - --hash=sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc \ - --hash=sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c \ - --hash=sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea \ - --hash=sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5 \ - --hash=sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50 \ - --hash=sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182 \ - --hash=sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453 \ - --hash=sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e \ - --hash=sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600 \ - --hash=sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733 \ - --hash=sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda \ - --hash=sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241 \ - --hash=sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461 \ - --hash=sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e \ - --hash=sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e \ - --hash=sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b \ - --hash=sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e \ - --hash=sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7 \ - --hash=sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386 \ - --hash=sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd \ - --hash=sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9 \ - --hash=sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf \ - --hash=sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee \ - --hash=sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5 \ - --hash=sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a \ - --hash=sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271 \ - --hash=sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54 \ - --hash=sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4 \ - --hash=sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496 \ - --hash=sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb \ - --hash=sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319 \ - --hash=sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3 \ - --hash=sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f \ - --hash=sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527 \ - --hash=sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed \ - --hash=sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604 \ - --hash=sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef \ - --hash=sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8 \ - --hash=sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5 \ - --hash=sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5 \ - --hash=sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626 \ - --hash=sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c \ - --hash=sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d \ - --hash=sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c \ - --hash=sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc \ - --hash=sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc \ - --hash=sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b \ - --hash=sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38 \ - --hash=sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450 \ - --hash=sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1 \ - --hash=sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f \ - --hash=sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3 \ - --hash=sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755 \ - --hash=sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226 \ - --hash=sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a \ - --hash=sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046 \ - --hash=sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf \ - --hash=sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479 \ - --hash=sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e \ - --hash=sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1 \ - --hash=sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a \ - --hash=sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83 \ - --hash=sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929 \ - --hash=sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93 \ - --hash=sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a \ - --hash=sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c \ - --hash=sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44 \ - --hash=sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89 \ - --hash=sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba \ - --hash=sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e \ - --hash=sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da \ - --hash=sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24 \ - --hash=sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423 \ - --hash=sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef +multidict==6.1.0 \ + --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ + --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ + --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ + --hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \ + --hash=sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b \ + --hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \ + --hash=sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748 \ + --hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \ + --hash=sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f \ + --hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \ + --hash=sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6 \ + --hash=sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada \ + --hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \ + --hash=sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2 \ + --hash=sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d \ + --hash=sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a \ + --hash=sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef \ + --hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \ + --hash=sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb \ + --hash=sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60 \ + --hash=sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6 \ + --hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \ + --hash=sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478 \ + --hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \ + --hash=sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7 \ + --hash=sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56 \ + --hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \ + --hash=sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6 \ + --hash=sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30 \ + --hash=sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb \ + --hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \ + --hash=sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0 \ + --hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \ + --hash=sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c \ + --hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \ + --hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \ + --hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \ + --hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \ + --hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \ + --hash=sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2 \ + --hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \ + --hash=sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3 \ + --hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \ + --hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \ + --hash=sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657 \ + --hash=sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581 \ + --hash=sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492 \ + --hash=sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43 \ + --hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \ + --hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \ + --hash=sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926 \ + --hash=sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057 \ + --hash=sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc \ + --hash=sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80 \ + --hash=sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255 \ + --hash=sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1 \ + --hash=sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972 \ + --hash=sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53 \ + --hash=sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1 \ + --hash=sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423 \ + --hash=sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a \ + --hash=sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160 \ + --hash=sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c \ + --hash=sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd \ + --hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \ + --hash=sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5 \ + --hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \ + --hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \ + --hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \ + --hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \ + --hash=sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4 \ + --hash=sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156 \ + --hash=sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753 \ + --hash=sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28 \ + --hash=sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d \ + --hash=sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a \ + --hash=sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304 \ + --hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \ + --hash=sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429 \ + --hash=sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72 \ + --hash=sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399 \ + --hash=sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3 \ + --hash=sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392 \ + --hash=sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167 \ + --hash=sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c \ + --hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \ + --hash=sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351 \ + --hash=sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76 \ + --hash=sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875 \ + --hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \ + --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \ + --hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db # via # -r requirements.in # aiohttp From eb61f368690cae173502f80549b7e2169ec24766 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:04:08 +0100 Subject: [PATCH 09/21] build(deps): bump yarl from 1.11.0 to 1.11.1 in /tools/base (#36049) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 186 ++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 088fdc49c291..76c8cb8b8a58 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1518,99 +1518,99 @@ yapf==0.40.2 \ # via # -r requirements.in # envoy-code-check -yarl==1.11.0 \ - --hash=sha256:01a7905e662665ca8e058635377522bc3c98bdb873be761ff42c86eb72b03914 \ - --hash=sha256:0310eb2e63872de66047e05ad9982f2e53ad6405dc42fa60d7cc670bf6ca8aa8 \ - --hash=sha256:03717a6627e55934b2a1d9caf24f299b461a2e8d048a90920f42ad5c20ae1b82 \ - --hash=sha256:03a726fb50588307dfe1d233b67535d493fb0bb157bdbfda6bb34e04189f2f57 \ - --hash=sha256:05ab59db0bb64e847972373c5cda8924e6605480f6b13cc04573fa0d87bfc637 \ - --hash=sha256:07e8cfb1dd7669a129f8fd5df1da65efa73aea77582bde2a3a837412e2863543 \ - --hash=sha256:0a657db1b9982f3dac0e360614d0e8945d2873da6e681fb7fca23ef1c3eb37f8 \ - --hash=sha256:0c58656c2e0b41b5d325130b8da4f8e216aad10029e7de5c523a6be25faa9fe8 \ - --hash=sha256:11af21bbf807688d49b7d4915bb28cbc2e3aa028a2ee194738477eabcc413c65 \ - --hash=sha256:121d3798e4bb35a4321b2422cb887f80ea39f94bf52f0eb5cb2c168bb0043c9b \ - --hash=sha256:18ec42da256cfcb9b4cd5d253e04c291f69911a5228d1438a7d431c15ba0ae40 \ - --hash=sha256:195f7791bc23d5f2480efe53f935daf8a61661000dfbfbdd70dbd06397594fff \ - --hash=sha256:1a29b82c42a7791ffe53ee6dfbf29acc61ea7ec05643dcacc50510ed6187b897 \ - --hash=sha256:202f5ec49ff163dcc767426deb55020a28078e61d6bbe1f80331d92bca53b236 \ - --hash=sha256:2371510367d39d74997acfdcd1dead17938c79c99365482821627f7838a8eba0 \ - --hash=sha256:24da0b38274727fe9266d09229987e7f0efdb97beb94c0bb2d327d65f112e78d \ - --hash=sha256:2516e238daf0339c8ac4dfab9d7cda9afad652ff073517f200d653d5d8371f7e \ - --hash=sha256:25f8bc849004122591104793a576e9c747b0e5d9486d6a30225521b817255748 \ - --hash=sha256:2949067359d1ef5bf3228c7f1deb102c209832a13df5419239f99449bc1d3fa9 \ - --hash=sha256:2a596bb15e036952549871a4ccd2205679902dc7f241e3ced6b2ab2e44c55795 \ - --hash=sha256:30f391ccf4b1b1e0ba4880075ba337d41a619a5350f67053927f67ebe764bf44 \ - --hash=sha256:31df9d9b3fe6e15decee629fc7976a5fb21eaa39e290f60e57e1d422827194c6 \ - --hash=sha256:361fdb3993431157302b7104d525092b5df4d7d346df5a5ffeee2d1ca8e0d15b \ - --hash=sha256:39e3087e1ef70862de81e22af9eb299faee580f41673ef92829949022791b521 \ - --hash=sha256:3a601c99fc20fd0eea84e7bc0dc9e7f196f55a0ded67242d724988c754295538 \ - --hash=sha256:3ade2265716667b6bd4123d6f684b5f7cf4a8d83dcf1d5581ac44643466bb00a \ - --hash=sha256:3c458483711d393dad51340505c3fab3194748fd06bab311d2f8b5b7a7349e9a \ - --hash=sha256:3d1bd3262e00043907e0a6d7d4f7b7a4815281acc25699a2384552870c79f1f0 \ - --hash=sha256:418eeb8f228ea36c368bf6782ebd6016ecebfb1a8b90145ef6726ffcbba65ef8 \ - --hash=sha256:42ff79371614764fc0a4ab8eaba9adb493bf9ad856e2a4664f6c754fc907a903 \ - --hash=sha256:48bac099586cf75ae5837b0ac17a674450d01f451f38afcb02acfc940110b60b \ - --hash=sha256:4a0d090d296ced05edfe29c6ff34869412fa6a97d0928c12b00939c4842884cd \ - --hash=sha256:4ae63bc65e5bf8843bd1eca46e75eaa9eb157e0312fb362123181512892daad8 \ - --hash=sha256:4c19a0d95943bb2c914b4e71043803be34bc75c08c4a6ca232bdc649a1e9ef1b \ - --hash=sha256:4c8dc0efcf8266ecfe057b95e01f43eb62516196a4bbf3918fd1dcb8d0dc0dff \ - --hash=sha256:4fa9d762eee63eed767895d68b994c58e29f809292a4d0fca483e9cc6fdc22c8 \ - --hash=sha256:50ceaeda771ee3e382291168c90c7ede62b63ecf3e181024bcfeb35c0ea6c84f \ - --hash=sha256:52433604340a4ab3d1f32281c6eb9ad9b47c99435b4212f763121bf7348c8c00 \ - --hash=sha256:53c80b1927b75aed208d7fd965a3a705dc8c1db4d50b9112418fa0f7784363e6 \ - --hash=sha256:540fd5f62fe21f3d1d9efe8af5c4d9dbbb184ce03ce95acb0289500e46215dd2 \ - --hash=sha256:5b008c3127382503e7a1e12b4c3a3236e3dd833a4c62a066f4a0fbd650c655d2 \ - --hash=sha256:60ed3c7f64e820959d7f682ec2f559b4f4df723dc09df619d269853a4214a4b4 \ - --hash=sha256:6471d747d0ac8059895e66d32ca8630c8db5b572ca7763150d0927eaa257df67 \ - --hash=sha256:65a1a05efca52b102691e64db5fcf973030a1c88fee393804ff91f99c95a6e74 \ - --hash=sha256:68e14ae71e5b51c8282ae5db53ccb3baffc40e1551370a8a2361f1c1d8a0bf8c \ - --hash=sha256:69a45c711fea9b783b592a75f26f6dc59b2e4a923b97bf6eec357566fcb1d922 \ - --hash=sha256:6e73dab98e3c3b5441720153e72a5f28e717aac2d22f1ec4b08ef33417d9987e \ - --hash=sha256:706ac0f77b45e9e0278ec6c98929764e119d3ce3136792b6475e7ae961da53ec \ - --hash=sha256:732d56da00ea7a5da4f0d15adbbd22dcb37da7825510aafde40112e53f6baa52 \ - --hash=sha256:765128029218eade3a01187cdd7f375977cc827505ed31828196c8ae9b622928 \ - --hash=sha256:79d420399f0e82e302236a762d8b8ceec89761ce3b30c83ac1d4d6e29f811444 \ - --hash=sha256:7bd54d79025b59d1dc5fb26a09734d6a9cc651a04bc381966ed264b28331a168 \ - --hash=sha256:7fd535cc41b81a566ad347081b671ab5c7e5f5b6a15526d85b4e748baf065cf0 \ - --hash=sha256:7ff371002fbbb79613269d76a2932c99979dac15fac30107064ef70d25f35474 \ - --hash=sha256:8055b0d78ce1cafa657c4b455e22661e8d3b2834de66a0753c3567da47fcc4aa \ - --hash=sha256:84624db40e2358cfd5cf2558b1aaffd93366d27ee32228a97785f2ec87d44a17 \ - --hash=sha256:8aee7c8378c6aa3103b99d1eb9995268ef730fa9f88ea68b9eee4341e204eec9 \ - --hash=sha256:9057f5de2fade7440e6db358913bc7ae8de43ba72c83cf95420a1fc1a6c6b59e \ - --hash=sha256:93fca4c9f88c17ead902b3f3285b2d039fc8f26d117e1441973ba64315109b54 \ - --hash=sha256:9425c333575fce5e0fb414b766492c6ba4aa335ef910a7540dbdefe58a78232e \ - --hash=sha256:969ad4ee3892e893471b6572bbf2bbb091f93e7c81de25d6b3a5c0a5126e5ccb \ - --hash=sha256:976d02274e6d88b24c7131e7b26a083412b2592f2bbcef53d3b00b2508cad26c \ - --hash=sha256:98e2eb182d59f0845a79434003f94b4f61cd69465248f9388c2e5bf2191c9f7f \ - --hash=sha256:9dc66e2420e1e282105071934883bbb9c37c16901b5b8aa0a8aee370b477eac6 \ - --hash=sha256:a45e51ba3777031e0b20c1e7ab59114ed4e1884b3c1db48962c1d8d08aefb418 \ - --hash=sha256:a4f7e470f2c9c8b8774a5bda72adfb8e9dc4ec32311fe9bdaa4921e36cf6659b \ - --hash=sha256:aacd62ff67efd54cb18cea2aa7ae4fb83cfbca19a07055d4777266b70561defe \ - --hash=sha256:b3dd10f0fe0e0f659926c1da791de5bef05fd48974ad74618c9168e302e2b7cc \ - --hash=sha256:b8bbac56c80610dd659ace534765d7bcd2488f6600023f6984f35108b2b3f4f0 \ - --hash=sha256:bc94be7472b9f88d7441340534a3ecae05c86ccfec7ba75ce5b6e4778b2bfc6e \ - --hash=sha256:c006fe73f851cf20b9986b3b4cc15239795bd5da9c3fda76bb3e043da5bec4ff \ - --hash=sha256:c6c0d640bad721834a737e25267fb71d296684ada21ca7d5ad2e63da7b73f1b7 \ - --hash=sha256:c9d4d2cc4b076c8ad0175a15ee9482a387b3303c97d4b71062db7356b2ac04c7 \ - --hash=sha256:c9fbe9dc6ee8bfe1af34137e3add6f0e49799dd5467dd6af189d27616879161e \ - --hash=sha256:d10be62bee117f05b1ad75a6c2538ca9e5367342dc8a4f3c206c87dadbc1189c \ - --hash=sha256:d29e446cfb0a82d3df7745968b9fa286665a9be8b4d68de46bcc32d917cb218e \ - --hash=sha256:d97cb22ad380850754fa16ef8d490d9340d8573d81f73429f3975e8e87db0586 \ - --hash=sha256:ddab47748933ac9cf5f29d6e9e2e2060cff40b2751d02c55129661ea4e577152 \ - --hash=sha256:e24bb6a8be89ccc3ce8c47e8940fdfcb7429e9efbf65ce6fa3e7d122fcf0bcf0 \ - --hash=sha256:e300eaf5e0329ad31b3d53e2f3d26b4b6dff1217207c6ab1d4212967b54b2185 \ - --hash=sha256:e38176a559edde0cfff4b663791a007a5f9f90c73aee1d6f7ddbcf6bfb7287b3 \ - --hash=sha256:e7dddf5f41395c84fc59e0ed5493b24bfeb39fb04823e880b52c8c55085d4695 \ - --hash=sha256:ea501ea07e14ba6364ff2621bfc8b2381e5b1e10353927fa9a607057fd2b98e5 \ - --hash=sha256:ead4d89eade0e09b8ef97877664abb0e2e8704787db5564f83658fdee5c36497 \ - --hash=sha256:ed0c090f00c3fc024f7b0799cab9dd7c419fcd8f1a00634d1f9952bab7e7bfb2 \ - --hash=sha256:f1e2d4ce72e06e38a16da3e9c24a0520dbc19018a69ef6ed57b6b38527cb275c \ - --hash=sha256:f4cb417d380e2d77961eecec75aaaf6f7ab14e6de26eb3a498f498029a6556a1 \ - --hash=sha256:f7cc02d8e9a612174869f4b983f159e87659096f7e2dc1fe9effd9902e408739 \ - --hash=sha256:f86f4f4a57a29ef08fa70c4667d04c5e3ba513500da95586208b285437cb9592 \ - --hash=sha256:fa9de2f87be58f714a230bd1f3ef3aad1ed65c9931146e3fc55f85fcbe6bacc3 \ - --hash=sha256:fcb7c36ba8b663a5900e6d40533f0e698ba0f38f744aad5410d4e38129e41a70 \ - --hash=sha256:fe78dec8caeda1e7b353cbd8aa0cc5a5bc182b22998d64ec8fa9ee59c898ab3b +yarl==1.11.1 \ + --hash=sha256:01a8697ec24f17c349c4f655763c4db70eebc56a5f82995e5e26e837c6eb0e49 \ + --hash=sha256:02da8759b47d964f9173c8675710720b468aa1c1693be0c9c64abb9d8d9a4867 \ + --hash=sha256:04293941646647b3bfb1719d1d11ff1028e9c30199509a844da3c0f5919dc520 \ + --hash=sha256:067b961853c8e62725ff2893226fef3d0da060656a9827f3f520fb1d19b2b68a \ + --hash=sha256:077da604852be488c9a05a524068cdae1e972b7dc02438161c32420fb4ec5e14 \ + --hash=sha256:09696438cb43ea6f9492ef237761b043f9179f455f405279e609f2bc9100212a \ + --hash=sha256:0b8486f322d8f6a38539136a22c55f94d269addb24db5cb6f61adc61eabc9d93 \ + --hash=sha256:0ea9682124fc062e3d931c6911934a678cb28453f957ddccf51f568c2f2b5e05 \ + --hash=sha256:0f351fa31234699d6084ff98283cb1e852270fe9e250a3b3bf7804eb493bd937 \ + --hash=sha256:14438dfc5015661f75f85bc5adad0743678eefee266ff0c9a8e32969d5d69f74 \ + --hash=sha256:15061ce6584ece023457fb8b7a7a69ec40bf7114d781a8c4f5dcd68e28b5c53b \ + --hash=sha256:15439f3c5c72686b6c3ff235279630d08936ace67d0fe5c8d5bbc3ef06f5a420 \ + --hash=sha256:17b5a386d0d36fb828e2fb3ef08c8829c1ebf977eef88e5367d1c8c94b454639 \ + --hash=sha256:18ac56c9dd70941ecad42b5a906820824ca72ff84ad6fa18db33c2537ae2e089 \ + --hash=sha256:1bb2d9e212fb7449b8fb73bc461b51eaa17cc8430b4a87d87be7b25052d92f53 \ + --hash=sha256:1e969fa4c1e0b1a391f3fcbcb9ec31e84440253325b534519be0d28f4b6b533e \ + --hash=sha256:1fa2e7a406fbd45b61b4433e3aa254a2c3e14c4b3186f6e952d08a730807fa0c \ + --hash=sha256:2164cd9725092761fed26f299e3f276bb4b537ca58e6ff6b252eae9631b5c96e \ + --hash=sha256:21a7c12321436b066c11ec19c7e3cb9aec18884fe0d5b25d03d756a9e654edfe \ + --hash=sha256:238a21849dd7554cb4d25a14ffbfa0ef380bb7ba201f45b144a14454a72ffa5a \ + --hash=sha256:250e888fa62d73e721f3041e3a9abf427788a1934b426b45e1b92f62c1f68366 \ + --hash=sha256:25861303e0be76b60fddc1250ec5986c42f0a5c0c50ff57cc30b1be199c00e63 \ + --hash=sha256:267b24f891e74eccbdff42241c5fb4f974de2d6271dcc7d7e0c9ae1079a560d9 \ + --hash=sha256:27fcb271a41b746bd0e2a92182df507e1c204759f460ff784ca614e12dd85145 \ + --hash=sha256:2909fa3a7d249ef64eeb2faa04b7957e34fefb6ec9966506312349ed8a7e77bf \ + --hash=sha256:3257978c870728a52dcce8c2902bf01f6c53b65094b457bf87b2644ee6238ddc \ + --hash=sha256:327c724b01b8641a1bf1ab3b232fb638706e50f76c0b5bf16051ab65c868fac5 \ + --hash=sha256:3de5292f9f0ee285e6bd168b2a77b2a00d74cbcfa420ed078456d3023d2f6dff \ + --hash=sha256:3fce4da3703ee6048ad4138fe74619c50874afe98b1ad87b2698ef95bf92c96d \ + --hash=sha256:3ff6b1617aa39279fe18a76c8d165469c48b159931d9b48239065767ee455b2b \ + --hash=sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00 \ + --hash=sha256:4179522dc0305c3fc9782549175c8e8849252fefeb077c92a73889ccbcd508ad \ + --hash=sha256:4307d9a3417eea87715c9736d050c83e8c1904e9b7aada6ce61b46361b733d92 \ + --hash=sha256:476e20c433b356e16e9a141449f25161e6b69984fb4cdbd7cd4bd54c17844998 \ + --hash=sha256:489fa8bde4f1244ad6c5f6d11bb33e09cf0d1d0367edb197619c3e3fc06f3d91 \ + --hash=sha256:48a28bed68ab8fb7e380775f0029a079f08a17799cb3387a65d14ace16c12e2b \ + --hash=sha256:48dfd117ab93f0129084577a07287376cc69c08138694396f305636e229caa1a \ + --hash=sha256:4973eac1e2ff63cf187073cd4e1f1148dcd119314ab79b88e1b3fad74a18c9d5 \ + --hash=sha256:498442e3af2a860a663baa14fbf23fb04b0dd758039c0e7c8f91cb9279799bff \ + --hash=sha256:501c503eed2bb306638ccb60c174f856cc3246c861829ff40eaa80e2f0330367 \ + --hash=sha256:504cf0d4c5e4579a51261d6091267f9fd997ef58558c4ffa7a3e1460bd2336fa \ + --hash=sha256:61a5f2c14d0a1adfdd82258f756b23a550c13ba4c86c84106be4c111a3a4e413 \ + --hash=sha256:637c7ddb585a62d4469f843dac221f23eec3cbad31693b23abbc2c366ad41ff4 \ + --hash=sha256:66b63c504d2ca43bf7221a1f72fbe981ff56ecb39004c70a94485d13e37ebf45 \ + --hash=sha256:67459cf8cf31da0e2cbdb4b040507e535d25cfbb1604ca76396a3a66b8ba37a6 \ + --hash=sha256:688654f8507464745ab563b041d1fb7dab5d9912ca6b06e61d1c4708366832f5 \ + --hash=sha256:6907daa4b9d7a688063ed098c472f96e8181733c525e03e866fb5db480a424df \ + --hash=sha256:69721b8effdb588cb055cc22f7c5105ca6fdaa5aeb3ea09021d517882c4a904c \ + --hash=sha256:6d23754b9939cbab02c63434776df1170e43b09c6a517585c7ce2b3d449b7318 \ + --hash=sha256:7175a87ab8f7fbde37160a15e58e138ba3b2b0e05492d7351314a250d61b1591 \ + --hash=sha256:72bf26f66456baa0584eff63e44545c9f0eaed9b73cb6601b647c91f14c11f38 \ + --hash=sha256:74db2ef03b442276d25951749a803ddb6e270d02dda1d1c556f6ae595a0d76a8 \ + --hash=sha256:750f656832d7d3cb0c76be137ee79405cc17e792f31e0a01eee390e383b2936e \ + --hash=sha256:75e0ae31fb5ccab6eda09ba1494e87eb226dcbd2372dae96b87800e1dcc98804 \ + --hash=sha256:768ecc550096b028754ea28bf90fde071c379c62c43afa574edc6f33ee5daaec \ + --hash=sha256:7d51324a04fc4b0e097ff8a153e9276c2593106a811704025bbc1d6916f45ca6 \ + --hash=sha256:7e975a2211952a8a083d1b9d9ba26472981ae338e720b419eb50535de3c02870 \ + --hash=sha256:8215f6f21394d1f46e222abeb06316e77ef328d628f593502d8fc2a9117bde83 \ + --hash=sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d \ + --hash=sha256:8418c053aeb236b20b0ab8fa6bacfc2feaaf7d4683dd96528610989c99723d5f \ + --hash=sha256:87f020d010ba80a247c4abc335fc13421037800ca20b42af5ae40e5fd75e7909 \ + --hash=sha256:884eab2ce97cbaf89f264372eae58388862c33c4f551c15680dd80f53c89a269 \ + --hash=sha256:8a336eaa7ee7e87cdece3cedb395c9657d227bfceb6781295cf56abcd3386a26 \ + --hash=sha256:8aef1b64da41d18026632d99a06b3fefe1d08e85dd81d849fa7c96301ed22f1b \ + --hash=sha256:8aef97ba1dd2138112890ef848e17d8526fe80b21f743b4ee65947ea184f07a2 \ + --hash=sha256:8ed653638ef669e0efc6fe2acb792275cb419bf9cb5c5049399f3556995f23c7 \ + --hash=sha256:9361628f28f48dcf8b2f528420d4d68102f593f9c2e592bfc842f5fb337e44fd \ + --hash=sha256:946eedc12895873891aaceb39bceb484b4977f70373e0122da483f6c38faaa68 \ + --hash=sha256:94d0caaa912bfcdc702a4204cd5e2bb01eb917fc4f5ea2315aa23962549561b0 \ + --hash=sha256:964a428132227edff96d6f3cf261573cb0f1a60c9a764ce28cda9525f18f7786 \ + --hash=sha256:999bfee0a5b7385a0af5ffb606393509cfde70ecca4f01c36985be6d33e336da \ + --hash=sha256:a08ea567c16f140af8ddc7cb58e27e9138a1386e3e6e53982abaa6f2377b38cc \ + --hash=sha256:a28b70c9e2213de425d9cba5ab2e7f7a1c8ca23a99c4b5159bf77b9c31251447 \ + --hash=sha256:a34e1e30f1774fa35d37202bbeae62423e9a79d78d0874e5556a593479fdf239 \ + --hash=sha256:a4264515f9117be204935cd230fb2a052dd3792789cc94c101c535d349b3dab0 \ + --hash=sha256:a7915ea49b0c113641dc4d9338efa9bd66b6a9a485ffe75b9907e8573ca94b84 \ + --hash=sha256:aac44097d838dda26526cffb63bdd8737a2dbdf5f2c68efb72ad83aec6673c7e \ + --hash=sha256:b91044952da03b6f95fdba398d7993dd983b64d3c31c358a4c89e3c19b6f7aef \ + --hash=sha256:ba444bdd4caa2a94456ef67a2f383710928820dd0117aae6650a4d17029fa25e \ + --hash=sha256:c2dc4250fe94d8cd864d66018f8344d4af50e3758e9d725e94fecfa27588ff82 \ + --hash=sha256:c35f493b867912f6fda721a59cc7c4766d382040bdf1ddaeeaa7fa4d072f4675 \ + --hash=sha256:c92261eb2ad367629dc437536463dc934030c9e7caca861cc51990fe6c565f26 \ + --hash=sha256:ce928c9c6409c79e10f39604a7e214b3cb69552952fbda8d836c052832e6a979 \ + --hash=sha256:d95b52fbef190ca87d8c42f49e314eace4fc52070f3dfa5f87a6594b0c1c6e46 \ + --hash=sha256:dae7bd0daeb33aa3e79e72877d3d51052e8b19c9025ecf0374f542ea8ec120e4 \ + --hash=sha256:e286580b6511aac7c3268a78cdb861ec739d3e5a2a53b4809faef6b49778eaff \ + --hash=sha256:e4b53f73077e839b3f89c992223f15b1d2ab314bdbdf502afdc7bb18e95eae27 \ + --hash=sha256:e8f63904df26d1a66aabc141bfd258bf738b9bc7bc6bdef22713b4f5ef789a4c \ + --hash=sha256:f3a6d90cab0bdf07df8f176eae3a07127daafcf7457b997b2bf46776da2c7eb7 \ + --hash=sha256:f41fa79114a1d2eddb5eea7b912d6160508f57440bd302ce96eaa384914cd265 \ + --hash=sha256:f46f81501160c28d0c0b7333b4f7be8983dbbc161983b6fb814024d1b4952f79 \ + --hash=sha256:f61db3b7e870914dbd9434b560075e0366771eecbe6d2b5561f5bc7485f39efd # via # -r requirements.in # aiohttp From 9bfbd600b98538e7dc7371153fcfe9975da49164 Mon Sep 17 00:00:00 2001 From: "Antonio V. Leonti" <53806445+antoniovleonti@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:22:16 -0400 Subject: [PATCH 10/21] ext_proc: elide redundant copy in ext_proc filter factory callback (#36015) Commit Message: elide redundant copy in ext_proc filter factory callback Additional Description: the shared ptr is not needed in the function that created it after creating the callback. Just move the shared ptr into the callback to avoid the reference count being incremented then immediately decremented. Risk Level: low Testing: - Docs Changes: - Release Notes: - Platform Specific Features: - Signed-off-by: antoniovleonti --- source/extensions/filters/http/ext_proc/config.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/extensions/filters/http/ext_proc/config.cc b/source/extensions/filters/http/ext_proc/config.cc index bd184557e191..134fa8d190b2 100644 --- a/source/extensions/filters/http/ext_proc/config.cc +++ b/source/extensions/filters/http/ext_proc/config.cc @@ -23,8 +23,8 @@ ExternalProcessingFilterConfig::createFilterFactoryFromProtoTyped( dual_info.scope, stats_prefix, dual_info.is_upstream, Envoy::Extensions::Filters::Common::Expr::getBuilder(context), context); - return [filter_config, grpc_service = proto_config.grpc_service(), &context, - dual_info](Http::FilterChainFactoryCallbacks& callbacks) { + return [filter_config = std::move(filter_config), grpc_service = proto_config.grpc_service(), + &context, dual_info](Http::FilterChainFactoryCallbacks& callbacks) { auto client = std::make_unique( context.clusterManager().grpcAsyncClientManager(), dual_info.scope); @@ -54,7 +54,7 @@ ExternalProcessingFilterConfig::createFilterFactoryFromProtoWithServerContextTyp server_context.scope(), stats_prefix, false, Envoy::Extensions::Filters::Common::Expr::getBuilder(server_context), server_context); - return [filter_config, grpc_service = proto_config.grpc_service(), + return [filter_config = std::move(filter_config), grpc_service = proto_config.grpc_service(), &server_context](Http::FilterChainFactoryCallbacks& callbacks) { auto client = std::make_unique( server_context.clusterManager().grpcAsyncClientManager(), server_context.scope()); From b3a107fd108537d9f96e16c286c6fbf3ccf9e231 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 10 Sep 2024 15:42:36 +0100 Subject: [PATCH 11/21] docs: Add `apt.envoyproxy.io` install information (#36050) Signed-off-by: Ryan Northey --- docs/root/start/install.rst | 86 ++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/docs/root/start/install.rst b/docs/root/start/install.rst index a04b04ff2c22..88a621a86fd1 100644 --- a/docs/root/start/install.rst +++ b/docs/root/start/install.rst @@ -10,54 +10,44 @@ If you are :ref:`installing on Mac OSX `, you can install Once you have installed Envoy, check out the :ref:`quick start ` guide for more information on getting your Envoy proxy up and running. -Install Envoy on Debian GNU/Linux -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can `install Envoy on Debian using packages created by Tetrate `_ -until `official packages exist `_. - -.. code-block:: console - - $ sudo apt update - $ sudo apt install debian-keyring debian-archive-keyring apt-transport-https curl lsb-release - $ curl -sL 'https://deb.dl.getenvoy.io/public/gpg.8115BA8E629CC074.key' | sudo gpg --dearmor -o /usr/share/keyrings/getenvoy-keyring.gpg - # Verify the keyring - this should yield "OK" - $ echo a077cb587a1b622e03aa4bf2f3689de14658a9497a9af2c427bba5f4cc3c4723 /usr/share/keyrings/getenvoy-keyring.gpg | sha256sum --check - $ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/getenvoy-keyring.gpg] https://deb.dl.getenvoy.io/public/deb/debian $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/getenvoy.list - $ sudo apt update - $ sudo apt install getenvoy-envoy - -Install Envoy on Ubuntu Linux -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can `install Envoy on Ubuntu using packages created by Tetrate `_ -until `official packages exist `_. - -.. code-block:: console - - $ sudo apt update - $ sudo apt install apt-transport-https gnupg2 curl lsb-release - $ curl -sL 'https://deb.dl.getenvoy.io/public/gpg.8115BA8E629CC074.key' | sudo gpg --dearmor -o /usr/share/keyrings/getenvoy-keyring.gpg - # Verify the keyring - this should yield "OK" - $ echo a077cb587a1b622e03aa4bf2f3689de14658a9497a9af2c427bba5f4cc3c4723 /usr/share/keyrings/getenvoy-keyring.gpg | sha256sum --check - $ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/getenvoy-keyring.gpg] https://deb.dl.getenvoy.io/public/deb/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/getenvoy.list - $ sudo apt update - $ sudo apt install -y getenvoy-envoy - -Install Envoy on RPM-based distros -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can install Envoy on Centos/Redhat Enterprise Linux (RHEL) using `packages created by Tetrate `_ -until `official packages exist `_. - -.. code-block:: console - - $ sudo yum install yum-utils - $ sudo rpm --import 'https://rpm.dl.getenvoy.io/public/gpg.CF716AF503183491.key' - $ curl -sL 'https://rpm.dl.getenvoy.io/public/config.rpm.txt?distro=el&codename=7' > /tmp/tetrate-getenvoy-rpm-stable.repo - $ sudo yum-config-manager --add-repo '/tmp/tetrate-getenvoy-rpm-stable.repo' - $ sudo yum makecache --disablerepo='*' --enablerepo='tetrate-getenvoy-rpm-stable' - $ sudo yum install getenvoy-envoy +Install Envoy on Debian-based Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + If you are using a different deb-based distribution to the ones shown below, you may still be able to use one of them. + +.. tabs:: + + .. code-tab:: console Debian bookworm + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bookworm main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version + + .. code-tab:: console Debian bullseye + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io bullseye main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version + + .. code-tab:: console Ubuntu focal + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io focal main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version + + .. code-tab:: console Ubuntu jammy + + $ wget https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg + $ echo "deb[signed-by=/etc/apt/keyrings/envoy-keyring.gpg] https://apt.envoyproxy.io jammy main" | sudo tee /etc/apt/sources.list.d/envoy.list + $ sudo apt-get update + $ sudo apt-get install envoy + $ envoy --version .. _start_install_macosx: From 2acf901aecc6ba984d8dc6621a47832b83b98219 Mon Sep 17 00:00:00 2001 From: code Date: Tue, 10 Sep 2024 22:49:13 +0800 Subject: [PATCH 12/21] json: make the streamer a template class (#36001) Commit Message: json: make the streamer a template class Additional Description: This PR make Streamer a template to accept different types of output (Buffer::Instance, std::string, etc.) Risk Level: low. Testing: unit. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping Signed-off-by: wangbaiping --- source/common/buffer/BUILD | 1 - source/common/buffer/buffer_util.cc | 45 ---------- source/common/buffer/buffer_util.h | 38 ++++++++- source/common/json/json_streamer.h | 74 +++++++++++------ test/common/json/json_streamer_test.cc | 110 ++++++++++++++----------- 5 files changed, 148 insertions(+), 120 deletions(-) delete mode 100644 source/common/buffer/buffer_util.cc diff --git a/source/common/buffer/BUILD b/source/common/buffer/BUILD index 0545b3b1558d..8236df805fdb 100644 --- a/source/common/buffer/BUILD +++ b/source/common/buffer/BUILD @@ -46,7 +46,6 @@ envoy_cc_library( envoy_cc_library( name = "buffer_util_lib", - srcs = ["buffer_util.cc"], hdrs = ["buffer_util.h"], deps = [ "//envoy/buffer:buffer_interface", diff --git a/source/common/buffer/buffer_util.cc b/source/common/buffer/buffer_util.cc deleted file mode 100644 index 849549714527..000000000000 --- a/source/common/buffer/buffer_util.cc +++ /dev/null @@ -1,45 +0,0 @@ -#include "source/common/buffer/buffer_util.h" - -#include -#include - -#include "source/common/common/macros.h" - -namespace Envoy { -namespace Buffer { - -void Util::serializeDouble(double number, Buffer::Instance& buffer) { - // Converting a double to a string: who would think it would be so complex? - // It's easy if you don't care about speed or accuracy :). Here we are measuring - // the speed with test/server/admin/stats_handler_speed_test --benchmark_filter=BM_HistogramsJson - // Here are some options: - // * absl::StrCat(number) -- fast (19ms on speed test) but loses precision (drops decimals). - // * absl::StrFormat("%.15g") -- works great but a bit slow (24ms on speed test) - // * `snprintf`(buf, sizeof(buf), "%.15g", ...) -- works but slow as molasses: 30ms. - // * fmt::format("{}") -- works great and is a little faster than absl::StrFormat: 21ms. - // * fmt::to_string -- works great and is a little faster than fmt::format: 19ms. - // * std::to_chars -- fast (16ms) and precise, but requires a few lines to - // generate the string_view, and does not work on all platforms yet. - // - // The accuracy is checked in buffer_util_test. -#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 14000 - // This version is awkward, and doesn't work on all platforms used in Envoy CI - // as of August 2023, but it is the fastest correct option on modern compilers. - char buf[100]; - std::to_chars_result result = std::to_chars(buf, buf + sizeof(buf), number); - ENVOY_BUG(result.ec == std::errc{}, std::make_error_code(result.ec).message()); - buffer.addFragments({absl::string_view(buf, result.ptr - buf)}); - - // Note: there is room to speed this up further by serializing the number directly - // into the buffer. However, buffer does not currently make it easy and fast - // to get (say) 100 characters of raw buffer to serialize into. -#else - // On older compilers, such as those found on Apple, and gcc, std::to_chars - // does not work with 'double', so we revert to the next fastest correct - // implementation. - buffer.addFragments({fmt::to_string(number)}); -#endif -} - -} // namespace Buffer -} // namespace Envoy diff --git a/source/common/buffer/buffer_util.h b/source/common/buffer/buffer_util.h index 9e8227fa1238..7a8e3aef3c07 100644 --- a/source/common/buffer/buffer_util.h +++ b/source/common/buffer/buffer_util.h @@ -1,7 +1,12 @@ #pragma once +#include +#include + #include "envoy/buffer/buffer.h" +#include "source/common/common/macros.h" + namespace Envoy { namespace Buffer { @@ -20,7 +25,38 @@ class Util { * @param number the number to convert. * @param buffer the buffer in which to write the double. */ - static void serializeDouble(double number, Buffer::Instance& buffer); + template static void serializeDouble(double number, Output& buffer) { + // Converting a double to a string: who would think it would be so complex? + // It's easy if you don't care about speed or accuracy :). Here we are measuring + // the speed with test/server/admin/stats_handler_speed_test + // --benchmark_filter=BM_HistogramsJson Here are some options: + // * absl::StrCat(number) -- fast (19ms on speed test) but loses precision (drops decimals). + // * absl::StrFormat("%.15g") -- works great but a bit slow (24ms on speed test) + // * `snprintf`(buf, sizeof(buf), "%.15g", ...) -- works but slow as molasses: 30ms. + // * fmt::format("{}") -- works great and is a little faster than absl::StrFormat: 21ms. + // * fmt::to_string -- works great and is a little faster than fmt::format: 19ms. + // * std::to_chars -- fast (16ms) and precise, but requires a few lines to + // generate the string_view, and does not work on all platforms yet. + // + // The accuracy is checked in buffer_util_test. +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 14000 + // This version is awkward, and doesn't work on all platforms used in Envoy CI + // as of August 2023, but it is the fastest correct option on modern compilers. + char buf[100]; + std::to_chars_result result = std::to_chars(buf, buf + sizeof(buf), number); + ENVOY_BUG(result.ec == std::errc{}, std::make_error_code(result.ec).message()); + buffer.add(absl::string_view(buf, result.ptr - buf)); + + // Note: there is room to speed this up further by serializing the number directly + // into the buffer. However, buffer does not currently make it easy and fast + // to get (say) 100 characters of raw buffer to serialize into. +#else + // On older compilers, such as those found on Apple, and gcc, std::to_chars + // does not work with 'double', so we revert to the next fastest correct + // implementation. + buffer.add(fmt::to_string(number)); +#endif + } }; } // namespace Buffer diff --git a/source/common/json/json_streamer.h b/source/common/json/json_streamer.h index 97d7ef424d54..8087cbf4ada6 100644 --- a/source/common/json/json_streamer.h +++ b/source/common/json/json_streamer.h @@ -39,7 +39,9 @@ namespace Json { #define ASSERT_LEVELS_EMPTY ASSERT(this->levels_.empty()) #endif -// Simple abstraction that provide a output buffer for streaming JSON output. +// Buffer wrapper that implements the necessary abstraction for the template +// StreamerBase. +// This could be used to stream JSON output of StreamerBase to a Buffer. class BufferOutput { public: void add(absl::string_view a) { buffer_.addFragments({a}); } @@ -51,24 +53,41 @@ class BufferOutput { Buffer::Instance& buffer_; }; +// String wrapper that implements the necessary abstraction for the template +// StreamerBase. +// This could be used to stream JSON output of StreamerBase to a single string. +class StringOutput { +public: + void add(absl::string_view a) { buffer_.append(a); } + void add(absl::string_view a, absl::string_view b, absl::string_view c) { + absl::StrAppend(&buffer_, a, b, c); + } + explicit StringOutput(std::string& output) : buffer_(output) {} + + std::string& buffer_; +}; + /** * Provides an API for streaming JSON output, as an alternative to populating a * JSON structure with an image of what you want to serialize, or using a * protobuf with reflection. The advantage of this approach is that it does not * require building an intermediate data structure with redundant copies of all * strings, maps, and arrays. + * + * NOTE: This template take a type that can be used to stream output. This is either + * BufferOutput, StringOutput or any other types that have implemented + * add(absl::string_view) and + * add(absl::string_view, absl::string_view, absl::string_view) methods. */ -class Streamer { +template class StreamerBase { public: using Value = absl::variant; /** - * @param response The buffer in which to stream output. Note: this buffer can - * be flushed during population; it is not necessary to hold - * the entire json structure in memory before streaming it to - * the network. + * @param response The buffer in which to stream output. + * NOTE: The response must could be used to construct instance of OutputBufferType. */ - explicit Streamer(Buffer::Instance& response) : response_(response) {} + template explicit StreamerBase(T& response) : response_(response) {} class Array; using ArrayPtr = std::unique_ptr; @@ -81,15 +100,15 @@ class Streamer { */ class Level { public: - Level(Streamer& streamer, absl::string_view opener, absl::string_view closer) + Level(StreamerBase& streamer, absl::string_view opener, absl::string_view closer) : streamer_(streamer), closer_(closer) { - streamer_.addConstantString(opener); + streamer_.addWithoutSanitizing(opener); #ifndef NDEBUG streamer_.push(this); #endif } virtual ~Level() { - streamer_.addConstantString(closer_); + streamer_.addWithoutSanitizing(closer_); #ifndef NDEBUG streamer_.pop(this); #endif @@ -180,7 +199,7 @@ class Streamer { if (is_first_) { is_first_ = false; } else { - streamer_.addConstantString(","); + streamer_.addWithoutSanitizing(","); } } @@ -223,11 +242,9 @@ class Streamer { } } - private: - friend Streamer; - + protected: bool is_first_{true}; // Used to control whether a comma-separator is added for a new entry. - Streamer& streamer_; + StreamerBase& streamer_; absl::string_view closer_; }; using LevelPtr = std::unique_ptr; @@ -241,7 +258,7 @@ class Streamer { using NameValue = std::pair; using Entries = absl::Span; - Map(Streamer& streamer) : Level(streamer, "{", "}") {} + Map(StreamerBase& streamer) : Level(streamer, "{", "}") {} /** * Initiates a new map key. This must be followed by rendering a value, @@ -292,7 +309,7 @@ class Streamer { */ class Array : public Level { public: - Array(Streamer& streamer) : Level(streamer, "[", "]") {} + Array(StreamerBase& streamer) : Level(streamer, "[", "]") {} using Entries = absl::Span; /** @@ -333,11 +350,6 @@ class Streamer { return std::make_unique(*this); } -private: - friend Level; - friend Map; - friend Array; - /** * Takes a raw string, sanitizes it using JSON syntax, surrounds it * with a prefix and suffix, and streams it out. @@ -361,7 +373,7 @@ class Streamer { if (std::isnan(d)) { response_.add(Constants::Null); } else { - Buffer::Util::serializeDouble(d, response_.buffer_); + Buffer::Util::serializeDouble(d, response_); } } void addNumber(uint64_t u) { response_.add(absl::StrCat(u)); } @@ -373,11 +385,14 @@ class Streamer { void addBool(bool b) { response_.add(b ? Constants::True : Constants::False); } /** - * Adds a constant string to the output stream. The string must outlive the - * Streamer object, and is intended for literal strings such as punctuation. + * Adds a pre-sanitized string or which doesn't require sanitizing to the output stream. + * NOTE: use this with care as it bypasses the sanitization process and may result in + * invalid JSON. If you are not sure if the string is already sanitized, use addString() + * or addSanitized() instead. */ - void addConstantString(absl::string_view str) { response_.add(str); } + void addWithoutSanitizing(absl::string_view str) { response_.add(str); } +private: #ifndef NDEBUG /** * @return the top Level*. This is used for asserts. @@ -399,7 +414,7 @@ class Streamer { #endif - BufferOutput response_; + OutputBufferType response_; std::string sanitize_buffer_; #ifndef NDEBUG @@ -409,5 +424,10 @@ class Streamer { #endif }; +/** + * A Streamer that streams to a Buffer::Instance. + */ +using Streamer = StreamerBase; + } // namespace Json } // namespace Envoy diff --git a/test/common/json/json_streamer_test.cc b/test/common/json/json_streamer_test.cc index 231fc33d1ba7..0e332c0ccd8f 100644 --- a/test/common/json/json_streamer_test.cc +++ b/test/common/json/json_streamer_test.cc @@ -11,124 +11,142 @@ namespace Envoy { namespace Json { namespace { -class JsonStreamerTest : public testing::Test { -protected: - Buffer::OwnedImpl buffer_; - Json::Streamer streamer_{buffer_}; +class BufferOutputWrapper { +public: + using Type = BufferOutput; + std::string toString() { return underlying_buffer_.toString(); } + Buffer::OwnedImpl underlying_buffer_; }; -TEST_F(JsonStreamerTest, Empty) { EXPECT_EQ("", buffer_.toString()); } +class StringOutputWrapper { +public: + using Type = StringOutput; + std::string toString() { return underlying_buffer_; } + std::string underlying_buffer_; +}; + +template class JsonStreamerTest : public testing::Test { +public: + T buffer_; + Json::StreamerBase streamer_{this->buffer_.underlying_buffer_}; +}; + +using OutputBufferTypes = ::testing::Types; +TYPED_TEST_SUITE(JsonStreamerTest, OutputBufferTypes); + +TYPED_TEST(JsonStreamerTest, Empty) { EXPECT_EQ("", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, EmptyMap) { - streamer_.makeRootMap(); - EXPECT_EQ("{}", buffer_.toString()); +TYPED_TEST(JsonStreamerTest, EmptyMap) { + this->streamer_.makeRootMap(); + EXPECT_EQ("{}", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneDouble) { +TYPED_TEST(JsonStreamerTest, MapOneDouble) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", 3.141592654}}); } - EXPECT_EQ(R"EOF({"a":3.141592654})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":3.141592654})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoDoubles) { +TYPED_TEST(JsonStreamerTest, MapTwoDoubles) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", -989282.1087}, {"b", 1.23456789012345e+67}}); } - EXPECT_EQ(R"EOF({"a":-989282.1087,"b":1.23456789012345e+67})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":-989282.1087,"b":1.23456789012345e+67})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneUInt) { +TYPED_TEST(JsonStreamerTest, MapOneUInt) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", static_cast(0xffffffffffffffff)}}); } - EXPECT_EQ(R"EOF({"a":18446744073709551615})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":18446744073709551615})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoInts) { +TYPED_TEST(JsonStreamerTest, MapTwoInts) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", static_cast(0x7fffffffffffffff)}, {"b", static_cast(0x8000000000000000)}}); } - EXPECT_EQ(R"EOF({"a":9223372036854775807,"b":-9223372036854775808})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":9223372036854775807,"b":-9223372036854775808})EOF", + this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneString) { +TYPED_TEST(JsonStreamerTest, MapOneString) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", "b"}}); } - EXPECT_EQ(R"EOF({"a":"b"})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":"b"})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneBool) { +TYPED_TEST(JsonStreamerTest, MapOneBool) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", true}}); } - EXPECT_EQ(R"EOF({"a":true})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":true})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoBools) { +TYPED_TEST(JsonStreamerTest, MapTwoBools) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addEntries({{"a", true}, {"b", false}}); } - EXPECT_EQ(R"EOF({"a":true,"b":false})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":true,"b":false})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapOneSanitized) { +TYPED_TEST(JsonStreamerTest, MapOneSanitized) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addKey("a"); map->addString("\b\001"); } - EXPECT_EQ(R"EOF({"a":"\b\u0001"})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":"\b\u0001"})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, MapTwoSanitized) { +TYPED_TEST(JsonStreamerTest, MapTwoSanitized) { { - Streamer::MapPtr map = streamer_.makeRootMap(); + auto map = this->streamer_.makeRootMap(); map->addKey("a"); map->addString("\b\001"); map->addKey("b"); map->addString("\r\002"); } - EXPECT_EQ(R"EOF({"a":"\b\u0001","b":"\r\u0002"})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":"\b\u0001","b":"\r\u0002"})EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, SubArray) { - Streamer::MapPtr map = streamer_.makeRootMap(); +TYPED_TEST(JsonStreamerTest, SubArray) { + auto map = this->streamer_.makeRootMap(); map->addKey("a"); - Streamer::ArrayPtr array = map->addArray(); + auto array = map->addArray(); array->addEntries({1.0, "two", 3.5, true, false, std::nan("")}); array.reset(); map->addEntries({{"embedded\"quote", "value"}}); map.reset(); EXPECT_EQ(R"EOF({"a":[1,"two",3.5,true,false,null],"embedded\"quote":"value"})EOF", - buffer_.toString()); + this->buffer_.toString()); } -TEST_F(JsonStreamerTest, TopArray) { +TYPED_TEST(JsonStreamerTest, TopArray) { { - Streamer::ArrayPtr array = streamer_.makeRootArray(); + auto array = this->streamer_.makeRootArray(); array->addEntries({1.0, "two", 3.5, true, false, std::nan("")}); } - EXPECT_EQ(R"EOF([1,"two",3.5,true,false,null])EOF", buffer_.toString()); + EXPECT_EQ(R"EOF([1,"two",3.5,true,false,null])EOF", this->buffer_.toString()); } -TEST_F(JsonStreamerTest, SubMap) { - Streamer::MapPtr map = streamer_.makeRootMap(); +TYPED_TEST(JsonStreamerTest, SubMap) { + auto map = this->streamer_.makeRootMap(); map->addKey("a"); - Streamer::MapPtr sub_map = map->addMap(); + auto sub_map = map->addMap(); sub_map->addEntries({{"one", 1.0}, {"three.5", 3.5}}); sub_map.reset(); map.reset(); - EXPECT_EQ(R"EOF({"a":{"one":1,"three.5":3.5}})EOF", buffer_.toString()); + EXPECT_EQ(R"EOF({"a":{"one":1,"three.5":3.5}})EOF", this->buffer_.toString()); } } // namespace From 3f0517bf5203b3d6b381523392e744c67cf7a602 Mon Sep 17 00:00:00 2001 From: code Date: Wed, 11 Sep 2024 00:55:47 +0800 Subject: [PATCH 13/21] json: add null support to the streamer (#36051) Commit Message: json: add null support to the streamer Additional Description: I initially think this is unnecessary. But when I retry to update the json formatter, I found this is still necessary. Risk Level: low. Testing: unit. Docs Changes: n/a. Release Notes: n/a. Platform Specific Features: n/a. --------- Signed-off-by: wangbaiping Signed-off-by: wangbaiping --- source/common/json/json_streamer.h | 44 ++++++++++++++++++------- test/common/json/json_streamer_test.cc | 45 ++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/source/common/json/json_streamer.h b/source/common/json/json_streamer.h index 8087cbf4ada6..ae18b7a38699 100644 --- a/source/common/json/json_streamer.h +++ b/source/common/json/json_streamer.h @@ -81,7 +81,7 @@ class StringOutput { */ template class StreamerBase { public: - using Value = absl::variant; + using Value = absl::variant; /** * @param response The buffer in which to stream output. @@ -190,6 +190,18 @@ template class StreamerBase { streamer_.addBool(b); } + /** + * Adds a null constant value to the current array or map. It's a programming + * error to call this method on a map or array that's not the top level. + * It's also a programming error to call this on map that isn't expecting + * a value. You must call Map::addKey prior to calling this. + */ + void addNull() { + ASSERT_THIS_IS_TOP_LEVEL; + nextField(); + streamer_.addNull(); + } + protected: /** * Initiates a new field, serializing a comma separator if this is not the @@ -211,34 +223,39 @@ template class StreamerBase { * @param Value the value to render. */ void addValue(const Value& value) { - static_assert(absl::variant_size_v == 5, "Value must be a variant with 5 types"); + static_assert(absl::variant_size_v == 6, "Value must be a variant with 6 types"); switch (value.index()) { case 0: - static_assert(std::is_same(value)), const absl::string_view&>::value, + static_assert(std::is_same_v, absl::string_view>, "value at index 0 must be an absl::string_vlew"); addString(absl::get(value)); break; case 1: - static_assert(std::is_same(value)), const double&>::value, + static_assert(std::is_same_v, double>, "value at index 1 must be a double"); addNumber(absl::get(value)); break; case 2: - static_assert(std::is_same(value)), const uint64_t&>::value, + static_assert(std::is_same_v, uint64_t>, "value at index 2 must be a uint64_t"); addNumber(absl::get(value)); break; case 3: - static_assert(std::is_same(value)), const int64_t&>::value, + static_assert(std::is_same_v, int64_t>, "value at index 3 must be an int64_t"); addNumber(absl::get(value)); break; case 4: - static_assert(std::is_same(value)), const bool&>::value, + static_assert(std::is_same_v, bool>, "value at index 4 must be a bool"); addBool(absl::get(value)); break; + case 5: + static_assert(std::is_same_v, absl::monostate>, + "value at index 5 must be an absl::monostate"); + addNull(); + break; } } @@ -385,14 +402,17 @@ template class StreamerBase { void addBool(bool b) { response_.add(b ? Constants::True : Constants::False); } /** - * Adds a pre-sanitized string or which doesn't require sanitizing to the output stream. - * NOTE: use this with care as it bypasses the sanitization process and may result in - * invalid JSON. If you are not sure if the string is already sanitized, use addString() - * or addSanitized() instead. + * Serializes a null to the output stream. */ - void addWithoutSanitizing(absl::string_view str) { response_.add(str); } + void addNull() { response_.add(Constants::Null); } private: + /** + * Adds a string to the output stream without sanitizing it. This is only used to push + * the delimiters to output buffer. + */ + void addWithoutSanitizing(absl::string_view str) { response_.add(str); } + #ifndef NDEBUG /** * @return the top Level*. This is used for asserts. diff --git a/test/common/json/json_streamer_test.cc b/test/common/json/json_streamer_test.cc index 0e332c0ccd8f..8bf9913101c2 100644 --- a/test/common/json/json_streamer_test.cc +++ b/test/common/json/json_streamer_test.cc @@ -15,6 +15,7 @@ class BufferOutputWrapper { public: using Type = BufferOutput; std::string toString() { return underlying_buffer_.toString(); } + void clear() { underlying_buffer_.drain(underlying_buffer_.length()); } Buffer::OwnedImpl underlying_buffer_; }; @@ -22,6 +23,7 @@ class StringOutputWrapper { public: using Type = StringOutput; std::string toString() { return underlying_buffer_; } + void clear() { underlying_buffer_.clear(); } std::string underlying_buffer_; }; @@ -134,9 +136,9 @@ TYPED_TEST(JsonStreamerTest, SubArray) { TYPED_TEST(JsonStreamerTest, TopArray) { { auto array = this->streamer_.makeRootArray(); - array->addEntries({1.0, "two", 3.5, true, false, std::nan("")}); + array->addEntries({1.0, "two", 3.5, true, false, std::nan(""), absl::monostate{}}); } - EXPECT_EQ(R"EOF([1,"two",3.5,true,false,null])EOF", this->buffer_.toString()); + EXPECT_EQ(R"EOF([1,"two",3.5,true,false,null,null])EOF", this->buffer_.toString()); } TYPED_TEST(JsonStreamerTest, SubMap) { @@ -149,6 +151,45 @@ TYPED_TEST(JsonStreamerTest, SubMap) { EXPECT_EQ(R"EOF({"a":{"one":1,"three.5":3.5}})EOF", this->buffer_.toString()); } +TYPED_TEST(JsonStreamerTest, SimpleDirectCall) { + { + this->streamer_.addBool(true); + EXPECT_EQ("true", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addBool(false); + EXPECT_EQ("false", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addString("hello"); + EXPECT_EQ(R"EOF("hello")EOF", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + uint64_t value = 1; + this->streamer_.addNumber(value); + EXPECT_EQ("1", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addNumber(1.5); + EXPECT_EQ("1.5", this->buffer_.toString()); + this->buffer_.clear(); + } + + { + this->streamer_.addNull(); + EXPECT_EQ("null", this->buffer_.toString()); + this->buffer_.clear(); + } +} + } // namespace } // namespace Json } // namespace Envoy From e18abd2b3988d0f8b371dc2ce467354bb6048907 Mon Sep 17 00:00:00 2001 From: birenroy Date: Tue, 10 Sep 2024 16:31:08 -0400 Subject: [PATCH 14/21] quic: removes more references to spdy::Http2HeaderBlock. (#36057) spdy::Http2HeaderBlock is just an alias for quiche::HttpHeaderBlock. Commit Message: removes more references to spdy::Http2HeaderBlock Additional Description: Risk Level: none Testing: ran unit and integration tests locally Docs Changes: Release Notes: Platform Specific Features: Signed-off-by: Biren Roy --- test/common/quic/envoy_quic_client_stream_test.cc | 10 +++++----- test/common/quic/envoy_quic_h3_fuzz_helper.cc | 6 +++--- test/common/quic/envoy_quic_server_stream_test.cc | 14 +++++++------- test/common/quic/envoy_quic_utils_test.cc | 10 +++++----- test/common/quic/test_utils.h | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/common/quic/envoy_quic_client_stream_test.cc b/test/common/quic/envoy_quic_client_stream_test.cc index 4ba077ead61d..e8fd682cadd6 100644 --- a/test/common/quic/envoy_quic_client_stream_test.cc +++ b/test/common/quic/envoy_quic_client_stream_test.cc @@ -153,7 +153,7 @@ class EnvoyQuicClientStreamTest : public testing::Test { EXPECT_EQ("200", headers->getStatusValue()); EXPECT_EQ(capsule_protocol[0]->value().getStringView(), "?1"); }); - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; response_headers["capsule-protocol"] = "?1"; std::string payload = spdyHeaderToHttp3StreamPayload(response_headers); @@ -189,8 +189,8 @@ class EnvoyQuicClientStreamTest : public testing::Test { std::string host_{"www.abc.com"}; Http::TestRequestHeaderMapImpl request_headers_; Http::TestRequestTrailerMapImpl request_trailers_; - spdy::Http2HeaderBlock spdy_response_headers_; - spdy::Http2HeaderBlock spdy_trailers_; + quiche::HttpHeaderBlock spdy_response_headers_; + quiche::HttpHeaderBlock spdy_trailers_; Buffer::OwnedImpl request_body_{"Hello world"}; std::string response_body_{"OK\n"}; #ifdef ENVOY_ENABLE_HTTP_DATAGRAMS @@ -346,7 +346,7 @@ TEST_F(EnvoyQuicClientStreamTest, PostRequestAnd1xx) { // Receive several 10x headers, only the first 100 Continue header should be // delivered. for (const std::string status : {"100", "199", "100"}) { - spdy::Http2HeaderBlock continue_header; + quiche::HttpHeaderBlock continue_header; continue_header[":status"] = status; continue_header["i"] = absl::StrCat("", i++); std::string data = spdyHeaderToHttp3StreamPayload(continue_header); @@ -365,7 +365,7 @@ TEST_F(EnvoyQuicClientStreamTest, ResetUpon101SwitchProtocol) { EXPECT_CALL(stream_callbacks_, onResetStream(Http::StreamResetReason::ProtocolError, _)); // Receive several 10x headers, only the first 100 Continue header should be // delivered. - spdy::Http2HeaderBlock continue_header; + quiche::HttpHeaderBlock continue_header; continue_header[":status"] = "101"; std::string data = spdyHeaderToHttp3StreamPayload(continue_header); quic::QuicStreamFrame frame(stream_id_, false, 0u, data); diff --git a/test/common/quic/envoy_quic_h3_fuzz_helper.cc b/test/common/quic/envoy_quic_h3_fuzz_helper.cc index a129446aaf31..6897306effac 100644 --- a/test/common/quic/envoy_quic_h3_fuzz_helper.cc +++ b/test/common/quic/envoy_quic_h3_fuzz_helper.cc @@ -25,7 +25,7 @@ class Delegate : public quic::QpackEncoder::DecoderStreamErrorDelegate { void OnDecoderStreamError(quic::QuicErrorCode, absl::string_view) override{}; }; -static std::string encodeHeaders(const spdy::Http2HeaderBlock& headers) { +static std::string encodeHeaders(const quiche::HttpHeaderBlock& headers) { static Delegate delegate; quic::QpackEncoder encoder(&delegate, quic::HuffmanEncoding::kEnabled, quic::CookieCrumbling::kEnabled); @@ -96,7 +96,7 @@ std::string H3Serializer::serialize(bool unidirectional, uint32_t type, uint32_t } case H3Frame::kHeaders: { const auto& f = h3frame.headers(); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; for (const auto& hdr : f.headers().headers()) { headers.AppendValueOrAddHeader(hdr.key(), hdr.value()); } @@ -120,7 +120,7 @@ std::string H3Serializer::serialize(bool unidirectional, uint32_t type, uint32_t case H3Frame::kPushPromise: { const auto& f = h3frame.push_promise(); uint64_t push_id = f.push_id(); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; for (auto& hdr : f.headers().headers()) { headers.AppendValueOrAddHeader(hdr.key(), hdr.value()); } diff --git a/test/common/quic/envoy_quic_server_stream_test.cc b/test/common/quic/envoy_quic_server_stream_test.cc index 68d1346efbe8..1027ad4351ac 100644 --- a/test/common/quic/envoy_quic_server_stream_test.cc +++ b/test/common/quic/envoy_quic_server_stream_test.cc @@ -128,7 +128,7 @@ class EnvoyQuicServerStreamTest : public testing::Test { EXPECT_FALSE(capsule_protocol.empty()); EXPECT_EQ(capsule_protocol[0]->value().getStringView(), "?1"); })); - spdy::Http2HeaderBlock request_headers; + quiche::HttpHeaderBlock request_headers; request_headers[":authority"] = host_; request_headers[":method"] = "CONNECT"; request_headers[":protocol"] = "connect-udp"; @@ -232,10 +232,10 @@ class EnvoyQuicServerStreamTest : public testing::Test { EnvoyQuicServerStream* quic_stream_; Http::MockRequestDecoder stream_decoder_; Http::MockStreamCallbacks stream_callbacks_; - spdy::Http2HeaderBlock spdy_request_headers_; + quiche::HttpHeaderBlock spdy_request_headers_; Http::TestResponseHeaderMapImpl response_headers_; Http::TestResponseTrailerMapImpl response_trailers_; - spdy::Http2HeaderBlock spdy_trailers_; + quiche::HttpHeaderBlock spdy_trailers_; std::string host_{"www.abc.com"}; std::string request_body_{"Hello world"}; #ifdef ENVOY_ENABLE_HTTP_DATAGRAMS @@ -263,7 +263,7 @@ TEST_F(EnvoyQuicServerStreamTest, GetRequestAndResponse) { headers->get(Http::Headers::get().Cookie)[0]->value().getStringView()); })); EXPECT_CALL(stream_decoder_, decodeData(BufferStringEqual(""), /*end_stream=*/true)); - spdy::Http2HeaderBlock spdy_headers; + quiche::HttpHeaderBlock spdy_headers; spdy_headers[":authority"] = host_; spdy_headers[":method"] = "GET"; spdy_headers[":path"] = "/"; @@ -710,7 +710,7 @@ TEST_F(EnvoyQuicServerStreamTest, RequestHeaderTooLarge) { EXPECT_CALL(quic_session_, MaybeSendStopSendingFrame(_, _)); EXPECT_CALL(quic_session_, MaybeSendRstStreamFrame(_, _, _)); EXPECT_CALL(stream_callbacks_, onResetStream(Http::StreamResetReason::LocalReset, _)); - spdy::Http2HeaderBlock spdy_headers; + quiche::HttpHeaderBlock spdy_headers; spdy_headers[":authority"] = host_; spdy_headers[":method"] = "POST"; spdy_headers[":path"] = "/"; @@ -734,7 +734,7 @@ TEST_F(EnvoyQuicServerStreamTest, RequestTrailerTooLarge) { EXPECT_CALL(quic_session_, MaybeSendStopSendingFrame(_, _)); EXPECT_CALL(quic_session_, MaybeSendRstStreamFrame(_, _, _)); EXPECT_CALL(stream_callbacks_, onResetStream(Http::StreamResetReason::LocalReset, _)); - spdy::Http2HeaderBlock spdy_trailers; + quiche::HttpHeaderBlock spdy_trailers; // This header exceeds max header size limit and should cause stream reset. spdy_trailers["long_header"] = std::string(16 * 1024 + 1, 'a'); std::string payload = spdyHeaderToHttp3StreamPayload(spdy_trailers); @@ -896,7 +896,7 @@ TEST_F(EnvoyQuicServerStreamTest, DecodeHttp3Datagram) { #endif TEST_F(EnvoyQuicServerStreamTest, RegularHeaderBeforePseudoHeader) { - spdy::Http2HeaderBlock spdy_headers; + quiche::HttpHeaderBlock spdy_headers; spdy_headers["foo"] = "bar"; spdy_headers[":authority"] = host_; spdy_headers[":method"] = "GET"; diff --git a/test/common/quic/envoy_quic_utils_test.cc b/test/common/quic/envoy_quic_utils_test.cc index def41145ad1d..3fbfe54e07f4 100644 --- a/test/common/quic/envoy_quic_utils_test.cc +++ b/test/common/quic/envoy_quic_utils_test.cc @@ -45,7 +45,7 @@ class MockServerHeaderValidator : public HeaderValidator { }; TEST(EnvoyQuicUtilsTest, HeadersConversion) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -118,7 +118,7 @@ TEST(EnvoyQuicUtilsTest, HeadersConversion) { } TEST(EnvoyQuicUtilsTest, HeadersSizeBounds) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -139,7 +139,7 @@ TEST(EnvoyQuicUtilsTest, HeadersSizeBounds) { } TEST(EnvoyQuicUtilsTest, TrailersSizeBounds) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -158,7 +158,7 @@ TEST(EnvoyQuicUtilsTest, TrailersSizeBounds) { } TEST(EnvoyQuicUtilsTest, TrailerCharacters) { - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; @@ -244,7 +244,7 @@ TEST(EnvoyQuicUtilsTest, HeaderMapMaxSizeLimit) { EXPECT_EQ(response_header->maxHeadersCount(), 100); EXPECT_EQ(response_header->maxHeadersKb(), 60); - spdy::Http2HeaderBlock headers_block; + quiche::HttpHeaderBlock headers_block; headers_block[":authority"] = "www.google.com"; headers_block[":path"] = "/index.hml"; headers_block[":scheme"] = "https"; diff --git a/test/common/quic/test_utils.h b/test/common/quic/test_utils.h index b19ede56a8bd..c9c1d04a7045 100644 --- a/test/common/quic/test_utils.h +++ b/test/common/quic/test_utils.h @@ -274,7 +274,7 @@ void setQuicConfigWithDefaultValues(quic::QuicConfig* config) { config, quic::kMinimumFlowControlSendWindow); } -std::string spdyHeaderToHttp3StreamPayload(const spdy::Http2HeaderBlock& header) { +std::string spdyHeaderToHttp3StreamPayload(const quiche::HttpHeaderBlock& header) { quic::test::NoopQpackStreamSenderDelegate encoder_stream_sender_delegate; quic::NoopDecoderStreamErrorDelegate decoder_stream_error_delegate; auto qpack_encoder = std::make_unique(&decoder_stream_error_delegate, From 2dc58ee18836307ecfa4cae47142875f8b822447 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 10 Sep 2024 16:57:16 -0400 Subject: [PATCH 15/21] docs: updating meeting info (#36052) Making it clear we hold the Envoy meeting iff there is agenda Signed-off-by: Alyssa Wilk --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f2f383d5f001..7d323eb59ef3 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,13 @@ have prior experience. To get started: ## Community Meeting -The Envoy team meets twice per month on Tuesday at 9am PT. The public -Google calendar is here: https://goo.gl/PkDijT - -* Meeting minutes are [here](https://goo.gl/5Cergb) -* Recorded videos are posted [here](https://www.youtube.com/channel/UC5z5mvPgqMs1xo5VuIWzYTA) +The Envoy team has a scheduled meeting time twice per month on Tuesday at 9am PT. The public +Google calendar is [here](https://goo.gl/PkDijT). The meeting will only be held +if there are agenda items listed in the [meeting +minutes](https://goo.gl/5Cergb). Any member of the community should be able to +propose agenda items by adding to the minutes. The maintainers will either confirm +the additions to the agenda, or will cancel the meeting within 24 hours of the scheduled +date if there is no confirmed agenda. ## Security From c091ca9974a88f8e75153f37851cf14ad021193a Mon Sep 17 00:00:00 2001 From: Ravi Gupta <32182026+dceravigupta@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:07:31 -0700 Subject: [PATCH 16/21] Typo in documentation of http original_src filter (#36060) The doc is about http original_src filter while in the example, the listed type is that of listener filter. ![image](https://github.com/user-attachments/assets/a6e6e473-9d02-4e92-a9e7-3f3bca7291ab) Existing example will result in following error: Didn't find a registered implementation for 'envoy.filters.http.original_src' with type URL: 'envoy.extensions.filters.listener.original_src.v3.OriginalSrc' Commit Message: Typo in documentation of http original_src filter Additional Description: Risk Level: Low Testing: Locally Docs Changes: Yes Release Notes: Typo in documentation of http original_src filter Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] Signed-off-by: Ravi Gupta <32182026+dceravigupta@users.noreply.github.com> --- .../configuration/http/http_filters/original_src_filter.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/root/configuration/http/http_filters/original_src_filter.rst b/docs/root/configuration/http/http_filters/original_src_filter.rst index 232f45a40a0c..b703ec0e3ab1 100644 --- a/docs/root/configuration/http/http_filters/original_src_filter.rst +++ b/docs/root/configuration/http/http_filters/original_src_filter.rst @@ -70,7 +70,7 @@ The following example configures Envoy to use the original source for all connec http_filters: - name: envoy.filters.http.original_src typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.listener.original_src.v3.OriginalSrc + "@type": type.googleapis.com/envoy.extensions.filters.http.original_src.v3.OriginalSrc mark: 123 - name: envoy.filters.http.router typed_config: From cd3346d541c9866bb60a26730da5edd13a2edfdc Mon Sep 17 00:00:00 2001 From: Gordon Wang <176503456+gordon-wang-lyft@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:27:50 -0400 Subject: [PATCH 17/21] runtime: load rtds bool correctly as true/false instead of 1/0 (#36044) Commit Message: Load RTDS boolean config correctly as true/false instead of 1/0 Additional Description: Currently, RTDS boolean values are being loaded as `1` or `0`, which is inconsistent with the expected `true` or `false` values. This discrepancy needs to be corrected so that boolean values are consistently loaded and represented as `true` or `false`. For further details, please refer to the [issue comment](https://github.com/envoyproxy/envoy/issues/35762#issuecomment-2338685970) where this inconsistency is discussed. Risk Level: Low (to be consistent with initially loaded true/false value) Testing: new Unit Test Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a [Optional Fixes #Issue] https://github.com/envoyproxy/envoy/issues/35762 --------- Signed-off-by: Gordon Wang --- changelogs/current.yaml | 5 ++++ source/common/runtime/runtime_features.cc | 1 + source/common/runtime/runtime_impl.cc | 8 +++++- test/common/runtime/runtime_impl_test.cc | 35 +++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index d46e53b6071e..d199a25651a2 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -128,6 +128,11 @@ bug_fixes: the number of requests per I/O cycle is configured and an HTTP decoder filter that pauses filter chain is present. This behavior can be reverted by setting the runtime guard ``envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream`` to false. +- area: runtime + change: | + Fixed an inconsistency in how boolean values are loaded in RTDS, where they were previously converted to "1"/"0" + instead of "true"/"false". The correct string representation ("true"/"false") will now be used. This change can be + reverted by setting the runtime guard ``envoy.reloadable_features.boolean_to_string_fix`` to false. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 1411ac47f991..860aaf353e56 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -30,6 +30,7 @@ // ASAP by filing a bug on github. Overriding non-buggy code is strongly discouraged to avoid the // problem of the bugs being found after the old code path has been removed. RUNTIME_GUARD(envoy_reloadable_features_allow_alt_svc_for_ips); +RUNTIME_GUARD(envoy_reloadable_features_boolean_to_string_fix); RUNTIME_GUARD(envoy_reloadable_features_check_switch_protocol_websocket_handshake); RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle); RUNTIME_GUARD(envoy_reloadable_features_consistent_header_validation); diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc index 917ef6e655a1..24b1f1ff04c2 100644 --- a/source/common/runtime/runtime_impl.cc +++ b/source/common/runtime/runtime_impl.cc @@ -375,7 +375,13 @@ SnapshotImpl::Entry SnapshotImpl::createEntry(const ProtobufWkt::Value& value, case ProtobufWkt::Value::kBoolValue: entry.bool_value_ = value.bool_value(); if (entry.raw_string_value_.empty()) { - entry.raw_string_value_ = absl::StrCat(value.bool_value()); + if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.boolean_to_string_fix")) { + // Convert boolean to "true"/"false" + entry.raw_string_value_ = value.bool_value() ? "true" : "false"; + } else { + // Use absl::StrCat for backward compatibility, which converts to "1"/"0" + entry.raw_string_value_ = absl::StrCat(value.bool_value()); + } } break; case ProtobufWkt::Value::kStructValue: diff --git a/test/common/runtime/runtime_impl_test.cc b/test/common/runtime/runtime_impl_test.cc index 37540ce90d29..16d1ea5a2ef7 100644 --- a/test/common/runtime/runtime_impl_test.cc +++ b/test/common/runtime/runtime_impl_test.cc @@ -32,6 +32,7 @@ #ifdef ENVOY_ENABLE_QUIC #include "quiche/common/platform/api/quiche_flags.h" #endif +ABSL_DECLARE_FLAG(bool, envoy_reloadable_features_boolean_to_string_fix); ABSL_DECLARE_FLAG(bool, envoy_reloadable_features_reject_invalid_yaml); using testing::_; @@ -1314,6 +1315,40 @@ TEST_F(RtdsLoaderImplTest, BadConfigSource) { "bad config"); } +TEST_F(RtdsLoaderImplTest, BooleanToStringConversionWhenFlagEnabled) { + setup(); + + absl::SetFlag(&FLAGS_envoy_reloadable_features_boolean_to_string_fix, true); + + auto runtime = TestUtility::parseYaml(R"EOF( + name: some_resource + layer: + toggle: true + )EOF"); + + EXPECT_CALL(rtds_init_callback_, Call()); + doOnConfigUpdateVerifyNoThrow(runtime); + + EXPECT_EQ("true", loader_->snapshot().get("toggle").value().get()); +} + +TEST_F(RtdsLoaderImplTest, BooleanToStringConversionWhenFlagDisabled) { + setup(); + + absl::SetFlag(&FLAGS_envoy_reloadable_features_boolean_to_string_fix, false); + + auto runtime = TestUtility::parseYaml(R"EOF( + name: some_resource + layer: + toggle: true + )EOF"); + + EXPECT_CALL(rtds_init_callback_, Call()); + doOnConfigUpdateVerifyNoThrow(runtime); + + EXPECT_EQ("1", loader_->snapshot().get("toggle").value().get()); // Assuming previous behavior +} + } // namespace } // namespace Runtime } // namespace Envoy From fad478ceb8e1812e9064fe71f8ce70f61a21596e Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 11 Sep 2024 13:11:34 -0400 Subject: [PATCH 18/21] coverage: ratcheting (#36058) Signed-off-by: Alyssa Wilk --- test/per_file_coverage.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index 5b5f6d472a7a..4a9420f37622 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -8,7 +8,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/api/posix:83.8" # flaky (accept failover non-deterministic): be careful adjusting "source/common/config:96.1" "source/common/crypto:95.5" -"source/common/event:95.1" # Emulated edge events guards don't report LCOV +"source/common/event:95.2" # Emulated edge events guards don't report LCOV "source/common/filesystem/posix:96.3" # FileReadToEndNotReadable fails in some env; createPath can't test all failure branches. "source/common/http/http2:96.0" "source/common/json:94.4" @@ -29,7 +29,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/common/wasm/ext:92.0" "source/extensions/filters/common/fault:94.5" "source/extensions/filters/common/rbac:90.8" -"source/extensions/filters/http/cache:95.1" +"source/extensions/filters/http/cache:95.3" "source/extensions/filters/http/grpc_json_transcoder:94.2" # TODO(#28232) "source/extensions/filters/http/ip_tagging:88.2" "source/extensions/filters/http/kill_request:91.7" # Death tests don't report LCOV @@ -52,8 +52,8 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/wasm_runtime/wamr:0.0" # Not enabled in coverage build "source/extensions/wasm_runtime/wasmtime:0.0" # Not enabled in coverage build "source/extensions/watchdog:83.3" # Death tests within extensions -"source/extensions/listener_managers:70.5" -"source/extensions/listener_managers/validation_listener_manager:70.5" +"source/extensions/listener_managers:77.3" +"source/extensions/listener_managers/validation_listener_manager:77.3" "source/extensions/watchdog/profile_action:83.3" "source/server:91.0" # flaky: be careful adjusting. See https://github.com/envoyproxy/envoy/issues/15239 "source/server/config_validation:91.8" From 54b2e865c04000ce1442db26367fac3cb26d4935 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 11 Sep 2024 14:02:21 -0400 Subject: [PATCH 19/21] exceptions: cleaning up macros (#35694) Risk Level: low Testing: existing tests Docs Changes: n/a Release Notes: n/a Signed-off-by: Alyssa Wilk --- .../filters/network/source/client_ssl_auth.cc | 2 +- .../filters/network/source/tra/tra_impl.cc | 2 +- envoy/common/exception.h | 13 +++---------- source/common/common/logger_delegates.cc | 2 +- source/common/formatter/http_specific_formatter.cc | 8 ++++---- source/common/listener_manager/listener_impl.cc | 6 +++--- source/common/protobuf/utility.cc | 2 +- source/common/secret/sds_api.cc | 2 +- source/common/upstream/cluster_manager_impl.cc | 2 +- .../common/upstream/health_checker_event_logger.h | 2 +- source/common/upstream/health_discovery_service.cc | 6 +++--- source/common/upstream/outlier_detection_impl.h | 2 +- source/common/upstream/upstream_impl.cc | 2 +- .../access_loggers/common/file_access_log_impl.cc | 2 +- .../access_loggers/grpc/grpc_access_log_impl.cc | 2 +- .../open_telemetry/grpc_access_log_impl.cc | 2 +- .../common/wasm/remote_async_datasource.cc | 2 +- .../compression/zstd/common/dictionary_manager.h | 2 +- .../grpc/grpc_collection_subscription_factory.cc | 6 +++--- .../config_subscription/grpc/grpc_mux_impl.cc | 6 +++--- .../config_subscription/grpc/grpc_mux_impl.h | 2 +- .../grpc/grpc_subscription_factory.cc | 12 ++++++------ .../config_subscription/grpc/new_grpc_mux_impl.cc | 4 ++-- .../config_subscription/grpc/watch_map.cc | 2 +- .../grpc/xds_mux/grpc_mux_impl.cc | 6 +++--- .../filters/common/ratelimit/ratelimit_impl.cc | 2 +- source/extensions/filters/http/composite/action.cc | 4 ++-- source/extensions/filters/http/ext_authz/config.cc | 2 +- .../extensions/filters/http/ext_proc/client_impl.cc | 2 +- .../grpc_json_transcoder/json_transcoder_filter.cc | 2 +- .../filters/http/rate_limit_quota/client_impl.cc | 2 +- .../extensions/filters/network/ext_authz/config.cc | 2 +- .../extensions/filters/network/mongo_proxy/proxy.cc | 2 +- .../filters/network/redis_proxy/config.cc | 2 +- .../sni_dynamic_forward_proxy/proxy_filter.cc | 2 +- .../dynamic_forward_proxy/proxy_filter.cc | 2 +- .../health_check/event_sinks/file/file_sink_impl.h | 2 +- .../health_checkers/http/health_checker_impl.cc | 2 +- .../health_checkers/tcp/health_checker_impl.cc | 4 ++-- source/extensions/key_value/file_based/config.cc | 2 +- .../injected_resource/injected_resource_monitor.cc | 2 +- .../extensions/stat_sinks/common/statsd/statsd.cc | 2 +- source/extensions/stat_sinks/dog_statsd/config.cc | 2 +- .../extensions/stat_sinks/graphite_statsd/config.cc | 2 +- .../extensions/stat_sinks/metrics_service/config.cc | 2 +- .../extensions/stat_sinks/open_telemetry/config.cc | 2 +- source/extensions/stat_sinks/statsd/config.cc | 2 +- source/extensions/tracers/datadog/tracer.cc | 6 +++--- .../opentelemetry/opentelemetry_tracer_impl.cc | 2 +- .../tracers/skywalking/skywalking_tracer_impl.cc | 2 +- .../extensions/tracers/zipkin/zipkin_tracer_impl.cc | 8 ++++---- source/server/config_validation/server.cc | 2 +- source/server/server.cc | 2 +- test/common/http/async_client_impl_test.cc | 4 ++-- test/common/router/header_formatter_test.cc | 2 +- test/common/upstream/upstream_impl_test.cc | 2 +- .../original_dst/original_dst_cluster_test.cc | 2 +- .../dynamic_forward_proxy/dns_cache_impl_test.cc | 2 +- .../filters/http/common/fuzz/uber_filter.cc | 2 +- test/fuzz/utility.h | 4 ++-- test/integration/admin_html/test_server.cc | 2 +- 61 files changed, 91 insertions(+), 98 deletions(-) diff --git a/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc b/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc index dc3415b4236f..305f2db8ed71 100644 --- a/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc +++ b/contrib/client_ssl_auth/filters/network/source/client_ssl_auth.cc @@ -35,7 +35,7 @@ ClientSslAuthConfig::ClientSslAuthConfig( std::chrono::milliseconds(1000)), tls_(tls.allocateSlot()), stats_(generateStats(scope, config.stat_prefix())) { auto list_or_error = Network::Address::IpList::create(config.ip_white_list()); - THROW_IF_STATUS_NOT_OK(list_or_error, throw); + THROW_IF_NOT_OK_REF(list_or_error.status()); ip_allowlist_ = std::move(list_or_error.value()); if (!cm.clusters().hasCluster(remote_cluster_name_)) { diff --git a/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc b/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc index 95b77c071d5a..e9c0eca313f4 100644 --- a/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc +++ b/contrib/sip_proxy/filters/network/source/tra/tra_impl.cc @@ -204,7 +204,7 @@ ClientPtr traClient(Event::Dispatcher& dispatcher, Server::Configuration::Factor .clusterManager() .grpcAsyncClientManager() .getOrCreateRawAsyncClient(grpc_service, context.scope(), true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); return std::make_unique( client_or_error.value(), dispatcher, timeout); } diff --git a/envoy/common/exception.h b/envoy/common/exception.h index 0688b440dfbc..5734df1f6628 100644 --- a/envoy/common/exception.h +++ b/envoy/common/exception.h @@ -42,21 +42,14 @@ class EnvoyException : public std::runtime_error { } \ } while (0) +// Simple macro to handle bridging functions which return absl::StatusOr, and +// functions which throw errors. #define THROW_IF_NOT_OK(status_fn) \ do { \ const absl::Status status = (status_fn); \ THROW_IF_NOT_OK_REF(status); \ } while (0) -// Simple macro to handle bridging functions which return absl::StatusOr, and -// functions which throw errors. -// -// The completely unnecessary throw_action argument was just so 'throw' appears -// at the call site, so format checks about use of exceptions would be triggered. -// This didn't work, so the variable is no longer used and is not duplicated in -// the macros above. -#define THROW_IF_STATUS_NOT_OK(variable, throw_action) THROW_IF_NOT_OK_REF(variable.status()); - #define RETURN_IF_NOT_OK_REF(variable) \ if (const absl::Status& temp_status = variable; !temp_status.ok()) { \ return temp_status; \ @@ -69,7 +62,7 @@ class EnvoyException : public std::runtime_error { } template Type returnOrThrow(absl::StatusOr type_or_error) { - THROW_IF_STATUS_NOT_OK(type_or_error, throw); + THROW_IF_NOT_OK_REF(type_or_error.status()); return std::move(type_or_error.value()); } diff --git a/source/common/common/logger_delegates.cc b/source/common/common/logger_delegates.cc index cf3874d6a654..52975cd22129 100644 --- a/source/common/common/logger_delegates.cc +++ b/source/common/common/logger_delegates.cc @@ -15,7 +15,7 @@ FileSinkDelegate::FileSinkDelegate(const std::string& log_path, : SinkDelegate(log_sink) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, log_path}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); log_file_ = file_or_error.value(); setDelegate(); } diff --git a/source/common/formatter/http_specific_formatter.cc b/source/common/formatter/http_specific_formatter.cc index a46c9559c9f5..ab668bb60ac2 100644 --- a/source/common/formatter/http_specific_formatter.cc +++ b/source/common/formatter/http_specific_formatter.cc @@ -300,7 +300,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, @@ -308,7 +308,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, @@ -316,7 +316,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, @@ -364,7 +364,7 @@ BuiltInHttpCommandParser::getKnownFormatters() { {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, [](absl::string_view format, absl::optional max_length) { auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format); - THROW_IF_STATUS_NOT_OK(result, throw); + THROW_IF_NOT_OK_REF(result.status()); return std::make_unique(result.value().first, result.value().second, max_length); }}}, diff --git a/source/common/listener_manager/listener_impl.cc b/source/common/listener_manager/listener_impl.cc index 5924d2deec86..a82bf3a8d375 100644 --- a/source/common/listener_manager/listener_impl.cc +++ b/source/common/listener_manager/listener_impl.cc @@ -236,7 +236,7 @@ std::string listenerStatsScope(const envoy::config::listener::v3::Listener& conf return absl::StrCat("envoy_internal_", config.name()); } auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); return address_or_error.value()->asString(); } } // namespace @@ -324,7 +324,7 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, // All the addresses should be same socket type, so get the first address's socket type is // enough. auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); auto address = std::move(address_or_error.value()); checkIpv4CompatAddress(address, config.address()); addresses_.emplace_back(address); @@ -340,7 +340,7 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, } auto addresses_or_error = Network::Address::resolveProtoAddress(config.additional_addresses(i).address()); - THROW_IF_STATUS_NOT_OK(addresses_or_error, throw); + THROW_IF_NOT_OK_REF(addresses_or_error.status()); auto additional_address = std::move(addresses_or_error.value()); checkIpv4CompatAddress(address, config.additional_addresses(i).address()); addresses_.emplace_back(additional_address); diff --git a/source/common/protobuf/utility.cc b/source/common/protobuf/utility.cc index e9b5003b9061..2bf646a6b907 100644 --- a/source/common/protobuf/utility.cc +++ b/source/common/protobuf/utility.cc @@ -936,7 +936,7 @@ void MessageUtil::loadFromFile(const std::string& path, Protobuf::Message& messa ProtobufMessage::ValidationVisitor& validation_visitor, Api::Api& api) { auto file_or_error = api.fileSystem().fileReadToEnd(path); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const std::string contents = file_or_error.value(); // If the filename ends with .pb, attempt to parse it as a binary proto. if (absl::EndsWithIgnoreCase(path, FileExtensions::get().ProtoBinary)) { diff --git a/source/common/secret/sds_api.cc b/source/common/secret/sds_api.cc index 620bffb4972d..1f88e78babc1 100644 --- a/source/common/secret/sds_api.cc +++ b/source/common/secret/sds_api.cc @@ -210,7 +210,7 @@ SdsApi::FileContentMap SdsApi::loadFiles() { FileContentMap files; for (auto const& filename : getDataSourceFilenames()) { auto file_or_error = api_.fileSystem().fileReadToEnd(filename); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); files[filename] = file_or_error.value(); } return files; diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index 6c16ac21db73..fcdef2ad85cf 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -844,7 +844,7 @@ bool ClusterManagerImpl::addOrUpdateCluster(const envoy::config::cluster::v3::Cl // before destroy to avoid early initialization complete. auto status_or_cluster = loadCluster(cluster, new_hash, version_info, /*added_via_api=*/true, /*required_for_ads=*/false, warming_clusters_); - THROW_IF_STATUS_NOT_OK(status_or_cluster, throw); + THROW_IF_NOT_OK_REF(status_or_cluster.status()); const ClusterDataPtr previous_cluster = std::move(status_or_cluster.value()); auto& cluster_entry = warming_clusters_.at(cluster_name); cluster_entry->cluster_->info()->configUpdateStats().warming_state_.set(1); diff --git a/source/common/upstream/health_checker_event_logger.h b/source/common/upstream/health_checker_event_logger.h index 38bd0ed9d0a6..1039f78493f8 100644 --- a/source/common/upstream/health_checker_event_logger.h +++ b/source/common/upstream/health_checker_event_logger.h @@ -34,7 +34,7 @@ class HealthCheckEventLoggerImpl : public HealthCheckEventLogger { auto file_or_error = context.serverFactoryContext().accessLogManager().createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, health_check_config.event_log_path()}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } for (const auto& config : health_check_config.event_logger()) { diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index b1b219263584..c12503b2169c 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -372,7 +372,7 @@ HdsCluster::HdsCluster(Server::Configuration::ServerFactoryContext& server_conte const LocalityEndpointTuple endpoint_key = {locality_endpoints.locality(), host}; // Initialize an endpoint host object. auto address_or_error = Network::Address::resolveProtoAddress(host.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); HostSharedPtr endpoint = std::make_shared( info_, "", std::move(address_or_error.value()), nullptr, nullptr, 1, locality_endpoints.locality(), host.endpoint().health_check_config(), 0, @@ -487,7 +487,7 @@ void HdsCluster::updateHosts( // We do not have this endpoint saved, so create a new one. auto address_or_error = Network::Address::resolveProtoAddress(endpoint.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); host = std::make_shared(info_, "", std::move(address_or_error.value()), nullptr, nullptr, 1, endpoints.locality(), endpoint.endpoint().health_check_config(), 0, @@ -560,7 +560,7 @@ void HdsCluster::initHealthchecks() { for (auto& health_check : cluster_.health_checks()) { auto health_checker_or_error = Upstream::HealthCheckerFactory::create(health_check, *this, server_context_); - THROW_IF_STATUS_NOT_OK(health_checker_or_error, throw); + THROW_IF_NOT_OK_REF(health_checker_or_error.status()); auto health_checker = health_checker_or_error.value(); health_checkers_.push_back(health_checker); diff --git a/source/common/upstream/outlier_detection_impl.h b/source/common/upstream/outlier_detection_impl.h index bf74a3d6b8c1..4eea999121a5 100644 --- a/source/common/upstream/outlier_detection_impl.h +++ b/source/common/upstream/outlier_detection_impl.h @@ -498,7 +498,7 @@ class EventLoggerImpl : public EventLogger { : time_source_(time_source) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, file_name}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index b75c0898e622..805ceb849c70 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -2546,7 +2546,7 @@ Network::Address::InstanceConstSharedPtr resolveHealthCheckAddress( const auto& port_value = health_check_config.port_value(); if (health_check_config.has_address()) { auto address_or_error = Network::Address::resolveProtoAddress(health_check_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); auto address = address_or_error.value(); health_check_address = port_value == 0 ? address : Network::Utility::getAddressWithPort(*address, port_value); diff --git a/source/extensions/access_loggers/common/file_access_log_impl.cc b/source/extensions/access_loggers/common/file_access_log_impl.cc index 4ec65df5a0fa..fa7b85554190 100644 --- a/source/extensions/access_loggers/common/file_access_log_impl.cc +++ b/source/extensions/access_loggers/common/file_access_log_impl.cc @@ -10,7 +10,7 @@ FileAccessLog::FileAccessLog(const Filesystem::FilePathAndType& access_log_file_ AccessLog::AccessLogManager& log_manager) : ImplBase(std::move(filter)), formatter_(std::move(formatter)) { auto file_or_error = log_manager.createAccessLog(access_log_file_info); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); log_file_ = file_or_error.value(); } diff --git a/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc b/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc index b1838fe56f9a..790c000aa24a 100644 --- a/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc +++ b/source/extensions/access_loggers/grpc/grpc_access_log_impl.cc @@ -63,7 +63,7 @@ GrpcAccessLoggerImpl::SharedPtr GrpcAccessLoggerCacheImpl::createLogger( // the main thread if necessary. auto factory_or_error = async_client_manager_.factoryForGrpcService(config.grpc_service(), scope_, true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); return std::make_shared( factory_or_error.value()->createUncachedRawAsyncClient(), config, dispatcher, local_info_, scope_); diff --git a/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc b/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc index d6100a807b60..c180f28aa564 100644 --- a/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc +++ b/source/extensions/access_loggers/open_telemetry/grpc_access_log_impl.cc @@ -116,7 +116,7 @@ GrpcAccessLoggerImpl::SharedPtr GrpcAccessLoggerCacheImpl::createLogger( // the main thread if necessary to ensure it does not throw here. auto factory_or_error = async_client_manager_.factoryForGrpcService( config.common_config().grpc_service(), scope_, true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); auto client = factory_or_error.value()->createUncachedRawAsyncClient(); return std::make_shared(std::move(client), config, dispatcher, local_info_, scope_); diff --git a/source/extensions/common/wasm/remote_async_datasource.cc b/source/extensions/common/wasm/remote_async_datasource.cc index 4ed28651c564..b3e8989e7a9a 100644 --- a/source/extensions/common/wasm/remote_async_datasource.cc +++ b/source/extensions/common/wasm/remote_async_datasource.cc @@ -32,7 +32,7 @@ RemoteAsyncDataProvider::RemoteAsyncDataProvider( auto strategy_or_error = Config::Utility::prepareJitteredExponentialBackOffStrategy( source, random, RetryInitialDelayMilliseconds, RetryMaxDelayMilliseconds); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); backoff_strategy_ = std::move(strategy_or_error.value()); retry_timer_ = dispatcher.createTimer([this]() -> void { start(); }); diff --git a/source/extensions/compression/zstd/common/dictionary_manager.h b/source/extensions/compression/zstd/common/dictionary_manager.h index 85d161c73559..99be8fc15fff 100644 --- a/source/extensions/compression/zstd/common/dictionary_manager.h +++ b/source/extensions/compression/zstd/common/dictionary_manager.h @@ -94,7 +94,7 @@ template class void onDictionaryUpdate(unsigned origin_id, const std::string& filename) { auto file_or_error = api_.fileSystem().fileReadToEnd(filename); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const auto data = file_or_error.value(); if (!data.empty()) { auto dictionary = DictionarySharedPtr(builder_(data.data(), data.length())); diff --git a/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc b/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc index 9468f1d32c2e..fb2b82033b7a 100644 --- a/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc +++ b/source/extensions/config_subscription/grpc/grpc_collection_subscription_factory.cc @@ -20,15 +20,15 @@ SubscriptionPtr DeltaGrpcCollectionConfigSubscriptionFactory::create( auto strategy_or_error = Utility::prepareJitteredExponentialBackOffStrategy( api_config_source, data.api_.randomGenerator(), SubscriptionFactory::RetryInitialDelayMs, SubscriptionFactory::RetryMaxDelayMs); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); JitteredExponentialBackOffStrategyPtr backoff_strategy = std::move(strategy_or_error.value()); auto factory_primary_or_error = Config::Utility::factoryForGrpcApiConfigSource( data.cm_.grpcAsyncClientManager(), api_config_source, data.scope_, true, 0); - THROW_IF_STATUS_NOT_OK(factory_primary_or_error, throw); + THROW_IF_NOT_OK_REF(factory_primary_or_error.status()); absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(api_config_source); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ factory_primary_or_error.value()->createUncachedRawAsyncClient(), /*failover_async_client_=*/nullptr, diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc index ba038b140955..4317cdca1a2c 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.cc @@ -48,7 +48,7 @@ bool isXdsTpWildcard(const std::string& resource_name) { std::string convertToWildcard(const std::string& resource_name) { ASSERT(XdsResourceIdentifier::hasXdsTpScheme(resource_name)); auto resource_or_error = XdsResourceIdentifier::decodeUrn(resource_name); - THROW_IF_STATUS_NOT_OK(resource_or_error, throw); + THROW_IF_NOT_OK_REF(resource_or_error.status()); xds::core::v3::ResourceName xdstp_resource = resource_or_error.value(); const auto pos = xdstp_resource.id().find_last_of('/'); xdstp_resource.set_id( @@ -445,7 +445,7 @@ void GrpcMuxImpl::processDiscoveryResources(const std::vectorname())) { // Sort the context params of an xdstp resource, so we can compare them easily. auto resource_or_error = XdsResourceIdentifier::decodeUrn(resource->name()); - THROW_IF_STATUS_NOT_OK(resource_or_error, throw); + THROW_IF_NOT_OK_REF(resource_or_error.status()); xds::core::v3::ResourceName xdstp_resource = resource_or_error.value(); XdsResourceIdentifier::EncodeOptions options; options.sort_context_params_ = true; @@ -631,7 +631,7 @@ class GrpcMuxFactory : public MuxFactory { XdsResourcesDelegateOptRef xds_resources_delegate, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client_=*/std::move(failover_async_client), diff --git a/source/extensions/config_subscription/grpc/grpc_mux_impl.h b/source/extensions/config_subscription/grpc/grpc_mux_impl.h index c6d6df79dc6d..885942f3fb2a 100644 --- a/source/extensions/config_subscription/grpc/grpc_mux_impl.h +++ b/source/extensions/config_subscription/grpc/grpc_mux_impl.h @@ -169,7 +169,7 @@ class GrpcMuxImpl : public GrpcMux, [this](const std::string& resource_name) -> std::string { if (XdsResourceIdentifier::hasXdsTpScheme(resource_name)) { auto xdstp_resource_or_error = XdsResourceIdentifier::decodeUrn(resource_name); - THROW_IF_STATUS_NOT_OK(xdstp_resource_or_error, throw); + THROW_IF_NOT_OK_REF(xdstp_resource_or_error.status()); auto xdstp_resource = xdstp_resource_or_error.value(); if (subscription_options_.add_xdstp_node_context_params_) { const auto context = XdsContextParams::encodeResource( diff --git a/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc b/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc index da174b438ce7..a93fb9b4544a 100644 --- a/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc +++ b/source/extensions/config_subscription/grpc/grpc_subscription_factory.cc @@ -23,15 +23,15 @@ GrpcConfigSubscriptionFactory::create(ConfigSubscriptionFactory::SubscriptionDat auto strategy_or_error = Utility::prepareJitteredExponentialBackOffStrategy( api_config_source, data.api_.randomGenerator(), SubscriptionFactory::RetryInitialDelayMs, SubscriptionFactory::RetryMaxDelayMs); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); JitteredExponentialBackOffStrategyPtr backoff_strategy = std::move(strategy_or_error.value()); auto factory_primary_or_error = Utility::factoryForGrpcApiConfigSource( data.cm_.grpcAsyncClientManager(), api_config_source, data.scope_, true, 0); - THROW_IF_STATUS_NOT_OK(factory_primary_or_error, throw); + THROW_IF_NOT_OK_REF(factory_primary_or_error.status()); absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(api_config_source); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/factory_primary_or_error.value()->createUncachedRawAsyncClient(), /*failover_async_client_=*/nullptr, // Failover is only supported for ADS. @@ -72,15 +72,15 @@ DeltaGrpcConfigSubscriptionFactory::create(ConfigSubscriptionFactory::Subscripti auto strategy_or_error = Utility::prepareJitteredExponentialBackOffStrategy( api_config_source, data.api_.randomGenerator(), SubscriptionFactory::RetryInitialDelayMs, SubscriptionFactory::RetryMaxDelayMs); - THROW_IF_STATUS_NOT_OK(strategy_or_error, throw); + THROW_IF_NOT_OK_REF(strategy_or_error.status()); JitteredExponentialBackOffStrategyPtr backoff_strategy = std::move(strategy_or_error.value()); auto factory_primary_or_error = Utility::factoryForGrpcApiConfigSource( data.cm_.grpcAsyncClientManager(), api_config_source, data.scope_, true, 0); - THROW_IF_STATUS_NOT_OK(factory_primary_or_error, throw); + THROW_IF_NOT_OK_REF(factory_primary_or_error.status()); absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(api_config_source); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/factory_primary_or_error.value()->createUncachedRawAsyncClient(), /*failover_async_client_=*/nullptr, // Failover is only supported for ADS. diff --git a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc index 15efac2b82d5..1a47a63572c7 100644 --- a/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/new_grpc_mux_impl.cc @@ -262,7 +262,7 @@ void NewGrpcMuxImpl::updateWatch(const std::string& type_url, Watch* watch, for (const auto& resource : resources) { if (XdsResourceIdentifier::hasXdsTpScheme(resource)) { auto xdstp_resource_or_error = XdsResourceIdentifier::decodeUrn(resource); - THROW_IF_STATUS_NOT_OK(xdstp_resource_or_error, throw); + THROW_IF_NOT_OK_REF(xdstp_resource_or_error.status()); auto xdstp_resource = xdstp_resource_or_error.value(); if (options.add_xdstp_node_context_params_) { const auto context = XdsContextParams::encodeResource( @@ -420,7 +420,7 @@ class NewGrpcMuxFactory : public MuxFactory { OptRef, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client_=*/std::move(failover_async_client), diff --git a/source/extensions/config_subscription/grpc/watch_map.cc b/source/extensions/config_subscription/grpc/watch_map.cc index 88bbf01125de..5b40d625fadb 100644 --- a/source/extensions/config_subscription/grpc/watch_map.cc +++ b/source/extensions/config_subscription/grpc/watch_map.cc @@ -96,7 +96,7 @@ absl::flat_hash_set WatchMap::watchesInterestedIn(const std::string& res // operations, but this implementation provides a reference for later optimization while we // adopt xdstp://. auto resource_or_error = XdsResourceIdentifier::decodeUrn(resource_name); - THROW_IF_STATUS_NOT_OK(resource_or_error, throw); + THROW_IF_NOT_OK_REF(resource_or_error.status()); xdstp_resource = resource_or_error.value(); } auto watches_interested = watch_interest_.find( diff --git a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc index 9269df1d37df..273fb0081040 100644 --- a/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc +++ b/source/extensions/config_subscription/grpc/xds_mux/grpc_mux_impl.cc @@ -167,7 +167,7 @@ void GrpcMuxImpl::updateWatch(const std::string& type_url, Watch* for (const auto& resource : resources) { if (XdsResourceIdentifier::hasXdsTpScheme(resource)) { auto xdstp_resource_or_error = XdsResourceIdentifier::decodeUrn(resource); - THROW_IF_STATUS_NOT_OK(xdstp_resource_or_error, throw); + THROW_IF_NOT_OK_REF(xdstp_resource_or_error.status()); auto xdstp_resource = xdstp_resource_or_error.value(); if (options.add_xdstp_node_context_params_) { const auto context = XdsContextParams::encodeResource( @@ -456,7 +456,7 @@ class DeltaGrpcMuxFactory : public MuxFactory { XdsResourcesDelegateOptRef, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client=*/std::move(failover_async_client), @@ -495,7 +495,7 @@ class SotwGrpcMuxFactory : public MuxFactory { XdsResourcesDelegateOptRef, bool use_eds_resources_cache) override { absl::StatusOr rate_limit_settings_or_error = Utility::parseRateLimitSettings(ads_config); - THROW_IF_STATUS_NOT_OK(rate_limit_settings_or_error, throw); + THROW_IF_NOT_OK_REF(rate_limit_settings_or_error.status()); GrpcMuxContext grpc_mux_context{ /*async_client_=*/std::move(async_client), /*failover_async_client_=*/std::move(failover_async_client), diff --git a/source/extensions/filters/common/ratelimit/ratelimit_impl.cc b/source/extensions/filters/common/ratelimit/ratelimit_impl.cc index a72fa1b81661..3350e132562a 100644 --- a/source/extensions/filters/common/ratelimit/ratelimit_impl.cc +++ b/source/extensions/filters/common/ratelimit/ratelimit_impl.cc @@ -132,7 +132,7 @@ ClientPtr rateLimitClient(Server::Configuration::FactoryContext& context, .clusterManager() .grpcAsyncClientManager() .getOrCreateRawAsyncClientWithHashKey(config_with_hash_key, context.scope(), true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); return std::make_unique(client_or_error.value(), timeout); } diff --git a/source/extensions/filters/http/composite/action.cc b/source/extensions/filters/http/composite/action.cc index 27cfe9e6f28e..9d70c9c10671 100644 --- a/source/extensions/filters/http/composite/action.cc +++ b/source/extensions/filters/http/composite/action.cc @@ -115,7 +115,7 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createStaticActionFactoryCb if (context.factory_context_.has_value()) { auto callback_or_status = factory.createFilterFactoryFromProto( *message, context.stat_prefix_, context.factory_context_.value()); - THROW_IF_STATUS_NOT_OK(callback_or_status, throw); + THROW_IF_NOT_OK_REF(callback_or_status.status()); callback = callback_or_status.value(); } @@ -146,7 +146,7 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createStaticActionFactoryCb if (context.upstream_factory_context_.has_value()) { auto callback_or_status = factory.createFilterFactoryFromProto( *message, context.stat_prefix_, context.upstream_factory_context_.value()); - THROW_IF_STATUS_NOT_OK(callback_or_status, throw); + THROW_IF_NOT_OK_REF(callback_or_status.status()); callback = callback_or_status.value(); } diff --git a/source/extensions/filters/http/ext_authz/config.cc b/source/extensions/filters/http/ext_authz/config.cc index 949d3f4654db..bfdab7fe36f2 100644 --- a/source/extensions/filters/http/ext_authz/config.cc +++ b/source/extensions/filters/http/ext_authz/config.cc @@ -54,7 +54,7 @@ Http::FilterFactoryCb ExtAuthzFilterConfig::createFilterFactoryFromProtoWithServ .grpcAsyncClientManager() .getOrCreateRawAsyncClientWithHashKey( config_with_hash_key, server_context.scope(), true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); auto client = std::make_unique( client_or_error.value(), std::chrono::milliseconds(timeout_ms)); callbacks.addStreamFilter(std::make_shared(filter_config, std::move(client))); diff --git a/source/extensions/filters/http/ext_proc/client_impl.cc b/source/extensions/filters/http/ext_proc/client_impl.cc index 8bfc80bc5908..fef44968dc5d 100644 --- a/source/extensions/filters/http/ext_proc/client_impl.cc +++ b/source/extensions/filters/http/ext_proc/client_impl.cc @@ -18,7 +18,7 @@ ExternalProcessorStreamPtr ExternalProcessorClientImpl::start( Http::StreamFilterSidestreamWatermarkCallbacks& sidestream_watermark_callbacks) { auto client_or_error = client_manager_.getOrCreateRawAsyncClientWithHashKey(config_with_hash_key, scope_, true); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); Grpc::AsyncClient grpcClient(client_or_error.value()); return ExternalProcessorStreamImpl::create(std::move(grpcClient), callbacks, options, sidestream_watermark_callbacks); diff --git a/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc b/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc index 63be1f6fe24a..2ffc80e63720 100644 --- a/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc +++ b/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc @@ -124,7 +124,7 @@ JsonTranscoderConfig::JsonTranscoderConfig( case envoy::extensions::filters::http::grpc_json_transcoder::v3::GrpcJsonTranscoder:: DescriptorSetCase::kProtoDescriptor: { auto file_or_error = api.fileSystem().fileReadToEnd(proto_config.proto_descriptor()); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); if (!descriptor_set.ParseFromString(file_or_error.value())) { throw EnvoyException("transcoding_filter: Unable to parse proto descriptor"); } diff --git a/source/extensions/filters/http/rate_limit_quota/client_impl.cc b/source/extensions/filters/http/rate_limit_quota/client_impl.cc index 92390ea8a302..7d886a49e7b3 100644 --- a/source/extensions/filters/http/rate_limit_quota/client_impl.cc +++ b/source/extensions/filters/http/rate_limit_quota/client_impl.cc @@ -9,7 +9,7 @@ namespace RateLimitQuota { Grpc::RawAsyncClientSharedPtr getOrThrow(absl::StatusOr client_or_error) { - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); return client_or_error.value(); } diff --git a/source/extensions/filters/network/ext_authz/config.cc b/source/extensions/filters/network/ext_authz/config.cc index b4d62365d02f..ab0560664863 100644 --- a/source/extensions/filters/network/ext_authz/config.cc +++ b/source/extensions/filters/network/ext_authz/config.cc @@ -34,7 +34,7 @@ Network::FilterFactoryCb ExtAuthzConfigFactory::createFilterFactoryFromProtoType .clusterManager() .grpcAsyncClientManager() .factoryForGrpcService(grpc_service, context.scope(), true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); auto client = std::make_unique( factory_or_error.value()->createUncachedRawAsyncClient(), std::chrono::milliseconds(timeout_ms)); diff --git a/source/extensions/filters/network/mongo_proxy/proxy.cc b/source/extensions/filters/network/mongo_proxy/proxy.cc index 87f9b6a073d6..fd56c5caa8a7 100644 --- a/source/extensions/filters/network/mongo_proxy/proxy.cc +++ b/source/extensions/filters/network/mongo_proxy/proxy.cc @@ -39,7 +39,7 @@ AccessLog::AccessLog(const std::string& file_name, Envoy::AccessLog::AccessLogMa : time_source_(time_source) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, file_name}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } diff --git a/source/extensions/filters/network/redis_proxy/config.cc b/source/extensions/filters/network/redis_proxy/config.cc index ebae3bee724a..9e45c04a3d4f 100644 --- a/source/extensions/filters/network/redis_proxy/config.cc +++ b/source/extensions/filters/network/redis_proxy/config.cc @@ -111,7 +111,7 @@ Network::FilterFactoryCb RedisProxyFilterConfigFactory::createFilterFactoryFromP .clusterManager() .grpcAsyncClientManager() .factoryForGrpcService(grpc_service, context.scope(), true); - THROW_IF_STATUS_NOT_OK(auth_client_factory_or_error, throw); + THROW_IF_NOT_OK_REF(auth_client_factory_or_error.status()); auth_client = std::make_unique( auth_client_factory_or_error.value()->createUncachedRawAsyncClient(), diff --git a/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc b/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc index af3407c3d727..fd6f87d7d200 100644 --- a/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc +++ b/source/extensions/filters/network/sni_dynamic_forward_proxy/proxy_filter.cc @@ -22,7 +22,7 @@ ProxyFilterConfig::ProxyFilterConfig( : port_(static_cast(proto_config.port_value())), dns_cache_manager_(cache_manager_factory.get()) { auto cache_or_error = dns_cache_manager_->getCache(proto_config.dns_cache_config()); - THROW_IF_STATUS_NOT_OK(cache_or_error, throw); + THROW_IF_NOT_OK_REF(cache_or_error.status()); dns_cache_ = std::move(cache_or_error.value()); } diff --git a/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc b/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc index 00cd4298aa4a..abfd730e61a4 100644 --- a/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc +++ b/source/extensions/filters/udp/udp_proxy/session_filters/dynamic_forward_proxy/proxy_filter.cc @@ -36,7 +36,7 @@ ProxyFilterConfig::ProxyFilterConfig( DefaultMaxBufferedBytes) : DefaultMaxBufferedBytes) { auto cache_or_error = dns_cache_manager_->getCache(config.dns_cache_config()); - THROW_IF_STATUS_NOT_OK(cache_or_error, throw); + THROW_IF_NOT_OK_REF(cache_or_error.status()); dns_cache_ = std::move(cache_or_error.value()); } diff --git a/source/extensions/health_check/event_sinks/file/file_sink_impl.h b/source/extensions/health_check/event_sinks/file/file_sink_impl.h index b2e51da4f778..712e0fe2964f 100644 --- a/source/extensions/health_check/event_sinks/file/file_sink_impl.h +++ b/source/extensions/health_check/event_sinks/file/file_sink_impl.h @@ -16,7 +16,7 @@ class HealthCheckEventFileSink : public HealthCheckEventSink { AccessLog::AccessLogManager& log_manager) { auto file_or_error = log_manager.createAccessLog( Filesystem::FilePathAndType{Filesystem::DestinationType::File, config.event_log_path()}); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); file_ = file_or_error.value(); } diff --git a/source/extensions/health_checkers/http/health_checker_impl.cc b/source/extensions/health_checkers/http/health_checker_impl.cc index 88c02582abdd..bcbed8bd861e 100644 --- a/source/extensions/health_checkers/http/health_checker_impl.cc +++ b/source/extensions/health_checkers/http/health_checker_impl.cc @@ -76,7 +76,7 @@ HttpHealthCheckerImpl::HttpHealthCheckerImpl( // TODO(boteng): introduce additional validation for the authority and path headers // based on the default UHV when it is available. auto bytes_or_error = PayloadMatcher::loadProtoBytes(config.http_health_check().receive()); - THROW_IF_STATUS_NOT_OK(bytes_or_error, throw); + THROW_IF_NOT_OK_REF(bytes_or_error.status()); receive_bytes_ = bytes_or_error.value(); if (config.http_health_check().has_service_name_matcher()) { service_name_matcher_.emplace(config.http_health_check().service_name_matcher(), diff --git a/source/extensions/health_checkers/tcp/health_checker_impl.cc b/source/extensions/health_checkers/tcp/health_checker_impl.cc index 585df883a571..d1c75e45531b 100644 --- a/source/extensions/health_checkers/tcp/health_checker_impl.cc +++ b/source/extensions/health_checkers/tcp/health_checker_impl.cc @@ -55,7 +55,7 @@ TcpHealthCheckerImpl::TcpHealthCheckerImpl(const Cluster& cluster, send_repeated.Add()->CopyFrom(config.tcp_health_check().send()); } auto bytes_or_error = PayloadMatcher::loadProtoBytes(send_repeated); - THROW_IF_STATUS_NOT_OK(bytes_or_error, throw); + THROW_IF_NOT_OK_REF(bytes_or_error.status()); return bytes_or_error.value(); }()), proxy_protocol_config_(config.tcp_health_check().has_proxy_protocol_config() @@ -63,7 +63,7 @@ TcpHealthCheckerImpl::TcpHealthCheckerImpl(const Cluster& cluster, config.tcp_health_check().proxy_protocol_config()) : nullptr) { auto bytes_or_error = PayloadMatcher::loadProtoBytes(config.tcp_health_check().receive()); - THROW_IF_STATUS_NOT_OK(bytes_or_error, throw); + THROW_IF_NOT_OK_REF(bytes_or_error.status()); receive_bytes_ = bytes_or_error.value(); } diff --git a/source/extensions/key_value/file_based/config.cc b/source/extensions/key_value/file_based/config.cc index 195f07f6c0ed..0822c6a71c2e 100644 --- a/source/extensions/key_value/file_based/config.cc +++ b/source/extensions/key_value/file_based/config.cc @@ -17,7 +17,7 @@ FileBasedKeyValueStore::FileBasedKeyValueStore(Event::Dispatcher& dispatcher, return; } auto file_or_error = file_system_.fileReadToEnd(filename_); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const std::string contents = file_or_error.value(); if (!parseContents(contents)) { ENVOY_LOG(warn, "Failed to parse key value store file {}", filename); diff --git a/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc b/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc index 8b02e398431d..589652b7e77c 100644 --- a/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc +++ b/source/extensions/resource_monitors/injected_resource/injected_resource_monitor.cc @@ -31,7 +31,7 @@ void InjectedResourceMonitor::updateResourceUsage(Server::ResourceUpdateCallback file_changed_ = false; TRY_ASSERT_MAIN_THREAD { auto file_or_error = api_.fileSystem().fileReadToEnd(filename_); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); const std::string contents = file_or_error.value(); double pressure; if (absl::SimpleAtod(contents, &pressure)) { diff --git a/source/extensions/stat_sinks/common/statsd/statsd.cc b/source/extensions/stat_sinks/common/statsd/statsd.cc index 25872589ca74..48f76c620821 100644 --- a/source/extensions/stat_sinks/common/statsd/statsd.cc +++ b/source/extensions/stat_sinks/common/statsd/statsd.cc @@ -197,7 +197,7 @@ TcpStatsdSink::TcpStatsdSink(const LocalInfo::LocalInfo& local_info, THROW_IF_NOT_OK(Config::Utility::checkLocalInfo("tcp statsd", local_info)); const auto cluster_or_error = Config::Utility::checkCluster("tcp statsd", cluster_name, cluster_manager); - THROW_IF_STATUS_NOT_OK(cluster_or_error, throw); + THROW_IF_NOT_OK_REF(cluster_or_error.status()); const auto cluster = cluster_or_error.value(); cluster_info_ = cluster->get().info(); tls_->set([this](Event::Dispatcher& dispatcher) -> ThreadLocal::ThreadLocalObjectSharedPtr { diff --git a/source/extensions/stat_sinks/dog_statsd/config.cc b/source/extensions/stat_sinks/dog_statsd/config.cc index 78c39f20d914..a3fd1941cbe1 100644 --- a/source/extensions/stat_sinks/dog_statsd/config.cc +++ b/source/extensions/stat_sinks/dog_statsd/config.cc @@ -23,7 +23,7 @@ DogStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, MessageUtil::downcastAndValidate( config, server.messageValidationContext().staticValidationVisitor()); auto address_or_error = Network::Address::resolveProtoAddress(sink_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "dog_statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; diff --git a/source/extensions/stat_sinks/graphite_statsd/config.cc b/source/extensions/stat_sinks/graphite_statsd/config.cc index 93322442900d..1afd0a8846c3 100644 --- a/source/extensions/stat_sinks/graphite_statsd/config.cc +++ b/source/extensions/stat_sinks/graphite_statsd/config.cc @@ -26,7 +26,7 @@ GraphiteStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, case envoy::extensions::stat_sinks::graphite_statsd::v3::GraphiteStatsdSink::StatsdSpecifierCase:: kAddress: { auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; diff --git a/source/extensions/stat_sinks/metrics_service/config.cc b/source/extensions/stat_sinks/metrics_service/config.cc index 791f81508f31..1463b8e943af 100644 --- a/source/extensions/stat_sinks/metrics_service/config.cc +++ b/source/extensions/stat_sinks/metrics_service/config.cc @@ -30,7 +30,7 @@ MetricsServiceSinkFactory::createStatsSink(const Protobuf::Message& config, auto client_or_error = server.clusterManager().grpcAsyncClientManager().getOrCreateRawAsyncClient( grpc_service, server.scope(), false); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); std::shared_ptr> grpc_metrics_streamer = diff --git a/source/extensions/stat_sinks/open_telemetry/config.cc b/source/extensions/stat_sinks/open_telemetry/config.cc index 2dc66d339aef..4b7e806fd018 100644 --- a/source/extensions/stat_sinks/open_telemetry/config.cc +++ b/source/extensions/stat_sinks/open_telemetry/config.cc @@ -29,7 +29,7 @@ OpenTelemetrySinkFactory::createStatsSink(const Protobuf::Message& config, auto client_or_error = server.clusterManager().grpcAsyncClientManager().getOrCreateRawAsyncClient( grpc_service, server.scope(), false); - THROW_IF_STATUS_NOT_OK(client_or_error, throw); + THROW_IF_NOT_OK_REF(client_or_error.status()); std::shared_ptr grpc_metrics_exporter = std::make_shared(otlp_options, client_or_error.value()); diff --git a/source/extensions/stat_sinks/statsd/config.cc b/source/extensions/stat_sinks/statsd/config.cc index ae76707892a0..47b26bbc6834 100644 --- a/source/extensions/stat_sinks/statsd/config.cc +++ b/source/extensions/stat_sinks/statsd/config.cc @@ -24,7 +24,7 @@ StatsdSinkFactory::createStatsSink(const Protobuf::Message& config, switch (statsd_sink.statsd_specifier_case()) { case envoy::config::metrics::v3::StatsdSink::StatsdSpecifierCase::kAddress: { auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); return std::make_unique(server.threadLocal(), std::move(address), diff --git a/source/extensions/tracers/datadog/tracer.cc b/source/extensions/tracers/datadog/tracer.cc index 280647595558..ae5b510f9c0f 100644 --- a/source/extensions/tracers/datadog/tracer.cc +++ b/source/extensions/tracers/datadog/tracer.cc @@ -63,9 +63,9 @@ Tracer::Tracer(const std::string& collector_cluster, const std::string& collecto thread_local_slot_( ThreadLocal::TypedSlot::makeUnique(thread_local_slot_allocator)) { const bool allow_added_via_api = true; - THROW_IF_STATUS_NOT_OK(Config::Utility::checkCluster("envoy.tracers.datadog", collector_cluster, - cluster_manager, allow_added_via_api), - throw); + THROW_IF_NOT_OK_REF(Config::Utility::checkCluster("envoy.tracers.datadog", collector_cluster, + cluster_manager, allow_added_via_api) + .status()); thread_local_slot_->set([&logger = ENVOY_LOGGER(), collector_cluster, collector_reference_host, config, &tracer_stats = tracer_stats_, &cluster_manager, diff --git a/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc b/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc index d3fe8624c65d..5d9a9ed7b62e 100644 --- a/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc +++ b/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.cc @@ -92,7 +92,7 @@ Driver::Driver(const envoy::config::trace::v3::OpenTelemetryConfig& opentelemetr auto factory_or_error = factory_context.clusterManager().grpcAsyncClientManager().factoryForGrpcService( opentelemetry_config.grpc_service(), factory_context.scope(), true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); Grpc::AsyncClientFactoryPtr&& factory = std::move(factory_or_error.value()); const Grpc::RawAsyncClientSharedPtr& async_client_shared_ptr = factory->createUncachedRawAsyncClient(); diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc index d312b83f707d..5e73f32fe942 100644 --- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc +++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc @@ -38,7 +38,7 @@ Driver::Driver(const envoy::config::trace::v3::SkyWalkingConfig& proto_config, auto factory_or_error = factory_context.clusterManager().grpcAsyncClientManager().factoryForGrpcService( proto_config.grpc_service(), factory_context.scope(), true); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); TracerPtr tracer = std::make_unique(std::make_unique( std::move(factory_or_error.value()), dispatcher, factory_context.api().randomGenerator(), tracing_stats_, config_.delayed_buffer_size(), config_.token())); diff --git a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc index 2fda60aca87d..88b0f5d57325 100644 --- a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc +++ b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc @@ -77,10 +77,10 @@ Driver::Driver(const envoy::config::trace::v3::ZipkinConfig& zipkin_config, POOL_COUNTER_PREFIX(scope, "tracing.zipkin."))}, tls_(tls.allocateSlot()), runtime_(runtime), local_info_(local_info), time_source_(time_source) { - THROW_IF_STATUS_NOT_OK(Config::Utility::checkCluster("envoy.tracers.zipkin", - zipkin_config.collector_cluster(), cm_, - /* allow_added_via_api */ true), - throw); + THROW_IF_NOT_OK_REF(Config::Utility::checkCluster("envoy.tracers.zipkin", + zipkin_config.collector_cluster(), cm_, + /* allow_added_via_api */ true) + .status()); cluster_ = zipkin_config.collector_cluster(); hostname_ = !zipkin_config.collector_hostname().empty() ? zipkin_config.collector_hostname() : zipkin_config.collector_cluster(); diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index b19238c8226b..ac23e376900d 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -102,7 +102,7 @@ void ValidationInstance::initialize(const Options& options, auto producer_or_error = Stats::TagProducerImpl::createTagProducer(bootstrap_.stats_config(), options_.statsTags()); - THROW_IF_STATUS_NOT_OK(producer_or_error, throw); + THROW_IF_NOT_OK_REF(producer_or_error.status()); if (!bootstrap_.node().user_agent_build_version().has_version()) { *bootstrap_.mutable_node()->mutable_user_agent_build_version() = VersionInfo::buildVersion(); } diff --git a/source/server/server.cc b/source/server/server.cc index a8fbc195549e..6b3418bb84e6 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -828,7 +828,7 @@ void InstanceBase::onRuntimeReady() { // HDS does not support xDS-Failover. auto factory_or_error = Config::Utility::factoryForGrpcApiConfigSource( *async_client_manager_, hds_config, *stats_store_.rootScope(), false, 0); - THROW_IF_STATUS_NOT_OK(factory_or_error, throw); + THROW_IF_NOT_OK_REF(factory_or_error.status()); hds_delegate_ = std::make_unique( serverFactoryContext(), *stats_store_.rootScope(), factory_or_error.value()->createUncachedRawAsyncClient(), stats_store_, diff --git a/test/common/http/async_client_impl_test.cc b/test/common/http/async_client_impl_test.cc index dab5f185d3dc..0885eb927d3a 100644 --- a/test/common/http/async_client_impl_test.cc +++ b/test/common/http/async_client_impl_test.cc @@ -2221,7 +2221,7 @@ class AsyncClientImplUnitTest : public AsyncClientImplTest { auto policy_or_error = Router::RetryPolicyImpl::create(proto_policy, ProtobufMessage::getNullValidationVisitor(), factory_context, client_.factory_context_); - THROW_IF_STATUS_NOT_OK(policy_or_error, throw); + THROW_IF_NOT_OK_REF(policy_or_error.status()); retry_policy_ = std::move(policy_or_error.value()); EXPECT_TRUE(retry_policy_.get()); @@ -2259,7 +2259,7 @@ class AsyncClientImplUnitTest : public AsyncClientImplTest { auto policy_or_error = Router::RetryPolicyImpl::create(proto_policy, ProtobufMessage::getNullValidationVisitor(), factory_context, client_.factory_context_); - THROW_IF_STATUS_NOT_OK(policy_or_error, throw); + THROW_IF_NOT_OK_REF(policy_or_error.status()); retry_policy_ = std::move(policy_or_error.value()); EXPECT_TRUE(retry_policy_.get()); diff --git a/test/common/router/header_formatter_test.cc b/test/common/router/header_formatter_test.cc index 324492f2e689..0e27b66d6939 100644 --- a/test/common/router/header_formatter_test.cc +++ b/test/common/router/header_formatter_test.cc @@ -217,7 +217,7 @@ TEST(HeaderParserTest, TestParse) { if (test_case.expected_exception_) { EXPECT_FALSE(test_case.expected_output_); - EXPECT_THROW(THROW_IF_STATUS_NOT_OK(HeaderParser::configure(to_add), throw), EnvoyException); + EXPECT_THROW(THROW_IF_NOT_OK_REF(HeaderParser::configure(to_add).status()), EnvoyException); continue; } diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index b7c23e96f2ae..3ef5cef66f7f 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -75,7 +75,7 @@ class UpstreamImplTestBase { ClusterFactoryContext& context) { StaticClusterFactory factory; auto status_or_cluster = factory.createClusterImpl(cluster, context); - THROW_IF_STATUS_NOT_OK(status_or_cluster, throw); + THROW_IF_NOT_OK_REF(status_or_cluster.status()); return std::dynamic_pointer_cast(status_or_cluster->first); } diff --git a/test/extensions/clusters/original_dst/original_dst_cluster_test.cc b/test/extensions/clusters/original_dst/original_dst_cluster_test.cc index 301860fb6811..d0e1cd8e82f7 100644 --- a/test/extensions/clusters/original_dst/original_dst_cluster_test.cc +++ b/test/extensions/clusters/original_dst/original_dst_cluster_test.cc @@ -85,7 +85,7 @@ class OriginalDstClusterTest : public Event::TestUsingSimulatedTime, public test OriginalDstClusterFactory factory; auto status_or_pair = factory.createClusterImpl(cluster_config, factory_context); - THROW_IF_STATUS_NOT_OK(status_or_pair, throw); + THROW_IF_NOT_OK_REF(status_or_pair.status()); cluster_ = std::dynamic_pointer_cast(status_or_pair.value().first); priority_update_cb_ = cluster_->prioritySet().addPriorityUpdateCb( diff --git a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc index a39c18d30433..fd3a4819cf10 100644 --- a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc +++ b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc @@ -60,7 +60,7 @@ class DnsCacheImplTest : public testing::Test, public Event::TestUsingSimulatedT EXPECT_CALL(dns_resolver_factory_, createDnsResolver(_, _, _)) .WillRepeatedly(Return(resolver_)); auto status_or_cache = DnsCacheImpl::createDnsCacheImpl(context_, config_); - THROW_IF_STATUS_NOT_OK(status_or_cache, throw); + THROW_IF_NOT_OK_REF(status_or_cache.status()); dns_cache_ = status_or_cache.value(); update_callbacks_handle_ = dns_cache_->addUpdateCallbacks(update_callbacks_); } diff --git a/test/extensions/filters/http/common/fuzz/uber_filter.cc b/test/extensions/filters/http/common/fuzz/uber_filter.cc index 514379e66792..d4ada699261d 100644 --- a/test/extensions/filters/http/common/fuzz/uber_filter.cc +++ b/test/extensions/filters/http/common/fuzz/uber_filter.cc @@ -81,7 +81,7 @@ void UberFilterFuzzer::fuzz( // Clean-up config with filter-specific logic before it runs through validations. cleanFuzzedConfig(proto_config.name(), message.get()); auto cb_or = factory.createFilterFactoryFromProto(*message, "stats", factory_context_); - THROW_IF_STATUS_NOT_OK(cb_or, throw); + THROW_IF_NOT_OK_REF(cb_or.status()); cb_ = cb_or.value(); cb_(filter_callback_); } catch (const EnvoyException& e) { diff --git a/test/fuzz/utility.h b/test/fuzz/utility.h index 25120a3f69b6..d1ac39a70aa6 100644 --- a/test/fuzz/utility.h +++ b/test/fuzz/utility.h @@ -171,7 +171,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn stream_info.address().envoy_internal_address().server_listener_name())); } else { auto address_or_error = Envoy::Network::Address::resolveProtoAddress(stream_info.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); + THROW_IF_NOT_OK_REF(address_or_error.status()); address = address_or_error.value(); } } else { @@ -181,7 +181,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn if (stream_info.has_upstream_local_address()) { auto upstream_local_address_or_error = Envoy::Network::Address::resolveProtoAddress(stream_info.upstream_local_address()); - THROW_IF_STATUS_NOT_OK(upstream_local_address_or_error, throw); + THROW_IF_NOT_OK_REF(upstream_local_address_or_error.status()); upstream_local_address = upstream_local_address_or_error.value(); } else { upstream_local_address = *Network::Utility::resolveUrl("tcp://10.0.0.1:10000"); diff --git a/test/integration/admin_html/test_server.cc b/test/integration/admin_html/test_server.cc index d371d7b22108..a96432d303e5 100644 --- a/test/integration/admin_html/test_server.cc +++ b/test/integration/admin_html/test_server.cc @@ -42,7 +42,7 @@ Http::Code testCallback(Http::ResponseHeaderMap& response_headers, Buffer::Insta std::string path = absl::StrCat(prefix, leaf); TRY_ASSERT_MAIN_THREAD { auto file_or_error = file_system.fileReadToEnd(path); - THROW_IF_STATUS_NOT_OK(file_or_error, throw); + THROW_IF_NOT_OK_REF(file_or_error.status()); response.add(file_or_error.value()); } END_TRY From 1ef5996437437d4de34bba620eb457cc28eb3307 Mon Sep 17 00:00:00 2001 From: Athish Pranav D <105591739+Athishpranav2003@users.noreply.github.com> Date: Thu, 12 Sep 2024 00:37:04 +0530 Subject: [PATCH 20/21] jwks: Add UA string to headers (#35977) Commit Message: Add the "Go-browser" UA string to the headers to make request for JWKS Fetcher Additional Description: Since none of the requests are having a UA string it makes sense to add it as part of utility lib itself Risk Level: N/A Testing: N/A Docs Changes: N/A Release Notes: N/A Platform Specific Features: N/A Fixes #35785 --------- Signed-off-by: Athish Pranav D --- source/common/http/headers.h | 1 + .../filters/http/common/jwks_fetcher.cc | 1 + .../filters/http/common/jwks_fetcher_test.cc | 22 +++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/source/common/http/headers.h b/source/common/http/headers.h index b1368b060ea3..17550b4a0b62 100644 --- a/source/common/http/headers.h +++ b/source/common/http/headers.h @@ -350,6 +350,7 @@ class HeaderValues { struct { const std::string EnvoyHealthChecker{"Envoy/HC"}; + const std::string GoBrowser{"Go-browser"}; } UserAgentValues; struct { diff --git a/source/extensions/filters/http/common/jwks_fetcher.cc b/source/extensions/filters/http/common/jwks_fetcher.cc index 70cdbbc4c77b..fa281f973520 100644 --- a/source/extensions/filters/http/common/jwks_fetcher.cc +++ b/source/extensions/filters/http/common/jwks_fetcher.cc @@ -57,6 +57,7 @@ class JwksFetcherImpl : public JwksFetcher, Http::RequestMessagePtr message = Http::Utility::prepareHeaders(remote_jwks_.http_uri()); message->headers().setReferenceMethod(Http::Headers::get().MethodValues.Get); + message->headers().setReferenceUserAgent(Http::Headers::get().UserAgentValues.GoBrowser); ENVOY_LOG(debug, "fetch pubkey from [uri = {}]: start", remote_jwks_.http_uri().uri()); auto options = Http::AsyncClient::RequestOptions() .setTimeout(std::chrono::milliseconds( diff --git a/test/extensions/filters/http/common/jwks_fetcher_test.cc b/test/extensions/filters/http/common/jwks_fetcher_test.cc index 59184dda5b0e..571b61e23208 100644 --- a/test/extensions/filters/http/common/jwks_fetcher_test.cc +++ b/test/extensions/filters/http/common/jwks_fetcher_test.cc @@ -81,6 +81,28 @@ TEST_F(JwksFetcherTest, TestGetSuccess) { fetcher_->fetch(parent_span_, receiver); } +TEST_F(JwksFetcherTest, TestMessageHeader) { + // Setup + setupFetcher(config); + MockUpstream mock_pubkey(mock_factory_ctx_.server_factory_context_.cluster_manager_, "200", + publicKey); + MockJwksReceiver receiver; + + // Expectations for message + EXPECT_CALL(mock_factory_ctx_.server_factory_context_.cluster_manager_.thread_local_cluster_ + .async_client_, + send_(_, _, _)) + .WillOnce(Invoke([](Http::RequestMessagePtr& message, Http::AsyncClient::Callbacks&, + const Http::AsyncClient::RequestOptions&) -> Http::AsyncClient::Request* { + EXPECT_EQ(message->headers().getUserAgentValue(), + Http::Headers::get().UserAgentValues.GoBrowser); + return nullptr; + })); + + // Act + fetcher_->fetch(parent_span_, receiver); +} + TEST_F(JwksFetcherTest, TestGet400) { // Setup setupFetcher(config); From 4d121628c648d2f565b4e6651484036981051763 Mon Sep 17 00:00:00 2001 From: Can Cecen Date: Wed, 11 Sep 2024 14:48:03 -0700 Subject: [PATCH 21/21] Add a CPU utilization resource monitor for overload manager (#34713) Commit Message: Add a CPU utilization resource monitor for overload manager. i.e. this can be configured to reject requests once CPU Utilization reaches a certain brownout point. Signed-off-by: Can Cecen --- CODEOWNERS | 1 + api/BUILD | 1 + .../cpu_utilization/v3/BUILD | 9 ++ .../cpu_utilization/v3/cpu_utilization.proto | 19 +++ api/versioning/BUILD | 1 + changelogs/current.yaml | 4 + .../cpu_utilization_monitor_overload.yaml | 55 +++++++++ .../overload_manager/overload_manager.rst | 23 +++- source/extensions/extensions_build_config.bzl | 1 + source/extensions/extensions_metadata.yaml | 7 ++ .../resource_monitors/cpu_utilization/BUILD | 59 +++++++++ .../cpu_utilization/config.cc | 32 +++++ .../cpu_utilization/config.h | 29 +++++ .../cpu_utilization/cpu_stats_reader.h | 35 ++++++ .../cpu_utilization_monitor.cc | 72 +++++++++++ .../cpu_utilization/cpu_utilization_monitor.h | 33 +++++ .../cpu_utilization/linux_cpu_stats_reader.cc | 53 ++++++++ .../cpu_utilization/linux_cpu_stats_reader.h | 26 ++++ .../resource_monitors/cpu_utilization/BUILD | 53 ++++++++ .../cpu_utilization/config_test.cc | 38 ++++++ .../cpu_utilization_monitor_test.cc | 113 ++++++++++++++++++ .../linux_cpu_stats_reader_test.cc | 92 ++++++++++++++ tools/spelling/spelling_dictionary.txt | 1 + 23 files changed, 756 insertions(+), 1 deletion(-) create mode 100644 api/envoy/extensions/resource_monitors/cpu_utilization/v3/BUILD create mode 100644 api/envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.proto create mode 100644 docs/root/configuration/operations/overload_manager/_include/cpu_utilization_monitor_overload.yaml create mode 100644 source/extensions/resource_monitors/cpu_utilization/BUILD create mode 100644 source/extensions/resource_monitors/cpu_utilization/config.cc create mode 100644 source/extensions/resource_monitors/cpu_utilization/config.h create mode 100644 source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h create mode 100644 source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.cc create mode 100644 source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h create mode 100644 source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.cc create mode 100644 source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h create mode 100644 test/extensions/resource_monitors/cpu_utilization/BUILD create mode 100644 test/extensions/resource_monitors/cpu_utilization/config_test.cc create mode 100644 test/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor_test.cc create mode 100644 test/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader_test.cc diff --git a/CODEOWNERS b/CODEOWNERS index 3a4a6091bc07..b5eab51e164a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -142,6 +142,7 @@ extensions/filters/common/original_src @klarose @mattklein123 /*/extensions/resource_monitors/common @eziskind @yanavlasov @nezdolik /*/extensions/resource_monitors/fixed_heap @eziskind @yanavlasov @nezdolik /*/extensions/resource_monitors/downstream_connections @nezdolik @mattklein123 +/*/extensions/resource_monitors/cpu_utilization @cancecen @kbaichoo /*/extensions/retry/priority @alyssawilk @mattklein123 /*/extensions/retry/priority/previous_priorities @alyssawilk @mattklein123 /*/extensions/retry/host @alyssawilk @mattklein123 diff --git a/api/BUILD b/api/BUILD index 1fdfbcd1d0a0..12dafa02ee24 100644 --- a/api/BUILD +++ b/api/BUILD @@ -311,6 +311,7 @@ proto_library( "//envoy/extensions/rbac/matchers/upstream_ip_port/v3:pkg", "//envoy/extensions/regex_engines/v3:pkg", "//envoy/extensions/request_id/uuid/v3:pkg", + "//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg", "//envoy/extensions/resource_monitors/downstream_connections/v3:pkg", "//envoy/extensions/resource_monitors/fixed_heap/v3:pkg", "//envoy/extensions/resource_monitors/injected_resource/v3:pkg", diff --git a/api/envoy/extensions/resource_monitors/cpu_utilization/v3/BUILD b/api/envoy/extensions/resource_monitors/cpu_utilization/v3/BUILD new file mode 100644 index 000000000000..29ebf0741406 --- /dev/null +++ b/api/envoy/extensions/resource_monitors/cpu_utilization/v3/BUILD @@ -0,0 +1,9 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = ["@com_github_cncf_xds//udpa/annotations:pkg"], +) diff --git a/api/envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.proto b/api/envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.proto new file mode 100644 index 000000000000..a8362e7b8d05 --- /dev/null +++ b/api/envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package envoy.extensions.resource_monitors.cpu_utilization.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.resource_monitors.cpu_utilization.v3"; +option java_outer_classname = "CpuUtilizationProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/cpu_utilization/v3;cpu_utilizationv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: CPU utilization] +// [#extension: envoy.resource_monitors.cpu_utilization] + +// The CPU utilization resource monitor reports the Envoy process the CPU Utilization of the entire host. +// Today, this only works on Linux and is calculated using the stats in the /proc/stat file. +message CpuUtilizationConfig { +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 98e2ec21f881..bfc572f7f3bd 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -250,6 +250,7 @@ proto_library( "//envoy/extensions/rbac/matchers/upstream_ip_port/v3:pkg", "//envoy/extensions/regex_engines/v3:pkg", "//envoy/extensions/request_id/uuid/v3:pkg", + "//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg", "//envoy/extensions/resource_monitors/downstream_connections/v3:pkg", "//envoy/extensions/resource_monitors/fixed_heap/v3:pkg", "//envoy/extensions/resource_monitors/injected_resource/v3:pkg", diff --git a/changelogs/current.yaml b/changelogs/current.yaml index d199a25651a2..54811c128e21 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -317,5 +317,9 @@ new_features: change: | The :ref:`xff ` original IP detection method now supports using a list of trusted CIDRs when parsing ``x-forwarded-for``. +- area: resource_monitors + change: | + Added possibility to monitor CPU utilization in Linux based systems via :ref:`cpu utilization monitor + ` in overload manager. deprecated: diff --git a/docs/root/configuration/operations/overload_manager/_include/cpu_utilization_monitor_overload.yaml b/docs/root/configuration/operations/overload_manager/_include/cpu_utilization_monitor_overload.yaml new file mode 100644 index 000000000000..fa8ce6e18a8f --- /dev/null +++ b/docs/root/configuration/operations/overload_manager/_include/cpu_utilization_monitor_overload.yaml @@ -0,0 +1,55 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 8000 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + http_filters: + - name: envoy.filters.http.router + typed_config: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + route_config: + name: local_route + virtual_hosts: + - domains: + - '*' + name: local_service + routes: + - match: {prefix: "/"} + route: {cluster: default_service} + clusters: + - name: default_service + load_assignment: + cluster_name: default_service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10001 +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9901 + +overload_manager: + refresh_interval: 0.25s + resource_monitors: + - name: "envoy.resource_monitors.cpu_utilization" + typed_config: + "@type": type.googleapis.com/envoy.extensions.resource_monitors.cpu_utilization.v3.CpuUtilizationConfig + actions: + - name: "envoy.overload_actions.stop_accepting_requests" + triggers: + - name: "envoy.resource_monitors.cpu_utilization" + scaled: + scaling_threshold: 0.80 + saturation_threshold: 0.95 diff --git a/docs/root/configuration/operations/overload_manager/overload_manager.rst b/docs/root/configuration/operations/overload_manager/overload_manager.rst index 9b66b0d0b047..682e74b302a3 100644 --- a/docs/root/configuration/operations/overload_manager/overload_manager.rst +++ b/docs/root/configuration/operations/overload_manager/overload_manager.rst @@ -353,6 +353,28 @@ It's expected that the first few gradations shouldn't trigger anything, unless there's something seriously wrong e.g. in this example streams using ``>= 128MiB`` in buffers. +CPU Intensive Workload Brownout Protection +------------------------------------------ + +The ``envoy.overload_actions.stop_accepting_requests`` overload action can be used +to protect workloads from browning-out when an unexpected spike in the number of +requests the workload receives that causes the CPU to become saturated. This overload +action when used in conjunction with the ``envoy.resource_monitors.cpu_utilization`` +resource monitor can reduce the pressure on the CPU by cheaply rejecting new requests. +While the real mitigation for such request spikes are horizantally scaling the workload, +this overload action can be used to ensure the fleet does not get into a cascading failure +mode. +Some platform owners may choose to install this overload action by default to protect the fleet, +since it is easier to configure a target CPU utilization percentage than to configure a request rate per +workload. + +.. literalinclude:: _include/cpu_utilization_monitor_overload.yaml + :language: yaml + :lines: 43-55 + :emphasize-lines: 3-13 + :linenos: + :caption: :download:`cpu_utilization_monitor_overload.yaml <_include/cpu_utilization_monitor_overload.yaml>` + Statistics ---------- @@ -388,4 +410,3 @@ with the following statistics: scale_percent, Gauge, "Scaled value of the action as a percent (0-99=scaling, 100=saturated)" shed_load_count, Counter, "Total count the load is sheded" - diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index 8c1175d929a7..e8ddaf2a8bb7 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -248,6 +248,7 @@ EXTENSIONS = { "envoy.resource_monitors.fixed_heap": "//source/extensions/resource_monitors/fixed_heap:config", "envoy.resource_monitors.injected_resource": "//source/extensions/resource_monitors/injected_resource:config", "envoy.resource_monitors.global_downstream_max_connections": "//source/extensions/resource_monitors/downstream_connections:config", + "envoy.resource_monitors.cpu_utilization": "//source/extensions/resource_monitors/cpu_utilization:config", # # Stat sinks diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 894d9939c149..8bde25426929 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -1077,6 +1077,13 @@ envoy.request_id.uuid: status: stable type_urls: - envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig +envoy.resource_monitors.cpu_utilization: + categories: + - envoy.resource_monitors + security_posture: data_plane_agnostic + status: alpha + type_urls: + - envoy.extensions.resource_monitors.cpu_utilization.v3.CpuUtilizationConfig envoy.resource_monitors.global_downstream_max_connections: categories: - envoy.resource_monitors diff --git a/source/extensions/resource_monitors/cpu_utilization/BUILD b/source/extensions/resource_monitors/cpu_utilization/BUILD new file mode 100644 index 000000000000..c629250fa278 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/BUILD @@ -0,0 +1,59 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_library( + name = "cpu_utilization_monitor", + srcs = ["cpu_utilization_monitor.cc"], + hdrs = [ + "cpu_stats_reader.h", + "cpu_utilization_monitor.h", + ], + tags = ["skip_on_windows"], + deps = [ + "//envoy/common:exception_lib", + "//envoy/server:resource_monitor_config_interface", + "//source/common/runtime:runtime_features_lib", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) + +envoy_cc_library( + name = "linux_cpu_stats_reader", + srcs = ["linux_cpu_stats_reader.cc"], + hdrs = [ + "cpu_stats_reader.h", + "cpu_utilization_monitor.h", + "linux_cpu_stats_reader.h", + ], + tags = ["skip_on_windows"], + deps = [ + "//source/common/common:logger_lib", + "@com_google_absl//absl/strings", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + tags = ["skip_on_windows"], + deps = [ + ":cpu_utilization_monitor", + ":linux_cpu_stats_reader", + "//envoy/registry", + "//envoy/server:resource_monitor_config_interface", + "//source/common/common:logger_lib", + "//source/extensions/resource_monitors/common:factory_base_lib", + "//source/server:configuration_lib", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/resource_monitors/cpu_utilization/config.cc b/source/extensions/resource_monitors/cpu_utilization/config.cc new file mode 100644 index 000000000000..f04efa9187d6 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/config.cc @@ -0,0 +1,32 @@ +#include "source/extensions/resource_monitors/cpu_utilization/config.h" + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.validate.h" +#include "envoy/registry/registry.h" + +#include "source/common/protobuf/utility.h" +#include "source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h" +#include "source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +Server::ResourceMonitorPtr CpuUtilizationMonitorFactory::createResourceMonitorFromProtoTyped( + const envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig& config, + Server::Configuration::ResourceMonitorFactoryContext& /*unused_context*/) { + // In the future, the below can be configurable based on the operating system. + auto cpu_stats_reader = std::make_unique(); + return std::make_unique(config, std::move(cpu_stats_reader)); +} + +/** + * Static registration for the cpu resource monitor factory. @see RegistryFactory. + */ +REGISTER_FACTORY(CpuUtilizationMonitorFactory, Server::Configuration::ResourceMonitorFactory); + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/config.h b/source/extensions/resource_monitors/cpu_utilization/config.h new file mode 100644 index 000000000000..fb7ec2dbda9e --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/config.h @@ -0,0 +1,29 @@ +#pragma once + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.validate.h" +#include "envoy/server/resource_monitor_config.h" + +#include "source/extensions/resource_monitors/common/factory_base.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +class CpuUtilizationMonitorFactory + : public Common::FactoryBase< + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig> { +public: + CpuUtilizationMonitorFactory() : FactoryBase("envoy.resource_monitors.cpu_utilization") {} + +private: + Server::ResourceMonitorPtr createResourceMonitorFromProtoTyped( + const envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig& config, + Server::Configuration::ResourceMonitorFactoryContext& context) override; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h b/source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h new file mode 100644 index 000000000000..60aff11e13e8 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#include "source/common/common/logger.h" + +#include "absl/strings/str_split.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +struct CpuTimes { + bool is_valid; + uint64_t work_time; + uint64_t total_time; +}; + +class CpuStatsReader { +public: + CpuStatsReader() = default; + virtual ~CpuStatsReader() = default; + virtual CpuTimes getCpuTimes() = 0; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.cc b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.cc new file mode 100644 index 000000000000..6ff035430bd1 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.cc @@ -0,0 +1,72 @@ +#include "source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "source/common/common/fmt.h" + +#include "absl/strings/str_split.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +// The dampening alpha value used for EWMA calculation. +// The value is chosen to be very small to give past calculations higher priority. +// This helps in reducing the impact of sudden spikes or drops in CPU utilization. +constexpr double DAMPENING_ALPHA = 0.05; + +CpuUtilizationMonitor::CpuUtilizationMonitor( + const envoy::extensions::resource_monitors::cpu_utilization::v3:: + CpuUtilizationConfig& /*config*/, + std::unique_ptr cpu_stats_reader) + : utilization_(0.0), cpu_stats_reader_(std::move(cpu_stats_reader)) { + previous_cpu_times_ = cpu_stats_reader_->getCpuTimes(); +} + +void CpuUtilizationMonitor::updateResourceUsage(Server::ResourceUpdateCallbacks& callbacks) { + CpuTimes cpu_times = cpu_stats_reader_->getCpuTimes(); + if (!cpu_times.is_valid) { + const auto& error = EnvoyException("Can't open file to read CPU utilization"); + callbacks.onFailure(error); + return; + } + + const int64_t work_over_period = cpu_times.work_time - previous_cpu_times_.work_time; + const int64_t total_over_period = cpu_times.total_time - previous_cpu_times_.total_time; + if (work_over_period < 0 || total_over_period <= 0) { + const auto& error = EnvoyException( + fmt::format("Erroneous CPU stats calculation. Work_over_period='{}' cannot " + "be a negative number and total_over_period='{}' must be a positive number.", + work_over_period, total_over_period)); + callbacks.onFailure(error); + return; + } + const double current_utilization = static_cast(work_over_period) / total_over_period; + ENVOY_LOG_MISC(trace, "Prev work={}, Cur work={}, Prev Total={}, Cur Total={}", + previous_cpu_times_.work_time, cpu_times.work_time, previous_cpu_times_.total_time, + cpu_times.total_time); + // The new utilization is calculated/smoothed using EWMA + utilization_ = current_utilization * DAMPENING_ALPHA + (1 - DAMPENING_ALPHA) * utilization_; + + Server::ResourceUsage usage; + usage.resource_pressure_ = utilization_; + + callbacks.onSuccess(usage); + + previous_cpu_times_ = cpu_times; +} + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h new file mode 100644 index 000000000000..c23197695457 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/server/resource_monitor.h" + +#include "source/common/runtime/runtime_features.h" +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +class CpuUtilizationMonitor : public Server::ResourceMonitor { +public: + CpuUtilizationMonitor( + const envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig& config, + std::unique_ptr cpu_stats_reader); + + void updateResourceUsage(Server::ResourceUpdateCallbacks& callbacks) override; + +private: + double utilization_; + CpuTimes previous_cpu_times_; + std::unique_ptr cpu_stats_reader_; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.cc b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.cc new file mode 100644 index 000000000000..c5a9e75ea20f --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.cc @@ -0,0 +1,53 @@ +#include "source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h" + +#include +#include + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +constexpr uint64_t NUMBER_OF_CPU_TIMES_TO_PARSE = + 4; // we are interested in user, nice, system and idle times. + +LinuxCpuStatsReader::LinuxCpuStatsReader(const std::string& cpu_stats_filename) + : cpu_stats_filename_(cpu_stats_filename) {} + +CpuTimes LinuxCpuStatsReader::getCpuTimes() { + std::ifstream cpu_stats_file; + cpu_stats_file.open(cpu_stats_filename_); + if (!cpu_stats_file.is_open()) { + ENVOY_LOG_MISC(error, "Can't open linux cpu stats file {}", cpu_stats_filename_); + return {false, 0, 0}; + } + + // The first 5 bytes should be 'cpu ' without a cpu index. + std::string buffer(5, '\0'); + cpu_stats_file.read(buffer.data(), 5); + const std::string target = "cpu "; + if (!cpu_stats_file || buffer != target) { + ENVOY_LOG_MISC(error, "Unexpected format in linux cpu stats file {}", cpu_stats_filename_); + return {false, 0, 0}; + } + + std::array times; + for (uint64_t time, i = 0; i < NUMBER_OF_CPU_TIMES_TO_PARSE; ++i) { + cpu_stats_file >> time; + if (!cpu_stats_file) { + ENVOY_LOG_MISC(error, "Unexpected format in linux cpu stats file {}", cpu_stats_filename_); + return {false, 0, 0}; + } + times[i] = time; + } + + uint64_t work_time, total_time; + work_time = times[0] + times[1] + times[2]; // user + nice + system + total_time = work_time + times[3]; // idle + return {true, work_time, total_time}; +} + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h new file mode 100644 index 000000000000..4b6b7b5801a8 --- /dev/null +++ b/source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { + +static const std::string LINUX_CPU_STATS_FILE = "/proc/stat"; + +class LinuxCpuStatsReader : public CpuStatsReader { +public: + LinuxCpuStatsReader(const std::string& cpu_stats_filename = LINUX_CPU_STATS_FILE); + CpuTimes getCpuTimes() override; + +private: + const std::string cpu_stats_filename_; +}; + +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/resource_monitors/cpu_utilization/BUILD b/test/extensions/resource_monitors/cpu_utilization/BUILD new file mode 100644 index 000000000000..22d752a5f06a --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/BUILD @@ -0,0 +1,53 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_extension_cc_test( + name = "cpu_utilization_monitor_test", + srcs = ["cpu_utilization_monitor_test.cc"], + extension_names = ["envoy.resource_monitors.cpu_utilization"], + external_deps = ["abseil_optional"], + tags = ["skip_on_windows"], + deps = [ + "//source/extensions/resource_monitors/cpu_utilization:cpu_utilization_monitor", + "//source/extensions/resource_monitors/cpu_utilization:linux_cpu_stats_reader", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) + +envoy_extension_cc_test( + name = "linux_cpu_stats_reader_test", + srcs = ["linux_cpu_stats_reader_test.cc"], + extension_names = ["envoy.resource_monitors.cpu_utilization"], + external_deps = ["abseil_optional"], + tags = ["skip_on_windows"], + deps = [ + "//source/extensions/resource_monitors/cpu_utilization:linux_cpu_stats_reader", + "//test/test_common:environment_lib", + ], +) + +envoy_extension_cc_test( + name = "config_test", + srcs = ["config_test.cc"], + extension_names = ["envoy.resource_monitors.cpu_utilization"], + tags = ["skip_on_windows"], + deps = [ + "//envoy/registry", + "//source/common/stats:isolated_store_lib", + "//source/extensions/resource_monitors/cpu_utilization:config", + "//source/server:resource_monitor_config_lib", + "//test/mocks/event:event_mocks", + "//test/mocks/server:options_mocks", + "@envoy_api//envoy/extensions/resource_monitors/cpu_utilization/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/resource_monitors/cpu_utilization/config_test.cc b/test/extensions/resource_monitors/cpu_utilization/config_test.cc new file mode 100644 index 000000000000..bda708a08cf2 --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/config_test.cc @@ -0,0 +1,38 @@ +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" +#include "envoy/registry/registry.h" + +#include "source/extensions/resource_monitors/cpu_utilization/config.h" +#include "source/server/resource_monitor_config_impl.h" + +#include "test/mocks/event/mocks.h" +#include "test/mocks/server/options.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { +namespace { + +TEST(CpuUtilizationMonitorFactoryTest, CreateMonitor) { + auto factory = + Registry::FactoryRegistry::getFactory( + "envoy.resource_monitors.cpu_utilization"); + EXPECT_NE(factory, nullptr); + + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + Event::MockDispatcher dispatcher; + Api::ApiPtr api = Api::createApiForTest(); + Server::MockOptions options; + Server::Configuration::ResourceMonitorFactoryContextImpl context( + dispatcher, options, *api, ProtobufMessage::getStrictValidationVisitor()); + auto monitor = factory->createResourceMonitor(config, context); + EXPECT_NE(monitor, nullptr); +} + +} // namespace +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor_test.cc b/test/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor_test.cc new file mode 100644 index 000000000000..66d83caf1d0a --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor_test.cc @@ -0,0 +1,113 @@ +#include + +#include "envoy/extensions/resource_monitors/cpu_utilization/v3/cpu_utilization.pb.h" + +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" +#include "source/extensions/resource_monitors/cpu_utilization/cpu_utilization_monitor.h" + +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { +namespace { + +using testing::Return; + +class MockCpuStatsReader : public CpuStatsReader { +public: + MockCpuStatsReader() = default; + + MOCK_METHOD(CpuTimes, getCpuTimes, ()); +}; + +class ResourcePressure : public Server::ResourceUpdateCallbacks { +public: + void onSuccess(const Server::ResourceUsage& usage) override { + pressure_ = usage.resource_pressure_; + } + + void onFailure(const EnvoyException& error) override { error_ = error; } + + bool hasPressure() const { return pressure_.has_value(); } + bool hasError() const { return error_.has_value(); } + + double pressure() const { return *pressure_; } + +private: + absl::optional pressure_; + absl::optional error_; +}; + +TEST(CpuUtilizationMonitorTest, ComputesCorrectUsage) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{true, 50, 100})) + .WillOnce(Return(CpuTimes{true, 100, 200})) + .WillOnce(Return(CpuTimes{true, 200, 300})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasPressure()); + ASSERT_FALSE(resource.hasError()); + EXPECT_DOUBLE_EQ(resource.pressure(), 0.025); // dampening + + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasPressure()); + ASSERT_FALSE(resource.hasError()); + EXPECT_DOUBLE_EQ(resource.pressure(), 0.07375); // dampening +} + +TEST(CpuUtilizationMonitorTest, GetsErroneousStatsDenominator) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{true, 100, 100})) + .WillOnce(Return(CpuTimes{true, 100, 99})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); +} + +TEST(CpuUtilizationMonitorTest, GetsErroneousStatsNumerator) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{true, 100, 100})) + .WillOnce(Return(CpuTimes{true, 99, 150})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); +} + +TEST(CpuUtilizationMonitorTest, ReportsError) { + envoy::extensions::resource_monitors::cpu_utilization::v3::CpuUtilizationConfig config; + auto stats_reader = std::make_unique(); + EXPECT_CALL(*stats_reader, getCpuTimes()) + .WillOnce(Return(CpuTimes{false, 0, 0})) + .WillOnce(Return(CpuTimes{false, 0, 0})) + .WillOnce(Return(CpuTimes{false, 0, 200})); + auto monitor = std::make_unique(config, std::move(stats_reader)); + + ResourcePressure resource; + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); + + monitor->updateResourceUsage(resource); + ASSERT_TRUE(resource.hasError()); +} + +} // namespace +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader_test.cc b/test/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader_test.cc new file mode 100644 index 000000000000..a7d0476a4a82 --- /dev/null +++ b/test/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader_test.cc @@ -0,0 +1,92 @@ +#include + +#include "source/extensions/resource_monitors/cpu_utilization/cpu_stats_reader.h" +#include "source/extensions/resource_monitors/cpu_utilization/linux_cpu_stats_reader.h" + +#include "test/test_common/environment.h" + +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace ResourceMonitors { +namespace CpuUtilizationMonitor { +namespace { + +TEST(LinuxCpuStatsReader, ReadsCpuStats) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats"); + AtomicFileUpdater file_updater(temp_path); + const std::string contents = R"EOF(cpu 14987204 4857 3003536 11594988 53631 0 759314 2463 0 0 +cpu0 1907532 599 369969 1398344 5970 0 121763 18 0 0 +cpu1 1883161 620 375962 1448133 5963 0 85914 10 0 0 +cpu2 1877318 610 376223 1458160 5713 0 81227 10 0 0 +cpu3 1844673 653 373370 1493333 6063 0 80492 1124 0 0 +cpu4 1879904 572 380089 1440757 7348 0 91022 10 0 0 +cpu5 1873470 607 377632 1449005 6359 0 94092 8 0 0 +cpu6 1878276 576 375458 1423527 7995 0 115756 8 0 0 +cpu7 1842866 615 374829 1483725 8218 0 89044 1272 0 0 +intr 1219233916 0 10 0 0 555 0 0 0 0 0 0 0 154 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 12 20859 24167 1125607 1182080 40577 52852415 108966441 51142451 43742777 52285969 56216800 52419266 95242197 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +ctxt 5657586121 +btime 1700654901 +processes 34530 +procs_running 7 +procs_blocked 0 +softirq 1714610175 0 8718679 72686 1588388544 32 0 293214 77920941 12627 39203452 +)EOF"; + file_updater.update(contents); + + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + + EXPECT_EQ(cpu_times.work_time, 17995597); + EXPECT_EQ(cpu_times.total_time, 29590585); +} + +TEST(LinuxCpuStatsReader, CannotReadFile) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats_not_exists"); + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + EXPECT_FALSE(cpu_times.is_valid); + EXPECT_EQ(cpu_times.work_time, 0); + EXPECT_EQ(cpu_times.total_time, 0); +} + +TEST(LinuxCpuStatsReader, UnexpectedFormatCpuLine) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats_unexpected_format"); + AtomicFileUpdater file_updater(temp_path); + const std::string contents = R"EOF(cpu0 1907532 599 369969 1398344 5970 0 121763 18 0 0 +cpu1 1883161 620 375962 1448133 5963 0 85914 10 0 0 +cpu 14987204 4857 3003536 11594988 53631 0 759314 2463 0 0 +)EOF"; + file_updater.update(contents); + + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + EXPECT_FALSE(cpu_times.is_valid); + EXPECT_EQ(cpu_times.work_time, 0); + EXPECT_EQ(cpu_times.total_time, 0); +} + +TEST(LinuxCpuStatsReader, UnexpectedFormatMissingTokens) { + const std::string temp_path = TestEnvironment::temporaryPath("cpu_stats_unexpected_format"); + AtomicFileUpdater file_updater(temp_path); + const std::string contents = R"EOF(cpu 14987204 4857 3003536 +cpu0 1907532 599 369969 1398344 5970 0 121763 18 0 0 +cpu1 1883161 620 375962 1448133 5963 0 85914 10 0 0 +)EOF"; + file_updater.update(contents); + + LinuxCpuStatsReader cpu_stats_reader(temp_path); + CpuTimes cpu_times = cpu_stats_reader.getCpuTimes(); + EXPECT_FALSE(cpu_times.is_valid); + EXPECT_EQ(cpu_times.work_time, 0); + EXPECT_EQ(cpu_times.total_time, 0); +} + +} // namespace +} // namespace CpuUtilizationMonitor +} // namespace ResourceMonitors +} // namespace Extensions +} // namespace Envoy diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index 263479eba905..452a48b9a23e 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -1537,3 +1537,4 @@ NAT NXDOMAIN DNAT RSP +EWMA