From c189ec331cae6f5b1e5b7782917685322a812ab3 Mon Sep 17 00:00:00 2001 From: Kuat Yessenov Date: Tue, 5 Sep 2023 20:00:31 +0000 Subject: [PATCH] filter state: register DFP objects Signed-off-by: Kuat Yessenov --- .../advanced/well_known_filter_state.rst | 9 ++++- .../common/stream_info/uint32_accessor_impl.h | 3 ++ .../clusters/dynamic_forward_proxy/BUILD | 2 ++ .../clusters/dynamic_forward_proxy/cluster.cc | 36 +++++++++++++++++-- .../dynamic_forward_proxy/cluster_test.cc | 25 +++++++++++++ 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/docs/root/configuration/advanced/well_known_filter_state.rst b/docs/root/configuration/advanced/well_known_filter_state.rst index 4d287cedf614..63dbdefe77ce 100644 --- a/docs/root/configuration/advanced/well_known_filter_state.rst +++ b/docs/root/configuration/advanced/well_known_filter_state.rst @@ -13,9 +13,16 @@ The following list of filter state objects are consumed by Envoy extensions: * - **Filter state key** - **Purpose** * - ``envoy.tcp_proxy.cluster`` - - :ref:`TCP proxy ` dynamic cluster selection on a per-connection basis. + - | :ref:`TCP proxy ` dynamic cluster name selection + | on a per-connection basis. * - ``envoy.network.transport_socket.original_dst_address`` - | :ref:`Original destination cluster ` dynamic address selection. | Fields: | - *ip*: IP address value; | - *port*: port value. + * - ``envoy.upstream.dynamic_host`` + - | :ref:`Dynamic forward proxy `` + | upstream host override on a per-connection basis. + * - ``envoy.upstream.dynamic_port`` + - | :ref:`Dynamic forward proxy `` + | upstream port override on a per-connection basis. diff --git a/source/common/stream_info/uint32_accessor_impl.h b/source/common/stream_info/uint32_accessor_impl.h index 8254ece897a3..862dc9c8028f 100644 --- a/source/common/stream_info/uint32_accessor_impl.h +++ b/source/common/stream_info/uint32_accessor_impl.h @@ -18,6 +18,9 @@ class UInt32AccessorImpl : public UInt32Accessor { message->set_value(value_); return message; } + absl::optional serializeAsString() const override { + return absl::StrCat(value_); + } // From UInt32Accessor. void increment() override { value_++; } diff --git a/source/extensions/clusters/dynamic_forward_proxy/BUILD b/source/extensions/clusters/dynamic_forward_proxy/BUILD index 22d3ceacdfdb..be4b2b430e46 100644 --- a/source/extensions/clusters/dynamic_forward_proxy/BUILD +++ b/source/extensions/clusters/dynamic_forward_proxy/BUILD @@ -20,6 +20,8 @@ envoy_cc_extension( "//source/extensions/common/dynamic_forward_proxy:cluster_store", "//source/extensions/common/dynamic_forward_proxy:dns_cache_interface", "//source/extensions/common/dynamic_forward_proxy:dns_cache_manager_impl", + "//source/common/router:string_accessor_lib", + "//source/common/stream_info:uint32_accessor_lib", "//source/extensions/transport_sockets/tls/cert_validator:cert_validator_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", "@envoy_api//envoy/config/endpoint/v3:pkg_cc_proto", diff --git a/source/extensions/clusters/dynamic_forward_proxy/cluster.cc b/source/extensions/clusters/dynamic_forward_proxy/cluster.cc index 37b455e97f2b..fea3b34f11d0 100644 --- a/source/extensions/clusters/dynamic_forward_proxy/cluster.cc +++ b/source/extensions/clusters/dynamic_forward_proxy/cluster.cc @@ -10,6 +10,8 @@ #include "source/common/http/utility.h" #include "source/common/network/transport_socket_options_impl.h" +#include "source/common/router/string_accessor_impl.h" +#include "source/common/stream_info/uint32_accessor_impl.h" #include "source/extensions/common/dynamic_forward_proxy/dns_cache_manager_impl.h" #include "source/extensions/transport_sockets/tls/cert_validator/default_validator.h" #include "source/extensions/transport_sockets/tls/utility.h" @@ -19,6 +21,36 @@ namespace Extensions { namespace Clusters { namespace DynamicForwardProxy { +namespace { +constexpr absl::string_view DynamicHostFilterStateKey = "envoy.upstream.dynamic_host"; +constexpr absl::string_view DynamicPortFilterStateKey = "envoy.upstream.dynamic_port"; + +class DynamicHostObjectFactory : public StreamInfo::FilterState::ObjectFactory { +public: + std::string name() const override { return std::string(DynamicHostFilterStateKey); } + std::unique_ptr + createFromBytes(absl::string_view data) const override { + return std::make_unique(data); + } +}; +class DynamicPortObjectFactory : public StreamInfo::FilterState::ObjectFactory { +public: + std::string name() const override { return std::string(DynamicPortFilterStateKey); } + std::unique_ptr + createFromBytes(absl::string_view data) const override { + uint32_t port = 0; + if (absl::SimpleAtoi(data, &port)) { + return std::make_unique(port); + } + return nullptr; + } +}; + +} // namespace + +REGISTER_FACTORY(DynamicHostObjectFactory, StreamInfo::FilterState::ObjectFactory); +REGISTER_FACTORY(DynamicPortObjectFactory, StreamInfo::FilterState::ObjectFactory); + Cluster::Cluster( const envoy::config::cluster::v3::Cluster& cluster, const envoy::extensions::clusters::dynamic_forward_proxy::v3::ClusterConfig& config, @@ -316,7 +348,7 @@ Cluster::LoadBalancer::chooseHost(Upstream::LoadBalancerContext* context) { context->downstreamConnection() ->streamInfo() .filterState() - .getDataReadOnly("envoy.upstream.dynamic_host"); + .getDataReadOnly(DynamicHostFilterStateKey); } absl::string_view raw_host; @@ -343,7 +375,7 @@ Cluster::LoadBalancer::chooseHost(Upstream::LoadBalancerContext* context) { context->downstreamConnection() ->streamInfo() .filterState() - .getDataReadOnly("envoy.upstream.dynamic_port"); + .getDataReadOnly(DynamicPortFilterStateKey); if (dynamic_port_filter_state != nullptr && dynamic_port_filter_state->value() > 0 && dynamic_port_filter_state->value() <= 65535) { port = dynamic_port_filter_state->value(); diff --git a/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc b/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc index 72e97c6111dc..0c72656c0668 100644 --- a/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc +++ b/test/extensions/clusters/dynamic_forward_proxy/cluster_test.cc @@ -722,6 +722,31 @@ connect_timeout: 0.25s EXPECT_THROW(createCluster(yaml_config), EnvoyException); } +TEST(ObjectFactory, DynamicHost) { + const std::string name = "envoy.upstream.dynamic_host"; + auto* factory = + Registry::FactoryRegistry::getFactory(name); + ASSERT_NE(nullptr, factory); + EXPECT_EQ(name, factory->name()); + const std::string host = "site.com"; + auto object = factory->createFromBytes(host); + ASSERT_NE(nullptr, object); + EXPECT_EQ(host, object->serializeAsString()); +} + +TEST(ObjectFactory, DynamicPort) { + const std::string name = "envoy.upstream.dynamic_port"; + auto* factory = + Registry::FactoryRegistry::getFactory(name); + ASSERT_NE(nullptr, factory); + EXPECT_EQ(name, factory->name()); + const std::string port = "8080"; + auto object = factory->createFromBytes(port); + ASSERT_NE(nullptr, object); + EXPECT_EQ(port, object->serializeAsString()); + ASSERT_EQ(nullptr, factory->createFromBytes("blah")); +} + } // namespace DynamicForwardProxy } // namespace Clusters } // namespace Extensions