mirror of https://github.com/istio/proxy.git
move flatbuffers
Change-Id: Ic0390cdcf4f6696dbedf644f25bf1d4c3b2bf8c6 Signed-off-by: Kuat Yessenov <kuat@google.com>
This commit is contained in:
parent
0ecfabc99a
commit
789b8a7e95
|
|
@ -20,15 +20,6 @@ load(
|
||||||
"envoy_cc_library",
|
"envoy_cc_library",
|
||||||
"envoy_cc_test",
|
"envoy_cc_test",
|
||||||
)
|
)
|
||||||
load(
|
|
||||||
"@com_github_google_flatbuffers//:build_defs.bzl",
|
|
||||||
"DEFAULT_FLATC_ARGS",
|
|
||||||
"flatbuffer_library_public",
|
|
||||||
)
|
|
||||||
load(
|
|
||||||
"@envoy//test/extensions:extensions_build_system.bzl",
|
|
||||||
"envoy_extension_cc_benchmark_binary",
|
|
||||||
)
|
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
|
@ -44,11 +35,7 @@ envoy_cc_library(
|
||||||
],
|
],
|
||||||
repository = "@envoy",
|
repository = "@envoy",
|
||||||
deps = [
|
deps = [
|
||||||
":metadata_object_lib",
|
|
||||||
":node_info_fb_cc",
|
|
||||||
":util",
|
|
||||||
"@com_google_protobuf//:protobuf",
|
"@com_google_protobuf//:protobuf",
|
||||||
"@proxy_wasm_cpp_host//:null_lib",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -66,18 +53,6 @@ envoy_cc_library(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
envoy_cc_test(
|
|
||||||
name = "proto_util_test",
|
|
||||||
size = "small",
|
|
||||||
srcs = ["proto_util_test.cc"],
|
|
||||||
repository = "@envoy",
|
|
||||||
deps = [
|
|
||||||
":node_info_fb_cc",
|
|
||||||
":proto_util",
|
|
||||||
"@com_google_protobuf//:protobuf",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
envoy_cc_test(
|
envoy_cc_test(
|
||||||
name = "util_test",
|
name = "util_test",
|
||||||
size = "small",
|
size = "small",
|
||||||
|
|
@ -88,62 +63,12 @@ envoy_cc_test(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: fix this build on mac m1?
|
|
||||||
envoy_extension_cc_benchmark_binary(
|
|
||||||
name = "proto_util_speed_test",
|
|
||||||
srcs = select({
|
|
||||||
"@envoy//bazel:linux": ["proto_util_speed_test.cc"],
|
|
||||||
"//conditions:default": [],
|
|
||||||
}),
|
|
||||||
extension_names = ["envoy.wasm.runtime.null"],
|
|
||||||
external_deps = [
|
|
||||||
"benchmark",
|
|
||||||
],
|
|
||||||
repository = "@envoy",
|
|
||||||
deps = select({
|
|
||||||
"@envoy//bazel:linux": [
|
|
||||||
":metadata_object_lib",
|
|
||||||
":node_info_fb_cc",
|
|
||||||
":proto_util",
|
|
||||||
"@envoy//source/common/stream_info:filter_state_lib",
|
|
||||||
"@envoy//source/extensions/filters/common/expr:cel_state_lib",
|
|
||||||
"@envoy//test/test_common:status_utility_lib",
|
|
||||||
],
|
|
||||||
"//conditions:default": [],
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
flatbuffer_library_public(
|
|
||||||
name = "node_info_fbs",
|
|
||||||
srcs = ["node_info.fbs"],
|
|
||||||
outs = [
|
|
||||||
"node_info_bfbs_generated.h",
|
|
||||||
"node_info_generated.h",
|
|
||||||
],
|
|
||||||
flatc_args = DEFAULT_FLATC_ARGS + ["--bfbs-gen-embed"],
|
|
||||||
language_flag = "-c",
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "node_info_fb_cc",
|
|
||||||
srcs = [":node_info_fbs"],
|
|
||||||
hdrs = [":node_info_fbs"],
|
|
||||||
features = ["-parse_headers"],
|
|
||||||
linkstatic = True,
|
|
||||||
deps = [
|
|
||||||
"@com_github_google_flatbuffers//:flatbuffers",
|
|
||||||
"@com_github_google_flatbuffers//:runtime_cc",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
envoy_cc_library(
|
envoy_cc_library(
|
||||||
name = "metadata_object_lib",
|
name = "metadata_object_lib",
|
||||||
srcs = ["metadata_object.cc"],
|
srcs = ["metadata_object.cc"],
|
||||||
hdrs = ["metadata_object.h"],
|
hdrs = ["metadata_object.h"],
|
||||||
repository = "@envoy",
|
repository = "@envoy",
|
||||||
deps = [
|
deps = [
|
||||||
":node_info_fb_cc",
|
|
||||||
"@com_github_google_flatbuffers//:flatbuffers",
|
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
"@com_google_absl//absl/types:optional",
|
"@com_google_absl//absl/types:optional",
|
||||||
"@envoy//envoy/common:hashable_interface",
|
"@envoy//envoy/common:hashable_interface",
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@
|
||||||
#include "extensions/common/metadata_object.h"
|
#include "extensions/common/metadata_object.h"
|
||||||
|
|
||||||
#include "absl/strings/str_join.h"
|
#include "absl/strings/str_join.h"
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "extensions/common/node_info_bfbs_generated.h"
|
|
||||||
#include "source/common/common/hash.h"
|
#include "source/common/common/hash.h"
|
||||||
|
|
||||||
namespace Istio {
|
namespace Istio {
|
||||||
|
|
@ -170,108 +168,89 @@ absl::optional<uint64_t> WorkloadMetadataObject::hash() const {
|
||||||
return Envoy::HashUtil::xxHash64(absl::StrCat(instance_name_, "/", namespace_name_));
|
return Envoy::HashUtil::xxHash64(absl::StrCat(instance_name_, "/", namespace_name_));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
std::string WorkloadMetadataObject::owner() const {
|
||||||
// Returns a string view stored in a flatbuffers string.
|
switch (workload_type_) {
|
||||||
absl::string_view toAbslStringView(const flatbuffers::String* str) {
|
|
||||||
return str ? absl::string_view(str->c_str(), str->size()) : absl::string_view();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view toStdStringView(absl::string_view view) {
|
|
||||||
return std::string_view(view.data(), view.size());
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
std::string convertWorkloadMetadataToFlatNode(const WorkloadMetadataObject& obj) {
|
|
||||||
flatbuffers::FlatBufferBuilder fbb;
|
|
||||||
|
|
||||||
flatbuffers::Offset<flatbuffers::String> name, cluster, namespace_, workload_name, owner,
|
|
||||||
identity;
|
|
||||||
std::vector<flatbuffers::Offset<Wasm::Common::KeyVal>> labels;
|
|
||||||
|
|
||||||
name = fbb.CreateString(toStdStringView(obj.instance_name_));
|
|
||||||
namespace_ = fbb.CreateString(toStdStringView(obj.namespace_name_));
|
|
||||||
cluster = fbb.CreateString(toStdStringView(obj.cluster_name_));
|
|
||||||
workload_name = fbb.CreateString(toStdStringView(obj.workload_name_));
|
|
||||||
identity = fbb.CreateString(toStdStringView(obj.identity_));
|
|
||||||
|
|
||||||
switch (obj.workload_type_) {
|
|
||||||
case WorkloadType::Deployment:
|
case WorkloadType::Deployment:
|
||||||
owner = fbb.CreateString(absl::StrCat(OwnerPrefix, obj.namespace_name_, "/", DeploymentSuffix,
|
return absl::StrCat(OwnerPrefix, namespace_name_, "/", DeploymentSuffix, "s/", workload_name_);
|
||||||
"s/", obj.workload_name_));
|
|
||||||
break;
|
|
||||||
case WorkloadType::Job:
|
case WorkloadType::Job:
|
||||||
owner = fbb.CreateString(
|
return absl::StrCat(OwnerPrefix, namespace_name_, "/", JobSuffix, "s/", workload_name_);
|
||||||
absl::StrCat(OwnerPrefix, obj.namespace_name_, "/", JobSuffix, "s/", obj.workload_name_));
|
|
||||||
break;
|
|
||||||
case WorkloadType::CronJob:
|
case WorkloadType::CronJob:
|
||||||
owner = fbb.CreateString(absl::StrCat(OwnerPrefix, obj.namespace_name_, "/", CronJobSuffix,
|
return absl::StrCat(OwnerPrefix, namespace_name_, "/", CronJobSuffix, "s/", workload_name_);
|
||||||
"s/", obj.workload_name_));
|
|
||||||
break;
|
|
||||||
case WorkloadType::Pod:
|
case WorkloadType::Pod:
|
||||||
owner = fbb.CreateString(
|
return absl::StrCat(OwnerPrefix, namespace_name_, "/", PodSuffix, "s/", workload_name_);
|
||||||
absl::StrCat(OwnerPrefix, obj.namespace_name_, "/", PodSuffix, "s/", obj.workload_name_));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
labels.push_back(
|
|
||||||
Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(CanonicalNameLabel),
|
|
||||||
fbb.CreateString(toStdStringView(obj.canonical_name_))));
|
|
||||||
labels.push_back(
|
|
||||||
Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(CanonicalRevisionLabel),
|
|
||||||
fbb.CreateString(toStdStringView(obj.canonical_revision_))));
|
|
||||||
labels.push_back(Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(AppLabel),
|
|
||||||
fbb.CreateString(toStdStringView(obj.app_name_))));
|
|
||||||
labels.push_back(Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(VersionLabel),
|
|
||||||
fbb.CreateString(toStdStringView(obj.app_version_))));
|
|
||||||
|
|
||||||
auto labels_offset = fbb.CreateVectorOfSortedTables(&labels);
|
|
||||||
Wasm::Common::FlatNodeBuilder node(fbb);
|
|
||||||
node.add_name(name);
|
|
||||||
node.add_cluster_id(cluster);
|
|
||||||
node.add_namespace_(namespace_);
|
|
||||||
node.add_workload_name(workload_name);
|
|
||||||
node.add_owner(owner);
|
|
||||||
node.add_labels(labels_offset);
|
|
||||||
node.add_identity(identity);
|
|
||||||
auto data = node.Finish();
|
|
||||||
fbb.Finish(data);
|
|
||||||
auto fb = fbb.Release();
|
|
||||||
return std::string(reinterpret_cast<const char*>(fb.data()), fb.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkloadMetadataObject convertFlatNodeToWorkloadMetadata(const Wasm::Common::FlatNode& node) {
|
void WorkloadMetadataObject::toStruct(google::protobuf::Struct* out) const {
|
||||||
const absl::string_view instance = toAbslStringView(node.name());
|
if (!instance_name_.empty()) {
|
||||||
const absl::string_view cluster = toAbslStringView(node.cluster_id());
|
(*out->mutable_fields())["NAME"].set_string_value(instance_name_);
|
||||||
const absl::string_view workload = toAbslStringView(node.workload_name());
|
}
|
||||||
const absl::string_view namespace_name = toAbslStringView(node.namespace_());
|
if (!cluster_name_.empty()) {
|
||||||
const absl::string_view identity = toAbslStringView(node.identity());
|
(*out->mutable_fields())["CLUSTER_ID"].set_string_value(cluster_name_);
|
||||||
const auto* labels = node.labels();
|
}
|
||||||
|
if (!namespace_name_.empty()) {
|
||||||
|
(*out->mutable_fields())["NAMESPACE"].set_string_value(namespace_name_);
|
||||||
|
}
|
||||||
|
if (!workload_name_.empty()) {
|
||||||
|
(*out->mutable_fields())["WORKLOAD_NAME"].set_string_value(workload_name_);
|
||||||
|
}
|
||||||
|
(*out->mutable_fields())["OWNER"].set_string_value(owner());
|
||||||
|
auto* map = (*out->mutable_fields())["LABELS"].mutable_struct_value();
|
||||||
|
if (!canonical_name_.empty()) {
|
||||||
|
(*map->mutable_fields())[CanonicalNameLabel].set_string_value(canonical_name_);
|
||||||
|
}
|
||||||
|
if (!canonical_revision_.empty()) {
|
||||||
|
(*map->mutable_fields())[CanonicalRevisionLabel].set_string_value(canonical_revision_);
|
||||||
|
}
|
||||||
|
if (!app_name_.empty()) {
|
||||||
|
(*map->mutable_fields())[AppLabel].set_string_value(app_name_);
|
||||||
|
}
|
||||||
|
if (!app_version_.empty()) {
|
||||||
|
(*map->mutable_fields())[VersionLabel].set_string_value(app_version_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<WorkloadMetadataObject>
|
||||||
|
convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata) {
|
||||||
|
absl::string_view instance;
|
||||||
|
absl::string_view cluster;
|
||||||
|
absl::string_view workload;
|
||||||
|
absl::string_view namespace_name;
|
||||||
|
absl::string_view identity;
|
||||||
absl::string_view canonical_name;
|
absl::string_view canonical_name;
|
||||||
absl::string_view canonical_revision;
|
absl::string_view canonical_revision;
|
||||||
absl::string_view app_name;
|
absl::string_view app_name;
|
||||||
absl::string_view app_version;
|
absl::string_view app_version;
|
||||||
if (labels) {
|
absl::string_view owner;
|
||||||
const auto* name_iter = labels->LookupByKey(CanonicalNameLabel);
|
|
||||||
const auto* name = name_iter ? name_iter->value() : nullptr;
|
|
||||||
canonical_name = toAbslStringView(name);
|
|
||||||
|
|
||||||
const auto* revision_iter = labels->LookupByKey(CanonicalRevisionLabel);
|
for (const auto& it : metadata.fields()) {
|
||||||
const auto* revision = revision_iter ? revision_iter->value() : nullptr;
|
if (it.first == "NAME") {
|
||||||
canonical_revision = toAbslStringView(revision);
|
instance = it.second.string_value();
|
||||||
|
} else if (it.first == "NAMESPACE") {
|
||||||
const auto* app_iter = labels->LookupByKey(AppLabel);
|
namespace_name = it.second.string_value();
|
||||||
const auto* app = app_iter ? app_iter->value() : nullptr;
|
} else if (it.first == "OWNER") {
|
||||||
app_name = toAbslStringView(app);
|
owner = it.second.string_value();
|
||||||
|
} else if (it.first == "WORKLOAD_NAME") {
|
||||||
const auto* version_iter = labels->LookupByKey(VersionLabel);
|
workload = it.second.string_value();
|
||||||
const auto* version = version_iter ? version_iter->value() : nullptr;
|
} else if (it.first == "CLUSTER_ID") {
|
||||||
app_version = toAbslStringView(version);
|
cluster = it.second.string_value();
|
||||||
|
} else if (it.first == "LABELS") {
|
||||||
|
for (const auto& labels_it : it.second.struct_value().fields()) {
|
||||||
|
if (labels_it.first == CanonicalNameLabel) {
|
||||||
|
canonical_name = labels_it.second.string_value();
|
||||||
|
} else if (labels_it.first == CanonicalRevisionLabel) {
|
||||||
|
canonical_revision = labels_it.second.string_value();
|
||||||
|
} else if (labels_it.first == AppLabel) {
|
||||||
|
app_name = labels_it.second.string_value();
|
||||||
|
} else if (labels_it.first == VersionLabel) {
|
||||||
|
app_version = labels_it.second.string_value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkloadType workload_type = WorkloadType::Pod;
|
WorkloadType workload_type = WorkloadType::Pod;
|
||||||
// Strip "s/workload_name" and check for workload type.
|
// Strip "s/workload_name" and check for workload type.
|
||||||
absl::string_view owner = toAbslStringView(node.owner());
|
|
||||||
if (owner.size() > workload.size() + 2) {
|
if (owner.size() > workload.size() + 2) {
|
||||||
owner.remove_suffix(workload.size() + 2);
|
owner.remove_suffix(workload.size() + 2);
|
||||||
size_t last = owner.rfind('/');
|
size_t last = owner.rfind('/');
|
||||||
|
|
@ -298,8 +277,9 @@ WorkloadMetadataObject convertFlatNodeToWorkloadMetadata(const Wasm::Common::Fla
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return WorkloadMetadataObject(instance, cluster, namespace_name, workload, canonical_name,
|
return std::make_shared<WorkloadMetadataObject>(instance, cluster, namespace_name, workload,
|
||||||
canonical_revision, app_name, app_version, workload_type, identity);
|
canonical_name, canonical_revision, app_name,
|
||||||
|
app_version, workload_type, identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<WorkloadMetadataObject>
|
absl::optional<WorkloadMetadataObject>
|
||||||
|
|
@ -313,10 +293,5 @@ convertEndpointMetadata(const std::string& endpoint_encoding) {
|
||||||
parts[3], "", "", WorkloadType::Pod, "");
|
parts[3], "", "", WorkloadType::Pod, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view nodeInfoSchema() {
|
|
||||||
return std::string_view(reinterpret_cast<const char*>(Wasm::Common::FlatNodeBinarySchema::data()),
|
|
||||||
Wasm::Common::FlatNodeBinarySchema::size());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
} // namespace Istio
|
} // namespace Istio
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
#include "envoy/common/hashable.h"
|
#include "envoy/common/hashable.h"
|
||||||
#include "envoy/ssl/connection.h"
|
#include "envoy/ssl/connection.h"
|
||||||
#include "envoy/stream_info/filter_state.h"
|
#include "envoy/stream_info/filter_state.h"
|
||||||
#include "extensions/common/node_info_generated.h"
|
|
||||||
|
|
||||||
namespace Istio {
|
namespace Istio {
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
@ -90,6 +89,9 @@ struct WorkloadMetadataObject : public Envoy::StreamInfo::FilterState::Object,
|
||||||
|
|
||||||
absl::optional<uint64_t> hash() const override;
|
absl::optional<uint64_t> hash() const override;
|
||||||
|
|
||||||
|
std::string owner() const;
|
||||||
|
void toStruct(google::protobuf::Struct* out) const;
|
||||||
|
|
||||||
absl::optional<std::string> serializeAsString() const override { return baggage(); }
|
absl::optional<std::string> serializeAsString() const override { return baggage(); }
|
||||||
|
|
||||||
const std::string instance_name_;
|
const std::string instance_name_;
|
||||||
|
|
@ -104,11 +106,9 @@ struct WorkloadMetadataObject : public Envoy::StreamInfo::FilterState::Object,
|
||||||
const std::string identity_;
|
const std::string identity_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert metadata object to flatbuffer.
|
// Convert metadata struct to metadata object.
|
||||||
std::string convertWorkloadMetadataToFlatNode(const WorkloadMetadataObject& obj);
|
std::shared_ptr<WorkloadMetadataObject>
|
||||||
|
convertStructToWorkloadMetadata(const google::protobuf::Struct& metadata);
|
||||||
// Convert flatbuffer to metadata object.
|
|
||||||
WorkloadMetadataObject convertFlatNodeToWorkloadMetadata(const Wasm::Common::FlatNode& node);
|
|
||||||
|
|
||||||
// Convert endpoint metadata string to a metadata object.
|
// Convert endpoint metadata string to a metadata object.
|
||||||
// Telemetry metadata is compressed into a semicolon separated string:
|
// Telemetry metadata is compressed into a semicolon separated string:
|
||||||
|
|
@ -118,8 +118,5 @@ WorkloadMetadataObject convertFlatNodeToWorkloadMetadata(const Wasm::Common::Fla
|
||||||
absl::optional<WorkloadMetadataObject>
|
absl::optional<WorkloadMetadataObject>
|
||||||
convertEndpointMetadata(const std::string& endpoint_encoding);
|
convertEndpointMetadata(const std::string& endpoint_encoding);
|
||||||
|
|
||||||
// Returns flatbuffer schema for node info.
|
|
||||||
std::string_view nodeInfoSchema();
|
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
} // namespace Istio
|
} // namespace Istio
|
||||||
|
|
|
||||||
|
|
@ -17,114 +17,9 @@
|
||||||
|
|
||||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
||||||
|
|
||||||
#include "absl/strings/str_join.h"
|
|
||||||
#include "absl/strings/str_split.h"
|
|
||||||
#include "extensions/common/util.h"
|
|
||||||
#include "extensions/common/metadata_object.h"
|
|
||||||
|
|
||||||
// WASM_PROLOG
|
|
||||||
#ifndef NULL_PLUGIN
|
|
||||||
#include "proxy_wasm_intrinsics.h"
|
|
||||||
|
|
||||||
#else // NULL_PLUGIN
|
|
||||||
|
|
||||||
#include "include/proxy-wasm/null_plugin.h"
|
|
||||||
|
|
||||||
#endif // NULL_PLUGIN
|
|
||||||
|
|
||||||
// END WASM_PROLOG
|
|
||||||
|
|
||||||
namespace Wasm {
|
namespace Wasm {
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
flatbuffers::DetachedBuffer
|
|
||||||
extractNodeFlatBufferFromStruct(const google::protobuf::Struct& metadata) {
|
|
||||||
flatbuffers::FlatBufferBuilder fbb;
|
|
||||||
flatbuffers::Offset<flatbuffers::String> name, namespace_, owner, workload_name, cluster_id;
|
|
||||||
std::vector<flatbuffers::Offset<KeyVal>> labels, platform_metadata;
|
|
||||||
for (const auto& it : metadata.fields()) {
|
|
||||||
if (it.first == "NAME") {
|
|
||||||
name = fbb.CreateString(it.second.string_value());
|
|
||||||
} else if (it.first == "NAMESPACE") {
|
|
||||||
namespace_ = fbb.CreateString(it.second.string_value());
|
|
||||||
} else if (it.first == "OWNER") {
|
|
||||||
owner = fbb.CreateString(it.second.string_value());
|
|
||||||
} else if (it.first == "WORKLOAD_NAME") {
|
|
||||||
workload_name = fbb.CreateString(it.second.string_value());
|
|
||||||
} else if (it.first == "CLUSTER_ID") {
|
|
||||||
cluster_id = fbb.CreateString(it.second.string_value());
|
|
||||||
} else if (it.first == "LABELS") {
|
|
||||||
for (const auto& labels_it : it.second.struct_value().fields()) {
|
|
||||||
if (labels_it.first == Istio::Common::CanonicalNameLabel ||
|
|
||||||
labels_it.first == Istio::Common::CanonicalRevisionLabel ||
|
|
||||||
labels_it.first == Istio::Common::AppLabel ||
|
|
||||||
labels_it.first == Istio::Common::VersionLabel) {
|
|
||||||
labels.push_back(CreateKeyVal(fbb, fbb.CreateString(labels_it.first),
|
|
||||||
fbb.CreateString(labels_it.second.string_value())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (it.first == "PLATFORM_METADATA") {
|
|
||||||
for (const auto& platform_it : it.second.struct_value().fields()) {
|
|
||||||
platform_metadata.push_back(
|
|
||||||
CreateKeyVal(fbb, fbb.CreateString(platform_it.first),
|
|
||||||
fbb.CreateString(platform_it.second.string_value())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// finish pre-order construction
|
|
||||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyVal>>> labels_offset,
|
|
||||||
platform_metadata_offset;
|
|
||||||
if (labels.size() > 0) {
|
|
||||||
labels_offset = fbb.CreateVectorOfSortedTables(&labels);
|
|
||||||
}
|
|
||||||
if (platform_metadata.size() > 0) {
|
|
||||||
platform_metadata_offset = fbb.CreateVectorOfSortedTables(&platform_metadata);
|
|
||||||
}
|
|
||||||
FlatNodeBuilder node(fbb);
|
|
||||||
node.add_name(name);
|
|
||||||
node.add_namespace_(namespace_);
|
|
||||||
node.add_owner(owner);
|
|
||||||
node.add_workload_name(workload_name);
|
|
||||||
node.add_cluster_id(cluster_id);
|
|
||||||
node.add_labels(labels_offset);
|
|
||||||
node.add_platform_metadata(platform_metadata_offset);
|
|
||||||
auto data = node.Finish();
|
|
||||||
fbb.Finish(data);
|
|
||||||
return fbb.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void extractStructFromNodeFlatBuffer(const FlatNode& node, google::protobuf::Struct* metadata) {
|
|
||||||
if (node.name()) {
|
|
||||||
(*metadata->mutable_fields())["NAME"].set_string_value(node.name()->str());
|
|
||||||
}
|
|
||||||
if (node.namespace_()) {
|
|
||||||
(*metadata->mutable_fields())["NAMESPACE"].set_string_value(node.namespace_()->str());
|
|
||||||
}
|
|
||||||
if (node.owner()) {
|
|
||||||
(*metadata->mutable_fields())["OWNER"].set_string_value(node.owner()->str());
|
|
||||||
}
|
|
||||||
if (node.workload_name()) {
|
|
||||||
(*metadata->mutable_fields())["WORKLOAD_NAME"].set_string_value(node.workload_name()->str());
|
|
||||||
}
|
|
||||||
if (node.cluster_id()) {
|
|
||||||
(*metadata->mutable_fields())["CLUSTER_ID"].set_string_value(node.cluster_id()->str());
|
|
||||||
}
|
|
||||||
if (node.labels()) {
|
|
||||||
auto* map = (*metadata->mutable_fields())["LABELS"].mutable_struct_value();
|
|
||||||
for (const auto keyval : *node.labels()) {
|
|
||||||
(*map->mutable_fields())[flatbuffers::GetString(keyval->key())].set_string_value(
|
|
||||||
flatbuffers::GetString(keyval->value()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node.platform_metadata()) {
|
|
||||||
auto* map = (*metadata->mutable_fields())["PLATFORM_METADATA"].mutable_struct_value();
|
|
||||||
for (const auto keyval : *node.platform_metadata()) {
|
|
||||||
(*map->mutable_fields())[flatbuffers::GetString(keyval->key())].set_string_value(
|
|
||||||
flatbuffers::GetString(keyval->value()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool serializeToStringDeterministic(const google::protobuf::Message& metadata,
|
bool serializeToStringDeterministic(const google::protobuf::Message& metadata,
|
||||||
std::string* metadata_bytes) {
|
std::string* metadata_bytes) {
|
||||||
google::protobuf::io::StringOutputStream md(metadata_bytes);
|
google::protobuf::io::StringOutputStream md(metadata_bytes);
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "extensions/common/node_info_generated.h"
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "google/protobuf/struct.pb.h"
|
#include "google/protobuf/struct.pb.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -25,13 +23,6 @@
|
||||||
namespace Wasm {
|
namespace Wasm {
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
// Extract node info into a flatbuffer from a struct.
|
|
||||||
flatbuffers::DetachedBuffer
|
|
||||||
extractNodeFlatBufferFromStruct(const google::protobuf::Struct& metadata);
|
|
||||||
|
|
||||||
// Extract struct from a flatbuffer. This is an inverse of the above function.
|
|
||||||
void extractStructFromNodeFlatBuffer(const FlatNode& node, google::protobuf::Struct* metadata);
|
|
||||||
|
|
||||||
// Serialize deterministically a protobuf to a string.
|
// Serialize deterministically a protobuf to a string.
|
||||||
bool serializeToStringDeterministic(const google::protobuf::Message& metadata,
|
bool serializeToStringDeterministic(const google::protobuf::Message& metadata,
|
||||||
std::string* metadata_bytes);
|
std::string* metadata_bytes);
|
||||||
|
|
|
||||||
|
|
@ -1,220 +0,0 @@
|
||||||
/* Copyright 2019 Istio Authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "benchmark/benchmark.h"
|
|
||||||
#include "extensions/common/metadata_object.h"
|
|
||||||
#include "extensions/common/node_info_generated.h"
|
|
||||||
#include "extensions/common/proto_util.h"
|
|
||||||
#include "extensions/common/util.h"
|
|
||||||
#include "google/protobuf/util/json_util.h"
|
|
||||||
#include "source/common/common/base64.h"
|
|
||||||
#include "source/common/stream_info/filter_state_impl.h"
|
|
||||||
#include "source/extensions/filters/common/expr/cel_state.h"
|
|
||||||
#include "test/test_common/status_utility.h"
|
|
||||||
|
|
||||||
// WASM_PROLOG
|
|
||||||
#ifdef NULL_PLUGIN
|
|
||||||
namespace Wasm {
|
|
||||||
#endif // NULL_PLUGIN
|
|
||||||
|
|
||||||
// END WASM_PROLOG
|
|
||||||
|
|
||||||
namespace Common {
|
|
||||||
|
|
||||||
using namespace google::protobuf::util;
|
|
||||||
|
|
||||||
constexpr std::string_view node_metadata_json = R"###(
|
|
||||||
{
|
|
||||||
"NAME":"test_pod",
|
|
||||||
"NAMESPACE":"test_namespace",
|
|
||||||
"LABELS": {
|
|
||||||
"app": "productpage",
|
|
||||||
"version": "v1",
|
|
||||||
"pod-template-hash": "84975bc778"
|
|
||||||
},
|
|
||||||
"OWNER":"test_owner",
|
|
||||||
"WORKLOAD_NAME":"test_workload",
|
|
||||||
"PLATFORM_METADATA":{
|
|
||||||
"gcp_project":"test_project",
|
|
||||||
"gcp_cluster_location":"test_location",
|
|
||||||
"gcp_cluster_name":"test_cluster"
|
|
||||||
},
|
|
||||||
"ISTIO_VERSION":"istio-1.4",
|
|
||||||
"MESH_ID":"test-mesh"
|
|
||||||
}
|
|
||||||
)###";
|
|
||||||
|
|
||||||
constexpr std::string_view metadata_id_key = "envoy.wasm.metadata_exchange.downstream_id";
|
|
||||||
constexpr std::string_view metadata_key = "envoy.wasm.metadata_exchange.downstream";
|
|
||||||
constexpr std::string_view node_id = "test_pod.test_namespace";
|
|
||||||
|
|
||||||
static void setData(Envoy::StreamInfo::FilterStateImpl& filter_state, std::string_view key,
|
|
||||||
std::string_view value) {
|
|
||||||
Envoy::Extensions::Filters::Common::Expr::CelStatePrototype prototype;
|
|
||||||
auto state_ptr = std::make_unique<Envoy::Extensions::Filters::Common::Expr::CelState>(prototype);
|
|
||||||
state_ptr->setValue(toAbslStringView(value));
|
|
||||||
filter_state.setData(toAbslStringView(key), std::move(state_ptr),
|
|
||||||
Envoy::StreamInfo::FilterState::StateType::Mutable);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const std::string& getData(Envoy::StreamInfo::FilterStateImpl& filter_state,
|
|
||||||
std::string_view key) {
|
|
||||||
return filter_state
|
|
||||||
.getDataReadOnly<Envoy::Extensions::Filters::Common::Expr::CelState>(toAbslStringView(key))
|
|
||||||
->value();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BM_ReadFlatBuffer(benchmark::State& state) {
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
JsonParseOptions json_parse_options;
|
|
||||||
ASSERT_OK(
|
|
||||||
JsonStringToMessage(std::string(node_metadata_json), &metadata_struct, json_parse_options));
|
|
||||||
auto out = extractNodeFlatBufferFromStruct(metadata_struct);
|
|
||||||
|
|
||||||
Envoy::StreamInfo::FilterStateImpl filter_state{
|
|
||||||
Envoy::StreamInfo::FilterState::LifeSpan::TopSpan};
|
|
||||||
setData(filter_state, metadata_key,
|
|
||||||
std::string_view(reinterpret_cast<const char*>(out.data()), out.size()));
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
for (auto _ : state) {
|
|
||||||
auto buf = getData(filter_state, metadata_key);
|
|
||||||
auto peer = flatbuffers::GetRoot<FlatNode>(buf.data());
|
|
||||||
size += peer->workload_name()->size() + peer->namespace_()->size() +
|
|
||||||
peer->labels()->LookupByKey("app")->value()->size() +
|
|
||||||
peer->labels()->LookupByKey("version")->value()->size();
|
|
||||||
benchmark::DoNotOptimize(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_ReadFlatBuffer);
|
|
||||||
|
|
||||||
static void BM_WriteRawBytes(benchmark::State& state) {
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
JsonParseOptions json_parse_options;
|
|
||||||
ASSERT_OK(
|
|
||||||
JsonStringToMessage(std::string(node_metadata_json), &metadata_struct, json_parse_options));
|
|
||||||
auto bytes = metadata_struct.SerializeAsString();
|
|
||||||
Envoy::StreamInfo::FilterStateImpl filter_state{
|
|
||||||
Envoy::StreamInfo::FilterState::LifeSpan::TopSpan};
|
|
||||||
|
|
||||||
for (auto _ : state) {
|
|
||||||
setData(filter_state, metadata_id_key, node_id);
|
|
||||||
setData(filter_state, metadata_key, bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_WriteRawBytes);
|
|
||||||
|
|
||||||
static void BM_WriteFlatBufferWithCache(benchmark::State& state) {
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
JsonParseOptions json_parse_options;
|
|
||||||
ASSERT_OK(
|
|
||||||
JsonStringToMessage(std::string(node_metadata_json), &metadata_struct, json_parse_options));
|
|
||||||
auto bytes = metadata_struct.SerializeAsString();
|
|
||||||
Envoy::StreamInfo::FilterStateImpl filter_state{
|
|
||||||
Envoy::StreamInfo::FilterState::LifeSpan::TopSpan};
|
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> cache;
|
|
||||||
|
|
||||||
for (auto _ : state) {
|
|
||||||
// lookup cache by key
|
|
||||||
auto nodeinfo_it = cache.find(std::string(node_id));
|
|
||||||
std::string node_info;
|
|
||||||
if (nodeinfo_it == cache.end()) {
|
|
||||||
google::protobuf::Struct test_struct;
|
|
||||||
test_struct.ParseFromArray(bytes.data(), bytes.size());
|
|
||||||
benchmark::DoNotOptimize(test_struct);
|
|
||||||
|
|
||||||
auto out = extractNodeFlatBufferFromStruct(test_struct);
|
|
||||||
|
|
||||||
node_info =
|
|
||||||
cache.emplace(node_id, std::string(reinterpret_cast<const char*>(out.data()), out.size()))
|
|
||||||
.first->second;
|
|
||||||
} else {
|
|
||||||
node_info = nodeinfo_it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(filter_state, metadata_id_key, node_id);
|
|
||||||
setData(filter_state, metadata_key, node_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_WriteFlatBufferWithCache);
|
|
||||||
|
|
||||||
constexpr std::string_view node_flatbuffer_json = R"###(
|
|
||||||
{
|
|
||||||
"NAME":"test_pod",
|
|
||||||
"NAMESPACE":"default",
|
|
||||||
"CLUSTER_ID": "client-cluster",
|
|
||||||
"LABELS": {
|
|
||||||
"app": "productpage",
|
|
||||||
"version": "v1",
|
|
||||||
"service.istio.io/canonical-name": "productpage-v1",
|
|
||||||
"service.istio.io/canonical-revision": "version-1"
|
|
||||||
},
|
|
||||||
"OWNER": "kubernetes://apis/apps/v1/namespaces/default/deployments/productpage-v1",
|
|
||||||
"WORKLOAD_NAME":"productpage-v1"
|
|
||||||
}
|
|
||||||
)###";
|
|
||||||
|
|
||||||
// Measure decoding performance of x-envoy-peer-metadata.
|
|
||||||
static void BM_DecodeFlatBuffer(benchmark::State& state) {
|
|
||||||
// Construct a header from sample value.
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
JsonParseOptions json_parse_options;
|
|
||||||
ASSERT_OK(
|
|
||||||
JsonStringToMessage(std::string(node_flatbuffer_json), &metadata_struct, json_parse_options));
|
|
||||||
std::string metadata_bytes;
|
|
||||||
::Wasm::Common::serializeToStringDeterministic(metadata_struct, &metadata_bytes);
|
|
||||||
const std::string header_value =
|
|
||||||
Envoy::Base64::encode(metadata_bytes.data(), metadata_bytes.size());
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
for (auto _ : state) {
|
|
||||||
auto bytes = Envoy::Base64::decodeWithoutPadding(header_value);
|
|
||||||
google::protobuf::Struct metadata;
|
|
||||||
metadata.ParseFromString(bytes);
|
|
||||||
auto fb = ::Wasm::Common::extractNodeFlatBufferFromStruct(metadata);
|
|
||||||
size += fb.size();
|
|
||||||
benchmark::DoNotOptimize(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BENCHMARK(BM_DecodeFlatBuffer);
|
|
||||||
|
|
||||||
// Measure decoding performance of baggage.
|
|
||||||
static void BM_DecodeBaggage(benchmark::State& state) {
|
|
||||||
// Construct a header from sample value.
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
JsonParseOptions json_parse_options;
|
|
||||||
ASSERT_OK(
|
|
||||||
JsonStringToMessage(std::string(node_flatbuffer_json), &metadata_struct, json_parse_options));
|
|
||||||
auto fb = ::Wasm::Common::extractNodeFlatBufferFromStruct(metadata_struct);
|
|
||||||
const auto& node = *flatbuffers::GetRoot<Wasm::Common::FlatNode>(fb.data());
|
|
||||||
const std::string baggage = Istio::Common::convertFlatNodeToWorkloadMetadata(node).baggage();
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
for (auto _ : state) {
|
|
||||||
auto obj = Istio::Common::WorkloadMetadataObject::fromBaggage(baggage);
|
|
||||||
size += obj.namespace_name_.size();
|
|
||||||
benchmark::DoNotOptimize(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK(BM_DecodeBaggage);
|
|
||||||
|
|
||||||
} // namespace Common
|
|
||||||
|
|
||||||
// WASM_EPILOG
|
|
||||||
#ifdef NULL_PLUGIN
|
|
||||||
} // namespace Wasm
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
/* Copyright 2019 Istio Authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "extensions/common/proto_util.h"
|
|
||||||
|
|
||||||
#include "extensions/common/node_info_generated.h"
|
|
||||||
#include "google/protobuf/struct.pb.h"
|
|
||||||
#include "google/protobuf/text_format.h"
|
|
||||||
#include "google/protobuf/util/json_util.h"
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
// WASM_PROLOG
|
|
||||||
#ifdef NULL_PLUGIN
|
|
||||||
namespace Wasm {
|
|
||||||
#endif // NULL_PLUGIN
|
|
||||||
|
|
||||||
// END WASM_PROLOG
|
|
||||||
|
|
||||||
namespace Common {
|
|
||||||
|
|
||||||
using namespace google::protobuf;
|
|
||||||
using namespace google::protobuf::util;
|
|
||||||
|
|
||||||
constexpr std::string_view node_metadata_json = R"###(
|
|
||||||
{
|
|
||||||
"NAME":"test_pod",
|
|
||||||
"NAMESPACE":"test_namespace",
|
|
||||||
"OWNER":"test_owner",
|
|
||||||
"WORKLOAD_NAME":"test_workload",
|
|
||||||
"CLUSTER_ID":"test-cluster",
|
|
||||||
"LABELS":{
|
|
||||||
"app":"test",
|
|
||||||
"version":"v1"
|
|
||||||
},
|
|
||||||
"PLATFORM_METADATA":{
|
|
||||||
"gcp_cluster_location":"test_location",
|
|
||||||
"gcp_cluster_name":"test_cluster",
|
|
||||||
"gcp_project":"test_project"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)###";
|
|
||||||
|
|
||||||
// Test all possible metadata field.
|
|
||||||
TEST(ProtoUtilTest, extractNodeMetadata) {
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
JsonParseOptions json_parse_options;
|
|
||||||
EXPECT_TRUE(
|
|
||||||
JsonStringToMessage(std::string(node_metadata_json), &metadata_struct, json_parse_options)
|
|
||||||
.ok());
|
|
||||||
auto out = extractNodeFlatBufferFromStruct(metadata_struct);
|
|
||||||
auto peer = flatbuffers::GetRoot<FlatNode>(out.data());
|
|
||||||
EXPECT_EQ(peer->name()->string_view(), "test_pod");
|
|
||||||
EXPECT_EQ(peer->namespace_()->string_view(), "test_namespace");
|
|
||||||
EXPECT_EQ(peer->owner()->string_view(), "test_owner");
|
|
||||||
EXPECT_EQ(peer->workload_name()->string_view(), "test_workload");
|
|
||||||
EXPECT_EQ(peer->cluster_id()->string_view(), "test-cluster");
|
|
||||||
EXPECT_EQ(peer->platform_metadata()->Get(2)->key()->string_view(), "gcp_project");
|
|
||||||
EXPECT_EQ(peer->platform_metadata()->Get(2)->value()->string_view(), "test_project");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test roundtripping
|
|
||||||
TEST(ProtoUtilTest, Rountrip) {
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
JsonParseOptions json_parse_options;
|
|
||||||
EXPECT_TRUE(
|
|
||||||
JsonStringToMessage(std::string(node_metadata_json), &metadata_struct, json_parse_options)
|
|
||||||
.ok());
|
|
||||||
auto out = extractNodeFlatBufferFromStruct(metadata_struct);
|
|
||||||
auto peer = flatbuffers::GetRoot<FlatNode>(out.data());
|
|
||||||
|
|
||||||
google::protobuf::Struct output_struct;
|
|
||||||
extractStructFromNodeFlatBuffer(*peer, &output_struct);
|
|
||||||
|
|
||||||
// Validate serialized bytes
|
|
||||||
std::string input_bytes;
|
|
||||||
EXPECT_TRUE(serializeToStringDeterministic(metadata_struct, &input_bytes));
|
|
||||||
std::string output_bytes;
|
|
||||||
EXPECT_TRUE(serializeToStringDeterministic(output_struct, &output_bytes));
|
|
||||||
EXPECT_EQ(input_bytes, output_bytes)
|
|
||||||
<< metadata_struct.DebugString() << output_struct.DebugString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test roundtrip for an empty struct (for corner cases)
|
|
||||||
TEST(ProtoUtilTest, RountripEmpty) {
|
|
||||||
google::protobuf::Struct metadata_struct;
|
|
||||||
auto out = extractNodeFlatBufferFromStruct(metadata_struct);
|
|
||||||
auto peer = flatbuffers::GetRoot<FlatNode>(out.data());
|
|
||||||
google::protobuf::Struct output_struct;
|
|
||||||
extractStructFromNodeFlatBuffer(*peer, &output_struct);
|
|
||||||
EXPECT_EQ(0, output_struct.fields().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Common
|
|
||||||
|
|
||||||
// WASM_EPILOG
|
|
||||||
#ifdef NULL_PLUGIN
|
|
||||||
} // namespace Wasm
|
|
||||||
#endif
|
|
||||||
|
|
@ -19,6 +19,11 @@ load(
|
||||||
"@envoy//bazel:envoy_build_system.bzl",
|
"@envoy//bazel:envoy_build_system.bzl",
|
||||||
"envoy_cc_library",
|
"envoy_cc_library",
|
||||||
)
|
)
|
||||||
|
load(
|
||||||
|
"@com_github_google_flatbuffers//:build_defs.bzl",
|
||||||
|
"DEFAULT_FLATC_ARGS",
|
||||||
|
"flatbuffer_library_public",
|
||||||
|
)
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
|
@ -34,7 +39,7 @@ envoy_cc_library(
|
||||||
],
|
],
|
||||||
repository = "@envoy",
|
repository = "@envoy",
|
||||||
deps = [
|
deps = [
|
||||||
"//extensions/common:node_info_fb_cc",
|
":node_info_fb_cc",
|
||||||
"//extensions/common:util",
|
"//extensions/common:util",
|
||||||
"@proxy_wasm_cpp_host//:null_lib",
|
"@proxy_wasm_cpp_host//:null_lib",
|
||||||
],
|
],
|
||||||
|
|
@ -63,3 +68,26 @@ envoy_cc_library(
|
||||||
"@proxy_wasm_cpp_sdk//contrib:contrib_lib",
|
"@proxy_wasm_cpp_sdk//contrib:contrib_lib",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
flatbuffer_library_public(
|
||||||
|
name = "node_info_fbs",
|
||||||
|
srcs = ["node_info.fbs"],
|
||||||
|
outs = [
|
||||||
|
"node_info_bfbs_generated.h",
|
||||||
|
"node_info_generated.h",
|
||||||
|
],
|
||||||
|
flatc_args = DEFAULT_FLATC_ARGS + ["--bfbs-gen-embed"],
|
||||||
|
language_flag = "-c",
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "node_info_fb_cc",
|
||||||
|
srcs = [":node_info_fbs"],
|
||||||
|
hdrs = [":node_info_fbs"],
|
||||||
|
features = ["-parse_headers"],
|
||||||
|
linkstatic = True,
|
||||||
|
deps = [
|
||||||
|
"@com_github_google_flatbuffers//:flatbuffers",
|
||||||
|
"@com_github_google_flatbuffers//:runtime_cc",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,53 @@ bool extractPeerMetadataFromUpstreamHostMetadata(flatbuffers::FlatBufferBuilder&
|
||||||
return extractPeerMetadataFromUpstreamMetadata("upstream_host_metadata", fbb);
|
return extractPeerMetadataFromUpstreamMetadata("upstream_host_metadata", fbb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Returns a string view stored in a flatbuffers string.
|
||||||
|
std::string_view toStdStringView(absl::string_view view) {
|
||||||
|
return std::string_view(view.data(), view.size());
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::string convertWorkloadMetadataToFlatNode(const Istio::Common::WorkloadMetadataObject& obj) {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
|
||||||
|
flatbuffers::Offset<flatbuffers::String> name, cluster, namespace_, workload_name, owner,
|
||||||
|
identity;
|
||||||
|
std::vector<flatbuffers::Offset<Wasm::Common::KeyVal>> labels;
|
||||||
|
|
||||||
|
name = fbb.CreateString(toStdStringView(obj.instance_name_));
|
||||||
|
namespace_ = fbb.CreateString(toStdStringView(obj.namespace_name_));
|
||||||
|
cluster = fbb.CreateString(toStdStringView(obj.cluster_name_));
|
||||||
|
workload_name = fbb.CreateString(toStdStringView(obj.workload_name_));
|
||||||
|
identity = fbb.CreateString(toStdStringView(obj.identity_));
|
||||||
|
owner = fbb.CreateString(obj.owner());
|
||||||
|
|
||||||
|
labels.push_back(
|
||||||
|
Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(CanonicalNameLabel),
|
||||||
|
fbb.CreateString(toStdStringView(obj.canonical_name_))));
|
||||||
|
labels.push_back(
|
||||||
|
Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(CanonicalRevisionLabel),
|
||||||
|
fbb.CreateString(toStdStringView(obj.canonical_revision_))));
|
||||||
|
labels.push_back(Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(AppLabel),
|
||||||
|
fbb.CreateString(toStdStringView(obj.app_name_))));
|
||||||
|
labels.push_back(Wasm::Common::CreateKeyVal(fbb, fbb.CreateString(VersionLabel),
|
||||||
|
fbb.CreateString(toStdStringView(obj.app_version_))));
|
||||||
|
|
||||||
|
auto labels_offset = fbb.CreateVectorOfSortedTables(&labels);
|
||||||
|
Wasm::Common::FlatNodeBuilder node(fbb);
|
||||||
|
node.add_name(name);
|
||||||
|
node.add_cluster_id(cluster);
|
||||||
|
node.add_namespace_(namespace_);
|
||||||
|
node.add_workload_name(workload_name);
|
||||||
|
node.add_owner(owner);
|
||||||
|
node.add_labels(labels_offset);
|
||||||
|
node.add_identity(identity);
|
||||||
|
auto data = node.Finish();
|
||||||
|
fbb.Finish(data);
|
||||||
|
auto fb = fbb.Release();
|
||||||
|
return std::string(reinterpret_cast<const char*>(fb.data()), fb.size());
|
||||||
|
}
|
||||||
|
|
||||||
PeerNodeInfo::PeerNodeInfo(const std::string_view peer_metadata_id_key,
|
PeerNodeInfo::PeerNodeInfo(const std::string_view peer_metadata_id_key,
|
||||||
const std::string_view peer_metadata_key) {
|
const std::string_view peer_metadata_key) {
|
||||||
// Attempt to read from filter_state first.
|
// Attempt to read from filter_state first.
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,9 @@ bool extractPeerMetadataFromUpstreamHostMetadata(flatbuffers::FlatBufferBuilder&
|
||||||
// Returns true if the metadata is found in the upstream cluster metadata.
|
// Returns true if the metadata is found in the upstream cluster metadata.
|
||||||
bool extractPeerMetadataFromUpstreamClusterMetadata(flatbuffers::FlatBufferBuilder& fbb);
|
bool extractPeerMetadataFromUpstreamClusterMetadata(flatbuffers::FlatBufferBuilder& fbb);
|
||||||
|
|
||||||
|
// Convert metadata object to flatbuffer.
|
||||||
|
std::string convertWorkloadMetadataToFlatNode(const Istio::Common::WorkloadMetadataObject& obj);
|
||||||
|
|
||||||
class PeerNodeInfo {
|
class PeerNodeInfo {
|
||||||
public:
|
public:
|
||||||
explicit PeerNodeInfo(const std::string_view peer_metadata_id_key,
|
explicit PeerNodeInfo(const std::string_view peer_metadata_id_key,
|
||||||
|
|
|
||||||
|
|
@ -123,16 +123,13 @@ bool peerInfoRead(Reporter reporter, const StreamInfo::FilterState& filter_state
|
||||||
filter_state.hasDataWithName("envoy.wasm.metadata_exchange.peer_unknown");
|
filter_state.hasDataWithName("envoy.wasm.metadata_exchange.peer_unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
const Wasm::Common::FlatNode* peerInfo(Reporter reporter,
|
const Istio::Common::WorkloadMetadataObject* peerInfo(Reporter reporter,
|
||||||
const StreamInfo::FilterState& filter_state) {
|
const StreamInfo::FilterState& filter_state) {
|
||||||
const auto& filter_state_key =
|
const auto& filter_state_key =
|
||||||
reporter == Reporter::ServerSidecar || reporter == Reporter::ServerGateway
|
reporter == Reporter::ServerSidecar || reporter == Reporter::ServerGateway
|
||||||
? "wasm.downstream_peer"
|
? "wasm.downstream_peer"
|
||||||
: "wasm.upstream_peer";
|
: "wasm.upstream_peer";
|
||||||
const auto* object =
|
return filter_state.getDataReadOnly<Istio::Common::WorkloadMetadataObject>(filter_state_key);
|
||||||
filter_state.getDataReadOnly<Envoy::Extensions::Filters::Common::Expr::CelState>(
|
|
||||||
filter_state_key);
|
|
||||||
return object ? flatbuffers::GetRoot<Wasm::Common::FlatNode>(object->value().data()) : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process-wide context shared with all filter instances.
|
// Process-wide context shared with all filter instances.
|
||||||
|
|
@ -1000,7 +997,7 @@ private:
|
||||||
absl::optional<Istio::Common::WorkloadMetadataObject> peer;
|
absl::optional<Istio::Common::WorkloadMetadataObject> peer;
|
||||||
const auto* object = peerInfo(config_->reporter(), filter_state);
|
const auto* object = peerInfo(config_->reporter(), filter_state);
|
||||||
if (object) {
|
if (object) {
|
||||||
peer.emplace(Istio::Common::convertFlatNodeToWorkloadMetadata(*object));
|
peer.emplace(*object);
|
||||||
} else if (config_->reporter() == Reporter::ClientSidecar) {
|
} else if (config_->reporter() == Reporter::ClientSidecar) {
|
||||||
if (auto label_obj = extractEndpointMetadata(info); label_obj) {
|
if (auto label_obj = extractEndpointMetadata(info); label_obj) {
|
||||||
peer.emplace(label_obj.value());
|
peer.emplace(label_obj.value());
|
||||||
|
|
@ -1138,7 +1135,7 @@ private:
|
||||||
std::optional<Istio::Common::WorkloadMetadataObject> endpoint_peer;
|
std::optional<Istio::Common::WorkloadMetadataObject> endpoint_peer;
|
||||||
const auto* endpoint_object = peerInfo(Reporter::ClientSidecar, filter_state);
|
const auto* endpoint_object = peerInfo(Reporter::ClientSidecar, filter_state);
|
||||||
if (endpoint_object) {
|
if (endpoint_object) {
|
||||||
endpoint_peer.emplace(Istio::Common::convertFlatNodeToWorkloadMetadata(*endpoint_object));
|
endpoint_peer.emplace(*endpoint_object);
|
||||||
}
|
}
|
||||||
tags_.push_back(
|
tags_.push_back(
|
||||||
{context_.destination_workload_,
|
{context_.destination_workload_,
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ envoy_cc_extension(
|
||||||
"@envoy//source/common/http:header_utility_lib",
|
"@envoy//source/common/http:header_utility_lib",
|
||||||
"@envoy//source/common/http:utility_lib",
|
"@envoy//source/common/http:utility_lib",
|
||||||
"@envoy//source/common/network:utility_lib",
|
"@envoy//source/common/network:utility_lib",
|
||||||
|
"@envoy//source/common/router:string_accessor_lib",
|
||||||
"@envoy//source/extensions/filters/common/expr:cel_state_lib",
|
"@envoy//source/extensions/filters/common/expr:cel_state_lib",
|
||||||
"@envoy//source/extensions/filters/http/common:factory_base_lib",
|
"@envoy//source/extensions/filters/http/common:factory_base_lib",
|
||||||
"@envoy//source/extensions/filters/http/common:pass_through_filter_lib",
|
"@envoy//source/extensions/filters/http/common:pass_through_filter_lib",
|
||||||
|
|
|
||||||
|
|
@ -23,36 +23,13 @@
|
||||||
#include "source/common/http/header_utility.h"
|
#include "source/common/http/header_utility.h"
|
||||||
#include "source/common/http/utility.h"
|
#include "source/common/http/utility.h"
|
||||||
#include "source/common/network/utility.h"
|
#include "source/common/network/utility.h"
|
||||||
#include "source/extensions/filters/common/expr/cel_state.h"
|
#include "source/common/router/string_accessor_impl.h"
|
||||||
|
|
||||||
namespace Envoy {
|
namespace Envoy {
|
||||||
namespace Extensions {
|
namespace Extensions {
|
||||||
namespace HttpFilters {
|
namespace HttpFilters {
|
||||||
namespace PeerMetadata {
|
namespace PeerMetadata {
|
||||||
|
|
||||||
// Extended peer info that supports "hashing" to enable sharing with the
|
|
||||||
// upstream connection via an internal listener.
|
|
||||||
class CelStateHashable : public Filters::Common::Expr::CelState, public Hashable {
|
|
||||||
public:
|
|
||||||
explicit CelStateHashable(const Filters::Common::Expr::CelStatePrototype& proto)
|
|
||||||
: CelState(proto) {}
|
|
||||||
absl::optional<uint64_t> hash() const override { return HashUtil::xxHash64(value()); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CelPrototypeValues {
|
|
||||||
const Filters::Common::Expr::CelStatePrototype NodeInfo{
|
|
||||||
true, Filters::Common::Expr::CelStateType::FlatBuffers,
|
|
||||||
toAbslStringView(Istio::Common::nodeInfoSchema()),
|
|
||||||
// Life span is only needed for Wasm set_property, not in the native filters.
|
|
||||||
StreamInfo::FilterState::LifeSpan::FilterChain};
|
|
||||||
const Filters::Common::Expr::CelStatePrototype NodeId{
|
|
||||||
true, Filters::Common::Expr::CelStateType::String, absl::string_view(),
|
|
||||||
// Life span is only needed for Wasm set_property, not in the native filters.
|
|
||||||
StreamInfo::FilterState::LifeSpan::FilterChain};
|
|
||||||
};
|
|
||||||
|
|
||||||
using CelPrototypes = ConstSingleton<CelPrototypeValues>;
|
|
||||||
|
|
||||||
class XDSMethod : public DiscoveryMethod {
|
class XDSMethod : public DiscoveryMethod {
|
||||||
public:
|
public:
|
||||||
XDSMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context)
|
XDSMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context)
|
||||||
|
|
@ -104,7 +81,7 @@ absl::optional<PeerInfo> XDSMethod::derivePeerInfo(const StreamInfo::StreamInfo&
|
||||||
}
|
}
|
||||||
const auto metadata_object = metadata_provider_->GetMetadata(peer_address);
|
const auto metadata_object = metadata_provider_->GetMetadata(peer_address);
|
||||||
if (metadata_object) {
|
if (metadata_object) {
|
||||||
return Istio::Common::convertWorkloadMetadataToFlatNode(metadata_object.value());
|
return std::make_shared<Istio::Common::WorkloadMetadataObject>(metadata_object.value());
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -154,8 +131,7 @@ absl::optional<PeerInfo> MXMethod::lookup(absl::string_view id, absl::string_vie
|
||||||
if (!metadata.ParseFromString(bytes)) {
|
if (!metadata.ParseFromString(bytes)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const auto fb = ::Wasm::Common::extractNodeFlatBufferFromStruct(metadata);
|
const auto out = Istio::Common::convertStructToWorkloadMetadata(metadata);
|
||||||
std::string out(reinterpret_cast<const char*>(fb.data()), fb.size());
|
|
||||||
if (max_peer_cache_size_ > 0 && !id.empty()) {
|
if (max_peer_cache_size_ > 0 && !id.empty()) {
|
||||||
// do not let the cache grow beyond max cache size.
|
// do not let the cache grow beyond max cache size.
|
||||||
if (static_cast<uint32_t>(cache.size()) > max_peer_cache_size_) {
|
if (static_cast<uint32_t>(cache.size()) > max_peer_cache_size_) {
|
||||||
|
|
@ -175,11 +151,10 @@ MXPropagationMethod::MXPropagationMethod(
|
||||||
|
|
||||||
std::string MXPropagationMethod::computeValue(
|
std::string MXPropagationMethod::computeValue(
|
||||||
Server::Configuration::ServerFactoryContext& factory_context) const {
|
Server::Configuration::ServerFactoryContext& factory_context) const {
|
||||||
const auto fb = ::Wasm::Common::extractNodeFlatBufferFromStruct(
|
const auto out =
|
||||||
factory_context.localInfo().node().metadata());
|
Istio::Common::convertStructToWorkloadMetadata(factory_context.localInfo().node().metadata());
|
||||||
google::protobuf::Struct metadata;
|
google::protobuf::Struct metadata;
|
||||||
::Wasm::Common::extractStructFromNodeFlatBuffer(
|
out->toStruct(&metadata);
|
||||||
*flatbuffers::GetRoot<::Wasm::Common::FlatNode>(fb.data()), &metadata);
|
|
||||||
std::string metadata_bytes;
|
std::string metadata_bytes;
|
||||||
::Wasm::Common::serializeToStringDeterministic(metadata, &metadata_bytes);
|
::Wasm::Common::serializeToStringDeterministic(metadata, &metadata_bytes);
|
||||||
return Base64::encode(metadata_bytes.data(), metadata_bytes.size());
|
return Base64::encode(metadata_bytes.data(), metadata_bytes.size());
|
||||||
|
|
@ -296,15 +271,13 @@ void FilterConfig::injectUpstream(const StreamInfo::StreamInfo& info,
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilterConfig::setFilterState(StreamInfo::StreamInfo& info, bool downstream,
|
void FilterConfig::setFilterState(StreamInfo::StreamInfo& info, bool downstream,
|
||||||
const std::string& value) const {
|
const PeerInfo& value) const {
|
||||||
const absl::string_view key =
|
const absl::string_view key =
|
||||||
downstream ? Istio::Common::WasmDownstreamPeer : Istio::Common::WasmUpstreamPeer;
|
downstream ? Istio::Common::WasmDownstreamPeer : Istio::Common::WasmUpstreamPeer;
|
||||||
if (!info.filterState()->hasDataWithName(key)) {
|
if (!info.filterState()->hasDataWithName(key)) {
|
||||||
auto node_info = std::make_unique<CelStateHashable>(CelPrototypes::get().NodeInfo);
|
info.filterState()->setData(key, value, StreamInfo::FilterState::StateType::Mutable,
|
||||||
node_info->setValue(value);
|
StreamInfo::FilterState::LifeSpan::FilterChain,
|
||||||
info.filterState()->setData(
|
sharedWithUpstream());
|
||||||
key, std::move(node_info), StreamInfo::FilterState::StateType::Mutable,
|
|
||||||
StreamInfo::FilterState::LifeSpan::FilterChain, sharedWithUpstream());
|
|
||||||
} else {
|
} else {
|
||||||
ENVOY_LOG(debug, "Duplicate peer metadata, skipping");
|
ENVOY_LOG(debug, "Duplicate peer metadata, skipping");
|
||||||
}
|
}
|
||||||
|
|
@ -313,11 +286,10 @@ void FilterConfig::setFilterState(StreamInfo::StreamInfo& info, bool downstream,
|
||||||
const absl::string_view id_key =
|
const absl::string_view id_key =
|
||||||
downstream ? Istio::Common::WasmDownstreamPeerID : Istio::Common::WasmUpstreamPeerID;
|
downstream ? Istio::Common::WasmDownstreamPeerID : Istio::Common::WasmUpstreamPeerID;
|
||||||
if (!info.filterState()->hasDataWithName(id_key)) {
|
if (!info.filterState()->hasDataWithName(id_key)) {
|
||||||
auto node_id = std::make_unique<Filters::Common::Expr::CelState>(CelPrototypes::get().NodeId);
|
info.filterState()->setData(id_key, std::make_shared<Router::StringAccessorImpl>("unknown"),
|
||||||
node_id->setValue("unknown");
|
StreamInfo::FilterState::StateType::Mutable,
|
||||||
info.filterState()->setData(
|
StreamInfo::FilterState::LifeSpan::FilterChain,
|
||||||
id_key, std::move(node_id), StreamInfo::FilterState::StateType::Mutable,
|
sharedWithUpstream());
|
||||||
StreamInfo::FilterState::LifeSpan::FilterChain, sharedWithUpstream());
|
|
||||||
} else {
|
} else {
|
||||||
ENVOY_LOG(debug, "Duplicate peer id, skipping");
|
ENVOY_LOG(debug, "Duplicate peer id, skipping");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ struct HeaderValues {
|
||||||
using Headers = ConstSingleton<HeaderValues>;
|
using Headers = ConstSingleton<HeaderValues>;
|
||||||
|
|
||||||
// Peer info in the flatbuffers format.
|
// Peer info in the flatbuffers format.
|
||||||
using PeerInfo = std::string;
|
using PeerInfo = std::shared_ptr<Istio::Common::WorkloadMetadataObject>;
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
bool request_peer_id_received_{false};
|
bool request_peer_id_received_{false};
|
||||||
|
|
@ -62,7 +62,7 @@ private:
|
||||||
absl::optional<PeerInfo> lookup(absl::string_view id, absl::string_view value) const;
|
absl::optional<PeerInfo> lookup(absl::string_view id, absl::string_view value) const;
|
||||||
const bool downstream_;
|
const bool downstream_;
|
||||||
struct MXCache : public ThreadLocal::ThreadLocalObject {
|
struct MXCache : public ThreadLocal::ThreadLocalObject {
|
||||||
absl::flat_hash_map<std::string, std::string> cache_;
|
absl::flat_hash_map<std::string, PeerInfo> cache_;
|
||||||
};
|
};
|
||||||
mutable ThreadLocal::TypedSlot<MXCache> tls_;
|
mutable ThreadLocal::TypedSlot<MXCache> tls_;
|
||||||
const int64_t max_peer_cache_size_{500};
|
const int64_t max_peer_cache_size_{500};
|
||||||
|
|
@ -114,7 +114,7 @@ private:
|
||||||
: StreamInfo::StreamSharingMayImpactPooling::None;
|
: StreamInfo::StreamSharingMayImpactPooling::None;
|
||||||
}
|
}
|
||||||
void discover(StreamInfo::StreamInfo&, bool downstream, Http::HeaderMap&, Context&) const;
|
void discover(StreamInfo::StreamInfo&, bool downstream, Http::HeaderMap&, Context&) const;
|
||||||
void setFilterState(StreamInfo::StreamInfo&, bool downstream, const std::string& value) const;
|
void setFilterState(StreamInfo::StreamInfo&, bool downstream, const PeerInfo& value) const;
|
||||||
const bool shared_with_upstream_;
|
const bool shared_with_upstream_;
|
||||||
const std::vector<DiscoveryMethodPtr> downstream_discovery_;
|
const std::vector<DiscoveryMethodPtr> downstream_discovery_;
|
||||||
const std::vector<DiscoveryMethodPtr> upstream_discovery_;
|
const std::vector<DiscoveryMethodPtr> upstream_discovery_;
|
||||||
|
|
|
||||||
|
|
@ -84,16 +84,11 @@ protected:
|
||||||
void checkPeerNamespace(bool downstream, const std::string& expected) {
|
void checkPeerNamespace(bool downstream, const std::string& expected) {
|
||||||
EXPECT_TRUE(stream_info_.filterState()->hasDataWithName(
|
EXPECT_TRUE(stream_info_.filterState()->hasDataWithName(
|
||||||
downstream ? Istio::Common::WasmDownstreamPeerID : Istio::Common::WasmUpstreamPeerID));
|
downstream ? Istio::Common::WasmDownstreamPeerID : Istio::Common::WasmUpstreamPeerID));
|
||||||
const auto* obj = stream_info_.filterState()->getDataReadOnly<Filters::Common::Expr::CelState>(
|
const auto* obj =
|
||||||
|
stream_info_.filterState()->getDataReadOnly<Istio::Common::WorkloadMetadataObject>(
|
||||||
downstream ? Istio::Common::WasmDownstreamPeer : Istio::Common::WasmUpstreamPeer);
|
downstream ? Istio::Common::WasmDownstreamPeer : Istio::Common::WasmUpstreamPeer);
|
||||||
ASSERT_NE(nullptr, obj);
|
ASSERT_NE(nullptr, obj);
|
||||||
Protobuf::Arena arena;
|
EXPECT_EQ(expected, obj->namespace_name_);
|
||||||
auto map = obj->exprValue(&arena, false);
|
|
||||||
ASSERT_TRUE(map.IsMap());
|
|
||||||
auto value =
|
|
||||||
(*map.MapOrDie())[google::api::expr::runtime::CelValue::CreateStringView("namespace")];
|
|
||||||
ASSERT_TRUE(value.has_value());
|
|
||||||
EXPECT_EQ(expected, value.value().StringOrDie().value());
|
|
||||||
}
|
}
|
||||||
void checkShared(bool expected) {
|
void checkShared(bool expected) {
|
||||||
EXPECT_EQ(expected,
|
EXPECT_EQ(expected,
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ envoy_cc_library(
|
||||||
"@envoy//source/common/network:utility_lib",
|
"@envoy//source/common/network:utility_lib",
|
||||||
"@envoy//source/common/protobuf",
|
"@envoy//source/common/protobuf",
|
||||||
"@envoy//source/common/protobuf:utility_lib",
|
"@envoy//source/common/protobuf:utility_lib",
|
||||||
"@envoy//source/extensions/filters/common/expr:cel_state_lib",
|
"@envoy//source/common/router:string_accessor_lib",
|
||||||
"@envoy//source/extensions/filters/network:well_known_names",
|
"@envoy//source/extensions/filters/network:well_known_names",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "envoy/stats/scope.h"
|
#include "envoy/stats/scope.h"
|
||||||
#include "source/common/buffer/buffer_impl.h"
|
#include "source/common/buffer/buffer_impl.h"
|
||||||
#include "source/common/protobuf/utility.h"
|
#include "source/common/protobuf/utility.h"
|
||||||
|
#include "source/common/router/string_accessor_impl.h"
|
||||||
#include "source/extensions/filters/network/metadata_exchange/metadata_exchange_initial_header.h"
|
#include "source/extensions/filters/network/metadata_exchange/metadata_exchange_initial_header.h"
|
||||||
|
|
||||||
namespace Envoy {
|
namespace Envoy {
|
||||||
|
|
@ -58,18 +59,6 @@ constructProxyHeaderData(const Envoy::ProtobufWkt::Any& proxy_data) {
|
||||||
return proxy_data_buffer;
|
return proxy_data_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool serializeToStringDeterministic(const google::protobuf::Struct& metadata,
|
|
||||||
std::string* metadata_bytes) {
|
|
||||||
google::protobuf::io::StringOutputStream md(metadata_bytes);
|
|
||||||
google::protobuf::io::CodedOutputStream mcs(&md);
|
|
||||||
|
|
||||||
mcs.SetSerializationDeterministic(true);
|
|
||||||
if (!metadata.SerializeToCodedStream(&mcs)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
MetadataExchangeConfig::MetadataExchangeConfig(
|
MetadataExchangeConfig::MetadataExchangeConfig(
|
||||||
|
|
@ -209,7 +198,7 @@ void MetadataExchangeFilter::writeNodeMetadata() {
|
||||||
Envoy::ProtobufWkt::Any metadata_any_value;
|
Envoy::ProtobufWkt::Any metadata_any_value;
|
||||||
metadata_any_value.set_type_url(StructTypeUrl);
|
metadata_any_value.set_type_url(StructTypeUrl);
|
||||||
std::string serialized_data;
|
std::string serialized_data;
|
||||||
serializeToStringDeterministic(data, &serialized_data);
|
::Wasm::Common::serializeToStringDeterministic(data, &serialized_data);
|
||||||
*metadata_any_value.mutable_value() = serialized_data;
|
*metadata_any_value.mutable_value() = serialized_data;
|
||||||
std::unique_ptr<::Envoy::Buffer::OwnedImpl> buf = constructProxyHeaderData(metadata_any_value);
|
std::unique_ptr<::Envoy::Buffer::OwnedImpl> buf = constructProxyHeaderData(metadata_any_value);
|
||||||
write_callbacks_->injectWriteDataToFilterChain(*buf, false);
|
write_callbacks_->injectWriteDataToFilterChain(*buf, false);
|
||||||
|
|
@ -274,9 +263,8 @@ void MetadataExchangeFilter::tryReadProxyData(Buffer::Instance& data) {
|
||||||
Envoy::MessageUtil::anyConvert<Envoy::ProtobufWkt::Struct>(proxy_data);
|
Envoy::MessageUtil::anyConvert<Envoy::ProtobufWkt::Struct>(proxy_data);
|
||||||
auto key_metadata_it = value_struct.fields().find(ExchangeMetadataHeader);
|
auto key_metadata_it = value_struct.fields().find(ExchangeMetadataHeader);
|
||||||
if (key_metadata_it != value_struct.fields().end()) {
|
if (key_metadata_it != value_struct.fields().end()) {
|
||||||
const auto fb =
|
const auto out =
|
||||||
::Wasm::Common::extractNodeFlatBufferFromStruct(key_metadata_it->second.struct_value());
|
Istio::Common::convertStructToWorkloadMetadata(key_metadata_it->second.struct_value());
|
||||||
std::string out(reinterpret_cast<const char*>(fb.data()), fb.size());
|
|
||||||
updatePeer(out);
|
updatePeer(out);
|
||||||
}
|
}
|
||||||
const auto key_metadata_id_it = value_struct.fields().find(ExchangeMetadataHeaderId);
|
const auto key_metadata_id_it = value_struct.fields().find(ExchangeMetadataHeaderId);
|
||||||
|
|
@ -289,36 +277,25 @@ void MetadataExchangeFilter::tryReadProxyData(Buffer::Instance& data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetadataExchangeFilter::updatePeer(const std::string& fb) {
|
void MetadataExchangeFilter::updatePeer(
|
||||||
// Filter object captures schema by view, hence the global singleton for the
|
const std::shared_ptr<Istio::Common::WorkloadMetadataObject>& obj) {
|
||||||
// prototype.
|
|
||||||
auto state = std::make_unique<::Envoy::Extensions::Filters::Common::Expr::CelState>(
|
|
||||||
MetadataExchangeConfig::nodeInfoPrototype());
|
|
||||||
state->setValue(fb);
|
|
||||||
|
|
||||||
auto key = config_->filter_direction_ == FilterDirection::Downstream ? kDownstreamMetadataKey
|
auto key = config_->filter_direction_ == FilterDirection::Downstream ? kDownstreamMetadataKey
|
||||||
: kUpstreamMetadataKey;
|
: kUpstreamMetadataKey;
|
||||||
read_callbacks_->connection().streamInfo().filterState()->setData(
|
read_callbacks_->connection().streamInfo().filterState()->setData(
|
||||||
absl::StrCat("wasm.", key), std::move(state), StreamInfo::FilterState::StateType::Mutable,
|
absl::StrCat("wasm.", key), obj, StreamInfo::FilterState::StateType::Mutable,
|
||||||
StreamInfo::FilterState::LifeSpan::Connection);
|
StreamInfo::FilterState::LifeSpan::Connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetadataExchangeFilter::updatePeerId(absl::string_view key, absl::string_view value) {
|
void MetadataExchangeFilter::updatePeerId(absl::string_view key, absl::string_view value) {
|
||||||
CelStatePrototype prototype(
|
|
||||||
/* read_only = */ false, ::Envoy::Extensions::Filters::Common::Expr::CelStateType::String,
|
|
||||||
absl::string_view(), StreamInfo::FilterState::LifeSpan::Connection);
|
|
||||||
auto state = std::make_unique<::Envoy::Extensions::Filters::Common::Expr::CelState>(prototype);
|
|
||||||
state->setValue(value);
|
|
||||||
read_callbacks_->connection().streamInfo().filterState()->setData(
|
read_callbacks_->connection().streamInfo().filterState()->setData(
|
||||||
absl::StrCat("wasm.", key), std::move(state), StreamInfo::FilterState::StateType::Mutable,
|
absl::StrCat("wasm.", key), std::make_shared<Router::StringAccessorImpl>(value),
|
||||||
prototype.life_span_);
|
StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetadataExchangeFilter::getMetadata(google::protobuf::Struct* metadata) {
|
void MetadataExchangeFilter::getMetadata(google::protobuf::Struct* metadata) {
|
||||||
if (local_info_.node().has_metadata()) {
|
if (local_info_.node().has_metadata()) {
|
||||||
const auto fb = ::Wasm::Common::extractNodeFlatBufferFromStruct(local_info_.node().metadata());
|
const auto out = Istio::Common::convertStructToWorkloadMetadata(local_info_.node().metadata());
|
||||||
::Wasm::Common::extractStructFromNodeFlatBuffer(
|
out->toStruct(metadata);
|
||||||
*flatbuffers::GetRoot<::Wasm::Common::FlatNode>(fb.data()), metadata);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,7 +308,7 @@ void MetadataExchangeFilter::setMetadataNotFoundFilterState() {
|
||||||
ENVOY_LOG(debug, "Look up metadata based on peer address {}", peer_address->asString());
|
ENVOY_LOG(debug, "Look up metadata based on peer address {}", peer_address->asString());
|
||||||
const auto metadata_object = config_->metadata_provider_->GetMetadata(peer_address);
|
const auto metadata_object = config_->metadata_provider_->GetMetadata(peer_address);
|
||||||
if (metadata_object) {
|
if (metadata_object) {
|
||||||
updatePeer(Istio::Common::convertWorkloadMetadataToFlatNode(metadata_object.value()));
|
updatePeer(std::make_shared<Istio::Common::WorkloadMetadataObject>(metadata_object.value()));
|
||||||
updatePeerId(config_->filter_direction_ == FilterDirection::Downstream
|
updatePeerId(config_->filter_direction_ == FilterDirection::Downstream
|
||||||
? kDownstreamMetadataIdKey
|
? kDownstreamMetadataIdKey
|
||||||
: kUpstreamMetadataIdKey,
|
: kUpstreamMetadataIdKey,
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,10 @@
|
||||||
#include "envoy/stats/scope.h"
|
#include "envoy/stats/scope.h"
|
||||||
#include "envoy/stats/stats_macros.h"
|
#include "envoy/stats/stats_macros.h"
|
||||||
#include "envoy/stream_info/filter_state.h"
|
#include "envoy/stream_info/filter_state.h"
|
||||||
#include "extensions/common/node_info_bfbs_generated.h"
|
|
||||||
#include "extensions/common/proto_util.h"
|
#include "extensions/common/proto_util.h"
|
||||||
#include "extensions/common/metadata_object.h"
|
#include "extensions/common/metadata_object.h"
|
||||||
#include "source/common/common/stl_helpers.h"
|
#include "source/common/common/stl_helpers.h"
|
||||||
#include "source/common/protobuf/protobuf.h"
|
#include "source/common/protobuf/protobuf.h"
|
||||||
#include "source/extensions/filters/common/expr/cel_state.h"
|
|
||||||
#include "source/extensions/filters/network/metadata_exchange/config/metadata_exchange.pb.h"
|
#include "source/extensions/filters/network/metadata_exchange/config/metadata_exchange.pb.h"
|
||||||
#include "source/extensions/common/workload_discovery/api.h"
|
#include "source/extensions/common/workload_discovery/api.h"
|
||||||
|
|
||||||
|
|
@ -36,8 +34,6 @@ namespace Envoy {
|
||||||
namespace Tcp {
|
namespace Tcp {
|
||||||
namespace MetadataExchange {
|
namespace MetadataExchange {
|
||||||
|
|
||||||
using ::Envoy::Extensions::Filters::Common::Expr::CelStatePrototype;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All MetadataExchange filter stats. @see stats_macros.h
|
* All MetadataExchange filter stats. @see stats_macros.h
|
||||||
*/
|
*/
|
||||||
|
|
@ -86,13 +82,6 @@ public:
|
||||||
// Stats for MetadataExchange Filter.
|
// Stats for MetadataExchange Filter.
|
||||||
MetadataExchangeStats stats_;
|
MetadataExchangeStats stats_;
|
||||||
|
|
||||||
static const CelStatePrototype& nodeInfoPrototype() {
|
|
||||||
static const CelStatePrototype* const prototype = new CelStatePrototype(
|
|
||||||
true, ::Envoy::Extensions::Filters::Common::Expr::CelStateType::FlatBuffers,
|
|
||||||
::Istio::Common::nodeInfoSchema(), StreamInfo::FilterState::LifeSpan::Connection);
|
|
||||||
return *prototype;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MetadataExchangeStats generateStats(const std::string& prefix, Stats::Scope& scope) {
|
MetadataExchangeStats generateStats(const std::string& prefix, Stats::Scope& scope) {
|
||||||
return MetadataExchangeStats{ALL_METADATA_EXCHANGE_STATS(POOL_COUNTER_PREFIX(scope, prefix))};
|
return MetadataExchangeStats{ALL_METADATA_EXCHANGE_STATS(POOL_COUNTER_PREFIX(scope, prefix))};
|
||||||
|
|
@ -137,7 +126,7 @@ private:
|
||||||
void tryReadProxyData(Buffer::Instance& data);
|
void tryReadProxyData(Buffer::Instance& data);
|
||||||
|
|
||||||
// Helper function to share the metadata with other filters.
|
// Helper function to share the metadata with other filters.
|
||||||
void updatePeer(const std::string& fb);
|
void updatePeer(const std::shared_ptr<Istio::Common::WorkloadMetadataObject>& obj);
|
||||||
void updatePeerId(absl::string_view key, absl::string_view value);
|
void updatePeerId(absl::string_view key, absl::string_view value);
|
||||||
|
|
||||||
// Helper function to get Dynamic metadata.
|
// Helper function to get Dynamic metadata.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue