Unverified Commit cc690ca4 authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Generate a region setter in config when the model uses SigV4 (#2960)

SDK ad-hoc clients sometimes have endpoint rulesets without a region,
but use SigV4. In these cases, the region setter on config is still
necessary for signing to succeed, so they should retain the setters for
region.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent cf95f480
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -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,
+105 −0
Original line number Diff line number Diff line
/*
 * 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("))
    }
}