Skip to content

Commit 8ea9445

Browse files
author
Timur Sadykov
authored
fix: marking 503 as retryable for Compute credentials (#1205)
* fix: add retryable for GCE credential in case of 503 * fix: add tests for 503 retryable * fix: update user credential tests
1 parent 9cce49c commit 8ea9445

File tree

5 files changed

+87
-8
lines changed

5 files changed

+87
-8
lines changed

oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.google.api.client.http.HttpHeaders;
3838
import com.google.api.client.http.HttpRequest;
3939
import com.google.api.client.http.HttpResponse;
40+
import com.google.api.client.http.HttpResponseException;
4041
import com.google.api.client.http.HttpStatusCodes;
4142
import com.google.api.client.json.JsonObjectParser;
4243
import com.google.api.client.util.GenericData;
@@ -284,6 +285,12 @@ private HttpResponse getMetadataResponse(String url) throws IOException {
284285
+ " likely because code is not running on Google Compute Engine.",
285286
exception);
286287
}
288+
289+
if (response.getStatusCode() == 503) {
290+
throw GoogleAuthException.createWithTokenEndpointResponseException(
291+
new HttpResponseException(response));
292+
}
293+
287294
return response;
288295
}
289296

oauth2_http/java/com/google/auth/oauth2/GoogleAuthException.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,7 @@ static GoogleAuthException createWithTokenEndpointResponseException(
121121
int responseStatus = responseException.getStatusCode();
122122
boolean isRetryable =
123123
OAuth2Utils.TOKEN_ENDPOINT_RETRYABLE_STATUS_CODES.contains(responseStatus);
124-
// TODO: temporarily setting to default to remove a direct dependency, to be reverted after
125-
// release
126-
int retryCount = ServiceAccountCredentials.DEFAULT_NUMBER_OF_RETRIES;
124+
int retryCount = responseException.getAttemptCount() - 1;
127125

128126
if (message == null) {
129127
return new GoogleAuthException(isRetryable, retryCount, responseException);

oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@
5555
import com.google.auth.oauth2.GoogleCredentialsTest.MockHttpTransportFactory;
5656
import java.io.IOException;
5757
import java.net.URI;
58+
import java.util.ArrayDeque;
5859
import java.util.Arrays;
5960
import java.util.Collection;
6061
import java.util.Collections;
6162
import java.util.List;
6263
import java.util.Map;
64+
import java.util.Queue;
65+
import java.util.stream.IntStream;
6366
import org.junit.Test;
6467
import org.junit.runner.RunWith;
6568
import org.junit.runners.JUnit4;
@@ -533,6 +536,77 @@ public LowLevelHttpResponse execute() throws IOException {
533536
}
534537
}
535538

539+
@Test
540+
public void refresh_503_retryable_throws() {
541+
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
542+
543+
transportFactory.transport =
544+
new MockMetadataServerTransport() {
545+
@Override
546+
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
547+
return new MockLowLevelHttpRequest(url) {
548+
@Override
549+
public LowLevelHttpResponse execute() throws IOException {
550+
return new MockLowLevelHttpResponse()
551+
.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVICE_UNAVAILABLE)
552+
.setContent(TestUtils.errorJson("Some error"));
553+
}
554+
};
555+
}
556+
};
557+
558+
ComputeEngineCredentials credentials =
559+
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
560+
561+
try {
562+
credentials.refreshAccessToken();
563+
fail("Should have failed");
564+
} catch (IOException e) {
565+
assertTrue(e.getCause().getMessage().contains("503"));
566+
assertTrue(e instanceof GoogleAuthException);
567+
assertTrue(((GoogleAuthException) e).isRetryable());
568+
}
569+
}
570+
571+
@Test
572+
public void refresh_non503_ioexception_throws() {
573+
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
574+
final Queue<Integer> responseSequence = new ArrayDeque<>();
575+
IntStream.rangeClosed(400, 600).forEach(i -> responseSequence.add(i));
576+
577+
while (!responseSequence.isEmpty()) {
578+
if (responseSequence.peek() == 503) {
579+
responseSequence.poll();
580+
continue;
581+
}
582+
583+
transportFactory.transport =
584+
new MockMetadataServerTransport() {
585+
@Override
586+
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
587+
return new MockLowLevelHttpRequest(url) {
588+
@Override
589+
public LowLevelHttpResponse execute() throws IOException {
590+
return new MockLowLevelHttpResponse()
591+
.setStatusCode(responseSequence.poll())
592+
.setContent(TestUtils.errorJson("Some error"));
593+
}
594+
};
595+
}
596+
};
597+
598+
ComputeEngineCredentials credentials =
599+
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
600+
601+
try {
602+
credentials.refreshAccessToken();
603+
fail("Should have failed");
604+
} catch (IOException e) {
605+
assertFalse(e instanceof GoogleAuthException);
606+
}
607+
}
608+
}
609+
536610
@Test
537611
public void sign_emptyContent_throws() {
538612
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();

oauth2_http/javatests/com/google/auth/oauth2/ServiceAccountCredentialsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ public void refreshAccessToken_defaultRetriesDisabled() throws IOException {
747747
} catch (GoogleAuthException ex) {
748748
assertTrue(ex.getMessage().contains("Error getting access token for service account: 408"));
749749
assertTrue(ex.isRetryable());
750-
assertEquals(3, ex.getRetryCount());
750+
assertEquals(0, ex.getRetryCount());
751751
}
752752
}
753753

@@ -866,7 +866,7 @@ public void refreshAccessToken_4xx_5xx_NonRetryableFails() throws IOException {
866866
fail("Should not be able to use credential without exception.");
867867
} catch (GoogleAuthException ex) {
868868
assertFalse(ex.isRetryable());
869-
assertEquals(3, ex.getRetryCount());
869+
assertEquals(0, ex.getRetryCount());
870870
}
871871
}
872872
}

oauth2_http/javatests/com/google/auth/oauth2/UserCredentialsTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ public void IdTokenCredentials_NoRetry_RetryableStatus_throws() throws IOExcepti
758758
} catch (GoogleAuthException ex) {
759759
assertTrue(ex.getMessage().contains("com.google.api.client.http.HttpResponseException: 408"));
760760
assertTrue(ex.isRetryable());
761-
assertEquals(3, ex.getRetryCount());
761+
assertEquals(0, ex.getRetryCount());
762762
}
763763

764764
IdTokenCredentials tokenCredential =
@@ -774,7 +774,7 @@ public void IdTokenCredentials_NoRetry_RetryableStatus_throws() throws IOExcepti
774774
} catch (GoogleAuthException ex) {
775775
assertTrue(ex.getMessage().contains("com.google.api.client.http.HttpResponseException: 429"));
776776
assertTrue(ex.isRetryable());
777-
assertEquals(3, ex.getRetryCount());
777+
assertEquals(0, ex.getRetryCount());
778778
}
779779
}
780780

@@ -801,7 +801,7 @@ public void refreshAccessToken_4xx_5xx_NonRetryableFails() throws IOException {
801801
fail("Should not be able to use credential without exception.");
802802
} catch (GoogleAuthException ex) {
803803
assertFalse(ex.isRetryable());
804-
assertEquals(3, ex.getRetryCount());
804+
assertEquals(0, ex.getRetryCount());
805805
}
806806
}
807807
}

0 commit comments

Comments
 (0)