Skip to content

Commit 8845b99

Browse files
committed
Add CopyableBuilder and ToCopyableBuilder interfaces to the credential providers.
1 parent a2bb7a4 commit 8845b99

14 files changed

+302
-47
lines changed

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/AwsCredentialsProviderChain.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import software.amazon.awssdk.utils.SdkAutoCloseable;
2828
import software.amazon.awssdk.utils.ToString;
2929
import software.amazon.awssdk.utils.Validate;
30+
import software.amazon.awssdk.utils.builder.CopyableBuilder;
31+
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
3032

3133
/**
3234
* {@link AwsCredentialsProvider} implementation that chains together multiple credentials providers.
@@ -44,7 +46,10 @@
4446
* providers in the chain that need to be closed.</p>
4547
*/
4648
@SdkPublicApi
47-
public final class AwsCredentialsProviderChain implements AwsCredentialsProvider, SdkAutoCloseable {
49+
public final class AwsCredentialsProviderChain
50+
implements AwsCredentialsProvider,
51+
SdkAutoCloseable,
52+
ToCopyableBuilder<AwsCredentialsProviderChain.Builder, AwsCredentialsProviderChain> {
4853
private static final Logger log = Logger.loggerFor(AwsCredentialsProviderChain.class);
4954

5055
private final List<AwsCredentialsProvider> credentialsProviders;
@@ -124,10 +129,15 @@ public String toString() {
124129
.build();
125130
}
126131

132+
@Override
133+
public Builder toBuilder() {
134+
return new BuilderImpl(this);
135+
}
136+
127137
/**
128138
* A builder for a {@link AwsCredentialsProviderChain} that allows controlling its behavior.
129139
*/
130-
public interface Builder {
140+
public interface Builder extends CopyableBuilder<Builder, AwsCredentialsProviderChain> {
131141

132142
/**
133143
* Controls whether the chain should reuse the last successful credentials provider in the chain. Reusing the last
@@ -163,6 +173,11 @@ private static final class BuilderImpl implements Builder {
163173
private BuilderImpl() {
164174
}
165175

176+
private BuilderImpl(AwsCredentialsProviderChain provider) {
177+
this.reuseLastProviderEnabled = provider.reuseLastProviderEnabled;
178+
this.credentialsProviders = provider.credentialsProviders;
179+
}
180+
166181
@Override
167182
public Builder reuseLastProviderEnabled(Boolean reuseLastProviderEnabled) {
168183
this.reuseLastProviderEnabled = reuseLastProviderEnabled;

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsProvider.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import software.amazon.awssdk.utils.StringUtils;
4040
import software.amazon.awssdk.utils.ToString;
4141
import software.amazon.awssdk.utils.Validate;
42+
import software.amazon.awssdk.utils.builder.CopyableBuilder;
43+
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
4244
import software.amazon.awssdk.utils.cache.CachedSupplier;
4345
import software.amazon.awssdk.utils.cache.NonBlocking;
4446
import software.amazon.awssdk.utils.cache.RefreshResult;
@@ -60,18 +62,26 @@
6062
* Service (ECS)</a>
6163
*/
6264
@SdkPublicApi
63-
public final class ContainerCredentialsProvider implements HttpCredentialsProvider {
65+
public final class ContainerCredentialsProvider
66+
implements HttpCredentialsProvider,
67+
ToCopyableBuilder<ContainerCredentialsProvider.Builder, ContainerCredentialsProvider> {
6468
private static final Set<String> ALLOWED_HOSTS = unmodifiableSet(new HashSet<>(Arrays.asList("localhost", "127.0.0.1")));
6569

6670
private final String endpoint;
6771
private final HttpCredentialsLoader httpCredentialsLoader;
6872
private final CachedSupplier<AwsCredentials> credentialsCache;
6973

74+
private final Boolean asyncCredentialUpdateEnabled;
75+
76+
private final String asyncThreadName;
77+
7078
/**
7179
* @see #builder()
7280
*/
7381
private ContainerCredentialsProvider(BuilderImpl builder) {
7482
this.endpoint = builder.endpoint;
83+
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
84+
this.asyncThreadName = builder.asyncThreadName;
7585
this.httpCredentialsLoader = HttpCredentialsLoader.create();
7686

7787
if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
@@ -137,6 +147,11 @@ public void close() {
137147
credentialsCache.close();
138148
}
139149

150+
@Override
151+
public Builder toBuilder() {
152+
return new BuilderImpl(this);
153+
}
154+
140155
static final class ContainerCredentialsEndpointProvider implements ResourcesEndpointProvider {
141156
private final String endpoint;
142157

@@ -209,18 +224,25 @@ private URI createGenericContainerUrl() {
209224
/**
210225
* A builder for creating a custom a {@link ContainerCredentialsProvider}.
211226
*/
212-
public interface Builder extends HttpCredentialsProvider.Builder<ContainerCredentialsProvider, Builder> {
227+
public interface Builder extends HttpCredentialsProvider.Builder<ContainerCredentialsProvider, Builder>,
228+
CopyableBuilder<Builder, ContainerCredentialsProvider> {
213229
}
214230

215231
private static final class BuilderImpl implements Builder {
216232
private String endpoint;
217233
private Boolean asyncCredentialUpdateEnabled;
218234
private String asyncThreadName;
219235

220-
BuilderImpl() {
236+
private BuilderImpl() {
221237
asyncThreadName("container-credentials-provider");
222238
}
223239

240+
private BuilderImpl(ContainerCredentialsProvider credentialsProvider) {
241+
this.endpoint = credentialsProvider.endpoint;
242+
this.asyncCredentialUpdateEnabled = credentialsProvider.asyncCredentialUpdateEnabled;
243+
this.asyncThreadName = credentialsProvider.asyncThreadName;
244+
}
245+
224246
@Override
225247
public Builder endpoint(String endpoint) {
226248
this.endpoint = endpoint;

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import software.amazon.awssdk.profiles.ProfileFile;
2121
import software.amazon.awssdk.utils.SdkAutoCloseable;
2222
import software.amazon.awssdk.utils.ToString;
23+
import software.amazon.awssdk.utils.builder.CopyableBuilder;
24+
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
2325

2426
/**
2527
* AWS credentials provider chain that looks for credentials in this order:
@@ -41,16 +43,30 @@
4143
* @see InstanceProfileCredentialsProvider
4244
*/
4345
@SdkPublicApi
44-
public final class DefaultCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable {
46+
public final class DefaultCredentialsProvider
47+
implements AwsCredentialsProvider, SdkAutoCloseable,
48+
ToCopyableBuilder<DefaultCredentialsProvider.Builder, DefaultCredentialsProvider> {
4549

4650
private static final DefaultCredentialsProvider DEFAULT_CREDENTIALS_PROVIDER = new DefaultCredentialsProvider(builder());
4751

4852
private final LazyAwsCredentialsProvider providerChain;
4953

54+
private final ProfileFile profileFile;
55+
56+
private final String profileName;
57+
58+
private final Boolean reuseLastProviderEnabled;
59+
60+
private final Boolean asyncCredentialUpdateEnabled;
61+
5062
/**
5163
* @see #builder()
5264
*/
5365
private DefaultCredentialsProvider(Builder builder) {
66+
this.profileFile = builder.profileFile;
67+
this.profileName = builder.profileName;
68+
this.reuseLastProviderEnabled = builder.reuseLastProviderEnabled;
69+
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
5470
this.providerChain = createChain(builder);
5571
}
5672

@@ -119,10 +135,15 @@ public String toString() {
119135
.build();
120136
}
121137

138+
@Override
139+
public Builder toBuilder() {
140+
return new Builder(this);
141+
}
142+
122143
/**
123144
* Configuration that defines the {@link DefaultCredentialsProvider}'s behavior.
124145
*/
125-
public static final class Builder {
146+
public static final class Builder implements CopyableBuilder<Builder, DefaultCredentialsProvider> {
126147
private ProfileFile profileFile;
127148
private String profileName;
128149
private Boolean reuseLastProviderEnabled = true;
@@ -134,6 +155,13 @@ public static final class Builder {
134155
private Builder() {
135156
}
136157

158+
private Builder(DefaultCredentialsProvider credentialsProvider) {
159+
this.profileFile = credentialsProvider.profileFile;
160+
this.profileName = credentialsProvider.profileName;
161+
this.reuseLastProviderEnabled = credentialsProvider.reuseLastProviderEnabled;
162+
this.asyncCredentialUpdateEnabled = credentialsProvider.asyncCredentialUpdateEnabled;
163+
}
164+
137165
public Builder profileFile(ProfileFile profileFile) {
138166
this.profileFile = profileFile;
139167
return this;

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProvider.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
import software.amazon.awssdk.utils.Logger;
4343
import software.amazon.awssdk.utils.ToString;
4444
import software.amazon.awssdk.utils.Validate;
45+
import software.amazon.awssdk.utils.builder.CopyableBuilder;
46+
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
4547
import software.amazon.awssdk.utils.cache.CachedSupplier;
4648
import software.amazon.awssdk.utils.cache.NonBlocking;
4749
import software.amazon.awssdk.utils.cache.RefreshResult;
@@ -54,7 +56,9 @@
5456
* credentials from EC2 metadata service and will return null.
5557
*/
5658
@SdkPublicApi
57-
public final class InstanceProfileCredentialsProvider implements HttpCredentialsProvider {
59+
public final class InstanceProfileCredentialsProvider
60+
implements HttpCredentialsProvider,
61+
ToCopyableBuilder<InstanceProfileCredentialsProvider.Builder, InstanceProfileCredentialsProvider> {
5862
private static final Logger log = Logger.loggerFor(InstanceProfileCredentialsProvider.class);
5963
private static final String EC2_METADATA_TOKEN_HEADER = "x-aws-ec2-metadata-token";
6064

@@ -69,6 +73,14 @@ public final class InstanceProfileCredentialsProvider implements HttpCredentials
6973
private final HttpCredentialsLoader httpCredentialsLoader;
7074
private final CachedSupplier<AwsCredentials> credentialsCache;
7175

76+
private final Boolean asyncCredentialUpdateEnabled;
77+
78+
private final String asyncThreadName;
79+
80+
private final ProfileFile profileFile;
81+
82+
private final String profileName;
83+
7284
private volatile LoadedCredentials cachedCredentials;
7385

7486
/**
@@ -77,6 +89,11 @@ public final class InstanceProfileCredentialsProvider implements HttpCredentials
7789
private InstanceProfileCredentialsProvider(BuilderImpl builder) {
7890
this.clock = builder.clock;
7991
this.endpoint = builder.endpoint;
92+
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
93+
this.asyncThreadName = builder.asyncThreadName;
94+
this.profileFile = builder.profileFile;
95+
this.profileName = builder.profileName;
96+
8097
this.httpCredentialsLoader = HttpCredentialsLoader.create();
8198
this.configProvider =
8299
Ec2MetadataConfigProvider.builder()
@@ -275,10 +292,16 @@ private Map<String, String> getTokenHeaders(String metadataToken) {
275292
return Collections.singletonMap(EC2_METADATA_TOKEN_HEADER, metadataToken);
276293
}
277294

295+
@Override
296+
public Builder toBuilder() {
297+
return new BuilderImpl(this);
298+
}
299+
278300
/**
279301
* A builder for creating a custom a {@link InstanceProfileCredentialsProvider}.
280302
*/
281-
public interface Builder extends HttpCredentialsProvider.Builder<InstanceProfileCredentialsProvider, Builder> {
303+
public interface Builder extends HttpCredentialsProvider.Builder<InstanceProfileCredentialsProvider, Builder>,
304+
CopyableBuilder<Builder, InstanceProfileCredentialsProvider> {
282305
/**
283306
* Configure the profile file used for loading IMDS-related configuration, like the endpoint mode (IPv4 vs IPv6).
284307
*
@@ -312,6 +335,15 @@ private BuilderImpl() {
312335
asyncThreadName("instance-profile-credentials-provider");
313336
}
314337

338+
private BuilderImpl(InstanceProfileCredentialsProvider provider) {
339+
this.clock = provider.clock;
340+
this.endpoint = provider.endpoint;
341+
this.asyncCredentialUpdateEnabled = provider.asyncCredentialUpdateEnabled;
342+
this.asyncThreadName = provider.asyncThreadName;
343+
this.profileFile = provider.profileFile;
344+
this.profileName = provider.profileName;
345+
}
346+
315347
Builder clock(Clock clock) {
316348
this.clock = clock;
317349
return this;

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/ProcessCredentialsProvider.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import software.amazon.awssdk.utils.Platform;
3232
import software.amazon.awssdk.utils.SdkAutoCloseable;
3333
import software.amazon.awssdk.utils.Validate;
34+
import software.amazon.awssdk.utils.builder.CopyableBuilder;
35+
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
3436
import software.amazon.awssdk.utils.cache.CachedSupplier;
3537
import software.amazon.awssdk.utils.cache.NonBlocking;
3638
import software.amazon.awssdk.utils.cache.RefreshResult;
@@ -54,17 +56,24 @@
5456
* </ul>
5557
*/
5658
@SdkPublicApi
57-
public final class ProcessCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable {
59+
public final class ProcessCredentialsProvider
60+
implements AwsCredentialsProvider,
61+
SdkAutoCloseable,
62+
ToCopyableBuilder<ProcessCredentialsProvider.Builder, ProcessCredentialsProvider> {
5863
private static final JsonNodeParser PARSER = JsonNodeParser.builder()
5964
.removeErrorLocations(true)
6065
.build();
6166

62-
private final List<String> command;
67+
private final List<String> executableCommand;
6368
private final Duration credentialRefreshThreshold;
6469
private final long processOutputLimit;
6570

6671
private final CachedSupplier<AwsCredentials> processCredentialCache;
6772

73+
private final String commandFromBuilder;
74+
75+
private final Boolean asyncCredentialUpdateEnabled;
76+
6877
/**
6978
* @see #builder()
7079
*/
@@ -83,9 +92,11 @@ private ProcessCredentialsProvider(Builder builder) {
8392

8493
cmd.add(builderCommand);
8594

86-
this.command = Collections.unmodifiableList(cmd);
95+
this.executableCommand = Collections.unmodifiableList(cmd);
8796
this.processOutputLimit = Validate.isPositive(builder.processOutputLimit, "processOutputLimit");
8897
this.credentialRefreshThreshold = Validate.isPositive(builder.credentialRefreshThreshold, "expirationBuffer");
98+
this.commandFromBuilder = builder.command;
99+
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
89100

90101
CachedSupplier.Builder<AwsCredentials> cacheBuilder = CachedSupplier.builder(this::refreshCredentials);
91102
if (builder.asyncCredentialUpdateEnabled) {
@@ -185,7 +196,7 @@ private String getText(JsonNode jsonObject, String nodeName) {
185196
* Execute the external process to retrieve credentials.
186197
*/
187198
private String executeCommand() throws IOException, InterruptedException {
188-
ProcessBuilder processBuilder = new ProcessBuilder(command);
199+
ProcessBuilder processBuilder = new ProcessBuilder(executableCommand);
189200

190201
ByteArrayOutputStream commandOutput = new ByteArrayOutputStream();
191202

@@ -210,10 +221,15 @@ public void close() {
210221
processCredentialCache.close();
211222
}
212223

224+
@Override
225+
public Builder toBuilder() {
226+
return new Builder(this);
227+
}
228+
213229
/**
214230
* Used to configure and create a {@link ProcessCredentialsProvider}. See {@link #builder()} creation.
215231
*/
216-
public static class Builder {
232+
public static class Builder implements CopyableBuilder<Builder, ProcessCredentialsProvider> {
217233
private Boolean asyncCredentialUpdateEnabled = false;
218234
private String command;
219235
private Duration credentialRefreshThreshold = Duration.ofSeconds(15);
@@ -225,6 +241,13 @@ public static class Builder {
225241
private Builder() {
226242
}
227243

244+
private Builder(ProcessCredentialsProvider provider) {
245+
this.asyncCredentialUpdateEnabled = provider.asyncCredentialUpdateEnabled;
246+
this.command = provider.commandFromBuilder;
247+
this.credentialRefreshThreshold = provider.credentialRefreshThreshold;
248+
this.processOutputLimit = provider.processOutputLimit;
249+
}
250+
228251
/**
229252
* Configure whether the provider should fetch credentials asynchronously in the background. If this is true, threads are
230253
* less likely to block when credentials are loaded, but additional resources are used to maintain the provider.

0 commit comments

Comments
 (0)