From b8b3c67f3c9ad1a9a1af05e696f8b3c3caecd2ed Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Thu, 22 Jan 2026 17:27:19 +0000 Subject: [PATCH 1/4] Add locality to proxy metadata Signed-off-by: Keith Mattix II --- extensions/common/BUILD | 1 + extensions/common/metadata_object.cc | 64 +++++++++++++++++-- extensions/common/metadata_object.h | 20 +++++- extensions/common/metadata_object_test.cc | 10 +-- .../common/workload_discovery/api.cc | 5 +- .../filters/http/istio_stats/istio_stats.cc | 4 +- .../filters/http/peer_metadata/filter.cc | 4 +- .../filters/http/peer_metadata/filter_test.cc | 19 ++++-- 8 files changed, 103 insertions(+), 24 deletions(-) diff --git a/extensions/common/BUILD b/extensions/common/BUILD index 2bc1771291d..20e0ebb6ede 100644 --- a/extensions/common/BUILD +++ b/extensions/common/BUILD @@ -35,6 +35,7 @@ envoy_cc_library( "@com_google_absl//absl/types:optional", "@envoy//envoy/common:hashable_interface", "@envoy//envoy/registry", + "@envoy//envoy/local_info:local_info_interface", "@envoy//envoy/stream_info:filter_state_interface", "@envoy//source/common/common:hash_lib", ], diff --git a/extensions/common/metadata_object.cc b/extensions/common/metadata_object.cc index e3067fa6b31..ff82cd5d119 100644 --- a/extensions/common/metadata_object.cc +++ b/extensions/common/metadata_object.cc @@ -14,6 +14,7 @@ #include "extensions/common/metadata_object.h" +#include "envoy/config/core/v3/base.pb.h" #include "envoy/registry/registry.h" #include "source/common/common/hash.h" #include "source/common/protobuf/utility.h" @@ -37,6 +38,8 @@ static absl::flat_hash_map ALL_METADATA_FIELDS {WorkloadNameToken, BaggageToken::WorkloadName}, {WorkloadTypeToken, BaggageToken::WorkloadType}, {InstanceNameToken, BaggageToken::InstanceName}, + {RegionToken, BaggageToken::LocalityRegion}, + {ZoneToken, BaggageToken::LocalityZone}, }; // This maps baggage keys into baggage tokens. We use it to decode baggage keys @@ -141,6 +144,12 @@ Envoy::ProtobufTypes::MessagePtr WorkloadMetadataObject::serializeAsProto() cons if (!identity_.empty()) { (*message->mutable_fields())[IdentityToken].set_string_value(identity_); } + if (!locality_region_.empty()) { + (*message->mutable_fields())[RegionToken].set_string_value(locality_region_); + } + if (!locality_zone_.empty()) { + (*message->mutable_fields())[ZoneToken].set_string_value(locality_zone_); + } if (!labels_.empty()) { auto* labels = (*message->mutable_fields())[LabelsToken].mutable_struct_value(); @@ -183,6 +192,12 @@ WorkloadMetadataObject::serializeAsPairs() const { if (!app_version_.empty()) { parts.push_back({AppVersionToken, app_version_}); } + if (!locality_region_.empty()) { + parts.push_back({RegionToken, locality_region_}); + } + if (!locality_zone_.empty()) { + parts.push_back({ZoneToken, locality_zone_}); + } if (!labels_.empty()) { for (const auto& l : labels_) { parts.push_back({absl::StrCat("labels[]", l.first), absl::string_view(l.second)}); @@ -263,6 +278,12 @@ google::protobuf::Struct convertWorkloadMetadataToStruct(const WorkloadMetadataO if (const auto owner = obj.owner(); owner.has_value()) { (*metadata.mutable_fields())[OwnerMetadataField].set_string_value(*owner); } + if (!obj.locality_region_.empty()) { + (*metadata.mutable_fields())[RegionMetadataField].set_string_value(obj.locality_region_); + } + if (!obj.locality_zone_.empty()) { + (*metadata.mutable_fields())[ZoneMetadataField].set_string_value(obj.locality_zone_); + } return metadata; } @@ -272,11 +293,17 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata) { return convertStructToWorkloadMetadata(metadata, {}); } +std::unique_ptr +convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, const absl::flat_hash_set& additional_labels) { + return convertStructToWorkloadMetadata(metadata, additional_labels, {}); +} + std::unique_ptr convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, - const absl::flat_hash_set& additional_labels) { + const absl::flat_hash_set& additional_labels, + const absl::optional locality) { absl::string_view instance, namespace_name, owner, workload, cluster, canonical_name, - canonical_revision, app_name, app_version; + canonical_revision, app_name, app_version, region, zone; std::vector> labels; for (const auto& it : metadata.fields()) { if (it.first == InstanceMetadataField) { @@ -289,6 +316,10 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, workload = it.second.string_value(); } else if (it.first == ClusterMetadataField) { cluster = it.second.string_value(); + } else if (it.first == RegionMetadataField) { + region = it.second.string_value(); + } else if (it.first == ZoneMetadataField) { + zone = it.second.string_value(); } else if (it.first == LabelsMetadataField) { for (const auto& labels_it : it.second.struct_value().fields()) { if (labels_it.first == CanonicalNameLabel) { @@ -307,9 +338,20 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, } } } + std::string locality_region = std::string(region); + std::string locality_zone = std::string(zone); + if (locality.has_value()) { + if (!locality->region().empty() && locality_region.empty()) { + locality_region = locality->region(); + } + if (!locality->zone().empty() && locality_zone.empty()) { + locality_zone = locality->zone(); + } + } auto obj = std::make_unique(instance, cluster, namespace_name, workload, canonical_name, canonical_revision, app_name, - app_version, parseOwner(owner, workload), ""); + app_version, parseOwner(owner, workload), "", + locality_region, locality_zone); obj->setLabels(labels); return obj; } @@ -321,7 +363,7 @@ convertEndpointMetadata(const std::string& endpoint_encoding) { return {}; } return absl::make_optional("", parts[4], parts[1], parts[0], parts[2], - parts[3], "", "", WorkloadType::Unknown, ""); + parts[3], "", "", WorkloadType::Unknown, "", "", ""); } std::string serializeToStringDeterministic(const google::protobuf::Struct& metadata) { @@ -363,6 +405,10 @@ WorkloadMetadataObject::getField(absl::string_view field_name) const { return "unknown"; case BaggageToken::InstanceName: return instance_name_; + case BaggageToken::LocalityRegion: + return locality_region_; + case BaggageToken::LocalityZone: + return locality_zone_; } } return {}; @@ -383,6 +429,8 @@ convertBaggageToWorkloadMetadata(absl::string_view data, absl::string_view ident absl::string_view canonical_revision; absl::string_view app_name; absl::string_view app_version; + absl::string_view region; + absl::string_view zone; WorkloadType workload_type = WorkloadType::Unknown; std::vector properties = absl::StrSplit(data, ','); for (absl::string_view property : properties) { @@ -419,6 +467,12 @@ convertBaggageToWorkloadMetadata(absl::string_view data, absl::string_view ident case BaggageToken::InstanceName: instance = parts.second; break; + case BaggageToken::LocalityRegion: + region = parts.second; + break; + case BaggageToken::LocalityZone: + zone = parts.second; + break; default: break; } @@ -426,7 +480,7 @@ convertBaggageToWorkloadMetadata(absl::string_view data, absl::string_view ident } return std::make_unique(instance, cluster, namespace_name, workload, canonical_name, canonical_revision, app_name, - app_version, workload_type, identity); + app_version, workload_type, identity, region, zone); } } // namespace Common diff --git a/extensions/common/metadata_object.h b/extensions/common/metadata_object.h index 7253fdd539a..1dc31a19d03 100644 --- a/extensions/common/metadata_object.h +++ b/extensions/common/metadata_object.h @@ -15,6 +15,7 @@ #pragma once #include "envoy/common/hashable.h" +#include "envoy/config/core/v3/base.pb.h" #include "envoy/stream_info/filter_state.h" #include "source/common/protobuf/protobuf.h" @@ -65,6 +66,8 @@ enum class BaggageToken { WorkloadName, WorkloadType, InstanceName, + LocalityZone, + LocalityRegion }; // Field names accessible from WorkloadMetadataObject. @@ -79,6 +82,8 @@ constexpr absl::string_view WorkloadTypeToken = "type"; constexpr absl::string_view InstanceNameToken = "name"; constexpr absl::string_view LabelsToken = "labels"; constexpr absl::string_view IdentityToken = "identity"; +constexpr absl::string_view RegionToken = "region"; +constexpr absl::string_view ZoneToken = "availability_zone"; // Field names used to translate baggage content into // WorkloadMetadataObject information. @@ -100,6 +105,8 @@ constexpr absl::string_view ClusterMetadataField = "CLUSTER_ID"; constexpr absl::string_view OwnerMetadataField = "OWNER"; constexpr absl::string_view WorkloadMetadataField = "WORKLOAD_NAME"; constexpr absl::string_view LabelsMetadataField = "LABELS"; +constexpr absl::string_view RegionMetadataField = "REGION"; +constexpr absl::string_view ZoneMetadataField = "ZONE"; class WorkloadMetadataObject : public Envoy::StreamInfo::FilterState::Object, public Envoy::Hashable { @@ -109,11 +116,13 @@ class WorkloadMetadataObject : public Envoy::StreamInfo::FilterState::Object, absl::string_view canonical_name, absl::string_view canonical_revision, absl::string_view app_name, absl::string_view app_version, WorkloadType workload_type, - absl::string_view identity) + absl::string_view identity, absl::string_view region, + absl::string_view zone) : instance_name_(instance_name), cluster_name_(cluster_name), namespace_name_(namespace_name), workload_name_(workload_name), canonical_name_(canonical_name), canonical_revision_(canonical_revision), app_name_(app_name), app_version_(app_version), - workload_type_(workload_type), identity_(identity) {} + workload_type_(workload_type), identity_(identity), locality_region_(region), + locality_zone_(zone) {} absl::optional hash() const override; Envoy::ProtobufTypes::MessagePtr serializeAsProto() const override; @@ -137,6 +146,8 @@ class WorkloadMetadataObject : public Envoy::StreamInfo::FilterState::Object, const std::string app_version_; const WorkloadType workload_type_; const std::string identity_; + const std::string locality_region_; + const std::string locality_zone_; std::vector> labels_; }; @@ -157,6 +168,11 @@ std::unique_ptr convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, const absl::flat_hash_set& additional_labels); +std::unique_ptr +convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, + const absl::flat_hash_set& additional_labels, + const absl::optional locality); + // Convert endpoint metadata string to a metadata object. // Telemetry metadata is compressed into a semicolon separated string: // workload-name;namespace;canonical-service-name;canonical-service-revision;cluster-id. diff --git a/extensions/common/metadata_object_test.cc b/extensions/common/metadata_object_test.cc index 188defa777f..82542a0d597 100644 --- a/extensions/common/metadata_object_test.cc +++ b/extensions/common/metadata_object_test.cc @@ -27,16 +27,16 @@ using ::testing::NiceMock; TEST(WorkloadMetadataObjectTest, Baggage) { WorkloadMetadataObject deploy("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", WorkloadType::Deployment, ""); + "v1alpha3", "", "", WorkloadType::Deployment, "", "", ""); WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", WorkloadType::Pod, ""); + "v1alpha3", "", "", WorkloadType::Pod, "", "", ""); WorkloadMetadataObject cronjob("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "foo-app", "v1", WorkloadType::CronJob, ""); + "v1alpha3", "foo-app", "v1", WorkloadType::CronJob, "", "", ""); WorkloadMetadataObject job("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", WorkloadType::Job, ""); + "v1alpha3", "", "", WorkloadType::Job, "", "", ""); EXPECT_EQ(deploy.serializeAsString(), absl::StrCat("type=deployment,workload=foo,name=pod-foo-1234,cluster=my-cluster,", @@ -67,7 +67,7 @@ void checkStructConversion(const Envoy::StreamInfo::FilterState::Object& data) { TEST(WorkloadMetadataObjectTest, ConversionWithLabels) { WorkloadMetadataObject deploy("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", WorkloadType::Deployment, ""); + "v1alpha3", "", "", WorkloadType::Deployment, "", "", ""); deploy.setLabels({{"label1", "value1"}, {"label2", "value2"}}); auto pb = convertWorkloadMetadataToStruct(deploy); auto obj1 = convertStructToWorkloadMetadata(pb, {"label1", "label2"}); diff --git a/source/extensions/common/workload_discovery/api.cc b/source/extensions/common/workload_discovery/api.cc index 86ffcd24609..deb97ad4005 100644 --- a/source/extensions/common/workload_discovery/api.cc +++ b/source/extensions/common/workload_discovery/api.cc @@ -69,7 +69,8 @@ Istio::Common::WorkloadMetadataObject convert(const istio::workload::Workload& w return Istio::Common::WorkloadMetadataObject( workload.name(), workload.cluster_id(), ns, workload.workload_name(), workload.canonical_name(), workload.canonical_revision(), workload.canonical_name(), - workload.canonical_revision(), workload_type, identity); + workload.canonical_revision(), workload_type, identity, workload.locality().region(), + workload.locality().zone()); } } // namespace @@ -249,7 +250,7 @@ class WorkloadDiscoveryExtension : public Server::BootstrapExtension { }); } - void onWorkerThreadInitialized() override{}; + void onWorkerThreadInitialized() override {}; private: Server::Configuration::ServerFactoryContext& factory_context_; diff --git a/source/extensions/filters/http/istio_stats/istio_stats.cc b/source/extensions/filters/http/istio_stats/istio_stats.cc index 9bedf042928..48774a41747 100644 --- a/source/extensions/filters/http/istio_stats/istio_stats.cc +++ b/source/extensions/filters/http/istio_stats/istio_stats.cc @@ -154,7 +154,9 @@ peerInfo(Reporter reporter, const StreamInfo::FilterState& filter_state) { extractString(obj, Istio::Common::AppNameToken), extractString(obj, Istio::Common::AppVersionToken), Istio::Common::fromSuffix(extractString(obj, Istio::Common::WorkloadTypeToken)), - extractString(obj, Istio::Common::IdentityToken)); + extractString(obj, Istio::Common::IdentityToken), + extractString(obj, Istio::Common::RegionToken), + extractString(obj, Istio::Common::ZoneToken)); return peer_info; } diff --git a/source/extensions/filters/http/peer_metadata/filter.cc b/source/extensions/filters/http/peer_metadata/filter.cc index 80981b9bbee..176d8e8790b 100644 --- a/source/extensions/filters/http/peer_metadata/filter.cc +++ b/source/extensions/filters/http/peer_metadata/filter.cc @@ -228,8 +228,8 @@ BaggagePropagationMethod::BaggagePropagationMethod( std::string BaggagePropagationMethod::computeBaggageValue( Server::Configuration::ServerFactoryContext& factory_context) const { - const auto obj = - Istio::Common::convertStructToWorkloadMetadata(factory_context.localInfo().node().metadata()); + const auto obj = Istio::Common::convertStructToWorkloadMetadata( + factory_context.localInfo().node().metadata(), {}, factory_context.localInfo().node().locality()); return obj->baggage(); } diff --git a/source/extensions/filters/http/peer_metadata/filter_test.cc b/source/extensions/filters/http/peer_metadata/filter_test.cc index 7824c9a3d9b..2fb836ba059 100644 --- a/source/extensions/filters/http/peer_metadata/filter_test.cc +++ b/source/extensions/filters/http/peer_metadata/filter_test.cc @@ -133,7 +133,7 @@ TEST_F(PeerMetadataTest, DownstreamXDSNone) { TEST_F(PeerMetadataTest, DownstreamXDS) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -155,7 +155,7 @@ TEST_F(PeerMetadataTest, DownstreamXDS) { TEST_F(PeerMetadataTest, UpstreamXDS) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -191,7 +191,7 @@ TEST_F(PeerMetadataTest, UpstreamXDSInternal) { *host_metadata); const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -260,7 +260,7 @@ TEST_F(PeerMetadataTest, DownstreamFallbackFirst) { TEST_F(PeerMetadataTest, DownstreamFallbackSecond) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -343,7 +343,7 @@ TEST_F(PeerMetadataTest, UpstreamFallbackFirst) { TEST_F(PeerMetadataTest, UpstreamFallbackSecond) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -365,7 +365,7 @@ TEST_F(PeerMetadataTest, UpstreamFallbackSecond) { TEST_F(PeerMetadataTest, UpstreamFallbackFirstXDS) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -584,6 +584,9 @@ class BaggagePropagationMethodTest : public testing::Test { version: v2.1 service.istio.io/canonical-name: sample-service service.istio.io/canonical-revision: stable + locality: + zone: us-east4-b + region: us-east4 )EOF", context_.server_factory_context_.local_info_.node_); } @@ -614,8 +617,10 @@ TEST_F(BaggagePropagationMethodTest, DownstreamBaggageInjection) { EXPECT_TRUE(absl::StrContains(baggage_value, "service.version=stable")); EXPECT_TRUE(absl::StrContains(baggage_value, "app.name=sample-app")); EXPECT_TRUE(absl::StrContains(baggage_value, "app.version=v2.1")); - EXPECT_TRUE(absl::StrContains(baggage_value, "k8s.pod.name=sample-workload")); + EXPECT_TRUE(absl::StrContains(baggage_value, "k8s.pod.name=sample-workload")); // workload type is pod EXPECT_TRUE(absl::StrContains(baggage_value, "k8s.instance.name=sample-instance")); + EXPECT_TRUE(absl::StrContains(baggage_value, "cloud.region=us-east4")); + EXPECT_TRUE(absl::StrContains(baggage_value, "cloud.zone=us-east4-b")); } TEST_F(BaggagePropagationMethodTest, UpstreamBaggageInjection) { From d881f288f8e3978c2ce93cdf81f6b18a7690d45d Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Thu, 22 Jan 2026 17:41:13 +0000 Subject: [PATCH 2/4] Clang-tidy Signed-off-by: Keith Mattix II --- extensions/common/metadata_object.cc | 13 ++++++------ .../common/workload_discovery/api.cc | 2 +- .../filters/http/istio_stats/istio_stats.cc | 3 +-- .../filters/http/peer_metadata/filter.cc | 3 ++- .../filters/http/peer_metadata/filter_test.cc | 21 ++++++++++++------- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/extensions/common/metadata_object.cc b/extensions/common/metadata_object.cc index ff82cd5d119..55a4a9e83e0 100644 --- a/extensions/common/metadata_object.cc +++ b/extensions/common/metadata_object.cc @@ -294,7 +294,8 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata) { } std::unique_ptr -convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, const absl::flat_hash_set& additional_labels) { +convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, + const absl::flat_hash_set& additional_labels) { return convertStructToWorkloadMetadata(metadata, additional_labels, {}); } @@ -348,10 +349,9 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, locality_zone = locality->zone(); } } - auto obj = std::make_unique(instance, cluster, namespace_name, workload, - canonical_name, canonical_revision, app_name, - app_version, parseOwner(owner, workload), "", - locality_region, locality_zone); + auto obj = std::make_unique( + instance, cluster, namespace_name, workload, canonical_name, canonical_revision, app_name, + app_version, parseOwner(owner, workload), "", locality_region, locality_zone); obj->setLabels(labels); return obj; } @@ -363,7 +363,8 @@ convertEndpointMetadata(const std::string& endpoint_encoding) { return {}; } return absl::make_optional("", parts[4], parts[1], parts[0], parts[2], - parts[3], "", "", WorkloadType::Unknown, "", "", ""); + parts[3], "", "", WorkloadType::Unknown, "", + "", ""); } std::string serializeToStringDeterministic(const google::protobuf::Struct& metadata) { diff --git a/source/extensions/common/workload_discovery/api.cc b/source/extensions/common/workload_discovery/api.cc index deb97ad4005..28940840342 100644 --- a/source/extensions/common/workload_discovery/api.cc +++ b/source/extensions/common/workload_discovery/api.cc @@ -250,7 +250,7 @@ class WorkloadDiscoveryExtension : public Server::BootstrapExtension { }); } - void onWorkerThreadInitialized() override {}; + void onWorkerThreadInitialized() override{}; private: Server::Configuration::ServerFactoryContext& factory_context_; diff --git a/source/extensions/filters/http/istio_stats/istio_stats.cc b/source/extensions/filters/http/istio_stats/istio_stats.cc index 48774a41747..4027a602051 100644 --- a/source/extensions/filters/http/istio_stats/istio_stats.cc +++ b/source/extensions/filters/http/istio_stats/istio_stats.cc @@ -155,8 +155,7 @@ peerInfo(Reporter reporter, const StreamInfo::FilterState& filter_state) { extractString(obj, Istio::Common::AppVersionToken), Istio::Common::fromSuffix(extractString(obj, Istio::Common::WorkloadTypeToken)), extractString(obj, Istio::Common::IdentityToken), - extractString(obj, Istio::Common::RegionToken), - extractString(obj, Istio::Common::ZoneToken)); + extractString(obj, Istio::Common::RegionToken), extractString(obj, Istio::Common::ZoneToken)); return peer_info; } diff --git a/source/extensions/filters/http/peer_metadata/filter.cc b/source/extensions/filters/http/peer_metadata/filter.cc index 176d8e8790b..8ca85071734 100644 --- a/source/extensions/filters/http/peer_metadata/filter.cc +++ b/source/extensions/filters/http/peer_metadata/filter.cc @@ -229,7 +229,8 @@ BaggagePropagationMethod::BaggagePropagationMethod( std::string BaggagePropagationMethod::computeBaggageValue( Server::Configuration::ServerFactoryContext& factory_context) const { const auto obj = Istio::Common::convertStructToWorkloadMetadata( - factory_context.localInfo().node().metadata(), {}, factory_context.localInfo().node().locality()); + factory_context.localInfo().node().metadata(), {}, + factory_context.localInfo().node().locality()); return obj->baggage(); } diff --git a/source/extensions/filters/http/peer_metadata/filter_test.cc b/source/extensions/filters/http/peer_metadata/filter_test.cc index 2fb836ba059..fb168a6fd57 100644 --- a/source/extensions/filters/http/peer_metadata/filter_test.cc +++ b/source/extensions/filters/http/peer_metadata/filter_test.cc @@ -133,7 +133,8 @@ TEST_F(PeerMetadataTest, DownstreamXDSNone) { TEST_F(PeerMetadataTest, DownstreamXDS) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", + ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -155,7 +156,8 @@ TEST_F(PeerMetadataTest, DownstreamXDS) { TEST_F(PeerMetadataTest, UpstreamXDS) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", + ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -191,7 +193,8 @@ TEST_F(PeerMetadataTest, UpstreamXDSInternal) { *host_metadata); const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", + ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -260,7 +263,8 @@ TEST_F(PeerMetadataTest, DownstreamFallbackFirst) { TEST_F(PeerMetadataTest, DownstreamFallbackSecond) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "default", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", + ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -343,7 +347,8 @@ TEST_F(PeerMetadataTest, UpstreamFallbackFirst) { TEST_F(PeerMetadataTest, UpstreamFallbackSecond) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", + ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -365,7 +370,8 @@ TEST_F(PeerMetadataTest, UpstreamFallbackSecond) { TEST_F(PeerMetadataTest, UpstreamFallbackFirstXDS) { const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service", - "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", ""); + "v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "", + ""); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -617,7 +623,8 @@ TEST_F(BaggagePropagationMethodTest, DownstreamBaggageInjection) { EXPECT_TRUE(absl::StrContains(baggage_value, "service.version=stable")); EXPECT_TRUE(absl::StrContains(baggage_value, "app.name=sample-app")); EXPECT_TRUE(absl::StrContains(baggage_value, "app.version=v2.1")); - EXPECT_TRUE(absl::StrContains(baggage_value, "k8s.pod.name=sample-workload")); // workload type is pod + EXPECT_TRUE( + absl::StrContains(baggage_value, "k8s.pod.name=sample-workload")); // workload type is pod EXPECT_TRUE(absl::StrContains(baggage_value, "k8s.instance.name=sample-instance")); EXPECT_TRUE(absl::StrContains(baggage_value, "cloud.region=us-east4")); EXPECT_TRUE(absl::StrContains(baggage_value, "cloud.zone=us-east4-b")); From 4d75914e1031280876dc6a1afb9d5c67e7687279 Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Thu, 22 Jan 2026 17:45:19 +0000 Subject: [PATCH 3/4] Buildifier format Signed-off-by: Keith Mattix II --- extensions/common/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/common/BUILD b/extensions/common/BUILD index 20e0ebb6ede..5ac05f8a578 100644 --- a/extensions/common/BUILD +++ b/extensions/common/BUILD @@ -34,8 +34,8 @@ envoy_cc_library( "@com_google_absl//absl/strings", "@com_google_absl//absl/types:optional", "@envoy//envoy/common:hashable_interface", - "@envoy//envoy/registry", "@envoy//envoy/local_info:local_info_interface", + "@envoy//envoy/registry", "@envoy//envoy/stream_info:filter_state_interface", "@envoy//source/common/common:hash_lib", ], From 32e8e8f81fe064892ce552107d144574f57722ee Mon Sep 17 00:00:00 2001 From: Keith Mattix II Date: Fri, 23 Jan 2026 21:02:34 +0000 Subject: [PATCH 4/4] Rebase and fix some bugs Signed-off-by: Keith Mattix II --- extensions/common/metadata_object.cc | 13 ++++++------- extensions/common/metadata_object.h | 4 +++- .../filters/http/peer_metadata/filter_test.cc | 8 ++++---- .../network/metadata_exchange/metadata_exchange.cc | 5 +++-- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/extensions/common/metadata_object.cc b/extensions/common/metadata_object.cc index 55a4a9e83e0..c39c79431a7 100644 --- a/extensions/common/metadata_object.cc +++ b/extensions/common/metadata_object.cc @@ -56,6 +56,7 @@ static absl::flat_hash_map ALL_BAGGAGE_TOKENS = {CronjobNameBaggageToken, BaggageToken::WorkloadName}, {JobNameBaggageToken, BaggageToken::WorkloadName}, {InstanceNameBaggageToken, BaggageToken::InstanceName}, + }; static absl::flat_hash_map ALL_WORKLOAD_TOKENS = { @@ -98,6 +99,8 @@ std::string WorkloadMetadataObject::baggage() const { {Istio::Common::AppNameToken, Istio::Common::AppNameBaggageToken}, {Istio::Common::AppVersionToken, Istio::Common::AppVersionBaggageToken}, {Istio::Common::InstanceNameToken, Istio::Common::InstanceNameBaggageToken}, + {Istio::Common::RegionToken, Istio::Common::LocalityRegionBaggageToken}, + {Istio::Common::ZoneToken, Istio::Common::LocalityZoneBaggageToken}, }; for (const auto& [field_name, baggage_key] : field_to_baggage) { @@ -317,10 +320,6 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata, workload = it.second.string_value(); } else if (it.first == ClusterMetadataField) { cluster = it.second.string_value(); - } else if (it.first == RegionMetadataField) { - region = it.second.string_value(); - } else if (it.first == ZoneMetadataField) { - zone = it.second.string_value(); } else if (it.first == LabelsMetadataField) { for (const auto& labels_it : it.second.struct_value().fields()) { if (labels_it.first == CanonicalNameLabel) { @@ -479,9 +478,9 @@ convertBaggageToWorkloadMetadata(absl::string_view data, absl::string_view ident } } } - return std::make_unique(instance, cluster, namespace_name, workload, - canonical_name, canonical_revision, app_name, - app_version, workload_type, identity, region, zone); + return std::make_unique( + instance, cluster, namespace_name, workload, canonical_name, canonical_revision, app_name, + app_version, workload_type, identity, region, zone); } } // namespace Common diff --git a/extensions/common/metadata_object.h b/extensions/common/metadata_object.h index 1dc31a19d03..4356aba838f 100644 --- a/extensions/common/metadata_object.h +++ b/extensions/common/metadata_object.h @@ -98,6 +98,8 @@ constexpr absl::string_view PodNameBaggageToken = "k8s.pod.name"; constexpr absl::string_view CronjobNameBaggageToken = "k8s.cronjob.name"; constexpr absl::string_view JobNameBaggageToken = "k8s.job.name"; constexpr absl::string_view InstanceNameBaggageToken = "k8s.instance.name"; +constexpr absl::string_view LocalityRegionBaggageToken = "cloud.region"; +constexpr absl::string_view LocalityZoneBaggageToken = "cloud.availability_zone"; constexpr absl::string_view InstanceMetadataField = "NAME"; constexpr absl::string_view NamespaceMetadataField = "NAMESPACE"; @@ -106,7 +108,7 @@ constexpr absl::string_view OwnerMetadataField = "OWNER"; constexpr absl::string_view WorkloadMetadataField = "WORKLOAD_NAME"; constexpr absl::string_view LabelsMetadataField = "LABELS"; constexpr absl::string_view RegionMetadataField = "REGION"; -constexpr absl::string_view ZoneMetadataField = "ZONE"; +constexpr absl::string_view ZoneMetadataField = "AVAILABILITY_ZONE"; class WorkloadMetadataObject : public Envoy::StreamInfo::FilterState::Object, public Envoy::Hashable { diff --git a/source/extensions/filters/http/peer_metadata/filter_test.cc b/source/extensions/filters/http/peer_metadata/filter_test.cc index fb168a6fd57..446d2f14c9e 100644 --- a/source/extensions/filters/http/peer_metadata/filter_test.cc +++ b/source/extensions/filters/http/peer_metadata/filter_test.cc @@ -627,7 +627,7 @@ TEST_F(BaggagePropagationMethodTest, DownstreamBaggageInjection) { absl::StrContains(baggage_value, "k8s.pod.name=sample-workload")); // workload type is pod EXPECT_TRUE(absl::StrContains(baggage_value, "k8s.instance.name=sample-instance")); EXPECT_TRUE(absl::StrContains(baggage_value, "cloud.region=us-east4")); - EXPECT_TRUE(absl::StrContains(baggage_value, "cloud.zone=us-east4-b")); + EXPECT_TRUE(absl::StrContains(baggage_value, "cloud.availability_zone=us-east4-b")); } TEST_F(BaggagePropagationMethodTest, UpstreamBaggageInjection) { @@ -830,7 +830,7 @@ TEST_F(PeerMetadataTest, DownstreamBaggageFallbackSecond) { // No baggage header, so XDS should be called as fallback const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "xds-namespace", "foo", "foo-service", "v1alpha3", "", "", - Istio::Common::WorkloadType::Pod, ""); + Istio::Common::WorkloadType::Pod, "", "us-east4", "us-east4-b"); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -858,7 +858,7 @@ TEST_F(PeerMetadataTest, UpstreamBaggageFallbackFirst) { // WDS information is also present, and this is the one tha tshould be used. const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "xds-upstream", "foo", "foo-service", "v1alpha3", "", "", - Istio::Common::WorkloadType::Pod, ""); + Istio::Common::WorkloadType::Pod, "", "us-east4", "us-east4-b"); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { @@ -883,7 +883,7 @@ TEST_F(PeerMetadataTest, UpstreamBaggageFallbackSecond) { // but workload discovery should pick up the details. const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "xds-upstream", "foo", "foo-service", "v1alpha3", "", "", - Istio::Common::WorkloadType::Pod, ""); + Istio::Common::WorkloadType::Pod, "", "us-east4", "us-east4-b"); EXPECT_CALL(*metadata_provider_, GetMetadata(_)) .WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address) -> std::optional { diff --git a/source/extensions/filters/network/metadata_exchange/metadata_exchange.cc b/source/extensions/filters/network/metadata_exchange/metadata_exchange.cc index 997d32e182c..64875406185 100644 --- a/source/extensions/filters/network/metadata_exchange/metadata_exchange.cc +++ b/source/extensions/filters/network/metadata_exchange/metadata_exchange.cc @@ -188,8 +188,9 @@ void MetadataExchangeFilter::writeNodeMetadata() { } ENVOY_LOG(trace, "Writing metadata to the connection."); Protobuf::Struct data; - const auto obj = Istio::Common::convertStructToWorkloadMetadata(local_info_.node().metadata(), - config_->additional_labels_); + const auto obj = Istio::Common::convertStructToWorkloadMetadata( + local_info_.node().metadata(), config_->additional_labels_, local_info_.node().locality()); + *(*data.mutable_fields())[ExchangeMetadataHeader].mutable_struct_value() = Istio::Common::convertWorkloadMetadataToStruct(*obj); std::string metadata_id = getMetadataId();