Skip to content

Commit 54d5db3

Browse files
committed
Float LRU Cache across interceptors
1 parent 84c7713 commit 54d5db3

2 files changed

Lines changed: 52 additions & 18 deletions

File tree

xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,17 @@ final class GcpAuthenticationFilter implements Filter {
5959

6060
static final String TYPE_URL =
6161
"type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig";
62-
62+
private final LruCache<String, CallCredentials> callCredentialsCache;
6363
final String filterInstanceName;
6464

65-
GcpAuthenticationFilter(String name) {
65+
GcpAuthenticationFilter(String name, int cacheSize) {
6666
filterInstanceName = checkNotNull(name, "name");
67+
this.callCredentialsCache = new LruCache<>(cacheSize);
6768
}
6869

69-
7070
static final class Provider implements Filter.Provider {
71+
long cacheSize = 10;
72+
7173
@Override
7274
public String[] typeUrls() {
7375
return new String[]{TYPE_URL};
@@ -80,7 +82,7 @@ public boolean isClientFilter() {
8082

8183
@Override
8284
public GcpAuthenticationFilter newInstance(String name) {
83-
return new GcpAuthenticationFilter(name);
85+
return new GcpAuthenticationFilter(name, (int) cacheSize);
8486
}
8587

8688
@Override
@@ -97,7 +99,6 @@ public ConfigOrError<GcpAuthenticationConfig> parseFilterConfig(Message rawProto
9799
return ConfigOrError.fromError("Invalid proto: " + e);
98100
}
99101

100-
long cacheSize = 10;
101102
// Validate cache_config
102103
if (gcpAuthnProto.hasCacheConfig()) {
103104
TokenCacheConfig cacheConfig = gcpAuthnProto.getCacheConfig();
@@ -127,8 +128,6 @@ public ClientInterceptor buildClientInterceptor(FilterConfig config,
127128
@Nullable FilterConfig overrideConfig, ScheduledExecutorService scheduler) {
128129

129130
ComputeEngineCredentials credentials = ComputeEngineCredentials.create();
130-
LruCache<String, CallCredentials> callCredentialsCache =
131-
new LruCache<>(((GcpAuthenticationConfig) config).getCacheSize());
132131
return new ClientInterceptor() {
133132
@Override
134133
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(

xds/src/test/java/io/grpc/xds/GcpAuthenticationFilterTest.java

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import static org.junit.Assert.assertTrue;
3434
import static org.mockito.ArgumentMatchers.eq;
3535
import static org.mockito.Mockito.mock;
36+
import static org.mockito.Mockito.times;
3637
import static org.mockito.Mockito.verify;
3738

3839
import com.google.common.collect.ImmutableList;
@@ -89,8 +90,8 @@ public class GcpAuthenticationFilterTest {
8990

9091
@Test
9192
public void testNewFilterInstancesPerFilterName() {
92-
assertThat(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1"))
93-
.isNotEqualTo(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1"));
93+
assertThat(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1", 10))
94+
.isNotEqualTo(new GcpAuthenticationFilter("FILTER_INSTANCE_NAME1", 10));
9495
}
9596

9697
@Test
@@ -152,7 +153,7 @@ public void testClientInterceptor_success() throws IOException, ResourceInvalidE
152153
.withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0")
153154
.withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig);
154155
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
155-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
156+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
156157
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
157158
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
158159
Channel mockChannel = Mockito.mock(Channel.class);
@@ -181,7 +182,7 @@ public void testClientInterceptor_createsAndReusesCachedCredentials()
181182
.withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0")
182183
.withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig);
183184
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
184-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
185+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
185186
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
186187
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
187188
Channel mockChannel = Mockito.mock(Channel.class);
@@ -190,7 +191,7 @@ public void testClientInterceptor_createsAndReusesCachedCredentials()
190191
interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel);
191192
interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel);
192193

193-
verify(mockChannel, Mockito.times(2))
194+
verify(mockChannel, times(2))
194195
.newCall(eq(methodDescriptor), callOptionsCaptor.capture());
195196
CallOptions firstCapturedOptions = callOptionsCaptor.getAllValues().get(0);
196197
CallOptions secondCapturedOptions = callOptionsCaptor.getAllValues().get(1);
@@ -202,7 +203,7 @@ public void testClientInterceptor_createsAndReusesCachedCredentials()
202203
@Test
203204
public void testClientInterceptor_withoutClusterSelectionKey() throws Exception {
204205
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
205-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
206+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
206207
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
207208
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
208209
Channel mockChannel = mock(Channel.class);
@@ -233,7 +234,7 @@ public void testClientInterceptor_clusterSelectionKeyWithoutPrefix() throws Exce
233234
Channel mockChannel = mock(Channel.class);
234235

235236
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
236-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
237+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
237238
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
238239
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
239240
interceptor.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel);
@@ -244,7 +245,7 @@ public void testClientInterceptor_clusterSelectionKeyWithoutPrefix() throws Exce
244245
@Test
245246
public void testClientInterceptor_xdsConfigDoesNotExist() throws Exception {
246247
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
247-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
248+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
248249
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
249250
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
250251
Channel mockChannel = mock(Channel.class);
@@ -274,7 +275,7 @@ public void testClientInterceptor_incorrectClusterName() throws Exception {
274275
.withOption(CLUSTER_SELECTION_KEY, "cluster:cluster")
275276
.withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig);
276277
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
277-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
278+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
278279
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
279280
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
280281
Channel mockChannel = mock(Channel.class);
@@ -300,7 +301,7 @@ public void testClientInterceptor_statusOrError() throws Exception {
300301
.withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0")
301302
.withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig);
302303
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
303-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
304+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
304305
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
305306
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
306307
Channel mockChannel = mock(Channel.class);
@@ -329,7 +330,7 @@ public void testClientInterceptor_notAudienceWrapper()
329330
.withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0")
330331
.withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig);
331332
GcpAuthenticationConfig config = new GcpAuthenticationConfig(10);
332-
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME");
333+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 10);
333334
ClientInterceptor interceptor = filter.buildClientInterceptor(config, null, null);
334335
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
335336
Channel mockChannel = Mockito.mock(Channel.class);
@@ -342,6 +343,40 @@ public void testClientInterceptor_notAudienceWrapper()
342343
assertThat(clientCall.error.getDescription()).contains("GCP Authn found wrong type");
343344
}
344345

346+
@Test
347+
public void testLruCacheAcrossInterceptors() throws IOException, ResourceInvalidException {
348+
XdsConfig.XdsClusterConfig clusterConfig = new XdsConfig.XdsClusterConfig(
349+
CLUSTER_NAME, cdsUpdate, new EndpointConfig(StatusOr.fromValue(edsUpdate)));
350+
XdsConfig defaultXdsConfig = new XdsConfig.XdsConfigBuilder()
351+
.setListener(ldsUpdate)
352+
.setRoute(rdsUpdate)
353+
.setVirtualHost(rdsUpdate.virtualHosts.get(0))
354+
.addCluster(CLUSTER_NAME, StatusOr.fromValue(clusterConfig)).build();
355+
CallOptions callOptionsWithXds = CallOptions.DEFAULT
356+
.withOption(CLUSTER_SELECTION_KEY, "cluster:cluster0")
357+
.withOption(XDS_CONFIG_CALL_OPTION_KEY, defaultXdsConfig);
358+
GcpAuthenticationFilter filter = new GcpAuthenticationFilter("FILTER_INSTANCE_NAME", 2);
359+
ClientInterceptor interceptor1
360+
= filter.buildClientInterceptor(new GcpAuthenticationConfig(2), null, null);
361+
ClientInterceptor interceptor2
362+
= filter.buildClientInterceptor(new GcpAuthenticationConfig(2), null, null);
363+
MethodDescriptor<Void, Void> methodDescriptor = TestMethodDescriptors.voidMethod();
364+
Channel mockChannel = Mockito.mock(Channel.class);
365+
ArgumentCaptor<CallOptions> callOptionsCaptor = ArgumentCaptor.forClass(CallOptions.class);
366+
367+
interceptor1.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel);
368+
verify(mockChannel).newCall(eq(methodDescriptor), callOptionsCaptor.capture());
369+
CallOptions capturedOptions1 = callOptionsCaptor.getAllValues().get(0);
370+
assertNotNull(capturedOptions1.getCredentials());
371+
interceptor2.interceptCall(methodDescriptor, callOptionsWithXds, mockChannel);
372+
verify(mockChannel, times(2))
373+
.newCall(eq(methodDescriptor), callOptionsCaptor.capture());
374+
CallOptions capturedOptions2 = callOptionsCaptor.getAllValues().get(1);
375+
assertNotNull(capturedOptions2.getCredentials());
376+
377+
assertSame(capturedOptions1.getCredentials(), capturedOptions2.getCredentials());
378+
}
379+
345380
private static LdsUpdate getLdsUpdate() {
346381
Filter.NamedFilterConfig routerFilterConfig = new Filter.NamedFilterConfig(
347382
serverName, RouterFilter.ROUTER_CONFIG);

0 commit comments

Comments
 (0)