Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expr: Add upstream.locality attribute to obtain upstream host locality #38024

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/root/intro/arch_overview/advanced/attributes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ The following attributes are available once the upstream connection is establish
upstream.transport_failure_reason, string, The upstream transport failure reason e.g. certificate validation failed
upstream.request_attempt_count, uint, The count of upstream request attempts. A value of ‘0’ indicates that the request was never attempted upstream
upstream.cx_pool_ready_duration, duration, Total duration from when the upstream request was created to when the upstream connection pool is ready
upstream.locality, :ref:`Locality<envoy_v3_api_msg_config.core.v3.locality>`, Locality information of upstream host

Metadata and filter state
-------------------------
Expand Down
12 changes: 12 additions & 0 deletions source/extensions/filters/common/expr/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,18 @@ const UpstreamLookupValues& UpstreamLookupValues::get() {
}
return {};
}},
{UpstreamLocality,
[](const UpstreamWrapper& wrapper) -> absl::optional<CelValue> {
if (!wrapper.info_.upstreamInfo().has_value()) {
return {};
}
auto upstream_host = wrapper.info_.upstreamInfo().value().get().upstreamHost();
if (upstream_host == nullptr) {
return {};
}
return CelProtoWrapper::CreateMessage(&upstream_host.get()->locality(),
&wrapper.arena_);
}},
{UpstreamTransportFailureReason,
[](const UpstreamWrapper& wrapper) -> absl::optional<CelValue> {
if (!wrapper.info_.upstreamInfo().has_value()) {
Expand Down
1 change: 1 addition & 0 deletions source/extensions/filters/common/expr/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ constexpr absl::string_view Destination = "destination";
// Upstream properties
constexpr absl::string_view Upstream = "upstream";
constexpr absl::string_view UpstreamLocalAddress = "local_address";
constexpr absl::string_view UpstreamLocality = "locality";
constexpr absl::string_view UpstreamTransportFailureReason = "transport_failure_reason";
constexpr absl::string_view UpstreamRequestAttemptCount = "request_attempt_count";
constexpr absl::string_view UpstreamConnectionPoolReadyDuration = "cx_pool_ready_duration";
Expand Down
2 changes: 2 additions & 0 deletions test/extensions/filters/common/expr/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ envoy_extension_cc_test(
tags = ["skip_on_windows"],
deps = [
"//source/common/network:filter_state_dst_address_lib",
"//source/common/protobuf:utility_lib",
"//source/common/router:string_accessor_lib",
"//source/common/stream_info:stream_info_lib",
"//source/extensions/clusters/original_dst:original_dst_cluster_lib",
Expand All @@ -36,6 +37,7 @@ envoy_extension_cc_test(
"//test/mocks/upstream:host_mocks",
"//test/test_common:test_runtime_lib",
"//test/test_common:utility_lib",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
)

Expand Down
21 changes: 21 additions & 0 deletions test/extensions/filters/common/expr/context_test.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#include "envoy/config/core/v3/base.pb.h"

#include "source/common/network/address_impl.h"
#include "source/common/network/filter_state_dst_address.h"
#include "source/common/network/utility.h"
#include "source/common/protobuf/protobuf.h"
#include "source/common/protobuf/utility.h"
#include "source/common/router/string_accessor_impl.h"
#include "source/common/stream_info/filter_state_impl.h"
#include "source/extensions/filters/common/expr/cel_state.h"
Expand Down Expand Up @@ -548,6 +551,10 @@ TEST(Context, ConnectionAttributes) {
Network::Utility::parseInternetAddressNoThrow("10.1.2.3", 679, false);
Network::Address::InstanceConstSharedPtr upstream_local_address =
Network::Utility::parseInternetAddressNoThrow("10.1.2.3", 1000, false);
::envoy::config::core::v3::Locality upstream_locality;
upstream_locality.set_region("upstream_locality_region");
upstream_locality.set_zone("upstream_locality_zone");
upstream_locality.set_sub_zone("upstream_locality_sub_zone");
const std::string sni_name = "kittens.com";
info.downstream_connection_info_provider_->setLocalAddress(local);
info.downstream_connection_info_provider_->setRemoteAddress(remote);
Expand All @@ -570,6 +577,7 @@ TEST(Context, ConnectionAttributes) {

EXPECT_CALL(*downstream_ssl_info, peerCertificatePresented()).WillRepeatedly(Return(true));
EXPECT_CALL(*upstream_host, address()).WillRepeatedly(Return(upstream_address));
EXPECT_CALL(*upstream_host, locality()).WillRepeatedly(ReturnRef(upstream_locality));

const std::string tls_version = "TLSv1";
EXPECT_CALL(*downstream_ssl_info, tlsVersion()).WillRepeatedly(ReturnRef(tls_version));
Expand Down Expand Up @@ -832,6 +840,14 @@ TEST(Context, ConnectionAttributes) {
ASSERT_TRUE(value.value().IsString());
EXPECT_EQ(upstream_transport_failure_reason, value.value().StringOrDie().value());
}

{
auto value = upstream[CelValue::CreateStringView(UpstreamLocality)];
ASSERT_TRUE(value.has_value());
ASSERT_TRUE(value.value().IsMessage());
EXPECT_TRUE(Protobuf::util::MessageDifferencer::Equals(*value.value().MessageOrDie(),
upstream_locality));
}
}

TEST(Context, FilterStateAttributes) {
Expand Down Expand Up @@ -1187,6 +1203,11 @@ TEST(Context, UpstreamEdgeCases) {
const auto value = upstream[CelValue::CreateStringView(UpstreamConnectionPoolReadyDuration)];
EXPECT_FALSE(value.has_value());
}

{
const auto value = upstream[CelValue::CreateStringView(UpstreamLocality)];
EXPECT_FALSE(value.has_value());
}
}

TEST(Context, ExtractSslInfoEmptyValues) {
Expand Down