Skip to content

Commit acca0ae

Browse files
committed
Added support for endpoint variants in endpoint metadata: FIPS and DUALSTACK.
This adds the ability to resolve fips and dualstack endpoints with a "fips enabled" or "dualstack enabled" flag. E.g. ```java URI fipsEndpoint = ServiceMetadata.of(S3Client.SERVICE_METADATA_ID) .endpointFor(ServiceEndpointKey.builder() .region(Region.US_WEST_2) .tags(EndpointTag.FIPS) .build()); ``` The following public API changes were made: 1. Added `ServiceMetadata.endpointFor(ServiceEndpointKey)` 2. Added `ServiceMetadata.signingRegion(ServiceEndpointKey)` 3. Added `PartitionMetadata.hostname(PartitionEndpointKey)` 4. Added `PartitionMetadata.dnsSuffix(PartitionEndpointKey)` 5. Added a generated `EndpointTag` class, which currently contains FIPS and DUALSTACK. 6. Removed `ServiceMetadata.computeEndpoint`, because it shouldn't have ever been public, and no one should be using it. The following module changes were made: 1. Added `regions-testing` for verifying region resolution behavior that doesn't currently exist in the endpoints.json
1 parent 515e70e commit acca0ae

File tree

36 files changed

+18912
-1776
lines changed

36 files changed

+18912
-1776
lines changed

.brazil.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"protocol-tests": { "skipImport": true },
6969
"protocol-tests-core": { "skipImport": true },
7070
"protocols": { "skipImport": true },
71+
"region-testing": { "skipImport": true },
7172
"release-scripts": { "skipImport": true },
7273
"s3-benchmarks": { "skipImport": true },
7374
"sdk-benchmarks": { "skipImport": true },

buildspecs/release-to-maven.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ phases:
4040
awk 'BEGIN { var=ENVIRON["SDK_SIGNING_GPG_KEYNAME"] } { gsub("\\$SDK_SIGNING_GPG_KEYNAME", var, $0); print }' > \
4141
$SETTINGS_XML
4242
43-
mvn clean deploy -B -s $SETTINGS_XML -Ppublishing -DperformRelease -Dspotbugs.skip -DskipTests -Dcheckstyle.skip -Djapicmp.skip -Ddoclint=none -pl !:protocol-tests,!:protocol-tests-core,!:codegen-generated-classes-test,!:sdk-benchmarks,!:module-path-tests,!:tests-coverage-reporting,!:stability-tests,!:sdk-native-image-test,!:auth-sts-testing,!:s3-benchmarks -DautoReleaseAfterClose=true -DstagingProgressTimeoutMinutes=30
43+
mvn clean deploy -B -s $SETTINGS_XML -Ppublishing -DperformRelease -Dspotbugs.skip -DskipTests -Dcheckstyle.skip -Djapicmp.skip -Ddoclint=none -pl !:protocol-tests,!:protocol-tests-core,!:codegen-generated-classes-test,!:sdk-benchmarks,!:module-path-tests,!:tests-coverage-reporting,!:stability-tests,!:sdk-native-image-test,!:auth-sts-testing,!:s3-benchmarks,!:region-testing -DautoReleaseAfterClose=true -DstagingProgressTimeoutMinutes=30
4444
else
4545
echo "This version was already released."
4646
fi

codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.apache.maven.plugins.annotations.Parameter;
2727
import org.apache.maven.project.MavenProject;
2828
import software.amazon.awssdk.codegen.lite.CodeGenerator;
29+
import software.amazon.awssdk.codegen.lite.regions.EndpointTagGenerator;
2930
import software.amazon.awssdk.codegen.lite.regions.PartitionMetadataGenerator;
3031
import software.amazon.awssdk.codegen.lite.regions.PartitionMetadataProviderGenerator;
3132
import software.amazon.awssdk.codegen.lite.regions.RegionGenerator;
@@ -71,6 +72,7 @@ public void execute() throws MojoExecutionException {
7172
generatePartitionProvider(baseSourcesDirectory, partitions);
7273
generateRegionProvider(baseSourcesDirectory, partitions);
7374
generateServiceProvider(baseSourcesDirectory, partitions);
75+
generateEndpointTags(baseSourcesDirectory, partitions);
7476

7577
project.addCompileSourceRoot(baseSourcesDirectory.toFile().getAbsolutePath());
7678
project.addTestCompileSourceRoot(testsDirectory.toFile().getAbsolutePath());
@@ -138,4 +140,9 @@ public void generateServiceProvider(Path baseSourcesDirectory, Partitions partit
138140
REGION_BASE))
139141
.generate();
140142
}
143+
144+
public void generateEndpointTags(Path baseSourcesDirectory, Partitions partitions) {
145+
Path sourcesDirectory = baseSourcesDirectory.resolve(REGION_BASE.replace(".", "/"));
146+
new CodeGenerator(sourcesDirectory.toString(), new EndpointTagGenerator(partitions, REGION_BASE)).generate();
147+
}
141148
}
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
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.lite.regions;
17+
18+
import static javax.lang.model.element.Modifier.FINAL;
19+
import static javax.lang.model.element.Modifier.PRIVATE;
20+
import static javax.lang.model.element.Modifier.PUBLIC;
21+
import static javax.lang.model.element.Modifier.STATIC;
22+
23+
import com.squareup.javapoet.AnnotationSpec;
24+
import com.squareup.javapoet.ClassName;
25+
import com.squareup.javapoet.CodeBlock;
26+
import com.squareup.javapoet.FieldSpec;
27+
import com.squareup.javapoet.MethodSpec;
28+
import com.squareup.javapoet.ParameterizedTypeName;
29+
import com.squareup.javapoet.TypeName;
30+
import com.squareup.javapoet.TypeSpec;
31+
import java.util.Arrays;
32+
import java.util.Collections;
33+
import java.util.List;
34+
import java.util.Objects;
35+
import java.util.Set;
36+
import java.util.TreeSet;
37+
import java.util.concurrent.ConcurrentHashMap;
38+
import java.util.stream.Collectors;
39+
import java.util.stream.Stream;
40+
import software.amazon.awssdk.annotations.Generated;
41+
import software.amazon.awssdk.annotations.SdkPublicApi;
42+
import software.amazon.awssdk.codegen.lite.PoetClass;
43+
import software.amazon.awssdk.codegen.lite.regions.model.Endpoint;
44+
import software.amazon.awssdk.codegen.lite.regions.model.Partition;
45+
import software.amazon.awssdk.codegen.lite.regions.model.Partitions;
46+
import software.amazon.awssdk.codegen.lite.regions.model.Service;
47+
import software.amazon.awssdk.utils.StringUtils;
48+
import software.amazon.awssdk.utils.internal.CodegenNamingUtils;
49+
50+
public class EndpointTagGenerator implements PoetClass {
51+
private final Partitions partitions;
52+
private final String basePackage;
53+
54+
public EndpointTagGenerator(Partitions partitions,
55+
String basePackage) {
56+
this.partitions = partitions;
57+
this.basePackage = basePackage;
58+
}
59+
60+
@Override
61+
public TypeSpec poetClass() {
62+
TypeSpec.Builder builder = TypeSpec.classBuilder(className())
63+
.addModifiers(FINAL, PUBLIC)
64+
.addJavadoc(documentation())
65+
.addAnnotation(SdkPublicApi.class)
66+
.addAnnotation(AnnotationSpec.builder(Generated.class)
67+
.addMember("value",
68+
"$S",
69+
"software.amazon.awssdk:codegen")
70+
.build())
71+
.addMethod(MethodSpec.constructorBuilder()
72+
.addModifiers(PRIVATE)
73+
.addParameter(String.class, "id")
74+
.addStatement("this.id = id")
75+
.build());
76+
endpointTags(builder);
77+
78+
builder.addField(FieldSpec.builder(String.class, "id")
79+
.addModifiers(FINAL, PRIVATE)
80+
.build())
81+
.addMethod(tagOf())
82+
.addMethod(tagGetter())
83+
.addMethod(id())
84+
.addMethod(tagToString());
85+
86+
return builder.addType(cache()).build();
87+
}
88+
89+
private void endpointTags(TypeSpec.Builder builder) {
90+
Stream<Endpoint> endpointsFromPartitions = partitions.getPartitions().stream().map(Partition::getDefaults);
91+
Stream<Endpoint> endpointsFromServices = partitions.getPartitions().stream()
92+
.flatMap(p -> p.getServices().values().stream())
93+
.flatMap(s -> s.getEndpoints().values().stream());
94+
Stream<Endpoint> endpointsFromServiceDefaults = partitions.getPartitions().stream()
95+
.flatMap(p -> p.getServices().values().stream())
96+
.map(Service::getDefaults)
97+
.filter(Objects::nonNull);
98+
99+
Set<String> allTags =
100+
Stream.concat(endpointsFromPartitions, Stream.concat(endpointsFromServices, endpointsFromServiceDefaults))
101+
.flatMap(e -> e.getVariants().stream())
102+
.flatMap(v -> v.getTags().stream())
103+
.collect(Collectors.toCollection(TreeSet::new));
104+
105+
// Add each tag as a separate entry in the endpoint tags
106+
allTags.forEach(tag -> builder.addField(FieldSpec.builder(className(), enumValueForTagId(tag))
107+
.addModifiers(PUBLIC, STATIC, FINAL)
108+
.initializer("$T.of($S)", className(), tag)
109+
.build()));
110+
111+
String tagsCodeBlock = allTags.stream()
112+
.map(this::enumValueForTagId)
113+
.collect(Collectors.joining(", "));
114+
115+
CodeBlock initializer = CodeBlock.builder()
116+
.add("$T.unmodifiableList($T.asList(", Collections.class, Arrays.class)
117+
.add(tagsCodeBlock)
118+
.add("))")
119+
.build();
120+
121+
TypeName listOfTags = ParameterizedTypeName.get(ClassName.get(List.class), className());
122+
builder.addField(FieldSpec.builder(listOfTags, "ENDPOINT_TAGS")
123+
.addModifiers(PRIVATE, STATIC, FINAL)
124+
.initializer(initializer)
125+
.build());
126+
}
127+
128+
private String enumValueForTagId(String tag) {
129+
return Stream.of(CodegenNamingUtils.splitOnWordBoundaries(tag))
130+
.map(StringUtils::upperCase)
131+
.collect(Collectors.joining("_"));
132+
}
133+
134+
private MethodSpec tagOf() {
135+
return MethodSpec.methodBuilder("of")
136+
.addModifiers(PUBLIC, STATIC)
137+
.addParameter(String.class, "id")
138+
.returns(className())
139+
.addStatement("return EndpointTagCache.put($L)", "id")
140+
.build();
141+
142+
}
143+
144+
private MethodSpec id() {
145+
return MethodSpec.methodBuilder("id")
146+
.addModifiers(PUBLIC)
147+
.returns(String.class)
148+
.addStatement("return this.id")
149+
.build();
150+
}
151+
152+
private MethodSpec tagGetter() {
153+
return MethodSpec.methodBuilder("endpointTags")
154+
.addModifiers(PUBLIC, STATIC)
155+
.returns(ParameterizedTypeName.get(ClassName.get(List.class),
156+
className()))
157+
.addStatement("return $L", "ENDPOINT_TAGS")
158+
.build();
159+
}
160+
161+
private MethodSpec tagToString() {
162+
return MethodSpec.methodBuilder("toString")
163+
.addAnnotation(Override.class)
164+
.addModifiers(PUBLIC)
165+
.returns(String.class)
166+
.addStatement("return $L", "id")
167+
.build();
168+
}
169+
170+
private TypeSpec cache() {
171+
ParameterizedTypeName mapOfStringTags = ParameterizedTypeName.get(ClassName.get(ConcurrentHashMap.class),
172+
ClassName.get(String.class),
173+
className());
174+
175+
return TypeSpec.classBuilder("EndpointTagCache")
176+
.addModifiers(PRIVATE, STATIC)
177+
.addField(FieldSpec.builder(mapOfStringTags, "IDS")
178+
.addModifiers(PRIVATE, STATIC, FINAL)
179+
.initializer("new $T<>()", ConcurrentHashMap.class)
180+
.build())
181+
182+
.addMethod(MethodSpec.constructorBuilder().addModifiers(PRIVATE).build())
183+
.addMethod(MethodSpec.methodBuilder("put")
184+
.addModifiers(PRIVATE, STATIC)
185+
.addParameter(String.class, "id")
186+
.returns(className())
187+
.addStatement("return $L.computeIfAbsent(id, $T::new)",
188+
"IDS",
189+
className())
190+
.build())
191+
.build();
192+
}
193+
194+
private CodeBlock documentation() {
195+
return CodeBlock.builder()
196+
.add("A tag applied to endpoints to specify that they're to be used in certain contexts. For example, "
197+
+ "FIPS tags are applied to endpoints discussed here: https://aws.amazon.com/compliance/fips/ and "
198+
+ "DUALSTACK tags are applied to endpoints that can return IPv6 addresses.")
199+
.build();
200+
}
201+
202+
@Override
203+
public ClassName className() {
204+
return ClassName.get(basePackage, "EndpointTag");
205+
}
206+
}

0 commit comments

Comments
 (0)