forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxds_context_params.cc
120 lines (103 loc) · 4.81 KB
/
xds_context_params.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "source/common/config/xds_context_params.h"
#include "source/common/common/macros.h"
#include "source/common/protobuf/utility.h"
namespace Envoy {
namespace Config {
namespace {
using RenderContextParamCb = std::function<std::string(const envoy::config::core::v3::Node& node)>;
using NodeContextRenderers = absl::flat_hash_map<std::string, RenderContextParamCb>;
RenderContextParamCb directStringFieldRenderer(const std::string& field) {
return [field](const envoy::config::core::v3::Node& node) -> std::string {
return MessageUtil::getStringField(node, field);
};
}
RenderContextParamCb localityStringFieldRenderer(const std::string& field) {
return [field](const envoy::config::core::v3::Node& node) -> std::string {
return MessageUtil::getStringField(node.locality(), field);
};
}
std::string buildSemanticVersionRenderer(const envoy::config::core::v3::Node& node) {
const auto& semver = node.user_agent_build_version().version();
return fmt::format("{}.{}.{}", semver.major_number(), semver.minor_number(), semver.patch());
}
const NodeContextRenderers& nodeParamCbs() {
CONSTRUCT_ON_FIRST_USE(NodeContextRenderers, {"id", directStringFieldRenderer("id")},
{"cluster", directStringFieldRenderer("cluster")},
{"user_agent_name", directStringFieldRenderer("user_agent_name")},
{"user_agent_version", directStringFieldRenderer("user_agent_version")},
{"locality.region", localityStringFieldRenderer("region")},
{"locality.zone", localityStringFieldRenderer("zone")},
{"locality.sub_zone", localityStringFieldRenderer("sub_zone")},
{"user_agent_build_version.version", buildSemanticVersionRenderer});
}
void mergeMetadataJson(Protobuf::Map<std::string, std::string>& params,
const ProtobufWkt::Struct& metadata, const std::string& prefix) {
for (const auto& it : metadata.fields()) {
params[prefix + it.first] = MessageUtil::getJsonStringFromMessageOrDie(it.second);
}
}
} // namespace
xds::core::v3::ContextParams XdsContextParams::encodeResource(
const xds::core::v3::ContextParams& node_context_params,
const xds::core::v3::ContextParams& resource_context_params,
const std::vector<std::string>& client_features,
const absl::flat_hash_map<std::string, std::string>& extra_resource_params) {
xds::core::v3::ContextParams context_params;
// 1. Establish base layer of per-node context parameters.
context_params.MergeFrom(node_context_params);
// 2. Overlay with context parameters from resource name.
auto& mutable_params = *context_params.mutable_params();
for (const auto& it : resource_context_params.params()) {
mutable_params[it.first] = it.second;
}
// 3. Overlay with per-resource type context parameters.
for (const std::string& cf : client_features) {
mutable_params["xds.client_feature." + cf] = "true";
}
// 4. Overlay with per-resource well-known attributes.
for (const auto& it : extra_resource_params) {
mutable_params["xds.resource." + it.first] = it.second;
}
return context_params;
}
xds::core::v3::ContextParams XdsContextParams::encodeNodeContext(
const envoy::config::core::v3::Node& node,
const Protobuf::RepeatedPtrField<std::string>& node_context_params) {
// E.g. if we have a node instance with contents
//
// user_agent_build_version:
// version:
// major_number: 1
// minor_number: 2
// patch: 3
// metadata:
// foo: true
// bar: "a"
// baz: 42
//
// and node_context_params [user_agent_build_version.version, user_agent_build_version.metadata],
// we end up with the map:
//
// xds.node.user_agent_build_version.metadata.bar: "\"a\""
// xds.node.user_agent_build_version.metadata.baz: "42"
// xds.node.user_agent_build_version.metadata.foo: "true"
// xds.node.user_agent_build_version.version: "1.2.3"
xds::core::v3::ContextParams context_params;
auto& mutable_params = *context_params.mutable_params();
for (const std::string& ncp : node_context_params) {
// First attempt field accessors known ahead of time, if that fails we consider the cases of
// metadata, either directly in the Node message, or nested in the user_agent_build_version.
auto it = nodeParamCbs().find(ncp);
if (it != nodeParamCbs().end()) {
mutable_params["xds.node." + ncp] = (it->second)(node);
} else if (ncp == "metadata") {
mergeMetadataJson(mutable_params, node.metadata(), "xds.node.metadata.");
} else if (ncp == "user_agent_build_version.metadata") {
mergeMetadataJson(mutable_params, node.user_agent_build_version().metadata(),
"xds.node.user_agent_build_version.metadata.");
}
}
return context_params;
}
} // namespace Config
} // namespace Envoy