1
1
package io .envoyproxy .controlplane .cache ;
2
2
3
3
import static com .google .common .base .Strings .isNullOrEmpty ;
4
+ import static io .envoyproxy .controlplane .cache .Resources .ApiVersion .V2 ;
5
+ import static io .envoyproxy .controlplane .cache .Resources .ApiVersion .V3 ;
6
+ import static io .envoyproxy .controlplane .cache .Resources .ResourceType .CLUSTER ;
7
+ import static io .envoyproxy .controlplane .cache .Resources .ResourceType .ENDPOINT ;
8
+ import static io .envoyproxy .controlplane .cache .Resources .ResourceType .LISTENER ;
9
+ import static io .envoyproxy .controlplane .cache .Resources .ResourceType .ROUTE ;
10
+ import static io .envoyproxy .controlplane .cache .Resources .ResourceType .SECRET ;
4
11
import static io .envoyproxy .envoy .config .filter .network .http_connection_manager .v2 .HttpConnectionManager .RouteSpecifierCase .RDS ;
5
12
6
13
import com .google .common .base .Preconditions ;
30
37
31
38
public class Resources {
32
39
40
+ /**
41
+ * Version-agnostic representation of a resource. This is useful when the version qualifier
42
+ * isn't needed.
43
+ */
44
+ public enum ResourceType {
45
+ CLUSTER ,
46
+ ENDPOINT ,
47
+ LISTENER ,
48
+ ROUTE ,
49
+ SECRET
50
+ }
51
+
52
+ public enum ApiVersion {
53
+ V2 ,
54
+ V3
55
+ }
56
+
33
57
private static final Logger LOGGER = LoggerFactory .getLogger (Resources .class );
34
58
35
59
static final String FILTER_ENVOY_ROUTER = "envoy.router" ;
36
60
static final String FILTER_HTTP_CONNECTION_MANAGER = "envoy.http_connection_manager" ;
37
61
38
- private static final String TYPE_URL_PREFIX = "type.googleapis.com/envoy.api.v2." ;
39
-
40
- public static final String CLUSTER_TYPE_URL = TYPE_URL_PREFIX + "Cluster" ;
41
- public static final String ENDPOINT_TYPE_URL = TYPE_URL_PREFIX + "ClusterLoadAssignment" ;
42
- public static final String LISTENER_TYPE_URL = TYPE_URL_PREFIX + "Listener" ;
43
- public static final String ROUTE_TYPE_URL = TYPE_URL_PREFIX + "RouteConfiguration" ;
44
- public static final String SECRET_TYPE_URL = TYPE_URL_PREFIX + "auth.Secret" ;
45
-
46
- public static final List <String > TYPE_URLS = ImmutableList .of (
47
- CLUSTER_TYPE_URL ,
48
- ENDPOINT_TYPE_URL ,
49
- LISTENER_TYPE_URL ,
50
- ROUTE_TYPE_URL ,
51
- SECRET_TYPE_URL );
52
-
53
- public static final Map <String , Class <? extends Message >> RESOURCE_TYPE_BY_URL = ImmutableMap .of (
54
- CLUSTER_TYPE_URL , Cluster .class ,
55
- ENDPOINT_TYPE_URL , ClusterLoadAssignment .class ,
56
- LISTENER_TYPE_URL , Listener .class ,
57
- ROUTE_TYPE_URL , RouteConfiguration .class ,
58
- SECRET_TYPE_URL , Secret .class
59
- );
62
+ public static class V2 {
63
+ private static final String TYPE_URL_PREFIX = "type.googleapis.com/envoy.api.v2." ;
64
+ public static final String SECRET_TYPE_URL = TYPE_URL_PREFIX + "auth.Secret" ;
65
+ public static final String ROUTE_TYPE_URL = TYPE_URL_PREFIX + "RouteConfiguration" ;
66
+ public static final String LISTENER_TYPE_URL = TYPE_URL_PREFIX + "Listener" ;
67
+ public static final String ENDPOINT_TYPE_URL = TYPE_URL_PREFIX + "ClusterLoadAssignment" ;
68
+ public static final String CLUSTER_TYPE_URL = TYPE_URL_PREFIX + "Cluster" ;
69
+
70
+ public static final List <String > TYPE_URLS = ImmutableList .of (
71
+ CLUSTER_TYPE_URL ,
72
+ ENDPOINT_TYPE_URL ,
73
+ LISTENER_TYPE_URL ,
74
+ ROUTE_TYPE_URL ,
75
+ SECRET_TYPE_URL );
76
+ }
77
+
78
+ public static class V3 {
79
+
80
+ public static final String CLUSTER_TYPE_URL = "type.googleapis.com/envoy.config.cluster.v3"
81
+ + ".Cluster" ;
82
+ public static final String ENDPOINT_TYPE_URL = "type.googleapis.com/envoy.config.endpoint.v3"
83
+ + ".ClusterLoadAssignment" ;
84
+ public static final String LISTENER_TYPE_URL = "type.googleapis.com/envoy.config.listener.v3"
85
+ + ".Listener" ;
86
+ public static final String ROUTE_TYPE_URL = "type.googleapis.com/envoy.config.route.v3"
87
+ + ".RouteConfiguration" ;
88
+ public static final String SECRET_TYPE_URL = "type.googleapis.com/envoy.extensions"
89
+ + ".transport_sockets.tls.v3.Secret" ;
90
+
91
+ public static final List <String > TYPE_URLS = ImmutableList .of (
92
+ CLUSTER_TYPE_URL ,
93
+ ENDPOINT_TYPE_URL ,
94
+ LISTENER_TYPE_URL ,
95
+ ROUTE_TYPE_URL ,
96
+ SECRET_TYPE_URL );
97
+ }
98
+
99
+ public static final List <ResourceType > RESOURCE_TYPES_IN_ORDER = ImmutableList .of (
100
+ CLUSTER ,
101
+ ENDPOINT ,
102
+ LISTENER ,
103
+ ROUTE ,
104
+ SECRET );
105
+
106
+ public static final Map <String , String > V3_TYPE_URLS_TO_V2 = ImmutableMap .of (
107
+ Resources .V3 .CLUSTER_TYPE_URL , Resources .V2 .CLUSTER_TYPE_URL ,
108
+ Resources .V3 .ENDPOINT_TYPE_URL , Resources .V2 .ENDPOINT_TYPE_URL ,
109
+ Resources .V3 .LISTENER_TYPE_URL , Resources .V2 .LISTENER_TYPE_URL ,
110
+ Resources .V3 .ROUTE_TYPE_URL , Resources .V2 .ROUTE_TYPE_URL ,
111
+ Resources .V3 .SECRET_TYPE_URL , Resources .V2 .SECRET_TYPE_URL );
112
+
113
+ public static final Map <String , String > V2_TYPE_URLS_TO_V3 = ImmutableMap .of (
114
+ Resources .V2 .CLUSTER_TYPE_URL , Resources .V3 .CLUSTER_TYPE_URL ,
115
+ Resources .V2 .ENDPOINT_TYPE_URL , Resources .V3 .ENDPOINT_TYPE_URL ,
116
+ Resources .V2 .LISTENER_TYPE_URL , Resources .V3 .LISTENER_TYPE_URL ,
117
+ Resources .V2 .ROUTE_TYPE_URL , Resources .V3 .ROUTE_TYPE_URL ,
118
+ Resources .V2 .SECRET_TYPE_URL , Resources .V3 .SECRET_TYPE_URL );
119
+
120
+ public static final Map <String , ResourceType > TYPE_URLS_TO_RESOURCE_TYPE =
121
+ new ImmutableMap .Builder <String , ResourceType >()
122
+ .put (Resources .V3 .CLUSTER_TYPE_URL , CLUSTER )
123
+ .put (Resources .V2 .CLUSTER_TYPE_URL , CLUSTER )
124
+ .put (Resources .V3 .ENDPOINT_TYPE_URL , ENDPOINT )
125
+ .put (Resources .V2 .ENDPOINT_TYPE_URL , ENDPOINT )
126
+ .put (Resources .V3 .LISTENER_TYPE_URL , LISTENER )
127
+ .put (Resources .V2 .LISTENER_TYPE_URL , LISTENER )
128
+ .put (Resources .V3 .ROUTE_TYPE_URL , ROUTE )
129
+ .put (Resources .V2 .ROUTE_TYPE_URL , ROUTE )
130
+ .put (Resources .V3 .SECRET_TYPE_URL , SECRET )
131
+ .put (Resources .V2 .SECRET_TYPE_URL , SECRET )
132
+ .build ();
133
+
134
+ public static final Map <String , Class <? extends Message >> RESOURCE_TYPE_BY_URL =
135
+ new ImmutableMap .Builder <String , Class <? extends Message >>()
136
+ .put (Resources .V2 .CLUSTER_TYPE_URL , Cluster .class )
137
+ .put (Resources .V2 .ENDPOINT_TYPE_URL , ClusterLoadAssignment .class )
138
+ .put (Resources .V2 .LISTENER_TYPE_URL , Listener .class )
139
+ .put (Resources .V2 .ROUTE_TYPE_URL , RouteConfiguration .class )
140
+ .put (Resources .V2 .SECRET_TYPE_URL , Secret .class )
141
+ .put (Resources .V3 .CLUSTER_TYPE_URL , io .envoyproxy .envoy .config .cluster .v3 .Cluster .class )
142
+ .put (Resources .V3 .ENDPOINT_TYPE_URL , io .envoyproxy .envoy .config .endpoint .v3 .ClusterLoadAssignment .class )
143
+ .put (Resources .V3 .LISTENER_TYPE_URL , io .envoyproxy .envoy .config .listener .v3 .Listener .class )
144
+ .put (Resources .V3 .ROUTE_TYPE_URL , io .envoyproxy .envoy .config .route .v3 .RouteConfiguration .class )
145
+ .put (Resources .V3 .SECRET_TYPE_URL , io .envoyproxy .envoy .extensions .transport_sockets .tls .v3 .Secret .class )
146
+ .build ();
60
147
61
148
/**
62
149
* Returns the name of the given resource message.
@@ -84,6 +171,26 @@ public static String getResourceName(Message resource) {
84
171
return ((Secret ) resource ).getName ();
85
172
}
86
173
174
+ if (resource instanceof io .envoyproxy .envoy .config .cluster .v3 .Cluster ) {
175
+ return ((io .envoyproxy .envoy .config .cluster .v3 .Cluster ) resource ).getName ();
176
+ }
177
+
178
+ if (resource instanceof io .envoyproxy .envoy .config .endpoint .v3 .ClusterLoadAssignment ) {
179
+ return ((io .envoyproxy .envoy .config .endpoint .v3 .ClusterLoadAssignment ) resource ).getClusterName ();
180
+ }
181
+
182
+ if (resource instanceof io .envoyproxy .envoy .config .listener .v3 .Listener ) {
183
+ return ((io .envoyproxy .envoy .config .listener .v3 .Listener ) resource ).getName ();
184
+ }
185
+
186
+ if (resource instanceof io .envoyproxy .envoy .config .route .v3 .RouteConfiguration ) {
187
+ return ((io .envoyproxy .envoy .config .route .v3 .RouteConfiguration ) resource ).getName ();
188
+ }
189
+
190
+ if (resource instanceof io .envoyproxy .envoy .extensions .transport_sockets .tls .v3 .Secret ) {
191
+ return ((io .envoyproxy .envoy .extensions .transport_sockets .tls .v3 .Secret ) resource ).getName ();
192
+ }
193
+
87
194
return "" ;
88
195
}
89
196
@@ -133,6 +240,17 @@ public static Set<String> getResourceReferences(Collection<? extends Message> re
133
240
refs .add (c .getName ());
134
241
}
135
242
}
243
+ } else if (r instanceof io .envoyproxy .envoy .config .cluster .v3 .Cluster ) {
244
+ io .envoyproxy .envoy .config .cluster .v3 .Cluster c = (io .envoyproxy .envoy .config .cluster .v3 .Cluster ) r ;
245
+
246
+ // For EDS clusters, use the cluster name or the service name override.
247
+ if (c .getType () == io .envoyproxy .envoy .config .cluster .v3 .Cluster .DiscoveryType .EDS ) {
248
+ if (!isNullOrEmpty (c .getEdsClusterConfig ().getServiceName ())) {
249
+ refs .add (c .getEdsClusterConfig ().getServiceName ());
250
+ } else {
251
+ refs .add (c .getName ());
252
+ }
253
+ }
136
254
} else if (r instanceof Listener ) {
137
255
Listener l = (Listener ) r ;
138
256
@@ -144,17 +262,56 @@ public static Set<String> getResourceReferences(Collection<? extends Message> re
144
262
}
145
263
146
264
try {
147
- HttpConnectionManager .Builder config = HttpConnectionManager .newBuilder ();
148
-
149
- // TODO: Filter#getConfig() is deprecated, migrate to use Filter#getTypedConfig().
150
- structAsMessage (filter .getConfig (), config );
265
+ HttpConnectionManager config ;
266
+
267
+ if (filter .hasTypedConfig ()) {
268
+ config = filter .getTypedConfig ().unpack (HttpConnectionManager .class );
269
+ } else {
270
+ HttpConnectionManager .Builder builder = HttpConnectionManager .newBuilder ();
271
+ structAsMessage (filter .getConfig (), builder );
272
+ config = builder .build ();
273
+ }
151
274
152
275
if (config .getRouteSpecifierCase () == RDS && !isNullOrEmpty (config .getRds ().getRouteConfigName ())) {
153
276
refs .add (config .getRds ().getRouteConfigName ());
154
277
}
155
278
} catch (InvalidProtocolBufferException e ) {
156
279
LOGGER .error (
157
- "Failed to convert HTTP connection manager config struct into protobuf message for listener {}" ,
280
+ "Failed to convert v2 HTTP connection manager config struct into protobuf "
281
+ + "message for listener {}" ,
282
+ getResourceName (l ),
283
+ e );
284
+ }
285
+ }
286
+ }
287
+ } else if (r instanceof io .envoyproxy .envoy .config .listener .v3 .Listener ) {
288
+
289
+ io .envoyproxy .envoy .config .listener .v3 .Listener l =
290
+ (io .envoyproxy .envoy .config .listener .v3 .Listener ) r ;
291
+
292
+ // Extract the route configuration names from the HTTP connection manager.
293
+ for (io .envoyproxy .envoy .config .listener .v3 .FilterChain chain : l .getFilterChainsList ()) {
294
+ for (io .envoyproxy .envoy .config .listener .v3 .Filter filter : chain .getFiltersList ()) {
295
+ if (!filter .getName ().equals (FILTER_HTTP_CONNECTION_MANAGER )) {
296
+ continue ;
297
+ }
298
+
299
+ try {
300
+ io .envoyproxy .envoy .extensions .filters .network
301
+ .http_connection_manager .v3 .HttpConnectionManager config = filter
302
+ .getTypedConfig ().unpack (
303
+ io .envoyproxy .envoy .extensions .filters .network
304
+ .http_connection_manager .v3 .HttpConnectionManager .class );
305
+
306
+ if (config .getRouteSpecifierCase () == io .envoyproxy .envoy .extensions .filters .network
307
+ .http_connection_manager .v3 .HttpConnectionManager .RouteSpecifierCase .RDS
308
+ && !isNullOrEmpty (config .getRds ().getRouteConfigName ())) {
309
+ refs .add (config .getRds ().getRouteConfigName ());
310
+ }
311
+ } catch (InvalidProtocolBufferException e ) {
312
+ LOGGER .error (
313
+ "Failed to convert v3 HTTP connection manager config struct into protobuf "
314
+ + "message for listener {}" ,
158
315
getResourceName (l ),
159
316
e );
160
317
}
@@ -166,6 +323,19 @@ public static Set<String> getResourceReferences(Collection<? extends Message> re
166
323
return refs .build ();
167
324
}
168
325
326
+ /**
327
+ * Returns the API version (v2 or v3) for a given type URL.
328
+ */
329
+ public static ApiVersion getResourceApiVersion (String typeUrl ) {
330
+ if (Resources .V2 .TYPE_URLS .contains (typeUrl )) {
331
+ return V2 ;
332
+ } else if (Resources .V3 .TYPE_URLS .contains (typeUrl )) {
333
+ return V3 ;
334
+ }
335
+
336
+ throw new RuntimeException (String .format ("Unsupported API version for type URL %s" , typeUrl ));
337
+ }
338
+
169
339
private static void structAsMessage (Struct struct , Message .Builder messageBuilder )
170
340
throws InvalidProtocolBufferException {
171
341
0 commit comments