All options above can be configured by users, and the overridden value will take precedence.")
+ .add("
Note: for any mode other than {@link #LEGACY}, the vended default values might change "
+ + "as best practices may evolve. As a result, it is encouraged to perform testing when upgrading the SDK if"
+ + " you are using a mode other than {@link #LEGACY}")
+ .add(System.lineSeparator());
+
+ return builder.add("
While the {@link #LEGACY} defaults mode is specific to Java, other modes are "
+ + "standardized across "
+ + "all of the AWS SDKs
")
+ .add(System.lineSeparator())
+ .add("
The defaults mode can be configured:")
+ .add(System.lineSeparator())
+ .add("
")
+ .add("
Directly on a client via {@code ClientOverrideConfiguration.Builder#defaultsMode"
+ + "(DefaultsMode)}.
")
+ .add(System.lineSeparator())
+ .add("
On a configuration profile via the \"defaults_mode\" profile file property.
")
+ .add(System.lineSeparator())
+ .add("
Globally via the \"aws.defaultsMode\" system property.
")
+ .add("
Globally via the \"AWS_DEFAULTS_MODE\" environment variable.
")
+ .add("")
+ .build();
+ }
+
+
+ private MethodSpec fromValueSpec() {
+ return MethodSpec.methodBuilder("fromValue")
+ .returns(className())
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .addJavadoc("Use this in place of valueOf to convert the raw string returned by the service into the " +
+ "enum value.\n\n" +
+ "@param $N real value\n" +
+ "@return $T corresponding to the value\n", VALUE, className())
+ .addParameter(String.class, VALUE)
+ .addStatement("$T.paramNotNull(value, $S)", Validate.class, VALUE)
+ .beginControlFlow("if (!VALUE_MAP.containsKey(value))")
+ .addStatement("throw new IllegalArgumentException($S + value)", "The provided value is not a"
+ + " valid "
+ + "defaults mode ")
+ .endControlFlow()
+ .addStatement("return $N.get($N)", VALUE_MAP, VALUE)
+ .build();
+ }
+
+ private MethodSpec createConstructor() {
+ return MethodSpec.constructorBuilder()
+ .addModifiers(Modifier.PRIVATE)
+ .addParameter(String.class, VALUE)
+ .addStatement("this.$1N = $1N", VALUE)
+ .build();
+ }
+
+ private static MethodSpec.Builder toStringBuilder() {
+ return MethodSpec.methodBuilder("toString")
+ .returns(String.class)
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class);
+ }
+
+}
diff --git a/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/defaultsmode/DefaultsModeGenerationTest.java b/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/defaultsmode/DefaultsModeGenerationTest.java
new file mode 100644
index 000000000000..5a753db0af1d
--- /dev/null
+++ b/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/defaultsmode/DefaultsModeGenerationTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package software.amazon.awssdk.codegen.lite.defaultsmode;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.lite.PoetMatchers.generatesTo;
+
+import java.io.File;
+import java.nio.file.Paths;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DefaultsModeGenerationTest {
+
+ private static final String DEFAULT_CONFIGURATION = "/software/amazon/awssdk/codegen/lite/test-sdk-default-configuration.json";
+ private static final String DEFAULTS_MODE_BASE = "software.amazon.awssdk.defaultsmode";
+
+ private File file;
+ private DefaultConfiguration defaultConfiguration;
+
+ @Before
+ public void before() throws Exception {
+ this.file = Paths.get(getClass().getResource(DEFAULT_CONFIGURATION).toURI()).toFile();
+ this.defaultConfiguration = DefaultsLoader.load(file);
+ }
+
+ @Test
+ public void defaultsModeEnum() {
+ DefaultsModeGenerator generator = new DefaultsModeGenerator(DEFAULTS_MODE_BASE, defaultConfiguration);
+ assertThat(generator, generatesTo("defaults-mode.java"));
+ }
+
+}
diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/defaultsmode/defaults-mode.java b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/defaultsmode/defaults-mode.java
new file mode 100644
index 000000000000..0d78d3a2fd2f
--- /dev/null
+++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/defaultsmode/defaults-mode.java
@@ -0,0 +1,95 @@
+package software.amazon.awssdk.defaultsmode;
+
+import java.util.Map;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkPublicApi;
+import software.amazon.awssdk.utils.Validate;
+import software.amazon.awssdk.utils.internal.EnumUtils;
+
+/**
+ * A defaults mode determines how certain default configuration options are resolved in the SDK. Based on the provided
+ * mode, the SDK will vend sensible default values tailored to the mode for the following settings:
+ *
+ *
retryMode: PLACEHOLDER
+ *
s3UsEast1RegionalEndpoints: PLACEHOLDER
+ *
connectTimeoutInMillis: PLACEHOLDER
+ *
+ *
+ * All options above can be configured by users, and the overridden value will take precedence.
+ *
+ * Note: for any mode other than {@link #LEGACY}, the vended default values might change as best practices may
+ * evolve. As a result, it is encouraged to perform testing when upgrading the SDK if you are using a mode other than
+ * {@link #LEGACY}
+ *
+ * While the {@link #LEGACY} defaults mode is specific to Java, other modes are standardized across all of the AWS SDKs
+ *
+ *
+ * The defaults mode can be configured:
+ *
+ *
Directly on a client via {@code ClientOverrideConfiguration.Builder#defaultsMode(DefaultsMode)}.
+ *
On a configuration profile via the "defaults_mode" profile file property.
+ *
Globally via the "aws.defaultsMode" system property.
+ *
Globally via the "AWS_DEFAULTS_MODE" environment variable.
+ *
+ */
+@SdkPublicApi
+@Generated("software.amazon.awssdk:codegen")
+public enum DefaultsMode {
+ /**
+ * PLACEHOLDER
+ */
+ LEGACY("legacy"),
+
+ /**
+ * PLACEHOLDER
+ */
+ STANDARD("standard"),
+
+ /**
+ * PLACEHOLDER
+ */
+ MOBILE("mobile"),
+
+ /**
+ * PLACEHOLDER
+ */
+ CROSS_REGION("cross-region"),
+
+ /**
+ * PLACEHOLDER
+ */
+ IN_REGION("in-region"),
+
+ /**
+ * PLACEHOLDER
+ */
+ AUTO("auto");
+
+ private static final Map VALUE_MAP = EnumUtils.uniqueIndex(DefaultsMode.class, DefaultsMode::toString);
+
+ private final String value;
+
+ private DefaultsMode(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Use this in place of valueOf to convert the raw string returned by the service into the enum value.
+ *
+ * @param value
+ * real value
+ * @return DefaultsMode corresponding to the value
+ */
+ public static DefaultsMode fromValue(String value) {
+ Validate.paramNotNull(value, "value");
+ if (!VALUE_MAP.containsKey(value)) {
+ throw new IllegalArgumentException("The provided value is not a valid defaults mode " + value);
+ }
+ return VALUE_MAP.get(value);
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+}
diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/test-sdk-default-configuration.json b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/test-sdk-default-configuration.json
new file mode 100644
index 000000000000..5c9f0fab48b7
--- /dev/null
+++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/test-sdk-default-configuration.json
@@ -0,0 +1,64 @@
+{
+ "version": 1,
+ "base": {
+ "retryMode": "standard",
+ "stsRegionalEndpoints": "regional",
+ "s3UsEast1RegionalEndpoints": "regional",
+ "connectTimeoutInMillis": 1000,
+ "tlsNegotiationTimeoutInMillis": 1000
+ },
+ "modes": {
+ "standard": {
+ "connectTimeoutInMillis": {
+ "multiply":2
+ },
+ "tlsNegotiationTimeoutInMillis": {
+ "multiply":2
+ }
+ },
+ "in-region": {
+ "connectTimeoutInMillis": {
+ "multiply": 1
+ },
+ "tlsNegotiationTimeoutInMillis": {
+ "multiply": 1
+ }
+ },
+ "cross-region": {
+ "connectTimeoutInMillis": {
+ "multiply": 2.8
+ },
+ "tlsNegotiationTimeoutInMillis": {
+ "multiply": 2.8
+ }
+ },
+ "mobile": {
+ "connectTimeoutInMillis": {
+ "override": 10000
+ },
+ "tlsNegotiationTimeoutInMillis": {
+ "add": 10000
+ },
+ "retryMode": {
+ "override": "adaptive"
+ }
+ }
+ },
+ "documentation": {
+ "modes": {
+ "standard": "PLACEHOLDER",
+ "in-region": "PLACEHOLDER",
+ "cross-region": "PLACEHOLDER",
+ "mobile": "PLACEHOLDER",
+ "auto": "PLACEHOLDER",
+ "legacy": "PLACEHOLDER"
+ },
+ "configuration": {
+ "retryMode": "PLACEHOLDER",
+ "stsRegionalEndpoints": "PLACEHOLDER",
+ "s3UsEast1RegionalEndpoints": "PLACEHOLDER",
+ "connectTimeoutInMillis": "PLACEHOLDER",
+ "tlsNegotiationTimeoutInMillis": "PLACEHOLDER"
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java
index 88b0328871b9..6faf0cad42f2 100644
--- a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java
+++ b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java
@@ -99,6 +99,13 @@ public final class ProfileProperty {
*/
public static final String RETRY_MODE = "retry_mode";
+ /**
+ * The "defaults mode" to be used for clients created using the currently-configured profile. Defaults mode determins how SDK
+ * default configuration should be resolved. See the {@code DefaultsMode} class JavaDoc for more
+ * information.
+ */
+ public static final String DEFAULTS_MODE = "defaults_mode";
+
/**
* Aws region where the SSO directory for the given 'sso_start_url' is hosted. This is independent of the general 'region'.
*/
diff --git a/core/sdk-core/pom.xml b/core/sdk-core/pom.xml
index 3f59dc6a2e1a..204b49d4213d 100644
--- a/core/sdk-core/pom.xml
+++ b/core/sdk-core/pom.xml
@@ -238,6 +238,19 @@
+
+ software.amazon.awssdk
+ codegen-lite-maven-plugin
+ ${awsjavasdk.version}
+
+
+ generate-sources
+
+ generate-defaults-mode
+
+
+
+
diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java
index 8fe7845d2f71..be9ba3629161 100644
--- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java
+++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java
@@ -19,6 +19,7 @@
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.core.retry.RetryMode;
import software.amazon.awssdk.core.retry.RetryPolicy;
+import software.amazon.awssdk.defaultsmode.DefaultsMode;
import software.amazon.awssdk.utils.SystemSetting;
/**
@@ -168,6 +169,12 @@ public enum SdkSystemSetting implements SystemSetting {
*/
AWS_MAX_ATTEMPTS("aws.maxAttempts", null),
+ /**
+ * Which {@link DefaultsMode} to use, case insensitive
+ * @see DefaultsMode
+ */
+ AWS_DEFAULTS_MODE("aws.defaultsMode", null),
+
;
private final String systemProperty;
diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java
index 81b99d999667..4a57d3885456 100644
--- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java
+++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java
@@ -31,6 +31,7 @@
import software.amazon.awssdk.core.retry.RetryMode;
import software.amazon.awssdk.core.retry.RetryPolicy;
import software.amazon.awssdk.core.sync.ResponseTransformer;
+import software.amazon.awssdk.defaultsmode.DefaultsMode;
import software.amazon.awssdk.metrics.MetricPublisher;
import software.amazon.awssdk.profiles.ProfileFile;
import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
@@ -60,6 +61,7 @@ public final class ClientOverrideConfiguration
private final String defaultProfileName;
private final List metricPublishers;
private final ExecutionAttributes executionAttributes;
+ private final DefaultsMode defaultsMode;
/**
* Initialize this configuration. Private to require use of {@link #builder()}.
@@ -75,6 +77,7 @@ private ClientOverrideConfiguration(Builder builder) {
this.defaultProfileName = builder.defaultProfileName();
this.metricPublishers = Collections.unmodifiableList(new ArrayList<>(builder.metricPublishers()));
this.executionAttributes = ExecutionAttributes.unmodifiableExecutionAttributes(builder.executionAttributes());
+ this.defaultsMode = builder.defaultsMode();
}
@Override
@@ -201,6 +204,15 @@ public List metricPublishers() {
return metricPublishers;
}
+ /**
+ * The optional defaults mode that should be used to determine the default configuration
+ * @return the optional defaults mode
+ * @see Builder#defaultsMode(DefaultsMode)
+ */
+ public Optional defaultsMode() {
+ return Optional.of(defaultsMode);
+ }
+
/**
* Returns the additional execution attributes to be added for this client.
*
@@ -469,6 +481,16 @@ default Builder retryPolicy(RetryMode retryMode) {
Builder putExecutionAttribute(ExecutionAttribute attribute, T value);
ExecutionAttributes executionAttributes();
+
+ /**
+ * Sets the defaults mode that will be used to determine the default configuration
+ * @param defaultsMode the defaultsMode to use
+ * @return This object for method chaining.
+ * @see DefaultsMode
+ */
+ Builder defaultsMode(DefaultsMode defaultsMode);
+
+ DefaultsMode defaultsMode();
}
/**
@@ -485,6 +507,7 @@ private static final class DefaultClientOverrideConfigurationBuilder implements
private String defaultProfileName;
private List metricPublishers = new ArrayList<>();
private ExecutionAttributes.Builder executionAttributesBuilder = ExecutionAttributes.builder();
+ private DefaultsMode defaultsMode;
@Override
public Builder headers(Map> headers) {
@@ -667,6 +690,21 @@ public ExecutionAttributes executionAttributes() {
return executionAttributesBuilder.build();
}
+ @Override
+ public Builder defaultsMode(DefaultsMode mode) {
+ this.defaultsMode = mode;
+ return this;
+ }
+
+ @Override
+ public DefaultsMode defaultsMode() {
+ return defaultsMode;
+ }
+
+ public void setDefaultsMode(DefaultsMode mode) {
+ defaultsMode(mode);
+ }
+
@Override
public ClientOverrideConfiguration build() {
return new ClientOverrideConfiguration(this);
diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/defaultsmode/DefaultsModeResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/defaultsmode/DefaultsModeResolver.java
new file mode 100644
index 000000000000..f0a71f5df37d
--- /dev/null
+++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/defaultsmode/DefaultsModeResolver.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.core.internal.defaultsmode;
+
+import java.util.Locale;
+import java.util.Optional;
+import java.util.function.Supplier;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.core.SdkSystemSetting;
+import software.amazon.awssdk.core.retry.RetryMode;
+import software.amazon.awssdk.defaultsmode.DefaultsMode;
+import software.amazon.awssdk.profiles.ProfileFile;
+import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
+import software.amazon.awssdk.profiles.ProfileProperty;
+import software.amazon.awssdk.utils.OptionalUtils;
+
+/**
+ * Allows customizing the variables used during determination of a {@link DefaultsMode}. Created via {@link #create()}.
+ */
+@SdkInternalApi
+public final class DefaultsModeResolver {
+
+ private static final DefaultsMode SDK_DEFAULT_DEFAULTS_MODE = DefaultsMode.LEGACY;
+ private Supplier profileFile;
+ private String profileName;
+ private DefaultsMode mode;
+
+ private DefaultsModeResolver() {
+ }
+
+ public static DefaultsModeResolver create() {
+ return new DefaultsModeResolver();
+ }
+
+ /**
+ * Configure the profile file that should be used when determining the {@link RetryMode}. The supplier is only consulted
+ * if a higher-priority determinant (e.g. environment variables) does not find the setting.
+ */
+ public DefaultsModeResolver profileFile(Supplier profileFile) {
+ this.profileFile = profileFile;
+ return this;
+ }
+
+ /**
+ * Configure the profile file name should be used when determining the {@link RetryMode}.
+ */
+ public DefaultsModeResolver profileName(String profileName) {
+ this.profileName = profileName;
+ return this;
+ }
+
+ /**
+ * Configure the {@link DefaultsMode} that should be used if the mode is not specified anywhere else.
+ */
+ public DefaultsModeResolver defaultMode(DefaultsMode mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ /**
+ * Resolve which defaults mode should be used, based on the configured values.
+ */
+ public DefaultsMode resolve() {
+ return OptionalUtils.firstPresent(DefaultsModeResolver.fromSystemSettings(), () -> fromProfileFile(profileFile,
+ profileName))
+ .orElseGet(this::fromDefaultMode);
+ }
+
+ private static Optional fromSystemSettings() {
+ return SdkSystemSetting.AWS_DEFAULTS_MODE.getStringValue()
+ .map(value -> DefaultsMode.fromValue(value.toLowerCase(Locale.US)));
+ }
+
+ private static Optional fromProfileFile(Supplier profileFile, String profileName) {
+ profileFile = profileFile != null ? profileFile : ProfileFile::defaultProfileFile;
+ profileName = profileName != null ? profileName : ProfileFileSystemSetting.AWS_PROFILE.getStringValueOrThrow();
+ return profileFile.get()
+ .profile(profileName)
+ .flatMap(p -> p.property(ProfileProperty.DEFAULTS_MODE))
+ .map(value -> DefaultsMode.fromValue(value.toLowerCase(Locale.US)));
+ }
+
+ private DefaultsMode fromDefaultMode() {
+ return mode != null ? mode : SDK_DEFAULT_DEFAULTS_MODE;
+ }
+}
diff --git a/core/sdk-core/src/main/resources/software/amazon/awssdk/internal/defaults/sdk-default-configuration.json b/core/sdk-core/src/main/resources/software/amazon/awssdk/internal/defaults/sdk-default-configuration.json
new file mode 100644
index 000000000000..e99d2b038098
--- /dev/null
+++ b/core/sdk-core/src/main/resources/software/amazon/awssdk/internal/defaults/sdk-default-configuration.json
@@ -0,0 +1,53 @@
+{
+ "version": 1,
+ "base": {
+ "retryMode": "standard",
+ "stsRegionalEndpoints": "regional",
+ "s3UsEast1RegionalEndpoints": "regional",
+ "connectTimeoutInMillis": 1100,
+ "tlsNegotiationTimeoutInMillis": 1100
+ },
+ "modes": {
+ "standard": {
+ "connectTimeoutInMillis": {
+ "override": 3100
+ },
+ "tlsNegotiationTimeoutInMillis": {
+ "override": 3100
+ }
+ },
+ "in-region": {
+ "connectTimeoutInMillis": {
+ "multiply": 1
+ },
+ "tlsNegotiationTimeoutInMillis": {
+ "multiply": 1
+ }
+ },
+ "cross-region": {
+ "connectTimeoutInMillis": {
+ "override": 3100
+ },
+ "tlsNegotiationTimeoutInMillis": {
+ "override": 3100
+ }
+ }
+ },
+ "documentation": {
+ "modes": {
+ "standard": "PLACEHOLDER",
+ "in-region": "PLACEHOLDER",
+ "cross-region": "PLACEHOLDER",
+ "mobile": "PLACEHOLDER",
+ "auto": "PLACEHOLDER",
+ "legacy": "PLACEHOLDER"
+ },
+ "configuration": {
+ "retryMode": "PLACEHOLDER",
+ "stsRegionalEndpoints": "PLACEHOLDER",
+ "s3UsEast1RegionalEndpoints": "PLACEHOLDER",
+ "connectTimeoutInMillis": "PLACEHOLDER",
+ "tlsNegotiationTimeoutInMillis": "PLACEHOLDER"
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/defaultsmode/DefaultsModeTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/defaultsmode/DefaultsModeTest.java
new file mode 100644
index 000000000000..60e1538c83f9
--- /dev/null
+++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/defaultsmode/DefaultsModeTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package software.amazon.awssdk.core.internal.defaultsmode;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import software.amazon.awssdk.core.SdkSystemSetting;
+import software.amazon.awssdk.defaultsmode.DefaultsMode;
+import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
+import software.amazon.awssdk.testutils.EnvironmentVariableHelper;
+import software.amazon.awssdk.utils.Validate;
+
+@RunWith(Parameterized.class)
+public class DefaultsModeTest {
+ private static final EnvironmentVariableHelper ENVIRONMENT_VARIABLE_HELPER = new EnvironmentVariableHelper();
+
+ @Parameterized.Parameter
+ public TestData testData;
+
+ @Parameterized.Parameters
+ public static Collection