diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt index 5dacc952bd..25c72ee3ef 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt @@ -5,6 +5,8 @@ package software.amazon.smithy.rustsdk +import software.amazon.smithy.aws.traits.auth.SigV4Trait +import software.amazon.smithy.model.knowledge.ServiceIndex import software.amazon.smithy.model.node.Node import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.rulesengine.language.syntax.parameters.Builtins @@ -82,7 +84,11 @@ class RegionDecorator : ClientCodegenDecorator { override val name: String = "Region" override val order: Byte = 0 - private fun usesRegion(codegenContext: ClientCodegenContext) = codegenContext.getBuiltIn(Builtins.REGION) != null + // Services that have an endpoint ruleset that references the SDK::Region built in, or + // that use SigV4, both need a configurable region. + private fun usesRegion(codegenContext: ClientCodegenContext) = + codegenContext.getBuiltIn(Builtins.REGION) != null || ServiceIndex.of(codegenContext.model) + .getEffectiveAuthSchemes(codegenContext.serviceShape).containsKey(SigV4Trait.ID) override fun configCustomizations( codegenContext: ClientCodegenContext, diff --git a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RegionDecoratorTest.kt b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RegionDecoratorTest.kt new file mode 100644 index 0000000000..0900142258 --- /dev/null +++ b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RegionDecoratorTest.kt @@ -0,0 +1,105 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package software.amazon.smithy.rustsdk + +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import kotlin.io.path.readText + +class RegionDecoratorTest { + private val modelWithoutRegionParamOrSigV4AuthScheme = """ + namespace test + + use aws.api#service + use aws.protocols#awsJson1_0 + use smithy.rules#endpointRuleSet + + @awsJson1_0 + @endpointRuleSet({ + "version": "1.0", + "rules": [{ "type": "endpoint", "conditions": [], "endpoint": { "url": "https://example.com" } }], + "parameters": {} + }) + @service(sdkId: "dontcare") + service TestService { version: "2023-01-01", operations: [SomeOperation] } + structure SomeOutput { something: String } + operation SomeOperation { output: SomeOutput } + """.asSmithyModel() + + private val modelWithRegionParam = """ + namespace test + + use aws.api#service + use aws.protocols#awsJson1_0 + use smithy.rules#endpointRuleSet + + @awsJson1_0 + @endpointRuleSet({ + "version": "1.0", + "rules": [{ "type": "endpoint", "conditions": [], "endpoint": { "url": "https://example.com" } }], + "parameters": { + "Region": { "required": false, "type": "String", "builtIn": "AWS::Region" }, + } + }) + @service(sdkId: "dontcare") + service TestService { version: "2023-01-01", operations: [SomeOperation] } + structure SomeOutput { something: String } + operation SomeOperation { output: SomeOutput } + """.asSmithyModel() + + private val modelWithSigV4AuthScheme = """ + namespace test + + use aws.auth#sigv4 + use aws.api#service + use aws.protocols#awsJson1_0 + use smithy.rules#endpointRuleSet + + @auth([sigv4]) + @sigv4(name: "dontcare") + @awsJson1_0 + @endpointRuleSet({ + "version": "1.0", + "rules": [{ "type": "endpoint", "conditions": [], "endpoint": { "url": "https://example.com" } }], + "parameters": {} + }) + @service(sdkId: "dontcare") + service TestService { version: "2023-01-01", operations: [SomeOperation] } + structure SomeOutput { something: String } + operation SomeOperation { output: SomeOutput } + """.asSmithyModel() + + @Test + fun `models without region built-in params or SigV4 should not have configurable regions`() { + val path = awsSdkIntegrationTest( + modelWithoutRegionParamOrSigV4AuthScheme, + generateOrchestrator = true, + ) { _, _ -> /* it should generate and compile successfully */ } + val configContents = path.resolve("src/config.rs").readText() + assertFalse(configContents.contains("fn set_region(")) + } + + @Test + fun `models with region built-in params should have configurable regions`() { + val path = awsSdkIntegrationTest( + modelWithRegionParam, + generateOrchestrator = true, + ) { _, _ -> /* it should generate and compile successfully */ } + val configContents = path.resolve("src/config.rs").readText() + assertTrue(configContents.contains("fn set_region(")) + } + + @Test + fun `models with SigV4 should have configurable regions`() { + val path = awsSdkIntegrationTest( + modelWithSigV4AuthScheme, + generateOrchestrator = true, + ) { _, _ -> /* it should generate and compile successfully */ } + val configContents = path.resolve("src/config.rs").readText() + assertTrue(configContents.contains("fn set_region(")) + } +}