Skip to content

Commit

Permalink
auth: Add support for Retryable interface
Browse files Browse the repository at this point in the history
Retryable was added in google-auth-library 1.5.3 to make clear the
situations that deserve a retry of the RPC. Upgrading to that caused
problems because of transitive dependency issues syncing into Google so
it was reverted in 369f87b. google-auth-library 1.11.0 changed the
approach to avoid the transitive dependency updates. cl/601545581
upgraded to 1.22.0 inside Google. Bump to that version and swap away
from the imprecise IOException heuristic. go/auth-correct-retry

Fixes #6808
  • Loading branch information
ejona86 committed Feb 9, 2024
1 parent ff34d51 commit 372a535
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.google.auth.Credentials;
import com.google.auth.RequestMetadataCallback;
import com.google.auth.Retryable;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.BaseEncoding;
import io.grpc.InternalMayRequireSpecificExecutor;
Expand All @@ -28,7 +29,6 @@
import io.grpc.SecurityLevel;
import io.grpc.Status;
import io.grpc.StatusException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
Expand Down Expand Up @@ -143,8 +143,8 @@ public void onSuccess(Map<String, List<String>> metadata) {

@Override
public void onFailure(Throwable e) {
if (e instanceof IOException) {
// Since it's an I/O failure, let the call be retried with UNAVAILABLE.
if (e instanceof Retryable && ((Retryable) e).isRetryable()) {
// Let the call be retried with UNAVAILABLE.
applier.fail(Status.UNAVAILABLE
.withDescription("Credentials failed to obtain metadata")
.withCause(e));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import com.google.auth.Credentials;
import com.google.auth.RequestMetadataCallback;
import com.google.auth.Retryable;
import com.google.auth.http.HttpTransportFactory;
import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
Expand Down Expand Up @@ -191,8 +192,9 @@ public void invalidBase64() throws Exception {
}

@Test
public void credentialsFailsWithIoException() throws Exception {
Exception exception = new IOException("Broken");
public void credentialsFailsWithRetryableRetryableException() throws Exception {
boolean retryable = true;
Exception exception = new RetryableException(retryable);
when(credentials.getRequestMetadata(eq(expectedUri))).thenThrow(exception);

GoogleAuthLibraryCallCredentials callCredentials =
Expand All @@ -206,6 +208,23 @@ public void credentialsFailsWithIoException() throws Exception {
assertEquals(exception, status.getCause());
}

@Test
public void credentialsFailsWithUnretryableRetryableException() throws Exception {
boolean retryable = false;
Exception exception = new RetryableException(retryable);
when(credentials.getRequestMetadata(eq(expectedUri))).thenThrow(exception);

GoogleAuthLibraryCallCredentials callCredentials =
new GoogleAuthLibraryCallCredentials(credentials);
callCredentials.applyRequestMetadata(new RequestInfoImpl(), executor, applier);

verify(credentials).getRequestMetadata(eq(expectedUri));
verify(applier).fail(statusCaptor.capture());
Status status = statusCaptor.getValue();
assertEquals(Status.Code.UNAUTHENTICATED, status.getCode());
assertEquals(exception, status.getCause());
}

@Test
public void credentialsFailsWithRuntimeException() throws Exception {
Exception exception = new RuntimeException("Broken");
Expand Down Expand Up @@ -458,4 +477,21 @@ public Attributes getTransportAttrs() {
return Attributes.EMPTY;
}
}

private static class RetryableException extends IOException implements Retryable {
private final boolean retryable;

public RetryableException(boolean retryable) {
super("Broken");
this.retryable = retryable;
}

@Override public boolean isRetryable() {
return retryable;
}

@Override public int getRetryCount() {
return 0;
}
}
}
4 changes: 1 addition & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
[versions]
# Compatibility problem with internal version getting onto 1.5.3.
# https://github.com/grpc/grpc-java/pull/9118
googleauth = "1.4.0"
googleauth = "1.22.0"
netty = '4.1.100.Final'
# Keep the following references of tcnative version in sync whenever it's updated:
# SECURITY.md
Expand Down
4 changes: 2 additions & 2 deletions repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
IO_GRPC_GRPC_JAVA_ARTIFACTS = [
"com.google.android:annotations:4.1.1.4",
"com.google.api.grpc:proto-google-common-protos:2.29.0",
"com.google.auth:google-auth-library-credentials:1.4.0",
"com.google.auth:google-auth-library-oauth2-http:1.4.0",
"com.google.auth:google-auth-library-credentials:1.22.0",
"com.google.auth:google-auth-library-oauth2-http:1.22.0",
"com.google.auto.value:auto-value-annotations:1.10.4",
"com.google.auto.value:auto-value:1.10.4",
"com.google.code.findbugs:jsr305:3.0.2",
Expand Down

0 comments on commit 372a535

Please sign in to comment.