Skip to content

Commit 194b2ca

Browse files
cenedhrynakidambisrinivasan
authored andcommitted
Source account Id from credentials to use in endpoint construction (aws#5119)
* Adds account ID as a built-in endpoint parameter (aws#4016) * Refactors credential identity with separate implementing classes (aws#4024) (aws#4028) * Adds accountId as a parameter to AWS credentials identity (aws#4029) * Adds accountId to STS credentials providers (aws#4040) * Adding accountId support to environment variable credential provider (aws#4327) * Adds accountId support to process credentials provider (aws#4332) * Adds account ID support for profile credentials provider sources (aws#4340) * Adds accountId endpoint mode (aws#4984) * Adding back existing endpoint files (aws#5120) * changelog (aws#5121)
1 parent d4d18c6 commit 194b2ca

File tree

77 files changed

+2032
-526
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2032
-526
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AWS SDK for Java V2",
4+
"contributor": "",
5+
"description": "Source account Id from credentials to use in endpoint construction"
6+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.codegen.model.internal;
17+
18+
import com.squareup.javapoet.CodeBlock;
19+
20+
/**
21+
* Represents a generic parameter that can be code generated, but isn't tied to a model shape
22+
*/
23+
public class LocalParameter {
24+
25+
private final String name;
26+
private final Class<?> type;
27+
private final CodeBlock documentation;
28+
29+
public LocalParameter(String name, Class<?> type, CodeBlock documentation) {
30+
this.name = name;
31+
this.type = type;
32+
this.documentation = documentation;
33+
}
34+
35+
public String name() {
36+
return name;
37+
}
38+
39+
public Class<?> type() {
40+
return type;
41+
}
42+
43+
public CodeBlock documentation() {
44+
return documentation;
45+
}
46+
}

codegen/src/main/java/software/amazon/awssdk/codegen/model/rules/endpoints/BuiltInParameter.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public enum BuiltInParameter {
2323
AWS_USE_DUAL_STACK,
2424
AWS_USE_FIPS,
2525
SDK_ENDPOINT,
26+
AWS_AUTH_ACCOUNT_ID,
27+
AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE,
2628
AWS_STS_USE_GLOBAL_ENDPOINT,
2729
AWS_S3_FORCE_PATH_STYLE,
2830
AWS_S3_ACCELERATE,
@@ -43,6 +45,10 @@ public static BuiltInParameter fromValue(String s) {
4345
return AWS_USE_FIPS;
4446
case "sdk::endpoint":
4547
return SDK_ENDPOINT;
48+
case "aws::auth::accountid":
49+
return AWS_AUTH_ACCOUNT_ID;
50+
case "aws::auth::accountidendpointmode":
51+
return AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE;
4652
case "aws::sts::useglobalendpoint":
4753
return AWS_STS_USE_GLOBAL_ENDPOINT;
4854
case "aws::s3::forcepathstyle":

codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
5454
import software.amazon.awssdk.codegen.poet.auth.scheme.ModelAuthSchemeClassesKnowledgeIndex;
5555
import software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationUtils;
56+
import software.amazon.awssdk.codegen.poet.rules.EndpointParamsKnowledgeIndex;
5657
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
5758
import software.amazon.awssdk.codegen.utils.AuthUtils;
5859
import software.amazon.awssdk.core.SdkPlugin;
@@ -87,6 +88,7 @@ public class BaseClientBuilderClass implements ClassSpec {
8788
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
8889
private final AuthSchemeSpecUtils authSchemeSpecUtils;
8990
private final ServiceClientConfigurationUtils configurationUtils;
91+
private final EndpointParamsKnowledgeIndex endpointParamsKnowledgeIndex;
9092

9193
public BaseClientBuilderClass(IntermediateModel model) {
9294
this.model = model;
@@ -96,6 +98,7 @@ public BaseClientBuilderClass(IntermediateModel model) {
9698
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
9799
this.authSchemeSpecUtils = new AuthSchemeSpecUtils(model);
98100
this.configurationUtils = new ServiceClientConfigurationUtils(model);
101+
this.endpointParamsKnowledgeIndex = EndpointParamsKnowledgeIndex.of(model);
99102
}
100103

101104
@Override
@@ -162,6 +165,8 @@ public TypeSpec poetSpec() {
162165
});
163166
}
164167

168+
endpointParamsKnowledgeIndex.accountIdEndpointModeClassMethodSpec().ifPresent(builder::addMethod);
169+
165170
if (model.getCustomizationConfig().getServiceConfig().getClassName() != null) {
166171
builder.addMethod(setServiceConfigurationMethod())
167172
.addMethod(beanStyleSetServiceConfigurationMethod());
@@ -176,8 +181,10 @@ public TypeSpec poetSpec() {
176181
addServiceHttpConfigIfNeeded(builder, model);
177182
builder.addMethod(invokePluginsMethod());
178183
builder.addMethod(internalPluginsMethod());
179-
builder.addMethod(validateClientOptionsMethod());
180184

185+
endpointParamsKnowledgeIndex.resolveAccountIdEndpointModeMethod().ifPresent(builder::addMethod);
186+
187+
builder.addMethod(validateClientOptionsMethod());
181188

182189
return builder.build();
183190
}
@@ -430,6 +437,11 @@ private MethodSpec finalizeServiceConfigurationMethod() {
430437
builder.addCode(".option($T.CLIENT_CONTEXT_PARAMS, clientContextParams.build())", SdkClientOption.class);
431438
}
432439

440+
if (endpointParamsKnowledgeIndex.hasAccountIdEndpointModeBuiltIn()) {
441+
builder.addCode(".option($T.$L, resolveAccountIdEndpointMode(config))",
442+
AwsClientOption.class, model.getNamingStrategy().getEnumValueName("accountIdEndpointMode"));
443+
}
444+
433445
builder.addCode(";\n");
434446
builder.addStatement("return builder.build()");
435447
return builder.build();

codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import software.amazon.awssdk.codegen.poet.ClassSpec;
3737
import software.amazon.awssdk.codegen.poet.PoetUtils;
3838
import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
39+
import software.amazon.awssdk.codegen.poet.rules.EndpointParamsKnowledgeIndex;
3940
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
4041
import software.amazon.awssdk.codegen.utils.AuthUtils;
4142
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
@@ -53,12 +54,15 @@ public class BaseClientBuilderInterface implements ClassSpec {
5354
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
5455
private final AuthSchemeSpecUtils authSchemeSpecUtils;
5556

57+
private final EndpointParamsKnowledgeIndex endpointParamsKnowledgeIndex;
58+
5659
public BaseClientBuilderInterface(IntermediateModel model) {
5760
this.model = model;
5861
this.basePackage = model.getMetadata().getFullClientPackageName();
5962
this.builderInterfaceName = ClassName.get(basePackage, model.getMetadata().getBaseBuilderInterface());
6063
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
6164
this.authSchemeSpecUtils = new AuthSchemeSpecUtils(model);
65+
this.endpointParamsKnowledgeIndex = EndpointParamsKnowledgeIndex.of(model);
6266
}
6367

6468
@Override
@@ -87,17 +91,16 @@ public TypeSpec poetSpec() {
8791
builder.addMethod(authSchemeProviderMethod());
8892

8993
if (hasClientContextParams()) {
90-
model.getClientContextParams().forEach((n, m) -> {
91-
builder.addMethod(clientContextParamSetter(n, m));
92-
});
94+
model.getClientContextParams().forEach((n, m) -> builder.addMethod(clientContextParamSetter(n, m)));
9395
}
9496

9597
if (hasSdkClientContextParams()) {
96-
model.getCustomizationConfig().getCustomClientContextParams().forEach((n, m) -> {
97-
builder.addMethod(clientContextParamSetter(n, m));
98-
});
98+
model.getCustomizationConfig().getCustomClientContextParams()
99+
.forEach((n, m) -> builder.addMethod(clientContextParamSetter(n, m)));
99100
}
100101

102+
endpointParamsKnowledgeIndex.accountIdEndpointModeInterfaceMethodSpec().ifPresent(builder::addMethod);
103+
101104
if (generateTokenProviderMethod()) {
102105
builder.addMethod(tokenProviderMethod());
103106
builder.addMethod(tokenIdentityProviderMethod());
@@ -185,9 +188,9 @@ private MethodSpec clientContextParamSetter(String name, ClientContextParam para
185188
TypeName type = endpointRulesSpecUtils.toJavaType(param.getType());
186189

187190
MethodSpec.Builder b = MethodSpec.methodBuilder(setterName)
188-
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
189-
.addParameter(type, setterName)
190-
.returns(TypeVariableName.get("B"));
191+
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
192+
.addParameter(type, setterName)
193+
.returns(TypeVariableName.get("B"));
191194

192195
PoetUtils.addJavadoc(b::addJavadoc, param.getDocumentation());
193196

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.codegen.poet.rules;
17+
18+
import static javax.lang.model.element.Modifier.PRIVATE;
19+
import static javax.lang.model.element.Modifier.STATIC;
20+
21+
import com.squareup.javapoet.ClassName;
22+
import com.squareup.javapoet.CodeBlock;
23+
import com.squareup.javapoet.MethodSpec;
24+
import com.squareup.javapoet.ParameterizedTypeName;
25+
import com.squareup.javapoet.TypeName;
26+
import com.squareup.javapoet.TypeVariableName;
27+
import java.util.EnumMap;
28+
import java.util.Map;
29+
import java.util.Optional;
30+
import javax.lang.model.element.Modifier;
31+
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
32+
import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode;
33+
import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver;
34+
import software.amazon.awssdk.codegen.internal.Utils;
35+
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
36+
import software.amazon.awssdk.codegen.model.internal.LocalParameter;
37+
import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter;
38+
import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel;
39+
import software.amazon.awssdk.core.SelectedAuthScheme;
40+
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
41+
import software.amazon.awssdk.core.client.config.SdkClientOption;
42+
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
43+
import software.amazon.awssdk.identity.spi.Identity;
44+
import software.amazon.awssdk.utils.CompletableFutureUtils;
45+
import software.amazon.awssdk.utils.internal.CodegenNamingUtils;
46+
47+
/**
48+
* Knowledge index to get access to endpoint parameters known to the client builder classes.
49+
*/
50+
public final class EndpointParamsKnowledgeIndex {
51+
private static final Map<BuiltInParameter, LocalParameter> BUILT_IN_PARAMS_FOR_CLIENT_BUILDER =
52+
new EnumMap<>(BuiltInParameter.class);
53+
private final IntermediateModel intermediateModel;
54+
private Map<BuiltInParameter, LocalParameter> parametersToGenerate = new EnumMap<>(BuiltInParameter.class);
55+
56+
static {
57+
BUILT_IN_PARAMS_FOR_CLIENT_BUILDER.put(
58+
BuiltInParameter.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE,
59+
new LocalParameter("accountIdEndpointMode",
60+
AccountIdEndpointMode.class,
61+
CodeBlock.of("Sets the behavior when account ID based endpoints are created. "
62+
+ "See {@link $T} for values", AccountIdEndpointMode.class)));
63+
}
64+
65+
private EndpointParamsKnowledgeIndex(IntermediateModel intermediateModel) {
66+
this.intermediateModel = intermediateModel;
67+
this.parametersToGenerate = builtInsForClientBuilder(intermediateModel.getEndpointRuleSetModel().getParameters());
68+
}
69+
70+
/**
71+
* Creates a new {@link EndpointParamsKnowledgeIndex} using the given {@code intermediateModel}..
72+
*/
73+
public static EndpointParamsKnowledgeIndex of(IntermediateModel intermediateModel) {
74+
return new EndpointParamsKnowledgeIndex(intermediateModel);
75+
}
76+
77+
public boolean hasAccountIdEndpointModeBuiltIn() {
78+
return parametersToGenerate.containsKey(BuiltInParameter.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE);
79+
}
80+
81+
public Optional<MethodSpec> accountIdEndpointModeClassMethodSpec() {
82+
if (hasAccountIdEndpointModeBuiltIn()) {
83+
return Optional.of(clientClassBuilderParamSetter(accountIdEndpointModeBuiltInParam()));
84+
}
85+
return Optional.empty();
86+
}
87+
88+
public Optional<MethodSpec> accountIdEndpointModeInterfaceMethodSpec() {
89+
if (hasAccountIdEndpointModeBuiltIn()) {
90+
return Optional.of(clientInterfaceBuilderParamSetter(accountIdEndpointModeBuiltInParam()));
91+
}
92+
return Optional.empty();
93+
}
94+
95+
private LocalParameter accountIdEndpointModeBuiltInParam() {
96+
return parametersToGenerate.get(BuiltInParameter.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE);
97+
}
98+
99+
private MethodSpec clientClassBuilderParamSetter(LocalParameter param) {
100+
String setterName = Utils.unCapitalize(CodegenNamingUtils.pascalCase(param.name()));
101+
String keyName = intermediateModel.getNamingStrategy().getEnumValueName(param.name());
102+
TypeName type = TypeName.get(param.type());
103+
104+
return MethodSpec.methodBuilder(setterName)
105+
.addModifiers(Modifier.PUBLIC)
106+
.returns(TypeVariableName.get("B"))
107+
.addParameter(type, setterName)
108+
.addStatement("clientConfiguration.option($T.$L, $L)",
109+
AwsClientOption.class, keyName, setterName)
110+
.addStatement("return thisBuilder()")
111+
.build();
112+
}
113+
114+
private MethodSpec clientInterfaceBuilderParamSetter(LocalParameter param) {
115+
String setterName = Utils.unCapitalize(CodegenNamingUtils.pascalCase(param.name()));
116+
TypeName type = TypeName.get(param.type());
117+
118+
MethodSpec.Builder b = MethodSpec.methodBuilder(setterName)
119+
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
120+
.addParameter(type, setterName)
121+
.addJavadoc(param.documentation())
122+
.returns(TypeVariableName.get("B"));
123+
124+
return b.build();
125+
}
126+
127+
public Optional<MethodSpec> resolveAccountIdEndpointModeMethod() {
128+
if (!hasAccountIdEndpointModeBuiltIn()) {
129+
return Optional.empty();
130+
}
131+
132+
String name = "accountIdEndpointMode";
133+
String keyName = intermediateModel.getNamingStrategy().getEnumValueName(name);
134+
TypeName typeName = TypeName.get(AccountIdEndpointMode.class);
135+
136+
MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveAccountIdEndpointMode")
137+
.addModifiers(PRIVATE)
138+
.addParameter(SdkClientConfiguration.class, "config")
139+
.returns(typeName);
140+
141+
builder.addStatement("$T configuredMode = config.option($T.$L)", typeName, AwsClientOption.class, keyName);
142+
143+
builder.beginControlFlow("if (configuredMode == null)");
144+
builder.addCode("configuredMode = $T.create()", AccountIdEndpointModeResolver.class);
145+
builder.addCode(".profileFile(config.option($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class);
146+
builder.addCode(".profileName(config.option($T.PROFILE_NAME))", SdkClientOption.class);
147+
builder.addCode(".defaultMode($T.PREFERRED)", typeName);
148+
builder.addStatement(".resolve()");
149+
builder.endControlFlow();
150+
151+
builder.addStatement("return configuredMode");
152+
return Optional.of(builder.build());
153+
}
154+
155+
private Map<BuiltInParameter, LocalParameter> builtInsForClientBuilder(Map<String, ParameterModel> serviceEndpointParams) {
156+
Map<BuiltInParameter, LocalParameter> actualParams = new EnumMap<>(BuiltInParameter.class);
157+
serviceEndpointParams.forEach((k, v) -> {
158+
BuiltInParameter builtInEnum = v.getBuiltInEnum();
159+
if (builtInEnum != null && BUILT_IN_PARAMS_FOR_CLIENT_BUILDER.containsKey(builtInEnum)) {
160+
actualParams.put(builtInEnum, BUILT_IN_PARAMS_FOR_CLIENT_BUILDER.get(builtInEnum));
161+
}
162+
});
163+
return actualParams;
164+
}
165+
166+
public Optional<MethodSpec> accountIdFromIdentityMethod() {
167+
if (!hasAccountIdEndpointModeBuiltIn()) {
168+
return Optional.empty();
169+
}
170+
171+
ParameterizedTypeName paramType = ParameterizedTypeName.get(ClassName.get(SelectedAuthScheme.class),
172+
TypeVariableName.get("T"));
173+
174+
MethodSpec.Builder builder = MethodSpec.methodBuilder("accountIdFromIdentity")
175+
.addModifiers(PRIVATE, STATIC)
176+
.addTypeVariable(TypeVariableName.get("T", Identity.class))
177+
.addParameter(paramType, "selectedAuthScheme")
178+
.returns(String.class);
179+
180+
builder.addStatement("$T identity = $T.joinLikeSync(selectedAuthScheme.identity())", TypeVariableName.get("T"),
181+
CompletableFutureUtils.class);
182+
builder.addStatement("$T accountId = null", String.class);
183+
builder.beginControlFlow("if (identity instanceof $T)", AwsCredentialsIdentity.class);
184+
builder.addStatement("accountId = (($T) identity).accountId().orElse(null)", AwsCredentialsIdentity.class);
185+
builder.endControlFlow();
186+
builder.addStatement("return accountId");
187+
return Optional.of(builder.build());
188+
}
189+
}

0 commit comments

Comments
 (0)