Skip to content

Commit 1dfa3f2

Browse files
committed
Make AwsRegionProviders throw exceptions like AwsCredentialsProviders
1 parent a43939f commit 1dfa3f2

File tree

8 files changed

+51
-31
lines changed

8 files changed

+51
-31
lines changed

regions/src/main/java/software/amazon/awssdk/regions/providers/AwsProfileRegionProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import software.amazon.awssdk.annotations.SdkInternalApi;
1919
import software.amazon.awssdk.core.SdkSystemSetting;
20+
import software.amazon.awssdk.core.exception.SdkClientException;
2021
import software.amazon.awssdk.profiles.ProfileFile;
2122
import software.amazon.awssdk.profiles.ProfileProperties;
2223
import software.amazon.awssdk.regions.Region;
@@ -35,7 +36,7 @@ public Region getRegion() {
3536
.profile(profileName)
3637
.map(p -> p.properties().get(ProfileProperties.REGION))
3738
.map(Region::of)
38-
.orElse(null);
39+
.orElseThrow(() -> new SdkClientException("No region provided in profile: " + profileName));
3940
}
4041
}
4142

regions/src/main/java/software/amazon/awssdk/regions/providers/AwsRegionProvider.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
package software.amazon.awssdk.regions.providers;
1717

18-
import software.amazon.awssdk.annotations.ReviewBeforeRelease;
1918
import software.amazon.awssdk.annotations.SdkProtectedApi;
2019
import software.amazon.awssdk.core.exception.SdkClientException;
2120
import software.amazon.awssdk.regions.Region;
@@ -28,10 +27,10 @@
2827
@FunctionalInterface
2928
public interface AwsRegionProvider {
3029
/**
31-
* @return Region name to use or null if region information is not available.
30+
* Returns the region name to use. If region information is not available, throws an {@link SdkClientException}.
31+
*
32+
* @return Region name to use.
3233
*/
33-
@ReviewBeforeRelease("Should this throw exceptions so that its contract matches that of the credential providers? This is " +
34-
"currently a protected API used in STS, so we should decide before GA.")
35-
Region getRegion() throws SdkClientException;
34+
Region getRegion();
3635

3736
}

regions/src/main/java/software/amazon/awssdk/regions/providers/AwsRegionProviderChain.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
/**
2727
* Composite {@link AwsRegionProvider} that sequentially delegates to a chain of providers looking
2828
* for region information.
29+
*
30+
* Throws an {@link SdkClientException} if region could not be find in any of the providers.
2931
*/
3032
public class AwsRegionProviderChain implements AwsRegionProvider {
3133

@@ -40,6 +42,8 @@ public AwsRegionProviderChain(AwsRegionProvider... providers) {
4042

4143
@Override
4244
public Region getRegion() throws SdkClientException {
45+
List<String> exceptionMessages = null;
46+
4347
for (AwsRegionProvider provider : providers) {
4448
try {
4549
final Region region = provider.getRegion();
@@ -49,9 +53,16 @@ public Region getRegion() throws SdkClientException {
4953
} catch (Exception e) {
5054
// Ignore any exceptions and move onto the next provider
5155
log.debug("Unable to load region from {}:{}", provider.toString(), e.getMessage());
56+
57+
String message = provider.toString() + ": " + e.getMessage();
58+
if (exceptionMessages == null) {
59+
exceptionMessages = new ArrayList<>();
60+
}
61+
exceptionMessages.add(message);
5262
}
5363
}
5464

55-
return null;
65+
throw new SdkClientException("Unable to load region from any of the providers in the chain " + this
66+
+ ": " + exceptionMessages);
5667
}
5768
}

regions/src/main/java/software/amazon/awssdk/regions/providers/InstanceProfileRegionProvider.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515

1616
package software.amazon.awssdk.regions.providers;
1717

18-
import org.slf4j.LoggerFactory;
1918
import software.amazon.awssdk.core.exception.SdkClientException;
2019
import software.amazon.awssdk.regions.Region;
2120
import software.amazon.awssdk.regions.util.EC2MetadataUtils;
2221

2322
/**
2423
* Attempts to load region information from the EC2 Metadata service. If the application is not
25-
* running on EC2 this provider will return null.
24+
* running on EC2 this provider will thrown an exception.
2625
*/
2726
public class InstanceProfileRegionProvider implements AwsRegionProvider {
2827

@@ -41,16 +40,15 @@ public Region getRegion() throws SdkClientException {
4140
}
4241
}
4342

44-
return region == null ? null : Region.of(region);
43+
if (region == null) {
44+
throw new SdkClientException("Unable to retrieve region information from EC2 Metadata service. "
45+
+ "Please make sure the application is running on EC2.");
46+
}
47+
48+
return Region.of(region);
4549
}
4650

4751
private String tryDetectRegion() {
48-
try {
49-
return EC2MetadataUtils.getEC2InstanceRegion();
50-
} catch (SdkClientException sce) {
51-
LoggerFactory.getLogger(InstanceProfileRegionProvider.class)
52-
.debug("Ignoring failure to retrieve the region: {}", sce.getMessage());
53-
return null;
54-
}
52+
return EC2MetadataUtils.getEC2InstanceRegion();
5553
}
5654
}

regions/src/main/java/software/amazon/awssdk/regions/providers/SystemSettingsRegionProvider.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
public class SystemSettingsRegionProvider implements AwsRegionProvider {
2727
@Override
2828
public Region getRegion() throws SdkClientException {
29-
return SdkSystemSetting.AWS_REGION.getStringValue().map(Region::of).orElse(null);
29+
return SdkSystemSetting.AWS_REGION.getStringValue()
30+
.map(Region::of)
31+
.orElseThrow(this::exception);
32+
}
33+
34+
private SdkClientException exception() {
35+
return new SdkClientException(String.format("Unable to load region from system settings. Region must be specified either "
36+
+ "via environment variable (%s) or system property (%s).",
37+
SdkSystemSetting.AWS_REGION.environmentVariable(),
38+
SdkSystemSetting.AWS_REGION.property()));
3039
}
3140
}

regions/src/test/java/software/amazon/awssdk/regions/providers/AwsProfileRegionProviderTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
package software.amazon.awssdk.regions.providers;
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
1920

2021
import java.net.URISyntaxException;
2122
import java.nio.file.Paths;
2223
import org.junit.Rule;
2324
import org.junit.Test;
25+
import software.amazon.awssdk.core.exception.SdkClientException;
2426
import software.amazon.awssdk.regions.Region;
2527
import software.amazon.awssdk.testutils.EnvironmentVariableHelper;
2628
import software.amazon.awssdk.core.SdkSystemSetting;
@@ -31,10 +33,12 @@ public class AwsProfileRegionProviderTest {
3133
public EnvironmentVariableHelper settingsHelper = new EnvironmentVariableHelper();
3234

3335
@Test
34-
public void nonExistentDefaultConfigFile_ReturnsNull() {
36+
public void nonExistentDefaultConfigFile_ThrowsException() {
3537
settingsHelper.set(SdkSystemSetting.AWS_CONFIG_FILE, "/var/tmp/this/is/invalid.txt");
3638
settingsHelper.set(SdkSystemSetting.AWS_SHARED_CREDENTIALS_FILE, "/var/tmp/this/is/also.invalid.txt");
37-
assertThat(new AwsProfileRegionProvider().getRegion()).isNull();
39+
assertThatThrownBy(() -> new AwsProfileRegionProvider().getRegion())
40+
.isInstanceOf(SdkClientException.class)
41+
.hasMessageContaining("No region provided in profile: default");
3842
}
3943

4044
@Test

regions/src/test/java/software/amazon/awssdk/regions/providers/AwsRegionProviderChainTest.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package software.amazon.awssdk.regions.providers;
1717

1818
import static org.junit.Assert.assertEquals;
19-
import static org.junit.Assert.assertNull;
2019
import static org.mockito.Mockito.mock;
2120
import static org.mockito.Mockito.never;
2221
import static org.mockito.Mockito.verify;
@@ -77,12 +76,12 @@ public void providerThrowsError_DoesNotContinueChain() {
7776
assertEquals(expectedRegion, chain.getRegion());
7877
}
7978

80-
@Test
81-
public void noProviderGivesRegion_ReturnsNull() {
79+
@Test (expected = SdkClientException.class)
80+
public void noProviderGivesRegion_ThrowsException() {
8281
AwsRegionProviderChain chain = new AwsRegionProviderChain(new NeverAwsRegionProvider(),
8382
new NeverAwsRegionProvider(),
8483
new NeverAwsRegionProvider());
85-
assertNull(chain.getRegion());
84+
chain.getRegion();
8685
}
8786

8887
private static class NeverAwsRegionProvider implements AwsRegionProvider {

regions/src/test/java/software/amazon/awssdk/regions/providers/InstanceProfileRegionProviderTest.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package software.amazon.awssdk.regions.providers;
1717

1818
import static org.junit.Assert.assertEquals;
19-
import static org.junit.Assert.assertNull;
2019

2120
import java.io.IOException;
2221
import org.junit.AfterClass;
@@ -26,6 +25,7 @@
2625
import org.junit.experimental.runners.Enclosed;
2726
import org.junit.runner.RunWith;
2827
import software.amazon.awssdk.core.SdkSystemSetting;
28+
import software.amazon.awssdk.core.exception.SdkClientException;
2929
import software.amazon.awssdk.regions.Region;
3030
import software.amazon.awssdk.regions.util.EC2MetadataUtilsServer;
3131

@@ -73,9 +73,8 @@ public void metadataServiceRunning_ProvidesCorrectRegion() {
7373
}
7474

7575
/**
76-
* If the EC2 metadata service is not present then the provider should just return null instead
77-
* of failing. This is to allow the provider to be used in a chain context where another
78-
* provider further down the chain may be able to provide the region.
76+
* If the EC2 metadata service is not present then the provider will throw an exception. If the provider is used
77+
* in a {@link AwsRegionProviderChain}, the chain will catch the exception and go on to the next region provider.
7978
*/
8079
public static class MetadataServiceNotRunning {
8180

@@ -87,9 +86,9 @@ public void setup() {
8786
regionProvider = new InstanceProfileRegionProvider();
8887
}
8988

90-
@Test
91-
public void metadataServiceNotRunning_ProvidesCorrectRegion() {
92-
assertNull(regionProvider.getRegion());
89+
@Test (expected = SdkClientException.class)
90+
public void metadataServiceNotRunning_ThrowsException() {
91+
regionProvider.getRegion();
9392
}
9493

9594
}

0 commit comments

Comments
 (0)