Use FilterState instead of DynamicMetadata in Metadata Exchange Filter (#2452)

* Use FilterState instead  of  DynamicMetadata  in  Metadata Exchange  Plugin

Also made  the plugin  in sync with existing HTTP Metadata Exchange Wasm Plugin,  so that stats(prometheus)  plugin  can use this easily.

Fixed based on feedback

* Fix  build errors
This commit is contained in:
Nupur Garg 2019-10-16 13:47:15 -07:00 committed by Istio Automation
parent 08600d765c
commit fe67c04209
14 changed files with 247 additions and 98 deletions

View File

@ -15,6 +15,8 @@
#include "extensions/common/context.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "google/protobuf/util/json_util.h"
// WASM_PROLOG
@ -160,5 +162,41 @@ void populateHTTPRequestInfo(bool outbound, RequestInfo* request_info) {
request_info->destination_port = destination_port;
}
google::protobuf::util::Status extractNodeMetadataValue(
const google::protobuf::Struct& node_metadata,
google::protobuf::Struct* metadata) {
if (metadata == nullptr) {
return google::protobuf::util::Status(
google::protobuf::util::error::INVALID_ARGUMENT,
"metadata provided is null");
}
const auto key_it = node_metadata.fields().find("EXCHANGE_KEYS");
if (key_it == node_metadata.fields().end()) {
return google::protobuf::util::Status(
google::protobuf::util::error::INVALID_ARGUMENT,
"metadata exchange key is missing");
}
const auto& keys_value = key_it->second;
if (keys_value.kind_case() != google::protobuf::Value::kStringValue) {
return google::protobuf::util::Status(
google::protobuf::util::error::INVALID_ARGUMENT,
"metadata exchange key is not a string");
}
// select keys from the metadata using the keys
const std::set<std::string> keys =
absl::StrSplit(keys_value.string_value(), ',', absl::SkipWhitespace());
for (auto key : keys) {
const auto entry_it = node_metadata.fields().find(key);
if (entry_it == node_metadata.fields().end()) {
continue;
}
(*metadata->mutable_fields())[key] = entry_it->second;
}
return google::protobuf::util::Status(google::protobuf::util::error::OK, "");
}
} // namespace Common
} // namespace Wasm

View File

@ -131,5 +131,12 @@ google::protobuf::util::Status extractLocalNodeMetadata(
// the request context.
void populateHTTPRequestInfo(bool outbound, RequestInfo* request_info);
// Extracts node metadata value. It looks for values of all the keys
// corresponding to EXCHANGE_KEYS in node_metadata and populates it in
// google::protobuf::Value pointer that is passed in.
google::protobuf::util::Status extractNodeMetadataValue(
const google::protobuf::Struct& node_metadata,
google::protobuf::Struct* metadata);
} // namespace Common
} // namespace Wasm

View File

@ -129,6 +129,24 @@ TEST(ContextTest, extractNodeMetadataUnknownField) {
EXPECT_EQ(status, Status::OK);
}
// Test extractNodeMetadataValue.
TEST(ContextTest, extractNodeMetadataValue) {
google::protobuf::Struct metadata_struct;
auto node_metadata_map = metadata_struct.mutable_fields();
(*node_metadata_map)["EXCHANGE_KEYS"].set_string_value("namespace,labels");
(*node_metadata_map)["namespace"].set_string_value("default");
(*node_metadata_map)["labels"].set_string_value("{app, details}");
google::protobuf::Struct value_struct;
const auto status = extractNodeMetadataValue(metadata_struct, &value_struct);
EXPECT_EQ(status, Status::OK);
auto namespace_iter = value_struct.fields().find("namespace");
EXPECT_TRUE(namespace_iter != value_struct.fields().end());
EXPECT_EQ(namespace_iter->second.string_value(), "default");
auto label_iter = value_struct.fields().find("labels");
EXPECT_TRUE(label_iter != value_struct.fields().end());
EXPECT_EQ(label_iter->second.string_value(), "{app, details}");
}
} // namespace Common
// WASM_EPILOG

View File

@ -20,6 +20,7 @@ envoy_cc_library(
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
"//extensions/common:context",
"@envoy//source/common/common:base64_lib",
"@envoy//source/extensions/common/wasm/null:null_plugin_lib",
],

View File

@ -24,6 +24,7 @@
#else
#include "common/common/base64.h"
#include "extensions/common/context.h"
#include "extensions/metadata_exchange/plugin.h"
namespace Envoy {
@ -67,31 +68,12 @@ void PluginRootContext::updateMetadataValue() {
return;
}
const auto key_it = node_metadata.fields().find("EXCHANGE_KEYS");
if (key_it == node_metadata.fields().end()) {
logWarn("metadata exchange key is missing");
return;
}
const auto& keys_value = key_it->second;
if (keys_value.kind_case() != google::protobuf::Value::kStringValue) {
logWarn("metadata exchange key is not a string");
return;
}
google::protobuf::Value metadata;
// select keys from the metadata using the keys
const std::set<std::string> keys =
absl::StrSplit(keys_value.string_value(), ',', absl::SkipWhitespace());
for (auto key : keys) {
const auto entry_it = node_metadata.fields().find(key);
if (entry_it == node_metadata.fields().end()) {
logDebug(absl::StrCat("missing metadata exchange key: ", key));
continue;
}
(*metadata.mutable_struct_value()->mutable_fields())[key] =
entry_it->second;
const auto status = ::Wasm::Common::extractNodeMetadataValue(
node_metadata, metadata.mutable_struct_value());
if (!status.ok()) {
logWarn(status.message().ToString());
return;
}
// store serialized form

View File

@ -38,6 +38,7 @@ envoy_cc_library(
],
repository = "@envoy",
deps = [
"//extensions/common:context",
"//src/envoy/tcp/metadata_exchange/config:metadata_exchange_cc_proto",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:endian",
@ -47,10 +48,12 @@ envoy_cc_library(
"@envoy//include/envoy/network:filter_interface",
"@envoy//include/envoy/runtime:runtime_interface",
"@envoy//include/envoy/stats:stats_macros",
"@envoy//include/envoy/stream_info:filter_state_interface",
"@envoy//source/common/http:utility_lib",
"@envoy//source/common/network:utility_lib",
"@envoy//source/common/protobuf",
"@envoy//source/common/protobuf:utility_lib",
"@envoy//source/extensions/common/wasm:wasm_interoperation_lib",
"@envoy//source/extensions/filters/network:well_known_names",
],
)

View File

@ -34,8 +34,8 @@ Network::FilterFactoryCb createFilterFactoryHelper(
MetadataExchangeConfigSharedPtr filter_config(
std::make_shared<MetadataExchangeConfig>(
StatPrefix, proto_config.protocol(), proto_config.node_metadata_id(),
filter_direction, context.scope()));
StatPrefix, proto_config.protocol(), filter_direction,
context.scope()));
return [filter_config,
&context](Network::FilterManager& filter_manager) -> void {
filter_manager.addFilter(std::make_shared<MetadataExchangeFilter>(

View File

@ -28,8 +28,4 @@ message MetadataExchange {
// Protocol that Alpn should support on the server.
// [#comment:TODO(GargNupur): Make it a list.]
string protocol = 1;
// The node metadata id whose data will be written to connection data.
// [#comment: TODO(GargNupur): Remove this and use bootstrap node.id]
string node_metadata_id = 2;
}

View File

@ -17,11 +17,14 @@
#include <string>
#include "absl/base/internal/endian.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "common/buffer/buffer_impl.h"
#include "common/protobuf/utility.h"
#include "envoy/network/connection.h"
#include "envoy/stats/scope.h"
#include "extensions/common/context.h"
#include "extensions/common/wasm/wasm_state.h"
#include "src/envoy/tcp/metadata_exchange/metadata_exchange.h"
#include "src/envoy/tcp/metadata_exchange/metadata_exchange_initial_header.h"
@ -49,16 +52,26 @@ std::unique_ptr<::Envoy::Buffer::OwnedImpl> constructProxyHeaderData(
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
MetadataExchangeConfig::MetadataExchangeConfig(
const std::string& stat_prefix, const std::string& protocol,
const std::string& node_metadata_id, const FilterDirection filter_direction,
Stats::Scope& scope)
const FilterDirection filter_direction, Stats::Scope& scope)
: scope_(scope),
stat_prefix_(stat_prefix),
protocol_(protocol),
node_metadata_id_(node_metadata_id),
filter_direction_(filter_direction),
stats_(generateStats(stat_prefix, scope)) {}
@ -156,21 +169,24 @@ void MetadataExchangeFilter::writeNodeMetadata() {
return;
}
std::unique_ptr<const google::protobuf::Struct> metadata =
getMetadata(config_->node_metadata_id_);
if (metadata != nullptr) {
Envoy::ProtobufWkt::Struct data;
Envoy::ProtobufWkt::Struct* metadata =
(*data.mutable_fields())[ExchangeMetadataHeader].mutable_struct_value();
getMetadata(metadata);
std::string metadata_id = getMetadataId();
if (!metadata_id.empty()) {
(*data.mutable_fields())[ExchangeMetadataHeaderId].set_string_value(
metadata_id);
}
if (data.fields_size() > 0) {
Envoy::ProtobufWkt::Any metadata_any_value;
*metadata_any_value.mutable_type_url() = StructTypeUrl;
*metadata_any_value.mutable_value() = metadata->SerializeAsString();
std::string serialized_data;
serializeToStringDeterministic(data, &serialized_data);
*metadata_any_value.mutable_value() = serialized_data;
std::unique_ptr<::Envoy::Buffer::OwnedImpl> buf =
constructProxyHeaderData(metadata_any_value);
write_callbacks_->injectWriteDataToFilterChain(*buf, false);
if (config_->filter_direction_ == FilterDirection::Downstream) {
setMetadata(DownstreamDynamicDataKey, *metadata);
} else {
setMetadata(UpstreamDynamicDataKey, *metadata);
}
config_->stats().metadata_added_.inc();
}
@ -224,31 +240,58 @@ void MetadataExchangeFilter::tryReadProxyData(Buffer::Instance& data) {
}
data.drain(proxy_data_length_);
Envoy::ProtobufWkt::Struct struct_metadata =
// Set Metadata
Envoy::ProtobufWkt::Struct value_struct =
Envoy::MessageUtil::anyConvert<Envoy::ProtobufWkt::Struct>(proxy_data);
if (config_->filter_direction_ == FilterDirection::Downstream) {
setMetadata(UpstreamDynamicDataKey, struct_metadata);
} else {
setMetadata(DownstreamDynamicDataKey, struct_metadata);
auto key_metadata_it = value_struct.fields().find(ExchangeMetadataHeader);
if (key_metadata_it != value_struct.fields().end()) {
Envoy::ProtobufWkt::Value val = key_metadata_it->second;
setMetadata(config_->filter_direction_ == FilterDirection::Downstream
? UpstreamMetadataKey
: DownstreamMetadataKey,
val);
}
const auto key_metadata_id_it =
value_struct.fields().find(ExchangeMetadataHeaderId);
if (key_metadata_id_it != value_struct.fields().end()) {
Envoy::ProtobufWkt::Value val = key_metadata_it->second;
setMetadata(config_->filter_direction_ == FilterDirection::Downstream
? UpstreamMetadataIdKey
: DownstreamMetadataIdKey,
val);
}
}
void MetadataExchangeFilter::setMetadata(const std::string key,
const ProtobufWkt::Struct& value) {
read_callbacks_->connection().streamInfo().setDynamicMetadata(key, value);
void MetadataExchangeFilter::setMetadata(const std::string& key,
Envoy::ProtobufWkt::Value& value) {
read_callbacks_->connection().streamInfo().filterState().setData(
key,
std::make_unique<::Envoy::Extensions::Common::Wasm::WasmState>(value),
StreamInfo::FilterState::StateType::Mutable);
}
std::unique_ptr<const google::protobuf::Struct>
MetadataExchangeFilter::getMetadata(const std::string& key) {
void MetadataExchangeFilter::setMetadataStringValue(
const std::string& key, const std::string& str_value) {
Envoy::ProtobufWkt::Value value;
value.set_string_value(str_value);
setMetadata(key, value);
}
void MetadataExchangeFilter::getMetadata(google::protobuf::Struct* metadata) {
if (local_info_.node().has_metadata()) {
auto metadata_fields = local_info_.node().metadata().fields();
auto node_metadata = metadata_fields.find(key);
if (node_metadata != metadata_fields.end()) {
return std::make_unique<const google::protobuf::Struct>(
node_metadata->second.struct_value());
google::protobuf::Struct node_metadata = local_info_.node().metadata();
google::protobuf::Value value_struct;
const auto status =
Wasm::Common::extractNodeMetadataValue(node_metadata, metadata);
if (!status.ok()) {
return;
}
}
return nullptr;
}
std::string MetadataExchangeFilter::getMetadataId() {
return local_info_.node().id();
}
} // namespace MetadataExchange

View File

@ -23,6 +23,7 @@
#include "envoy/runtime/runtime.h"
#include "envoy/stats/scope.h"
#include "envoy/stats/stats_macros.h"
#include "envoy/stream_info/filter_state.h"
#include "src/envoy/tcp/metadata_exchange/config/metadata_exchange.pb.h"
namespace Envoy {
@ -59,7 +60,6 @@ class MetadataExchangeConfig {
public:
MetadataExchangeConfig(const std::string& stat_prefix,
const std::string& protocol,
const std::string& node_metadata_id,
const FilterDirection filter_direction,
Stats::Scope& scope);
@ -71,8 +71,6 @@ class MetadataExchangeConfig {
const std::string stat_prefix_;
// Expected Alpn Protocol.
const std::string protocol_;
// Node metadata id to read.
const std::string node_metadata_id_;
// Direction of filter.
const FilterDirection filter_direction_;
// Stats for MetadataExchange Filter.
@ -129,11 +127,20 @@ class MetadataExchangeFilter : public Network::Filter {
void tryReadProxyData(Buffer::Instance& data);
// Helper function to set Dynamic metadata.
void setMetadata(const std::string key, const ProtobufWkt::Struct& value);
void setMetadata(const std::string& key, ProtobufWkt::Value& value);
// Helper function to set Dynamic metadata string value.
void setMetadataStringValue(const std::string& key, const std::string& value);
// Helper function to set Dynamic metadata string value.
void setMetadataStructValue(const std::string& key,
const ProtobufWkt::Value& value);
// Helper function to get Dynamic metadata.
std::unique_ptr<const google::protobuf::Struct> getMetadata(
const std::string& key);
void getMetadata(google::protobuf::Struct* metadata);
// Helper function to get metadata id.
std::string getMetadataId();
// Config for MetadataExchange filter.
MetadataExchangeConfigSharedPtr config_;
@ -147,11 +154,20 @@ class MetadataExchangeFilter : public Network::Filter {
uint64_t proxy_data_length_{0};
// Key Identifier for dynamic metadata in upstream filter.
const std::string UpstreamDynamicDataKey =
"filters.network.metadata_exchange.upstream";
const std::string UpstreamMetadataKey =
"envoy.wasm.metadata_exchange.upstream";
const std::string UpstreamMetadataIdKey =
"envoy.wasm.metadata_exchange.upstream_id";
// Key Identifier for dynamic metadata in downstream filter.
const std::string DownstreamDynamicDataKey =
"filters.network.metadata_exchange.downstream";
const std::string DownstreamMetadataKey =
"envoy.wasm.metadata_exchange.downstream";
const std::string DownstreamMetadataIdKey =
"envoy.wasm.metadata_exchange.downstream_id";
const std::string ExchangeMetadataHeader = "x-envoy-peer-metadata";
const std::string ExchangeMetadataHeaderId = "x-envoy-peer-metadata-id";
// Type url of google::protobug::struct.
const std::string StructTypeUrl =
"type.googleapis.com/google.protobuf.Struct";

View File

@ -58,12 +58,16 @@ class MetadataExchangeFilterTest : public testing::Test {
void initialize() {
config_ = std::make_shared<MetadataExchangeConfig>(
stat_prefix_, "istio2", "istio/metadata", FilterDirection::Downstream,
scope_);
stat_prefix_, "istio2", FilterDirection::Downstream, scope_);
filter_ = std::make_unique<MetadataExchangeFilter>(config_, local_info_);
filter_->initializeReadFilterCallbacks(read_filter_callbacks_);
filter_->initializeWriteFilterCallbacks(write_filter_callbacks_);
metadata_node_.set_id("test");
auto node_metadata_map =
metadata_node_.mutable_metadata()->mutable_fields();
(*node_metadata_map)["EXCHANGE_KEYS"].set_string_value("namespace, labels");
(*node_metadata_map)["namespace"].set_string_value("default");
(*node_metadata_map)["labels"].set_string_value("{app, details}");
EXPECT_CALL(read_filter_callbacks_.connection_, streamInfo())
.WillRepeatedly(ReturnRef(stream_info_));
EXPECT_CALL(local_info_, node()).WillRepeatedly(ReturnRef(metadata_node_));
@ -98,18 +102,8 @@ TEST_F(MetadataExchangeFilterTest, MetadataExchangeFound) {
initialize();
initializeStructValues();
auto node_metadata_map = metadata_node_.mutable_metadata()->mutable_fields();
google::protobuf::Value& value = (*node_metadata_map)["istio/metadata"];
(*value.mutable_struct_value()).CopyFrom(details_value_);
EXPECT_CALL(read_filter_callbacks_.connection_, nextProtocol())
.WillRepeatedly(Return("istio2"));
EXPECT_CALL(stream_info_,
setDynamicMetadata("filters.network.metadata_exchange.downstream",
MapEq(details_value_)));
EXPECT_CALL(stream_info_,
setDynamicMetadata("filters.network.metadata_exchange.upstream",
MapEq(productpage_value_)));
::Envoy::Buffer::OwnedImpl data;
MetadataExchangeInitialHeader initial_header;

View File

@ -100,9 +100,12 @@ type TestSetup struct {
// Whether Tls is Enabled or not.
EnableTls bool
// Format for accesslog
// Format for client accesslog
AccesslogFormat string
// Format for server accesslog
ServerAccesslogFormat string
// TlsContext to be used.
TlsContext string
@ -212,6 +215,11 @@ func (s *TestSetup) SetAccessLogFormat(accesslogformat string) {
s.AccesslogFormat = accesslogformat
}
// SetServerAccessLogFormat sets the serverAccesslogformat.
func (s *TestSetup) SetServerAccessLogFormat(serverAccesslogformat string) {
s.ServerAccesslogFormat = serverAccesslogformat
}
// SetUpstreamFiltersInClient sets upstream filters chain in client envoy..
func (s *TestSetup) SetUpstreamFiltersInClient(upstreamFiltersInClient string) {
s.UpstreamFiltersInClient = upstreamFiltersInClient

View File

@ -64,7 +64,7 @@ static_resources:
- name: envoy.file_access_log
config:
path: {{.ClientAccessLogPath}}
{{.AccesslogFormat | indent 14 }}
format: {{.AccesslogFormat}}
{{.TlsContext | indent 6 }}
`
@ -117,6 +117,7 @@ static_resources:
- name: envoy.file_access_log
config:
path: {{.ServerAccessLogPath}}
format: {{.ServerAccesslogFormat}}
{{.TlsContext | indent 6 }}
`

View File

@ -31,7 +31,6 @@ const metadataExchangeIstioConfigFilter = `
- name: envoy.filters.network.metadata_exchange
config:
protocol: istio2
node_metadata_id: istio.io/metadata
`
const metadataExchangeIstioUpstreamConfigFilterChain = `
@ -40,7 +39,6 @@ filters:
typed_config:
"@type": type.googleapis.com/envoy.tcp.metadataexchange.config.MetadataExchange
protocol: istio2
node_metadata_id: istio.io/metadata
`
const tlsContext = `
@ -74,19 +72,63 @@ tls_context:
inline_string: "-----BEGIN CERTIFICATE-----\nMIIFFDCCAvygAwIBAgIUZqU0Sviq/wULK6UV7PoAZ7B+nqAwDQYJKoZIhvcNAQEL\nBQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMTkwNzIy\nMjEzMDA0WhcNMjkwNzE5MjEzMDA0WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE\nAwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANNl5/pH\n/ktdqEsb83cqHrYJCyzbvWce6k/iud4Czu6FClFX8b+n/Rv9GrZFxJwKAFlUx3iA\nBGlSn/1XYpnhudQhgVGvyuWNO5kX4BfrAJwfWt+7Mn6NcWvunDqwqUPxI07sgCJW\nAYBAwkZH/Nhn6tj571XWNPziUtCwlPNkFMiRu/2nI/tq12IgwimFjVgiCuprNfyX\ntQz/DMVTWpCRQLK5ptlYMfk0P25UKyJdKHnr1MPQBJmPXMfSSqpGjksikV4QnYc7\nCXB3ucq7ty0IWA8QXH+86WqMTh22mosWVXHe0OGbzYtuyVnXc1G7YRv4D87G3Ves\nG4n/8e+RaDTacvwOsYEkuQGk+s8pggPkIqydGy02JNZ4cSRpXJRTzME2BgBZxT8S\nEw1Omr5+iuLNRAKEYRM/eWI7qrs5fxpD6K9JELHS41hWHGdW94PP0wKz70trx5pM\nfLpcVm7BQ5ppgf+t4vgKnrNiACQpfyZbInCBU0doaZaqVMnKH0vgyM7xrC43fsOP\ny5URy3tEH8Uk7Dbvsmj7AXR7IPKlYtgcqcJXmeWa+kLOpx3G55hgJL1ySrxXg/qz\nAobgmV0IycH2ntn5lXvjbwe0cfXAnZgGoALZjJVuEazyBmmVzjBjG2Qcq35nHfp8\nRm6WnCZIaGsZqgoDuSJD280ZLWW7R0PMcnypAgMBAAGjQjBAMB0GA1UdDgQWBBQZ\nh3/ckcK23ZYKO+JsZowd3dIobDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE\nAwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAjh4CdrwnLsqwVxyVSgxd7TfSHtKE/J2Y\n2IZ4fJYXGkq3McPk2e9u0zjCH0buvfDwyAItLIacD+YwIP+OC2WxLe+YMZ5KkXl3\nLuhQ2TOoRlrbp5tYLQITZIIl9+vNkgnn1DkdxkLm9cDDag19LSxa9Rjrnb3wwFAT\nIzEhy+d18FpQtdMMhmonU/L8Oy5LqjT5BR3T8VrXYUsaAkcUs/yHNTFAY3iJFBWL\nZ8dFa5v0A1Ryi8quSNo7lK/hSEZvvV9k4XfFAolXSUqe8BCuXe0rbAq3Jq9HgDww\noImGM0uz4Zf89uhTk1O7UOUfQoSTmA0yZICtQkCiOC0J4AlAOTmiEXUC9gicV3R8\ndvVOqNBOcBELglZ+NIMm6FQQqPh1nZ6A3Bh+JRTPerAF12725RZZE6XMxq2MSr3G\nk5yH10QPMH7/DJRQUhRHAhbge+jk2csa7EGSxABcbsPLSV+cEzXRO4cJeItoZQLh\nsaFhIn9lGukXG6lgiperOqZl6DFVcUG6/nogK7KOTAnV9zjR/7vNwvYzPI9iOR3V\n6dbG38KnipcfL885VLJVTnfhvYHlxFklCKTEnOHnmKsM0qjQuky3DBzmDA6iqeOM\nSHRje5LKxi7mllJfu/X0MxYJWiu6i4gMCWZsC3UtAJQ09x7iwcNr/1bl9ApGszOy\nUff0OxD2hzk=\n-----END CERTIFICATE-----\n"
`
const clientNodeMetadata = `
"istio.io/metadata": {
namespace: default,
labels: { app: productpage },
}
`
const clientNodeMetadata = `"NAMESPACE": "default",
"INCLUDE_INBOUND_PORTS": "9080",
"app": "productpage",
"EXCHANGE_KEYS": "NAME,NAMESPACE,INSTANCE_IPS,LABELS,OWNER,PLATFORM_METADATA,WORKLOAD_NAME,CANONICAL_TELEMETRY_SERVICE,MESH_ID,SERVICE_ACCOUNT",
"INSTANCE_IPS": "10.52.0.34,fe80::a075:11ff:fe5e:f1cd",
"pod-template-hash": "84975bc778",
"INTERCEPTION_MODE": "REDIRECT",
"SERVICE_ACCOUNT": "bookinfo-productpage",
"CONFIG_NAMESPACE": "default",
"version": "v1",
"OWNER": "kubernetes://api/apps/v1/namespaces/default/deployment/productpage-v1",
"WORKLOAD_NAME": "productpage-v1",
"ISTIO_VERSION": "1.3-dev",
"kubernetes.io/limit-ranger": "LimitRanger plugin set: cpu request for container productpage",
"POD_NAME": "productpage-v1-84975bc778-pxz2w",
"istio": "sidecar",
"PLATFORM_METADATA": {
"gcp_cluster_name": "test-cluster",
"gcp_project": "test-project",
"gcp_cluster_location": "us-east4-b"
},
"LABELS": {
"app": "productpage",
"version": "v1",
"pod-template-hash": "84975bc778"
},
"ISTIO_PROXY_SHA": "istio-proxy:47e4559b8e4f0d516c0d17b233d127a3deb3d7ce",
"NAME": "productpage-v1-84975bc778-pxz2w",`
const serverNodeMetadata = `
"istio.io/metadata": {
namespace: default,
labels: { app: details },
}
`
const serverNodeMetadata = `"NAMESPACE": "default",
"INCLUDE_INBOUND_PORTS": "9080",
"app": "ratings",
"EXCHANGE_KEYS": "NAME,NAMESPACE,INSTANCE_IPS,LABELS,OWNER,PLATFORM_METADATA,WORKLOAD_NAME,CANONICAL_TELEMETRY_SERVICE,MESH_ID,SERVICE_ACCOUNT",
"INSTANCE_IPS": "10.52.0.34,fe80::a075:11ff:fe5e:f1cd",
"pod-template-hash": "84975bc778",
"INTERCEPTION_MODE": "REDIRECT",
"SERVICE_ACCOUNT": "bookinfo-ratings",
"CONFIG_NAMESPACE": "default",
"version": "v1",
"OWNER": "kubernetes://api/apps/v1/namespaces/default/deployment/ratings-v1",
"WORKLOAD_NAME": "ratings-v1",
"ISTIO_VERSION": "1.3-dev",
"kubernetes.io/limit-ranger": "LimitRanger plugin set: cpu request for container ratings",
"POD_NAME": "ratings-v1-84975bc778-pxz2w",
"istio": "sidecar",
"PLATFORM_METADATA": {
"gcp_cluster_name": "test-cluster",
"gcp_project": "test-project",
"gcp_cluster_location": "us-east4-b"
},
"LABELS": {
"app": "ratings",
"version": "v1",
"pod-template-hash": "84975bc778"
},
"ISTIO_PROXY_SHA": "istio-proxy:47e4559b8e4f0d516c0d17b233d127a3deb3d7ce",
"NAME": "ratings-v1-84975bc778-pxz2w",`
// Stats in Client Envoy proxy.
var expectedClientStats = map[string]int{
@ -140,7 +182,7 @@ func TestTcpMetadataExchange(t *testing.T) {
}
config := &tls.Config{Certificates: []tls.Certificate{certificate}, ServerName: "localhost", NextProtos: []string{"istio2"}, RootCAs: certPool}
conn, err := tls.Dial("tcp", fmt.Sprintf("localhost:%d", s.Ports().AppToClientProxyPort /*s.Ports().ProxyToServerProxyPort*/), config)
conn, err := tls.Dial("tcp", fmt.Sprintf("localhost:%d", s.Ports().AppToClientProxyPort), config)
if err != nil {
t.Fatal(err)
}