Skip to content

Commit 72ed172

Browse files
committed
address pr review
1 parent 0f84ab9 commit 72ed172

File tree

5 files changed

+191
-10
lines changed

5 files changed

+191
-10
lines changed

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/aws/customization/RegionSupport.kt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ class RegionSupport : KotlinIntegration {
5454
name = "regionProvider"
5555
symbol = RuntimeTypes.SmithyClient.Region.RegionProvider
5656
documentation = """
57-
An optional region provider that determines the AWS region for client operations. When specified, this provider
58-
takes precedence over the default region provider chain, unless a static region is explicitly configured.
57+
An optional region provider that determines the AWS region for client operations. When specified, this provider
58+
takes precedence over the default region provider chain, unless a static region is explicitly configured.
5959
60-
The region resolution order is:
61-
1. Static region (if specified)
62-
2. Custom region provider (if configured)
63-
3. Default region provider chain
60+
The region resolution order is:
61+
1. Static region (if specified)
62+
2. Custom region provider (if configured)
63+
3. Default region provider chain
6464
""".trimIndent()
6565
}
6666
}
@@ -77,10 +77,7 @@ class RegionSupport : KotlinIntegration {
7777
return supportsSigv4 || hasRegionBuiltin || isAwsSdk
7878
}
7979

80-
override fun additionalServiceConfigProps(ctx: CodegenContext): List<ConfigProperty> = buildList {
81-
add(RegionProp)
82-
add(RegionProviderProp)
83-
}
80+
override fun additionalServiceConfigProps(ctx: CodegenContext): List<ConfigProperty> = listOf(RegionProp, RegionProviderProp)
8481

8582
override fun customizeEndpointResolution(ctx: ProtocolGenerator.GenerationContext): EndpointCustomization =
8683
object : EndpointCustomization {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package software.amazon.smithy.kotlin.codegen.aws.customization
2+
3+
import org.junit.jupiter.api.Test
4+
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
5+
import software.amazon.smithy.kotlin.codegen.model.expectShape
6+
import software.amazon.smithy.kotlin.codegen.rendering.ServiceClientConfigGenerator
7+
import software.amazon.smithy.kotlin.codegen.test.newTestContext
8+
import software.amazon.smithy.kotlin.codegen.test.shouldContainOnlyOnceWithDiff
9+
import software.amazon.smithy.kotlin.codegen.test.toRenderingContext
10+
import software.amazon.smithy.kotlin.codegen.test.toSmithyModel
11+
import software.amazon.smithy.model.shapes.ServiceShape
12+
13+
class RegionSupportTest {
14+
@Test
15+
fun testRegionSupportProperties() {
16+
val model = """
17+
namespace com.test
18+
19+
use aws.protocols#awsJson1_1
20+
use aws.api#service
21+
use aws.auth#sigv4
22+
23+
@service(sdkId: "service with overrides", endpointPrefix: "service-with-overrides")
24+
@sigv4(name: "example")
25+
@awsJson1_1
26+
service Example {
27+
version: "1.0.0",
28+
operations: [GetFoo]
29+
}
30+
31+
operation GetFoo {}
32+
""".toSmithyModel()
33+
34+
val serviceShape = model.expectShape<ServiceShape>("com.test#Example")
35+
36+
val testCtx = model.newTestContext(serviceName = "Example")
37+
val writer = KotlinWriter("com.test")
38+
39+
val renderingCtx = testCtx.toRenderingContext(writer, serviceShape)
40+
.copy(integrations = listOf(RegionSupport()))
41+
42+
ServiceClientConfigGenerator(serviceShape, detectDefaultProps = false).render(renderingCtx, renderingCtx.writer)
43+
val contents = writer.toString()
44+
45+
val expectedProps = """
46+
public val region: String? = builder.region
47+
public val regionProvider: RegionProvider? = builder.regionProvider
48+
"""
49+
contents.shouldContainOnlyOnceWithDiff(expectedProps)
50+
51+
val expectedImpl = """
52+
/**
53+
* The AWS region to sign with and make requests to. When specified, this static region configuration
54+
* takes precedence over other region resolution methods.
55+
*
56+
* The region resolution order is:
57+
* 1. Static region (if specified)
58+
* 2. Custom region provider (if configured)
59+
* 3. Default region provider chain
60+
*/
61+
public var region: String? = null
62+
63+
/**
64+
* An optional region provider that determines the AWS region for client operations. When specified, this provider
65+
* takes precedence over the default region provider chain, unless a static region is explicitly configured.
66+
*
67+
* The region resolution order is:
68+
* 1. Static region (if specified)
69+
* 2. Custom region provider (if configured)
70+
* 3. Default region provider chain
71+
*/
72+
public var regionProvider: RegionProvider? = null
73+
"""
74+
contents.shouldContainOnlyOnceWithDiff(expectedImpl)
75+
}
76+
}
77+

runtime/smithy-client/api/smithy-client.api

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,11 @@ public abstract interface class aws/smithy/kotlin/runtime/client/region/RegionPr
329329
public abstract fun getRegion (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
330330
}
331331

332+
public class aws/smithy/kotlin/runtime/client/region/RegionProviderChain : aws/smithy/kotlin/runtime/client/region/RegionProvider {
333+
public fun <init> (Ljava/util/List;)V
334+
public fun <init> ([Laws/smithy/kotlin/runtime/client/region/RegionProvider;)V
335+
protected final fun getProviders ()[Laws/smithy/kotlin/runtime/client/region/RegionProvider;
336+
public fun getRegion (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
337+
public fun toString ()Ljava/lang/String;
338+
}
339+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package aws.smithy.kotlin.runtime.client.region
7+
8+
import aws.smithy.kotlin.runtime.telemetry.logging.logger
9+
import aws.smithy.kotlin.runtime.util.asyncLazy
10+
import kotlin.coroutines.coroutineContext
11+
12+
/**
13+
* Composite [RegionProvider] that delegates to a chain of providers.
14+
* [providers] are consulted in the order given and the first region found is returned
15+
*
16+
* @param providers the list of providers to delegate to
17+
*/
18+
public open class RegionProviderChain(
19+
protected vararg val providers: RegionProvider,
20+
) : RegionProvider {
21+
22+
public constructor(providers: List<RegionProvider>) : this(*providers.toTypedArray())
23+
24+
private val resolvedRegion = asyncLazy(::resolveRegion)
25+
26+
init {
27+
require(providers.isNotEmpty()) { "at least one provider must be in the chain" }
28+
}
29+
30+
override fun toString(): String =
31+
(listOf(this) + providers).map { it::class.simpleName }.joinToString(" -> ")
32+
33+
override suspend fun getRegion(): String? = resolvedRegion.get()
34+
35+
private suspend fun resolveRegion(): String? {
36+
val logger = coroutineContext.logger<RegionProviderChain>()
37+
for (provider in providers) {
38+
try {
39+
val region = provider.getRegion()
40+
if (region != null) {
41+
logger.debug { "resolved region ($region) from $provider " }
42+
return region
43+
}
44+
logger.debug { "failed to resolve region from $provider" }
45+
} catch (ex: Exception) {
46+
logger.debug { "unable to load region from $provider: ${ex.message}" }
47+
}
48+
}
49+
50+
return null
51+
}
52+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package aws.smithy.kotlin.runtime.client.region
7+
8+
import kotlinx.coroutines.test.runTest
9+
import kotlin.test.Test
10+
import kotlin.test.assertEquals
11+
import kotlin.test.assertFails
12+
13+
class AwsRegionProviderChainTest {
14+
@Test
15+
fun testNoProviders() {
16+
assertFails("at least one provider") {
17+
RegionProviderChain()
18+
}
19+
}
20+
data class TestProvider(val region: String? = null) : RegionProvider {
21+
override suspend fun getRegion(): String? = region
22+
}
23+
24+
@Test
25+
fun testChain() = runTest {
26+
val chain = RegionProviderChain(
27+
TestProvider(null),
28+
TestProvider("us-east-1"),
29+
TestProvider("us-east-2"),
30+
)
31+
32+
assertEquals("us-east-1", chain.getRegion())
33+
}
34+
35+
@Test
36+
fun testChainList() = runTest {
37+
val providers = listOf<RegionProvider>(
38+
TestProvider(null),
39+
TestProvider("us-east-1"),
40+
TestProvider("us-east-2"),
41+
)
42+
43+
val chain = RegionProviderChain(providers)
44+
45+
assertEquals("us-east-1", chain.getRegion())
46+
}
47+
}

0 commit comments

Comments
 (0)