Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 extensions/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ envoy_cc_library(
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:optional",
"@envoy//envoy/common:hashable_interface",
"@envoy//envoy/local_info:local_info_interface",
"@envoy//envoy/registry",
"@envoy//envoy/stream_info:filter_state_interface",
"@envoy//source/common/common:hash_lib",
Expand Down
70 changes: 62 additions & 8 deletions extensions/common/metadata_object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -37,6 +38,8 @@ static absl::flat_hash_map<absl::string_view, BaggageToken> 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
Expand All @@ -53,6 +56,7 @@ static absl::flat_hash_map<absl::string_view, BaggageToken> ALL_BAGGAGE_TOKENS =
{CronjobNameBaggageToken, BaggageToken::WorkloadName},
{JobNameBaggageToken, BaggageToken::WorkloadName},
{InstanceNameBaggageToken, BaggageToken::InstanceName},

};

static absl::flat_hash_map<absl::string_view, WorkloadType> ALL_WORKLOAD_TOKENS = {
Expand Down Expand Up @@ -95,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) {
Expand Down Expand Up @@ -141,6 +147,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();
Expand Down Expand Up @@ -183,6 +195,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)});
Expand Down Expand Up @@ -263,6 +281,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;
}

Expand All @@ -275,8 +299,15 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata) {
std::unique_ptr<WorkloadMetadataObject>
convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata,
const absl::flat_hash_set<std::string>& additional_labels) {
return convertStructToWorkloadMetadata(metadata, additional_labels, {});
}

std::unique_ptr<WorkloadMetadataObject>
convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata,
const absl::flat_hash_set<std::string>& additional_labels,
const absl::optional<envoy::config::core::v3::Locality> 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<std::pair<std::string, std::string>> labels;
for (const auto& it : metadata.fields()) {
if (it.first == InstanceMetadataField) {
Expand Down Expand Up @@ -307,9 +338,19 @@ convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata,
}
}
}
auto obj = std::make_unique<WorkloadMetadataObject>(instance, cluster, namespace_name, workload,
canonical_name, canonical_revision, app_name,
app_version, parseOwner(owner, workload), "");
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<WorkloadMetadataObject>(
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;
}
Expand All @@ -321,7 +362,8 @@ convertEndpointMetadata(const std::string& endpoint_encoding) {
return {};
}
return absl::make_optional<WorkloadMetadataObject>("", parts[4], parts[1], parts[0], parts[2],
parts[3], "", "", WorkloadType::Unknown, "");
parts[3], "", "", WorkloadType::Unknown, "",
"", "");
}

std::string serializeToStringDeterministic(const google::protobuf::Struct& metadata) {
Expand Down Expand Up @@ -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 {};
Expand All @@ -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<absl::string_view> properties = absl::StrSplit(data, ',');
for (absl::string_view property : properties) {
Expand Down Expand Up @@ -419,14 +467,20 @@ 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;
}
}
}
return std::make_unique<WorkloadMetadataObject>(instance, cluster, namespace_name, workload,
canonical_name, canonical_revision, app_name,
app_version, workload_type, identity);
return std::make_unique<WorkloadMetadataObject>(
instance, cluster, namespace_name, workload, canonical_name, canonical_revision, app_name,
app_version, workload_type, identity, region, zone);
}

} // namespace Common
Expand Down
22 changes: 20 additions & 2 deletions extensions/common/metadata_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -65,6 +66,8 @@ enum class BaggageToken {
WorkloadName,
WorkloadType,
InstanceName,
LocalityZone,
LocalityRegion
};

// Field names accessible from WorkloadMetadataObject.
Expand All @@ -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.
Expand All @@ -93,13 +98,17 @@ 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";
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 = "AVAILABILITY_ZONE";

class WorkloadMetadataObject : public Envoy::StreamInfo::FilterState::Object,
public Envoy::Hashable {
Expand All @@ -109,11 +118,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<uint64_t> hash() const override;
Envoy::ProtobufTypes::MessagePtr serializeAsProto() const override;
Expand All @@ -137,6 +148,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<std::pair<std::string, std::string>> labels_;
};

Expand All @@ -157,6 +170,11 @@ std::unique_ptr<WorkloadMetadataObject>
convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata,
const absl::flat_hash_set<std::string>& additional_labels);

std::unique_ptr<WorkloadMetadataObject>
convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata,
const absl::flat_hash_set<std::string>& additional_labels,
const absl::optional<envoy::config::core::v3::Locality> 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.
Expand Down
10 changes: 5 additions & 5 deletions extensions/common/metadata_object_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,",
Expand Down Expand Up @@ -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"});
Expand Down
3 changes: 2 additions & 1 deletion source/extensions/common/workload_discovery/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion source/extensions/filters/http/istio_stats/istio_stats.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ 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;
}
Expand Down
5 changes: 3 additions & 2 deletions source/extensions/filters/http/peer_metadata/filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,9 @@ 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();
}

Expand Down
Loading