diff --git a/.changes/next-release/feature-AWSSDKforJavav2-460eec0.json b/.changes/next-release/feature-AWSSDKforJavav2-460eec0.json new file mode 100644 index 000000000000..1be8dae06e1b --- /dev/null +++ b/.changes/next-release/feature-AWSSDKforJavav2-460eec0.json @@ -0,0 +1,6 @@ +{ + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Enable compiled endpoint rules for all services by default, with a fix for region parameter handling in the generated endpoint providers." +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java index d15ef90cd2e1..ab3c3f78833d 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java @@ -315,9 +315,9 @@ public class CustomizationConfig { private boolean s3ExpressAuthSupport; /** - * Set to true to enable compiled endpoint rules. Currently defaults to false. + * Set to true to enable compiled endpoint rules. Defaults to true. */ - private boolean enableGenerateCompiledEndpointRules = false; + private boolean enableGenerateCompiledEndpointRules = true; /** * Customization related to auth scheme derived from endpoints. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java index 86af5542e886..9599b90732fa 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java @@ -147,6 +147,13 @@ private void addAccessorMethods(TypeSpec.Builder b) { .addJavadoc("Returns the region. The region parameter may be used with the $S auth scheme.", AwsV4AuthScheme.SCHEME_ID) .build()); + b.addMethod(MethodSpec.methodBuilder("regionId") + .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT) + .returns(String.class) + .addJavadoc("Returns the region ID as a string. Returns null if region is not set.") + .addStatement("$T region = region()", Region.class) + .addStatement("return region == null ? null : region.id()") + .build()); } if (authSchemeSpecUtils.hasSigV4aSupport()) { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java index 28b62024a00d..cb8e31dd3aaf 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java @@ -187,6 +187,13 @@ private void addFieldsAndAccessors(TypeSpec.Builder b) { .returns(Region.class) .addStatement("return region") .build()); + + b.addMethod(MethodSpec.methodBuilder("regionId") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(String.class) + .addStatement("return region == null ? null : region.id()") + .build()); } if (authSchemeSpecUtils.hasSigV4aSupport()) { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java index eebe516b02d2..10e51bd7d18e 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java @@ -25,9 +25,11 @@ import javax.lang.model.element.Modifier; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter; import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetUtils; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.utils.builder.CopyableBuilder; import software.amazon.awssdk.utils.builder.ToCopyableBuilder; @@ -56,6 +58,9 @@ public TypeSpec poetSpec() { parameters().forEach((name, model) -> { b.addField(endpointRulesSpecUtils.parameterClassField(name, model)); b.addMethod(endpointRulesSpecUtils.parameterClassAccessorMethod(name, model)); + if (model.getBuiltInEnum() == BuiltInParameter.AWS_REGION) { + b.addMethod(regionIdAccessorMethod(name)); + } }); b.addMethod(toBuilderMethod()); @@ -156,6 +161,22 @@ private String variableName(String name) { return intermediateModel.getNamingStrategy().getVariableName(name); } + /** + * Creates a convenience accessor for Region-typed parameters that returns the region ID as a String. + */ + private MethodSpec regionIdAccessorMethod(String name) { + String varName = variableName(name); + String methodName = endpointRulesSpecUtils.paramMethodName(name) + "Id"; + return MethodSpec.methodBuilder(methodName) + .addModifiers(Modifier.PUBLIC) + .addJavadoc("Returns the region ID (the {@link $T#id()} value) as a String," + + " or null if region is not set.", + Region.class) + .returns(String.class) + .addStatement("return $N == null ? null : $N.id()", varName, varName) + .build(); + } + private MethodSpec.Builder toBuilderConstructor() { MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder(); constructorBuilder.addModifiers(Modifier.PRIVATE); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java index 04cc97420d5e..dd830de36aaa 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java @@ -253,6 +253,10 @@ public List rulesEngineResourceFiles() { } public List rulesEngineFilesFromDirectory(URL location) { + return rulesEngineFilesFromDirectory(location, RULES_ENGINE_RESOURCE_FILES_PREFIX); + } + + public List rulesEngineFilesFromDirectory(URL location, String prefix) { URI locationUri; try { locationUri = location.toURI(); @@ -268,7 +272,7 @@ public List rulesEngineFilesFromDirectory(URL location) { return Files.walk(directory) // Remove the root directory if the classes, paths are expected to be relative to this directory .map(f -> directory.relativize(f).toString()) - .filter(f -> f.startsWith(RULES_ENGINE_RESOURCE_FILES_PREFIX)) + .filter(f -> f.startsWith(prefix)) .collect(Collectors.toList()); } catch (IOException e) { throw new UncheckedIOException(e); @@ -277,6 +281,12 @@ public List rulesEngineFilesFromDirectory(URL location) { public List rulesEngineResourceFiles2() { URL currentJarUrl = EndpointRulesSpecUtils.class.getProtectionDomain().getCodeSource().getLocation(); + + // This would happen if the classes aren't loaded from a JAR, e.g. when unit testing + if (!currentJarUrl.toString().endsWith(".jar")) { + return rulesEngineFilesFromDirectory(currentJarUrl, "software/amazon/awssdk/codegen/rules2/"); + } + try (JarFile jarFile = new JarFile(currentJarUrl.getFile())) { return jarFile.stream() .map(ZipEntry::getName) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java index 6488f015ad7b..ea62782741cd 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java @@ -64,10 +64,6 @@ public RuleSetExpression root() { return root; } - public String regionParamName() { - return symbolTable.regionParamName(); - } - public SymbolTable symbolTable() { return symbolTable; } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java index 831b8d88af83..3e4818207ea2 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java @@ -40,7 +40,6 @@ import software.amazon.awssdk.codegen.poet.PoetUtils; import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; @@ -94,11 +93,7 @@ private static SymbolTable initSymbolTable(Map parameter parameters.forEach((k, v) -> { builder.putParam(k, fromParameterModel(v)); if (v.getBuiltInEnum() == BuiltInParameter.AWS_REGION) { - // Region is a special case since it's already public API and uses an actual `Region` instance instead of - // `String`. We then introduce here a local with the same name but with String type such that we don't have - // to do the conversion everywhere a string represented region is used. - builder.regionParamName(k); - builder.putLocal(k, RuleRuntimeTypeMirror.STRING); + builder.addRegionParam(k); } }); return builder.build(); @@ -150,14 +145,7 @@ private MethodSpec resolveEndpointMethod() { builder.addCode(validateRequiredParams()); builder.beginControlFlow("try"); - String regionParamName = utils.regionParamName(); - if (regionParamName != null) { - builder.addStatement("$T region = params.$L()", Region.class, regionParamName); - builder.addStatement("$T regionId = region == null ? null : region.id()", String.class); - builder.addStatement("$T result = $L(params, regionId)", ruleResult(), utils.root().ruleId()); - } else { - builder.addStatement("$T result = $L(params)", ruleResult(), utils.root().ruleId()); - } + builder.addStatement("$T result = $L(params)", ruleResult(), utils.root().ruleId()); builder.beginControlFlow("if (result.canContinue())") .addStatement("throw $T.create($S)", SdkClientException.class, "Rule engine did not reach an error or " + "endpoint result") diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java index 1c09b51c398a..e821905aba89 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java @@ -35,9 +35,9 @@ public RenameForCodegenVisitor(SymbolTable symbolTable) { * Returns the new symbol table with the renamed symbols. */ public SymbolTable symbolTable() { - String regionParamName = symbolTable.regionParamName(); - if (regionParamName != null) { - renames.regionParamName(javaName(regionParamName)); + // Carry over region params with their renamed java names + for (String regionParam : symbolTable.regionParams()) { + renames.addRegionParam(javaName(regionParam)); } return renames.build(); } @@ -58,11 +58,14 @@ public RuleExpression visitVariableReferenceExpression(VariableReferenceExpressi RuleType type = symbolTable.paramType(name); String newName = javaName(name); renames.putParam(newName, type); + // Region params return a Region object in Java but the rules use it as a String. + // Access the "{name}Id" method which returns the region ID as a String (null-safe). + String accessorName = symbolTable.isRegionParam(name) ? newName + "Id" : newName; return MemberAccessExpression .builder() .type(e.type()) .source(VariableReferenceExpression.builder().variableName("params").build()) - .name(newName) + .name(accessorName) .build(); } return e; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/SymbolTable.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/SymbolTable.java index 67176abfa146..5b30adefd85f 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/SymbolTable.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/SymbolTable.java @@ -16,19 +16,21 @@ package software.amazon.awssdk.codegen.poet.rules2; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; import software.amazon.awssdk.utils.Validate; public final class SymbolTable { private final Map params; private final Map locals; - private final String regionParamName; + private final Set regionParams; SymbolTable(Builder builder) { this.params = Collections.unmodifiableMap(new LinkedHashMap<>(builder.params)); this.locals = Collections.unmodifiableMap(new LinkedHashMap<>(builder.locals)); - this.regionParamName = builder.regionParamName; + this.regionParams = Collections.unmodifiableSet(new HashSet<>(builder.regionParams)); } public static Builder builder() { @@ -59,8 +61,20 @@ public Map params() { return params; } - public String regionParamName() { - return regionParamName; + /** + * Returns the set of parameter names that are Region-typed in Java (i.e., the Java getter returns {@code Region} + * rather than {@code String}). The codegen needs to append {@code .id()} when accessing these params to convert + * to the String value expected by the endpoint rules. + */ + public Set regionParams() { + return regionParams; + } + + /** + * Returns true if the given parameter name is a Region-typed param that needs {@code .id()} appended. + */ + public boolean isRegionParam(String name) { + return regionParams.contains(name); } public Builder toBuilder() { @@ -70,7 +84,7 @@ public Builder toBuilder() { public static class Builder { private final Map params = new LinkedHashMap<>(); private final Map locals = new LinkedHashMap<>(); - private String regionParamName; + private final Set regionParams = new HashSet<>(); public Builder() { } @@ -78,7 +92,7 @@ public Builder() { public Builder(SymbolTable table) { this.params.putAll(table.params); this.locals.putAll(table.locals); - this.regionParamName = table.regionParamName; + this.regionParams.addAll(table.regionParams); } public Builder putParam(String name, RuleType type) { @@ -99,8 +113,8 @@ public RuleType local(String name) { return locals.get(name); } - public Builder regionParamName(String regionParamName) { - this.regionParamName = regionParamName; + public Builder addRegionParam(String name) { + regionParams.add(Validate.paramNotNull(name, "name")); return this; } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java index 7426688dd92d..0573fe5f1f94 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java @@ -248,6 +248,32 @@ public static IntermediateModel queryServiceModelsWithUriCache() { return new IntermediateModelBuilder(models).build(); } + /** + * Returns a model where the root endpoint rule delegates to child rules without directly using the region parameter. + * This exercises the scenario where ComputeScopeTree does not include region in the root method's signature. + */ + public static IntermediateModel queryServiceModelsWithDelegatingRootRule() { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/service-2.json").getFile()); + File customizationModel = + new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/customization.config").getFile()); + File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/waiters-2.json").getFile()); + File endpointRuleSetModel = + new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/endpoint-rule-set.json").getFile()); + File endpointTestsModel = + new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/endpoint-tests.json").getFile()); + + C2jModels models = C2jModels + .builder() + .serviceModel(getServiceModel(serviceModel)) + .customizationConfig(getCustomizationConfig(customizationModel)) + .waitersModel(getWaiters(waitersModel)) + .endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel)) + .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel)) + .build(); + + return new IntermediateModelBuilder(models).build(); + } + public static IntermediateModel queryServiceModelsEndpointAuthParamsWithAllowList() { File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile()); File customizationModel = diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java index abf2ed3e3e22..b2a956119958 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java @@ -58,4 +58,12 @@ void endpointProviderClassWithMetricValues() { new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUnknownEndpointMetricValues()); assertThat(endpointProviderSpec, generatesTo("endpoint-provider-metric-values-class.java")); } + + @Test + void endpointProviderClass_regionDeclaredButNeverReferenced_compilesSuccessfully() { + // Covers the case where region is declared as a parameter but never referenced in any rule. + ClassSpec endpointProviderSpec = + new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithDelegatingRootRule()); + assertThat(endpointProviderSpec, generatesTo("endpoint-provider-delegating-root-class.java")); + } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java index 8fc91e2069fe..a39463292122 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java @@ -36,6 +36,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public RegionSet regionSet() { return regionSet; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java index 37a202d5ee3a..96769a75478d 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java @@ -31,6 +31,14 @@ static Builder builder() { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns the RegionSet. The regionSet parameter may be used with the "aws.auth#sigv4a" auth scheme. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java index 8d4589400e62..67ae1b14f8e5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java @@ -47,6 +47,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public QueryAuthSchemeParams.Builder toBuilder() { return new Builder(this); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java index b726c4a81e09..40dff2b6c01b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java @@ -45,6 +45,14 @@ static Builder builder() { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns a {@link Builder} to customize the parameters. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java index 87eaf93e4db4..90787b2a7359 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java @@ -73,6 +73,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public RegionSet regionSet() { return regionSet; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java index ee65f8d60da4..dc56b5a01cae 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java @@ -81,6 +81,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public RegionSet regionSet() { return regionSet; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java index 4ac1f03ed9e3..ae925b907d34 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java @@ -66,6 +66,14 @@ static Builder fromEndpointParams(QueryEndpointParams endpointParams) { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns the RegionSet. The regionSet parameter may be used with the "aws.auth#sigv4a" auth scheme. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java index b583bd4c120d..9ac4afccd3ed 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java @@ -59,6 +59,14 @@ static Builder fromEndpointParams(QueryEndpointParams endpointParams) { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns the RegionSet. The regionSet parameter may be used with the "aws.auth#sigv4a" auth scheme. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/customization.config new file mode 100644 index 000000000000..2c63c0851048 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/customization.config @@ -0,0 +1,2 @@ +{ +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-rule-set.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-rule-set.json new file mode 100644 index 000000000000..bfc38318e6a0 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-rule-set.json @@ -0,0 +1,57 @@ +{ + "version": "1.0", + "parameters": { + "region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint", + "type": "string" + }, + "useFIPSEndpoint": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "type": "boolean" + } + }, + "rules": [ + { + "documentation": "Root rule: region is declared but never referenced in any rule", + "type": "tree", + "conditions": [], + "rules": [ + { + "documentation": "If endpoint override is set, use it directly", + "conditions": [ + { + "fn": "isSet", + "argv": [{"ref": "Endpoint"}] + } + ], + "endpoint": { + "url": "{Endpoint}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "Default endpoint without using region", + "conditions": [], + "endpoint": { + "url": "https://query.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ] + } + ] +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-tests.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-tests.json new file mode 100644 index 000000000000..3ce5aaf4f010 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-tests.json @@ -0,0 +1 @@ +{"testCases": []} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/service-2.json new file mode 100644 index 000000000000..4182ad4d5d9c --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/service-2.json @@ -0,0 +1,471 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2010-05-08", + "endpointPrefix": "query-service", + "globalEndpoint": "query-service.amazonaws.com", + "protocol": "query", + "serviceAbbreviation": "Query Service", + "serviceFullName": "Some Service That Uses Query Protocol", + "serviceId":"Query Service", + "signatureVersion": "v4", + "uid": "query-service-2010-05-08", + "xmlNamespace": "https://query-service.amazonaws.com/doc/2010-05-08/" + }, + "clientContextParams": { + "booleanContextParam": { + "type": "boolean", + "documentation": "A boolean client context parameter" + }, + "stringContextParam": { + "type": "string", + "documentation": "a string client context parameter" + } + }, + "operations": { + "OperationWithContextParam": { + "name": "OperationWithContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input":{"shape":"WithContextParam"} + }, + "OperationWithOperationContextParam": { + "name": "OperationWithOperationContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "operationContextParams":{ + "customEndpointArray":{"path":"ListMember.StringList[*].LeafString"} + }, + "input":{"shape":"WithOperationContextParam"} + }, + "OperationWithCustomizedOperationContextParam": { + "name": "OperationWithCustomizedOperationContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input":{"shape":"WithOperationContextParam"} + }, + "OperationWithMapOperationContextParam": { + "name": "OperationWithMapOperationContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "operationContextParams":{ + "arnList":{"path":"keys(RequestMap)"} + }, + "input":{"shape":"WithMapOperationContextParam"} + }, + "OperationWithStaticContextParams": { + "name": "OperationWithStaticContextParams", + "http": { + "method": "POST", + "requestUri": "/" + }, + "staticContextParams": { + "staticStringParam" : { + "value": "hello" + } + } + }, + "OperationWithChecksumRequired": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "httpChecksumRequired": true + }, + "OperationWithNoneAuthType": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "authtype": "none" + }, + "OperationWithRequestCompression": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "requestcompression": { + "encodings": ["gzip"] + } + }, + "OperationWithCustomMember": { + "name": "OperationWithCustomMember", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input":{"shape":"WithCustomMember"} + }, + "APostOperation": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "endpoint": { + "hostPrefix": "foo-" + }, + "input": { + "shape": "APostOperationRequest" + }, + "errors": [ + { + "shape": "InvalidInputException" + } + ], + "documentation": "

Performs a post operation to the query service and has no output

" + }, + "APostOperationWithOutput": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "APostOperationWithOutputRequest" + }, + "output": { + "shape": "APostOperationWithOutputResponse", + "resultWrapper": "APostOperationWithOutputResult" + }, + "errors": [ + { + "shape": "InvalidInputException" + } + ], + "documentation": "

Performs a post operation to the query service and has modelled output

" + }, + "BearerAuthOperation": { + "name": "BearerAuthOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "BearerAuthOperationRequest" + }, + "authtype": "bearer" + }, + "StreamingInputOperation": { + "name": "StreamingInputOperation", + "http": { + "method": "POST", + "requestUri": "/2016-03-11/streamingInputOperation" + }, + "input": { + "shape": "StructureWithStreamingMember" + }, + "documentation": "Some operation with a streaming input" + }, + "StreamingOutputOperation": { + "name": "StreamingOutputOperation", + "http": { + "method": "POST", + "requestUri": "/2016-03-11/streamingOutputOperation" + }, + "output": { + "shape": "StructureWithStreamingMember" + }, + "documentation": "Some operation with a streaming output" + }, + "PutOperationWithChecksum":{ + "name":"PutOperationWithChecksum", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ChecksumStructureWithStreaming"}, + "output":{"shape":"ChecksumStructureWithStreaming"}, + "httpChecksum" : { + "requestValidationModeMember": "ChecksumMode", + "responseAlgorithms": ["CRC32C", "CRC32", "CRC64NVME", "MD5", "SHA1", "SHA256", "SHA512", "XXHASH64", "XXHASH3", "XXHASH128"] + } + }, + "GetOperationWithChecksum":{ + "name":"GetOperationWithChecksum", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ChecksumStructure"}, + "output":{"shape":"ChecksumStructure"}, + "httpChecksum" : { + "requestChecksumRequired": true, + "requestAlgorithmMember": "ChecksumAlgorithm" + } + } + }, + "shapes": { + "WithContextParam": { + "type": "structure", + "members": { + "StringMember" : { + "shape": "String", + "contextParam": { + "name": "operationContextParam" + } + }, + "IntegerMember": { + "shape": "Integer" + }, + "DoubleMember": { + "shape": "Double" + }, + "NestedMember": { + "shape": "ChecksumStructure" + } + } + }, + "WithCustomMember": { + "type": "structure", + "members": { + "StringMemberToBeUpdate" : { + "shape": "String" + }, + "StringMember": { + "shape": "String" + } + } + }, + "WithOperationContextParam": { + "type": "structure", + "members": { + "ListMember":{ + "shape":"ListMember" + } + } + }, + "WithMapOperationContextParam": { + "type": "structure", + "members": { + "OperationWithMapOperationContextParam":{ + "shape":"RequestMap" + } + } + }, + "RequestMap":{ + "type":"map", + "key":{"shape":"LeafString"}, + "value":{"shape":"AttributeValue"} + }, + "AttributeValue": { + "type": "structure", + "members": { + "S": { + "shape": "LeafString" + } + } + }, + "ListMember":{ + "type":"structure", + "members":{ + "Strings":{ + "shape":"StringList" + }, + "StringParam":{ + "shape":"String" + } + }, + "documentation":"

Container for the objects to delete.

" + }, + "StringList":{ + "type":"list", + "member":{"shape":"LeafNode"}, + "flattened":true + }, + "LeafNode":{ + "type":"structure", + "members":{ + "LeafString":{ + "shape":"LeafString" + } + }, + "documentation":"" + }, + "LeafString":{ + "type":"string" + }, + "APostOperationRequest": { + "type": "structure", + "required": [ + "SomeNestedMember" + ], + "members": { + "SomeNestedMember": { + "shape": "NestedMember", + "documentation": "

a member that has nested members

" + }, + "OptionalMember": { + "shape": "dateType", + "documentation": "

An optional member

" + } + } + }, + "APostOperationWithOutputRequest": { + "type": "structure", + "required": [ + "SomeNestedMember" + ], + "members": { + "SomeNestedMember": { + "shape": "NestedMember", + "documentation": "

a member that has nested members

" + }, + "OptionalMember": { + "shape": "dateType", + "documentation": "

An optional member

" + } + } + }, + "APostOperationWithOutputResponse": { + "type": "structure", + "required": [ + "NestedMember" + ], + "members": { + "NestedMember": { + "shape": "NestedMember", + "documentation": "

A structure containing nested members

" + } + }, + "documentation": "

Contains the response to a successful APostOperationWithOutput request.

" + }, + "InvalidInputException": { + "type": "structure", + "members": { + "message": { + "shape": "invalidInputMessage" + } + }, + "documentation": "

The request was rejected because an invalid or out-of-range value was supplied for an input parameter.

", + "error": { + "code": "InvalidInput", + "httpStatusCode": 400, + "senderFault": true + }, + "exception": true + }, + "NestedMember": { + "type": "structure", + "required": [ + "SubMember", + "CreateDate" + ], + "members": { + "SubMember": { + "shape": "subMember", + "documentation": "

A sub-member

" + }, + "CreateDate": { + "shape": "dateType", + "documentation": "

The date and time, in ISO 8601 date-time format, when the member was created.

" + } + }, + "documentation": "

A shape with nested sub-members" + }, + "subMember": { + "type": "string", + "max": 63, + "min": 3, + "pattern": "^[a-z0-9](([a-z0-9]|-(?!-))*[a-z0-9])?$" + }, + "dateType": { + "type": "timestamp" + }, + "invalidInputMessage": { + "type": "string" + }, + "StreamType": { + "type": "blob", + "streaming": true + }, + "StructureWithStreamingMember": { + "type": "structure", + "members": { + "StreamingMember": { + "shape": "StreamType", + "documentation": "This be a stream" + } + }, + "payload": "StreamingMember" + }, + "ChecksumAlgorithm":{ + "type":"string", + "enum":[ + "CRC32", + "CRC32C", + "CRC64NVME", + "MD5", + "SHA1", + "SHA256", + "SHA512", + "XXHASH64", + "XXHASH3", + "XXHASH128" + ] + }, + "ChecksumMode":{ + "type":"string", + "enum":["ENABLED"] + }, + "ChecksumStructureWithStreaming":{ + "type":"structure", + "members":{ + "Body":{ + "shape":"Body", + "documentation":"

Object data.

", + "streaming":true + }, + "ChecksumMode":{ + "shape":"ChecksumMode", + "location":"header", + "locationName":"x-amz-checksum-mode" + }, + "ChecksumAlgorithm":{ + "shape":"ChecksumAlgorithm", + "location":"header", + "locationName":"x-amz-sdk-checksum-algorithm" + } + }, + "payload":"Body" + }, + "Body":{"type":"blob"}, + "ChecksumStructure":{ + "type":"structure", + "members":{ + "Body":{"shape":"Body"}, + "ChecksumMode":{ + "shape":"ChecksumMode", + "location":"header", + "locationName":"x-amz-checksum-mode" + }, + "ChecksumAlgorithm":{ + "shape":"ChecksumAlgorithm", + "location":"header", + "locationName":"x-amz-sdk-checksum-algorithm" + } + }, + "payload":"Body" + }, + "String":{"type":"string"}, + "Integer":{"type":"integer"}, + "Double":{"type":"double"}, + "BearerAuthOperationRequest": { + "type": "structure", + "members": { + } + } + }, + "documentation": "A service that is implemented using the query protocol" +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/waiters-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/waiters-2.json new file mode 100644 index 000000000000..1b0a71e59472 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/waiters-2.json @@ -0,0 +1,80 @@ +{ + "version": 2, + "waiters": { + "PostOperationSuccess": { + "delay": 1, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "expected": 200, + "matcher": "status", + "state": "success" + }, + { + "state": "retry", + "matcher": "status", + "expected": 404 + }, + { + "matcher": "pathAny", + "expected": "baz", + "argument": "foo.bar", + "state": "success" + } + ] + }, + "FloatValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 42.5, + "argument": "FloatValue", + "state": "success" + } + ] + }, + "BigDecimalValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 123132.81289319837183771465876127837183719837123, + "argument": "BigDecimalValue", + "state": "success" + } + ] + }, + "LongValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 9223372036854775807, + "argument": "LongValue", + "state": "success" + } + ] + }, + "DoubleValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 1.7976931348623157E308, + "argument": "DoubleValue", + "state": "success" + } + ] + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java index 232b9fe14236..3164558e9c4c 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java @@ -73,6 +73,13 @@ public Region region() { return region; } + /** + * Returns the region ID (the {@link Region#id()} value) as a String, or null if region is not set. + */ + public String regionId() { + return region == null ? null : region.id(); + } + public Boolean useDualStackEndpoint() { return useDualStackEndpoint; } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java index 7810a21ca78e..d533d71b5784 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java @@ -10,7 +10,6 @@ import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.endpoints.EndpointUrl; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -23,9 +22,7 @@ public final class DefaultQueryEndpointProvider implements QueryEndpointProvider public CompletableFuture resolveEndpoint(QueryEndpointParams params) { Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); + RuleResult result = endpointRule0(params); if (result.canContinue()) { throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); } @@ -42,22 +39,22 @@ public CompletableFuture resolveEndpoint(QueryEndpointParams params) { } } - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); } - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); if (partitionResult != null) { RuleResult result = endpointRule2(params, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule6(params, region, partitionResult); + result = endpointRule6(params, partitionResult); if (result.isResolved()) { return result; } - return RuleResult.error(region + " is not a valid HTTP host-label"); + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.arnList() != null) { String firstArn = RulesFunctions.listAccess(params.arnList(), 0); @@ -92,8 +89,8 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), - -1, "")) + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -101,7 +98,9 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio } return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) @@ -110,12 +109,14 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.carryOn(); } - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -125,27 +126,32 @@ private static RuleResult endpointRule6(QueryEndpointParams params, String regio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); } if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint()) { return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dualStackDnsSuffix(), -1, - "")) + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build())).build()); } - return RuleResult.endpoint(Endpoint.builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dnsSuffix(), -1, "")).build()); + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); } return RuleResult.carryOn(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-delegating-root-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-delegating-root-class.java new file mode 100644 index 000000000000..0759d0bb5a49 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-delegating-root-class.java @@ -0,0 +1,60 @@ +package software.amazon.awssdk.services.query.endpoints.internal; + +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Validate; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { + @Override + public CompletableFuture resolveEndpoint(QueryEndpointParams params) { + Validate.notNull(params.region(), "Parameter 'region' must not be null"); + Validate.notNull(params.useFipsEndpoint(), "Parameter 'useFIPSEndpoint' must not be null"); + try { + RuleResult result = endpointRule0(params); + if (result.canContinue()) { + throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); + } + if (result.isError()) { + String errorMsg = result.error(); + if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + } + throw SdkClientException.create(errorMsg); + } + return CompletableFuture.completedFuture(result.endpoint()); + } catch (Exception error) { + return CompletableFutureUtils.failedFuture(error); + } + } + + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); + } + + private static RuleResult endpointRule1(QueryEndpointParams params) { + if (params.endpoint() != null) { + return RuleResult.endpoint(Endpoint.builder().endpointUrl(EndpointUrl.fromString(params.endpoint())).build()); + } + return RuleResult.endpoint(Endpoint.builder() + .endpointUrl(EndpointUrl.fromComponents("https", "query.amazonaws.com", -1, "")).build()); + } + + @Override + public boolean equals(Object rhs) { + return rhs != null && getClass().equals(rhs.getClass()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java index 7810a21ca78e..d533d71b5784 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java @@ -10,7 +10,6 @@ import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.endpoints.EndpointUrl; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -23,9 +22,7 @@ public final class DefaultQueryEndpointProvider implements QueryEndpointProvider public CompletableFuture resolveEndpoint(QueryEndpointParams params) { Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); + RuleResult result = endpointRule0(params); if (result.canContinue()) { throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); } @@ -42,22 +39,22 @@ public CompletableFuture resolveEndpoint(QueryEndpointParams params) { } } - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); } - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); if (partitionResult != null) { RuleResult result = endpointRule2(params, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule6(params, region, partitionResult); + result = endpointRule6(params, partitionResult); if (result.isResolved()) { return result; } - return RuleResult.error(region + " is not a valid HTTP host-label"); + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.arnList() != null) { String firstArn = RulesFunctions.listAccess(params.arnList(), 0); @@ -92,8 +89,8 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), - -1, "")) + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -101,7 +98,9 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio } return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) @@ -110,12 +109,14 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.carryOn(); } - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -125,27 +126,32 @@ private static RuleResult endpointRule6(QueryEndpointParams params, String regio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); } if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint()) { return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dualStackDnsSuffix(), -1, - "")) + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build())).build()); } - return RuleResult.endpoint(Endpoint.builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dnsSuffix(), -1, "")).build()); + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); } return RuleResult.carryOn(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-metric-values-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-metric-values-class.java index cadeb0b86890..fde716375b74 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-metric-values-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-metric-values-class.java @@ -10,7 +10,6 @@ import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.endpoints.EndpointUrl; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -23,9 +22,7 @@ public final class DefaultQueryEndpointProvider implements QueryEndpointProvider public CompletableFuture resolveEndpoint(QueryEndpointParams params) { Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); + RuleResult result = endpointRule0(params); if (result.canContinue()) { throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); } @@ -42,22 +39,22 @@ public CompletableFuture resolveEndpoint(QueryEndpointParams params) { } } - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); } - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); if (partitionResult != null) { RuleResult result = endpointRule2(params, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule6(params, region, partitionResult); + result = endpointRule6(params, partitionResult); if (result.isResolved()) { return result; } - return RuleResult.error(region + " is not a valid HTTP host-label"); + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); } return RuleResult.carryOn(); } @@ -71,8 +68,8 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), - -1, "")) + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -80,7 +77,9 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio } return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) @@ -89,12 +88,14 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.carryOn(); } - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -104,27 +105,32 @@ private static RuleResult endpointRule6(QueryEndpointParams params, String regio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); } if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint()) { return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dualStackDnsSuffix(), -1, - "")) + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build())).build()); } - return RuleResult.endpoint(Endpoint.builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dnsSuffix(), -1, "")).build()); + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); } return RuleResult.carryOn(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-uri-cache-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-uri-cache-class.java index 7810a21ca78e..d533d71b5784 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-uri-cache-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-uri-cache-class.java @@ -10,7 +10,6 @@ import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.endpoints.EndpointUrl; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -23,9 +22,7 @@ public final class DefaultQueryEndpointProvider implements QueryEndpointProvider public CompletableFuture resolveEndpoint(QueryEndpointParams params) { Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); + RuleResult result = endpointRule0(params); if (result.canContinue()) { throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); } @@ -42,22 +39,22 @@ public CompletableFuture resolveEndpoint(QueryEndpointParams params) { } } - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); } - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); if (partitionResult != null) { RuleResult result = endpointRule2(params, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule6(params, region, partitionResult); + result = endpointRule6(params, partitionResult); if (result.isResolved()) { return result; } - return RuleResult.error(region + " is not a valid HTTP host-label"); + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.arnList() != null) { String firstArn = RulesFunctions.listAccess(params.arnList(), 0); @@ -92,8 +89,8 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), - -1, "")) + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -101,7 +98,9 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio } return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) @@ -110,12 +109,14 @@ private static RuleResult endpointRule2(QueryEndpointParams params, RulePartitio return RuleResult.carryOn(); } - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { return RuleResult.endpoint(Endpoint .builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")) + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") @@ -125,27 +126,32 @@ private static RuleResult endpointRule6(QueryEndpointParams params, String regio return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); } if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint()) { return RuleResult.endpoint(Endpoint .builder() .endpointUrl( - EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dualStackDnsSuffix(), -1, - "")) + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) .putAttribute( AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().signingName("query") .signingRegionSet(Arrays.asList("*")).build())).build()); } - return RuleResult.endpoint(Endpoint.builder() - .endpointUrl(EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dnsSuffix(), -1, "")).build()); + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); } return RuleResult.carryOn(); } diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/customization.config new file mode 100644 index 000000000000..2c63c0851048 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/customization.config @@ -0,0 +1,2 @@ +{ +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-rule-set.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-rule-set.json new file mode 100644 index 000000000000..1e17a2a8641c --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-rule-set.json @@ -0,0 +1,42 @@ +{ + "version": "1.0", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region - declared but never referenced in rules", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint", + "type": "string" + } + }, + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [{"ref": "Endpoint"}] + } + ], + "endpoint": { + "url": "{Endpoint}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://regionnotused.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ] +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-tests.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-tests.json new file mode 100644 index 000000000000..3ce5aaf4f010 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-tests.json @@ -0,0 +1 @@ +{"testCases": []} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/service-2.json new file mode 100644 index 000000000000..2457bb476052 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/service-2.json @@ -0,0 +1,37 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2023-01-01", + "endpointPrefix": "regionnotused", + "protocol": "rest-json", + "serviceFullName": "Region Not Used Test Service", + "serviceId": "RegionNotUsed", + "signatureVersion": "v4", + "uid": "regionnotused-2023-01-01" + }, + "operations": { + "DoSomething": { + "name": "DoSomething", + "http": { + "method": "POST", + "requestUri": "/do-something" + }, + "input": { + "shape": "DoSomethingRequest" + }, + "output": { + "shape": "DoSomethingResponse" + } + } + }, + "shapes": { + "DoSomethingRequest": { + "type": "structure", + "members": {} + }, + "DoSomethingResponse": { + "type": "structure", + "members": {} + } + } +} \ No newline at end of file diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java index 38684df7d291..cb7c086e2a25 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java @@ -243,4 +243,19 @@ public void clientContextParams_setOnBuilder_resolvedCorrectly() { assertThat(params.stringClientContextParam()).isEqualTo("foobar"); assertThat(params.booleanClientContextParam()).isTrue(); } + + @Test + public void regionId_whenRegionIsSet_returnsRegionIdString() { + RestJsonEndpointProvidersEndpointParams params = RestJsonEndpointProvidersEndpointParams.builder() + .region(Region.of("us-west-2")) + .build(); + assertThat(params.regionId()).isEqualTo("us-west-2"); + } + + @Test + public void regionId_whenRegionIsNull_returnsNull() { + RestJsonEndpointProvidersEndpointParams params = RestJsonEndpointProvidersEndpointParams.builder() + .build(); + assertThat(params.regionId()).isNull(); + } }