85
85
import io .grpc .xds .client .Bootstrapper .BootstrapInfo ;
86
86
import io .grpc .xds .client .Bootstrapper .CertificateProviderInfo ;
87
87
import io .grpc .xds .client .Bootstrapper .ServerInfo ;
88
+ import io .grpc .xds .client .BootstrapperImpl ;
88
89
import io .grpc .xds .client .EnvoyProtoData .Node ;
89
90
import io .grpc .xds .client .LoadStatsManager2 .ClusterDropStats ;
90
91
import io .grpc .xds .client .Locality ;
145
146
public abstract class GrpcXdsClientImplTestBase {
146
147
147
148
private static final String SERVER_URI = "trafficdirector.googleapis.com" ;
148
- private static final String SERVER_URI_CUSTOME_AUTHORITY = "trafficdirector2.googleapis.com" ;
149
+ private static final String SERVER_URI_CUSTOM_AUTHORITY = "trafficdirector2.googleapis.com" ;
149
150
private static final String SERVER_URI_EMPTY_AUTHORITY = "trafficdirector3.googleapis.com" ;
150
151
private static final String LDS_RESOURCE = "listener.googleapis.com" ;
151
152
private static final String RDS_RESOURCE = "route-configuration.googleapis.com" ;
@@ -304,6 +305,30 @@ public long currentTimeNanos() {
304
305
private final BindableService adsService = createAdsService ();
305
306
private final BindableService lrsService = createLrsService ();
306
307
308
+ private XdsTransportFactory xdsTransportFactory = new XdsTransportFactory () {
309
+ @ Override
310
+ public XdsTransport create (ServerInfo serverInfo ) {
311
+ if (serverInfo .target ().equals (SERVER_URI )) {
312
+ return new GrpcXdsTransport (channel );
313
+ }
314
+ if (serverInfo .target ().equals (SERVER_URI_CUSTOM_AUTHORITY )) {
315
+ if (channelForCustomAuthority == null ) {
316
+ channelForCustomAuthority = cleanupRule .register (
317
+ InProcessChannelBuilder .forName (serverName ).directExecutor ().build ());
318
+ }
319
+ return new GrpcXdsTransport (channelForCustomAuthority );
320
+ }
321
+ if (serverInfo .target ().equals (SERVER_URI_EMPTY_AUTHORITY )) {
322
+ if (channelForEmptyAuthority == null ) {
323
+ channelForEmptyAuthority = cleanupRule .register (
324
+ InProcessChannelBuilder .forName (serverName ).directExecutor ().build ());
325
+ }
326
+ return new GrpcXdsTransport (channelForEmptyAuthority );
327
+ }
328
+ throw new IllegalArgumentException ("Can not create channel for " + serverInfo );
329
+ }
330
+ };
331
+
307
332
@ Before
308
333
public void setUp () throws IOException {
309
334
when (backoffPolicyProvider .get ()).thenReturn (backoffPolicy1 , backoffPolicy2 );
@@ -322,32 +347,9 @@ public void setUp() throws IOException {
322
347
.start ());
323
348
channel =
324
349
cleanupRule .register (InProcessChannelBuilder .forName (serverName ).directExecutor ().build ());
325
- XdsTransportFactory xdsTransportFactory = new XdsTransportFactory () {
326
- @ Override
327
- public XdsTransport create (ServerInfo serverInfo ) {
328
- if (serverInfo .target ().equals (SERVER_URI )) {
329
- return new GrpcXdsTransport (channel );
330
- }
331
- if (serverInfo .target ().equals (SERVER_URI_CUSTOME_AUTHORITY )) {
332
- if (channelForCustomAuthority == null ) {
333
- channelForCustomAuthority = cleanupRule .register (
334
- InProcessChannelBuilder .forName (serverName ).directExecutor ().build ());
335
- }
336
- return new GrpcXdsTransport (channelForCustomAuthority );
337
- }
338
- if (serverInfo .target ().equals (SERVER_URI_EMPTY_AUTHORITY )) {
339
- if (channelForEmptyAuthority == null ) {
340
- channelForEmptyAuthority = cleanupRule .register (
341
- InProcessChannelBuilder .forName (serverName ).directExecutor ().build ());
342
- }
343
- return new GrpcXdsTransport (channelForEmptyAuthority );
344
- }
345
- throw new IllegalArgumentException ("Can not create channel for " + serverInfo );
346
- }
347
- };
348
350
349
351
xdsServerInfo = ServerInfo .create (SERVER_URI , CHANNEL_CREDENTIALS , ignoreResourceDeletion (),
350
- true );
352
+ true , false );
351
353
BootstrapInfo bootstrapInfo =
352
354
Bootstrapper .BootstrapInfo .builder ()
353
355
.servers (Collections .singletonList (xdsServerInfo ))
@@ -357,7 +359,7 @@ public XdsTransport create(ServerInfo serverInfo) {
357
359
AuthorityInfo .create (
358
360
"xdstp://authority.xds.com/envoy.config.listener.v3.Listener/%s" ,
359
361
ImmutableList .of (Bootstrapper .ServerInfo .create (
360
- SERVER_URI_CUSTOME_AUTHORITY , CHANNEL_CREDENTIALS ))),
362
+ SERVER_URI_CUSTOM_AUTHORITY , CHANNEL_CREDENTIALS ))),
361
363
"" ,
362
364
AuthorityInfo .create (
363
365
"xdstp:///envoy.config.listener.v3.Listener/%s" ,
@@ -3155,6 +3157,108 @@ public void flowControlAbsent() throws Exception {
3155
3157
verify (anotherWatcher ).onError (any ());
3156
3158
}
3157
3159
3160
+ @ Test
3161
+ @ SuppressWarnings ("unchecked" )
3162
+ public void resourceTimerIsTransientError_schedulesExtendedTimeout () {
3163
+ BootstrapperImpl .xdsDataErrorHandlingEnabled = true ;
3164
+ ServerInfo serverInfo = ServerInfo .create (SERVER_URI , CHANNEL_CREDENTIALS ,
3165
+ false , true , true );
3166
+ BootstrapInfo bootstrapInfo =
3167
+ Bootstrapper .BootstrapInfo .builder ()
3168
+ .servers (Collections .singletonList (serverInfo ))
3169
+ .node (NODE )
3170
+ .authorities (ImmutableMap .of (
3171
+ "" ,
3172
+ AuthorityInfo .create (
3173
+ "xdstp:///envoy.config.listener.v3.Listener/%s" ,
3174
+ ImmutableList .of (Bootstrapper .ServerInfo .create (
3175
+ SERVER_URI_EMPTY_AUTHORITY , CHANNEL_CREDENTIALS )))))
3176
+ .certProviders (ImmutableMap .of ())
3177
+ .build ();
3178
+ xdsClient = new XdsClientImpl (
3179
+ xdsTransportFactory ,
3180
+ bootstrapInfo ,
3181
+ fakeClock .getScheduledExecutorService (),
3182
+ backoffPolicyProvider ,
3183
+ fakeClock .getStopwatchSupplier (),
3184
+ timeProvider ,
3185
+ MessagePrinter .INSTANCE ,
3186
+ new TlsContextManagerImpl (bootstrapInfo ),
3187
+ xdsClientMetricReporter );
3188
+ ResourceWatcher <CdsUpdate > watcher = mock (ResourceWatcher .class );
3189
+ String resourceName = "cluster.googleapis.com" ;
3190
+
3191
+ xdsClient .watchXdsResource (
3192
+ XdsClusterResource .getInstance (),
3193
+ resourceName ,
3194
+ watcher ,
3195
+ fakeClock .getScheduledExecutorService ());
3196
+
3197
+ ScheduledTask task = Iterables .getOnlyElement (
3198
+ fakeClock .getPendingTasks (CDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER ));
3199
+ assertThat (task .getDelay (TimeUnit .SECONDS ))
3200
+ .isEqualTo (XdsClientImpl .EXTENDED_RESOURCE_FETCH_TIMEOUT_SEC );
3201
+ fakeClock .runDueTasks ();
3202
+ BootstrapperImpl .xdsDataErrorHandlingEnabled = false ;
3203
+ }
3204
+
3205
+ @ Test
3206
+ @ SuppressWarnings ("unchecked" )
3207
+ public void resourceTimerIsTransientError_callsOnErrorUnavailable () {
3208
+ BootstrapperImpl .xdsDataErrorHandlingEnabled = true ;
3209
+ xdsServerInfo = ServerInfo .create (SERVER_URI , CHANNEL_CREDENTIALS , ignoreResourceDeletion (),
3210
+ true , true );
3211
+ BootstrapInfo bootstrapInfo =
3212
+ Bootstrapper .BootstrapInfo .builder ()
3213
+ .servers (Collections .singletonList (xdsServerInfo ))
3214
+ .node (NODE )
3215
+ .authorities (ImmutableMap .of (
3216
+ "authority.xds.com" ,
3217
+ AuthorityInfo .create (
3218
+ "xdstp://authority.xds.com/envoy.config.listener.v3.Listener/%s" ,
3219
+ ImmutableList .of (Bootstrapper .ServerInfo .create (
3220
+ SERVER_URI_CUSTOM_AUTHORITY , CHANNEL_CREDENTIALS ))),
3221
+ "" ,
3222
+ AuthorityInfo .create (
3223
+ "xdstp:///envoy.config.listener.v3.Listener/%s" ,
3224
+ ImmutableList .of (Bootstrapper .ServerInfo .create (
3225
+ SERVER_URI_EMPTY_AUTHORITY , CHANNEL_CREDENTIALS )))))
3226
+ .certProviders (ImmutableMap .of ("cert-instance-name" ,
3227
+ CertificateProviderInfo .create ("file-watcher" , ImmutableMap .of ())))
3228
+ .build ();
3229
+ xdsClient = new XdsClientImpl (
3230
+ xdsTransportFactory ,
3231
+ bootstrapInfo ,
3232
+ fakeClock .getScheduledExecutorService (),
3233
+ backoffPolicyProvider ,
3234
+ fakeClock .getStopwatchSupplier (),
3235
+ timeProvider ,
3236
+ MessagePrinter .INSTANCE ,
3237
+ new TlsContextManagerImpl (bootstrapInfo ),
3238
+ xdsClientMetricReporter );
3239
+ String timeoutResource = CDS_RESOURCE + "_timeout" ;
3240
+ ResourceWatcher <CdsUpdate > timeoutWatcher = mock (ResourceWatcher .class );
3241
+
3242
+ xdsClient .watchXdsResource (
3243
+ XdsClusterResource .getInstance (),
3244
+ timeoutResource ,
3245
+ timeoutWatcher ,
3246
+ fakeClock .getScheduledExecutorService ());
3247
+
3248
+ assertThat (resourceDiscoveryCalls ).hasSize (1 );
3249
+ DiscoveryRpcCall call = resourceDiscoveryCalls .poll ();
3250
+ call .verifyRequest (CDS , ImmutableList .of (timeoutResource ), "" , "" , NODE );
3251
+ fakeClock .forwardTime (XdsClientImpl .EXTENDED_RESOURCE_FETCH_TIMEOUT_SEC , TimeUnit .SECONDS );
3252
+ fakeClock .runDueTasks ();
3253
+ ArgumentCaptor <Status > errorCaptor = ArgumentCaptor .forClass (Status .class );
3254
+ verify (timeoutWatcher ).onError (errorCaptor .capture ());
3255
+ Status error = errorCaptor .getValue ();
3256
+ assertThat (error .getCode ()).isEqualTo (Status .Code .UNAVAILABLE );
3257
+ assertThat (error .getDescription ()).isEqualTo (
3258
+ "Timed out waiting for resource " + timeoutResource + " from xDS server" );
3259
+ BootstrapperImpl .xdsDataErrorHandlingEnabled = false ;
3260
+ }
3261
+
3158
3262
private Answer <Void > blockUpdate (CyclicBarrier barrier ) {
3159
3263
return new Answer <Void >() {
3160
3264
@ Override
@@ -4220,7 +4324,7 @@ private XdsClientImpl createXdsClient(String serverUri) {
4220
4324
private BootstrapInfo buildBootStrap (String serverUri ) {
4221
4325
4222
4326
ServerInfo xdsServerInfo = ServerInfo .create (serverUri , CHANNEL_CREDENTIALS ,
4223
- ignoreResourceDeletion (), true );
4327
+ ignoreResourceDeletion (), true , false );
4224
4328
4225
4329
return Bootstrapper .BootstrapInfo .builder ()
4226
4330
.servers (Collections .singletonList (xdsServerInfo ))
@@ -4230,7 +4334,7 @@ private BootstrapInfo buildBootStrap(String serverUri) {
4230
4334
AuthorityInfo .create (
4231
4335
"xdstp://authority.xds.com/envoy.config.listener.v3.Listener/%s" ,
4232
4336
ImmutableList .of (Bootstrapper .ServerInfo .create (
4233
- SERVER_URI_CUSTOME_AUTHORITY , CHANNEL_CREDENTIALS ))),
4337
+ SERVER_URI_CUSTOM_AUTHORITY , CHANNEL_CREDENTIALS ))),
4234
4338
"" ,
4235
4339
AuthorityInfo .create (
4236
4340
"xdstp:///envoy.config.listener.v3.Listener/%s" ,
0 commit comments