18
18
19
19
20
20
import static com .google .common .truth .Truth .assertThat ;
21
+ import static io .grpc .Metadata .ASCII_STRING_MARSHALLER ;
21
22
import static org .mockito .Mockito .verify ;
22
23
import static org .mockito .Mockito .verifyNoMoreInteractions ;
23
24
import static org .mockito .Mockito .when ;
24
25
26
+ import com .google .auth .oauth2 .AccessToken ;
27
+ import com .google .auth .oauth2 .OAuth2Credentials ;
28
+ import com .google .common .util .concurrent .SettableFuture ;
29
+ import io .grpc .CallCredentials ;
30
+ import io .grpc .Grpc ;
25
31
import io .grpc .InsecureChannelCredentials ;
32
+ import io .grpc .InsecureServerCredentials ;
33
+ import io .grpc .Metadata ;
26
34
import io .grpc .MetricRecorder ;
35
+ import io .grpc .Server ;
36
+ import io .grpc .ServerCall ;
37
+ import io .grpc .ServerCallHandler ;
38
+ import io .grpc .ServerInterceptor ;
39
+ import io .grpc .auth .MoreCallCredentials ;
27
40
import io .grpc .internal .ObjectPool ;
28
41
import io .grpc .xds .SharedXdsClientPoolProvider .RefCountedXdsClientObjectPool ;
42
+ import io .grpc .xds .XdsListenerResource .LdsUpdate ;
29
43
import io .grpc .xds .client .Bootstrapper .BootstrapInfo ;
30
44
import io .grpc .xds .client .Bootstrapper .ServerInfo ;
31
45
import io .grpc .xds .client .EnvoyProtoData .Node ;
32
46
import io .grpc .xds .client .XdsClient ;
47
+ import io .grpc .xds .client .XdsClient .ResourceWatcher ;
33
48
import io .grpc .xds .client .XdsInitializationException ;
34
49
import java .util .Collections ;
50
+ import java .util .concurrent .TimeUnit ;
35
51
import org .junit .Rule ;
36
52
import org .junit .Test ;
37
53
import org .junit .rules .ExpectedException ;
@@ -54,9 +70,12 @@ public class SharedXdsClientPoolProviderTest {
54
70
private final Node node = Node .newBuilder ().setId ("SharedXdsClientPoolProviderTest" ).build ();
55
71
private final MetricRecorder metricRecorder = new MetricRecorder () {};
56
72
private static final String DUMMY_TARGET = "dummy" ;
73
+ static final Metadata .Key <String > AUTHORIZATION_METADATA_KEY =
74
+ Metadata .Key .of ("Authorization" , ASCII_STRING_MARSHALLER );
57
75
58
76
@ Mock
59
77
private GrpcBootstrapperImpl bootstrapper ;
78
+ @ Mock private ResourceWatcher <LdsUpdate > ldsResourceWatcher ;
60
79
61
80
@ Test
62
81
public void noServer () throws XdsInitializationException {
@@ -138,4 +157,62 @@ public void refCountedXdsClientObjectPool_getObjectCreatesNewInstanceIfAlreadySh
138
157
assertThat (xdsClient2 ).isNotSameInstanceAs (xdsClient1 );
139
158
xdsClientPool .returnObject (xdsClient2 );
140
159
}
160
+
161
+ private class CallCredsServerInterceptor implements ServerInterceptor {
162
+ private SettableFuture <String > tokenFuture = SettableFuture .create ();
163
+
164
+ @ Override
165
+ public <ReqT , RespT > ServerCall .Listener <ReqT > interceptCall (
166
+ ServerCall <ReqT , RespT > serverCall ,
167
+ Metadata metadata ,
168
+ ServerCallHandler <ReqT , RespT > next ) {
169
+ tokenFuture .set (metadata .get (AUTHORIZATION_METADATA_KEY ));
170
+ return next .startCall (serverCall , metadata );
171
+ }
172
+
173
+ public String getTokenWithTimeout (long timeout , TimeUnit unit ) throws Exception {
174
+ return tokenFuture .get (timeout , unit );
175
+ }
176
+ }
177
+
178
+ @ Test
179
+ public void xdsClient_usesCallCredentials () throws Exception {
180
+ // Set up fake xDS server
181
+ XdsTestControlPlaneService fakeXdsService = new XdsTestControlPlaneService ();
182
+ CallCredsServerInterceptor callCredentialsInterceptor = new CallCredsServerInterceptor ();
183
+ Server xdsServer =
184
+ Grpc .newServerBuilderForPort (0 , InsecureServerCredentials .create ())
185
+ .addService (fakeXdsService )
186
+ .intercept (callCredentialsInterceptor )
187
+ .build ()
188
+ .start ();
189
+ String xdsServerUri = "localhost:" + xdsServer .getPort ();
190
+
191
+ // Set up bootstrap & xDS client pool provider
192
+ ServerInfo server = ServerInfo .create (xdsServerUri , InsecureChannelCredentials .create ());
193
+ BootstrapInfo bootstrapInfo =
194
+ BootstrapInfo .builder ().servers (Collections .singletonList (server )).node (node ).build ();
195
+ when (bootstrapper .bootstrap ()).thenReturn (bootstrapInfo );
196
+ SharedXdsClientPoolProvider provider = new SharedXdsClientPoolProvider (bootstrapper );
197
+
198
+ // Create custom xDS transport CallCredentials
199
+ CallCredentials sampleCreds =
200
+ MoreCallCredentials .from (
201
+ OAuth2Credentials .create (new AccessToken ("token" , /* expirationTime= */ null )));
202
+
203
+ // Create xDS client that uses the CallCredentials on the transport
204
+ ObjectPool <XdsClient > xdsClientPool =
205
+ provider .getOrCreate ("target" , metricRecorder , sampleCreds );
206
+ XdsClient xdsClient = xdsClientPool .getObject ();
207
+ xdsClient .watchXdsResource (
208
+ XdsListenerResource .getInstance (), "someLDSresource" , ldsResourceWatcher );
209
+
210
+ // Wait for xDS server to get the request and verify that it received the CallCredentials
211
+ assertThat (callCredentialsInterceptor .getTokenWithTimeout (5 , TimeUnit .SECONDS ))
212
+ .isEqualTo ("Bearer token" );
213
+
214
+ // Clean up
215
+ xdsClientPool .returnObject (xdsClient );
216
+ xdsServer .shutdownNow ();
217
+ }
141
218
}
0 commit comments