xref: /aosp_15_r20/external/grpc-grpc-java/xds/src/test/java/io/grpc/xds/XdsServerTestHelper.java (revision e07d83d3ffcef9ecfc9f7f475418ec639ff0e5fe)
1 /*
2  * Copyright 2020 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.xds;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import com.google.common.collect.ImmutableList;
22 import com.google.common.collect.ImmutableMap;
23 import com.google.common.util.concurrent.SettableFuture;
24 import io.grpc.InsecureChannelCredentials;
25 import io.grpc.internal.ObjectPool;
26 import io.grpc.xds.Bootstrapper.BootstrapInfo;
27 import io.grpc.xds.EnvoyServerProtoData.ConnectionSourceType;
28 import io.grpc.xds.EnvoyServerProtoData.FilterChain;
29 import io.grpc.xds.EnvoyServerProtoData.Listener;
30 import io.grpc.xds.Filter.FilterConfig;
31 import io.grpc.xds.Filter.NamedFilterConfig;
32 import io.grpc.xds.VirtualHost.Route;
33 import io.grpc.xds.XdsListenerResource.LdsUpdate;
34 import io.grpc.xds.XdsRouteConfigureResource.RdsUpdate;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.concurrent.CountDownLatch;
42 import javax.annotation.Nullable;
43 
44 /**
45  * Helper methods related to {@link XdsServerBuilder} and related classes.
46  */
47 public class XdsServerTestHelper {
48 
49   private static final String SERVER_URI = "trafficdirector.googleapis.com";
50   private static final String NODE_ID =
51       "projects/42/networks/default/nodes/5c85b298-6f5b-4722-b74a-f7d1f0ccf5ad";
52   private static final EnvoyProtoData.Node BOOTSTRAP_NODE =
53       EnvoyProtoData.Node.newBuilder().setId(NODE_ID).build();
54   static final Bootstrapper.BootstrapInfo BOOTSTRAP_INFO =
55       Bootstrapper.BootstrapInfo.builder()
56           .servers(Arrays.asList(
57               Bootstrapper.ServerInfo.create(
58                   SERVER_URI, InsecureChannelCredentials.create())))
59           .node(BOOTSTRAP_NODE)
60           .serverListenerResourceNameTemplate("grpc/server?udpa.resource.listening_address=%s")
61           .build();
62 
generateListenerUpdate(FakeXdsClient xdsClient, EnvoyServerProtoData.DownstreamTlsContext tlsContext, TlsContextManager tlsContextManager)63   static void generateListenerUpdate(FakeXdsClient xdsClient,
64                                      EnvoyServerProtoData.DownstreamTlsContext tlsContext,
65                                      TlsContextManager tlsContextManager) {
66     EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3",
67         ImmutableList.of(), tlsContext, null, tlsContextManager);
68     LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
69     xdsClient.deliverLdsUpdate(listenerUpdate);
70   }
71 
generateListenerUpdate( FakeXdsClient xdsClient, ImmutableList<Integer> sourcePorts, EnvoyServerProtoData.DownstreamTlsContext tlsContext, EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain, TlsContextManager tlsContextManager)72   static void generateListenerUpdate(
73       FakeXdsClient xdsClient, ImmutableList<Integer> sourcePorts,
74       EnvoyServerProtoData.DownstreamTlsContext tlsContext,
75       EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain,
76       TlsContextManager tlsContextManager) {
77     EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3", sourcePorts,
78         tlsContext, tlsContextForDefaultFilterChain, tlsContextManager);
79     LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
80     xdsClient.deliverLdsUpdate(listenerUpdate);
81   }
82 
buildTestListener( String name, String address, ImmutableList<Integer> sourcePorts, EnvoyServerProtoData.DownstreamTlsContext tlsContext, EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain, TlsContextManager tlsContextManager)83   static EnvoyServerProtoData.Listener buildTestListener(
84       String name, String address, ImmutableList<Integer> sourcePorts,
85       EnvoyServerProtoData.DownstreamTlsContext tlsContext,
86       EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain,
87       TlsContextManager tlsContextManager) {
88     EnvoyServerProtoData.FilterChainMatch filterChainMatch1 =
89         EnvoyServerProtoData.FilterChainMatch.create(
90             0,
91             ImmutableList.of(),
92             ImmutableList.of(),
93             ImmutableList.of(),
94             ConnectionSourceType.ANY,
95             sourcePorts,
96             ImmutableList.of(),
97             "");
98     EnvoyServerProtoData.FilterChainMatch defaultFilterChainMatch =
99         EnvoyServerProtoData.FilterChainMatch.create(
100             0,
101             ImmutableList.of(),
102             ImmutableList.of(),
103             ImmutableList.of(),
104             ConnectionSourceType.ANY,
105             ImmutableList.of(),
106             ImmutableList.of(),
107             "");
108     VirtualHost virtualHost =
109             VirtualHost.create(
110                     "virtual-host", Collections.singletonList("auth"), new ArrayList<Route>(),
111                     ImmutableMap.<String, FilterConfig>of());
112     HttpConnectionManager httpConnectionManager = HttpConnectionManager.forVirtualHosts(
113             0L, Collections.singletonList(virtualHost), new ArrayList<NamedFilterConfig>());
114     EnvoyServerProtoData.FilterChain filterChain1 = EnvoyServerProtoData.FilterChain.create(
115         "filter-chain-foo", filterChainMatch1, httpConnectionManager, tlsContext,
116         tlsContextManager);
117     EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create(
118         "filter-chain-bar", defaultFilterChainMatch, httpConnectionManager,
119         tlsContextForDefaultFilterChain, tlsContextManager);
120     EnvoyServerProtoData.Listener listener =
121         EnvoyServerProtoData.Listener.create(
122             name, address, ImmutableList.of(filterChain1), defaultFilterChain);
123     return listener;
124   }
125 
126   static final class FakeXdsClientPoolFactory
127         implements XdsNameResolverProvider.XdsClientPoolFactory {
128 
129     private XdsClient xdsClient;
130     Map<String, ?> savedBootstrap;
131 
FakeXdsClientPoolFactory(XdsClient xdsClient)132     FakeXdsClientPoolFactory(XdsClient xdsClient) {
133       this.xdsClient = xdsClient;
134     }
135 
136     @Override
setBootstrapOverride(Map<String, ?> bootstrap)137     public void setBootstrapOverride(Map<String, ?> bootstrap) {
138       this.savedBootstrap = bootstrap;
139     }
140 
141     @Override
142     @Nullable
get()143     public ObjectPool<XdsClient> get() {
144       throw new UnsupportedOperationException("Should not be called");
145     }
146 
147     @Override
getOrCreate()148     public ObjectPool<XdsClient> getOrCreate() throws XdsInitializationException {
149       return new ObjectPool<XdsClient>() {
150         @Override
151         public XdsClient getObject() {
152           return xdsClient;
153         }
154 
155         @Override
156         public XdsClient returnObject(Object object) {
157           xdsClient.shutdown();
158           return null;
159         }
160       };
161     }
162   }
163 
164   static final class FakeXdsClient extends XdsClient {
165     boolean shutdown;
166     SettableFuture<String> ldsResource = SettableFuture.create();
167     ResourceWatcher<LdsUpdate> ldsWatcher;
168     CountDownLatch rdsCount = new CountDownLatch(1);
169     final Map<String, ResourceWatcher<RdsUpdate>> rdsWatchers = new HashMap<>();
170 
171     @Override
172     public TlsContextManager getTlsContextManager() {
173       return null;
174     }
175 
176     @Override
177     public BootstrapInfo getBootstrapInfo() {
178       return BOOTSTRAP_INFO;
179     }
180 
181     @Override
182     @SuppressWarnings("unchecked")
183     <T extends ResourceUpdate> void watchXdsResource(XdsResourceType<T> resourceType,
184                                                      String resourceName,
185                                                      ResourceWatcher<T> watcher) {
186       switch (resourceType.typeName()) {
187         case "LDS":
188           assertThat(ldsWatcher).isNull();
189           ldsWatcher = (ResourceWatcher<LdsUpdate>) watcher;
190           ldsResource.set(resourceName);
191           break;
192         case "RDS":
193           //re-register is not allowed.
194           assertThat(rdsWatchers.put(resourceName, (ResourceWatcher<RdsUpdate>)watcher)).isNull();
195           rdsCount.countDown();
196           break;
197         default:
198       }
199     }
200 
201     @Override
202     <T extends ResourceUpdate> void cancelXdsResourceWatch(XdsResourceType<T> type,
203                                                            String resourceName,
204                                 ResourceWatcher<T> watcher) {
205       switch (type.typeName()) {
206         case "LDS":
207           assertThat(ldsWatcher).isNotNull();
208           ldsResource = null;
209           ldsWatcher = null;
210           break;
211         case "RDS":
212           rdsWatchers.remove(resourceName);
213           break;
214         default:
215       }
216     }
217 
218     @Override
219     void shutdown() {
220       shutdown = true;
221     }
222 
223     @Override
224     boolean isShutDown() {
225       return shutdown;
226     }
227 
228     void deliverLdsUpdate(List<FilterChain> filterChains,
229                           FilterChain defaultFilterChain) {
230       ldsWatcher.onChanged(LdsUpdate.forTcpListener(Listener.create(
231               "listener", "0.0.0.0:1", ImmutableList.copyOf(filterChains), defaultFilterChain)));
232     }
233 
234     void deliverLdsUpdate(LdsUpdate ldsUpdate) {
235       ldsWatcher.onChanged(ldsUpdate);
236     }
237 
238     void deliverRdsUpdate(String rdsName, List<VirtualHost> virtualHosts) {
239       rdsWatchers.get(rdsName).onChanged(new RdsUpdate(virtualHosts));
240     }
241   }
242 }
243