-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
utility.h
236 lines (206 loc) · 9.14 KB
/
utility.h
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#pragma once
#include "envoy/config/grpc_mux.h"
#include "envoy/config/subscription.h"
#include "envoy/json/json_object.h"
#include "envoy/local_info/local_info.h"
#include "envoy/registry/registry.h"
#include "envoy/stats/stats.h"
#include "envoy/upstream/cluster_manager.h"
#include "common/common/assert.h"
#include "common/common/hash.h"
#include "common/common/hex.h"
#include "common/grpc/common.h"
#include "common/protobuf/protobuf.h"
#include "common/protobuf/utility.h"
#include "common/singleton/const_singleton.h"
#include "api/base.pb.h"
#include "api/cds.pb.h"
#include "api/eds.pb.h"
#include "api/filter/network/http_connection_manager.pb.h"
#include "api/lds.pb.h"
#include "api/rds.pb.h"
namespace Envoy {
namespace Config {
/**
* Constant Api Type Values, used by envoy::api::v2::ApiConfigSource.
*/
class ApiTypeValues {
public:
const std::string RestLegacy{"REST_LEGACY"};
const std::string Rest{"REST"};
const std::string Grpc{"GRPC"};
};
typedef ConstSingleton<ApiTypeValues> ApiType;
/**
* General config API utilities.
*/
class Utility {
public:
/**
* Extract typed resources from a DiscoveryResponse.
* @param response reference to DiscoveryResponse.
* @return Protobuf::RepatedPtrField<ResourceType> vector of typed resources in response.
*/
template <class ResourceType>
static Protobuf::RepeatedPtrField<ResourceType>
getTypedResources(const envoy::api::v2::DiscoveryResponse& response) {
Protobuf::RepeatedPtrField<ResourceType> typed_resources;
for (const auto& resource : response.resources()) {
auto* typed_resource = typed_resources.Add();
resource.UnpackTo(typed_resource);
}
return typed_resources;
}
/**
* Legacy APIs uses JSON and do not have an explicit version.
* @param input the input to hash.
* @return std::pair<std::string, uint64_t> the string is the hash converted into
* a hex string, pre-pended by a user friendly prefix. The uint64_t is the
* raw hash.
*/
static std::pair<std::string, uint64_t> computeHashedVersion(const std::string& input) {
uint64_t hash = HashUtil::xxHash64(input);
return std::make_pair("hash_" + Hex::uint64ToHex(hash), hash);
}
/**
* Extract refresh_delay as a std::chrono::milliseconds from envoy::api::v2::ApiConfigSource.
*/
static std::chrono::milliseconds
apiConfigSourceRefreshDelay(const envoy::api::v2::ApiConfigSource& api_config_source);
/**
* Populate an envoy::api::v2::ApiConfigSource.
* @param cluster supplies the cluster name for the ApiConfigSource.
* @param refresh_delay_ms supplies the refresh delay for the ApiConfigSource in ms.
* @param api_type supplies the type of subscription to use for the ApiConfigSource.
* @param api_config_source a reference to the envoy::api::v2::ApiConfigSource object to populate.
*/
static void translateApiConfigSource(const std::string& cluster, uint32_t refresh_delay_ms,
const std::string& api_type,
envoy::api::v2::ApiConfigSource& api_config_source);
/**
* Check cluster info for API config sanity. Throws on error.
* @param error_prefix supplies the prefix to use in error messages.
* @param cluster_name supplies the cluster name to check.
* @param cm supplies the cluster manager.
*/
static void checkCluster(const std::string& error_prefix, const std::string& cluster_name,
Upstream::ClusterManager& cm);
/**
* Check cluster/local info for API config sanity. Throws on error.
* @param error_prefix supplies the prefix to use in error messages.
* @param cluster_name supplies the cluster name to check.
* @param cm supplies the cluster manager.
* @param local_info supplies the local info.
*/
static void checkClusterAndLocalInfo(const std::string& error_prefix,
const std::string& cluster_name,
Upstream::ClusterManager& cm,
const LocalInfo::LocalInfo& local_info);
/**
* Check local info for API config sanity. Throws on error.
* @param error_prefix supplies the prefix to use in error messages.
* @param local_info supplies the local info.
*/
static void checkLocalInfo(const std::string& error_prefix,
const LocalInfo::LocalInfo& local_info);
/**
* Convert a v1 SDS JSON config to v2 EDS envoy::api::v2::ConfigSource.
* @param json_config source v1 SDS JSON config.
* @param eds_config destination v2 EDS envoy::api::v2::ConfigSource.
*/
static void translateEdsConfig(const Json::Object& json_config,
envoy::api::v2::ConfigSource& eds_config);
/**
* Convert a v1 CDS JSON config to v2 CDS envoy::api::v2::ConfigSource.
* @param json_config source v1 CDS JSON config.
* @param cds_config destination v2 CDS envoy::api::v2::ConfigSource.
*/
static void translateCdsConfig(const Json::Object& json_config,
envoy::api::v2::ConfigSource& cds_config);
/**
* Convert a v1 RDS JSON config to v2 RDS envoy::api::v2::filter::network::Rds.
* @param json_rds source v1 RDS JSON config.
* @param rds destination v2 RDS envoy::api::v2::filter::network::Rds.
*/
static void translateRdsConfig(const Json::Object& json_rds,
envoy::api::v2::filter::network::Rds& rds);
/**
* Convert a v1 LDS JSON config to v2 LDS envoy::api::v2::ConfigSource.
* @param json_lds source v1 LDS JSON config.
* @param lds_config destination v2 LDS envoy::api::v2::ConfigSource.
*/
static void translateLdsConfig(const Json::Object& json_lds,
envoy::api::v2::ConfigSource& lds_config);
/**
* Generate a SubscriptionStats object from stats scope.
* @param scope for stats.
* @return SubscriptionStats for scope.
*/
static SubscriptionStats generateStats(Stats::Scope& scope) {
return {ALL_SUBSCRIPTION_STATS(POOL_COUNTER(scope), POOL_GAUGE(scope))};
}
/**
* Get a Factory from the registry with a particular name (and templated type) with error checking
* to ensure the name and factory are valid.
* @param name string identifier for the particular implementation. Note: this is a proto string
* because it is assumed that this value will be pulled directly from the configuration proto.
*/
template <class Factory> static Factory& getAndCheckFactory(const ProtobufTypes::String& name) {
if (name.empty()) {
throw EnvoyException("Provided name for static registration lookup was empty.");
}
Factory* factory = Registry::FactoryRegistry<Factory>::getFactory(name);
if (factory == nullptr) {
throw EnvoyException(
fmt::format("Didn't find a registered implementation for name: '{}'", name));
}
return *factory;
}
/**
* Translate a nested config into a proto message provided by the implementation factory.
* @param enclosing_message proto that contains a field 'config'. Note: the enclosing proto is
* provided because for statically registered implementations, a custom config is generally
* optional, which means the conversion must be done conditionally.
* @param factory implementation factory with the method 'createEmptyConfigProto' to produce a
* proto to be filled with the translated configuration.
*/
template <class ProtoMessage, class Factory>
static ProtobufTypes::MessagePtr translateToFactoryConfig(const ProtoMessage& enclosing_message,
Factory& factory) {
ProtobufTypes::MessagePtr config = factory.createEmptyConfigProto();
if (config == nullptr) {
throw EnvoyException(fmt::format(
"{} factory returned nullptr instead of empty config message.", factory.name()));
}
if (enclosing_message.has_config()) {
MessageUtil::jsonConvert(enclosing_message.config(), *config);
}
return config;
}
/**
* Obtain the "name" of a v2 API resource in a google.protobuf.Any, e.g. the route config name for
* a Routeconfiguration, based on the underlying resource type.
* TODO(htuch): This is kind of a hack. If we had a better support for resource names as first
* class in the API, this would not be necessary.
* @param resource google.protobuf.Any v2 API resource.
* @return std::string resource name.
*/
static std::string resourceName(const ProtobufWkt::Any& resource);
/**
* Creates the set of stats tag extractors requested by the config and transfers ownership to the
* caller.
* @param bootstrap bootstrap proto.
* @return std::vector<Stats::TagExtractorPtr> tag extractor vector.
*/
static std::vector<Stats::TagExtractorPtr>
createTagExtractors(const envoy::api::v2::Bootstrap& bootstrap);
/**
* Check user supplied name in RDS/CDS/LDS for sanity.
* It should be within the configured length limit. Throws on error.
* @param error_prefix supplies the prefix to use in error messages.
* @param name supplies the name to check for length limits.
*/
static void checkObjNameLength(const std::string& error_prefix, const std::string& name);
};
} // namespace Config
} // namespace Envoy