Skip to content

Commit d7cb21e

Browse files
committed
fix: overhaul endpoint discovery to favor endpointUrl when provided, make endpoint discoverers interfaces so custom implementations can be provided, and to respect environmental config
1 parent 757925d commit d7cb21e

File tree

14 files changed

+236
-4
lines changed

14 files changed

+236
-4
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"id": "49af01b8-6fed-4add-ace0-9f027e83425a",
3+
"type": "feature",
4+
"description": "⚠️ **IMPORTANT**: Refactor endpoint discoverer classes into interfaces so custom implementations may be provided",
5+
"issues": [
6+
"awslabs/aws-sdk-kotlin#1413"
7+
],
8+
"requiresMinorVersionBump": true
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"id": "929f0e2a-3af9-4f73-9f1b-b4e97f91f0db",
3+
"type": "feature",
4+
"description": "⚠️ **IMPORTANT**: Add support for enabling/disabling endpoint discovery via [standard cross-SDK config mechanisms](https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoint-discovery.html)",
5+
"issues": [
6+
"awslabs/aws-sdk-kotlin#1413"
7+
],
8+
"requiresMinorVersionBump": true
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "e6515649-dab5-4be9-b4b4-b289369960d5",
3+
"type": "bugfix",
4+
"description": "Favor `endpointUrl` instead of endpoint discovery if both are provided",
5+
"issues": [
6+
"awslabs/aws-sdk-kotlin#1413"
7+
]
8+
}

aws-runtime/aws-config/api/aws-config.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ public final class aws/sdk/kotlin/runtime/config/AwsSdkSetting {
237237
public final fun getAwsEc2MetadataDisabled ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting;
238238
public final fun getAwsEc2MetadataServiceEndpoint ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting;
239239
public final fun getAwsEc2MetadataServiceEndpointMode ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting;
240+
public final fun getAwsEndpointDiscoveryEnabled ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting;
240241
public final fun getAwsEndpointUrl ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting;
241242
public final fun getAwsExecutionEnv ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting;
242243
public final fun getAwsIgnoreEndpointUrls ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting;
@@ -280,6 +281,8 @@ public final class aws/sdk/kotlin/runtime/config/endpoints/ResolversKt {
280281
public static final fun resolveAccountId (Laws/sdk/kotlin/runtime/config/endpoints/AccountIdEndpointMode;Laws/smithy/kotlin/runtime/collections/Attributes;)Ljava/lang/String;
281282
public static final fun resolveAccountIdEndpointMode (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/util/LazyAsyncValue;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
282283
public static synthetic fun resolveAccountIdEndpointMode$default (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/util/LazyAsyncValue;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
284+
public static final fun resolveEndpointDiscoveryEnabled (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/util/LazyAsyncValue;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
285+
public static synthetic fun resolveEndpointDiscoveryEnabled$default (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/util/LazyAsyncValue;ZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
283286
public static final fun resolveEndpointUrl (Laws/smithy/kotlin/runtime/util/LazyAsyncValue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
284287
public static synthetic fun resolveEndpointUrl$default (Laws/smithy/kotlin/runtime/util/LazyAsyncValue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
285288
public static final fun resolveUseDualStack (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/util/LazyAsyncValue;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -459,6 +462,7 @@ public final class aws/sdk/kotlin/runtime/config/profile/AwsProfileKt {
459462
public static synthetic fun getBooleanOrNull$default (Laws/sdk/kotlin/runtime/config/profile/ConfigSection;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Boolean;
460463
public static final fun getCredentialProcess (Laws/sdk/kotlin/runtime/config/profile/ConfigSection;)Ljava/lang/String;
461464
public static final fun getDisableRequestCompression (Laws/sdk/kotlin/runtime/config/profile/ConfigSection;)Ljava/lang/Boolean;
465+
public static final fun getEndpointDiscoveryEnabled (Laws/sdk/kotlin/runtime/config/profile/ConfigSection;)Ljava/lang/Boolean;
462466
public static final fun getEndpointUrl (Laws/sdk/kotlin/runtime/config/profile/ConfigSection;)Laws/smithy/kotlin/runtime/net/url/Url;
463467
public static final fun getIgnoreEndpointUrls (Laws/sdk/kotlin/runtime/config/profile/ConfigSection;)Ljava/lang/Boolean;
464468
public static final fun getIntOrNull (Laws/sdk/kotlin/runtime/config/profile/ConfigSection;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Integer;

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkSetting.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ public object AwsSdkSetting {
208208
*/
209209
public val AwsSigV4aSigningRegionSet: EnvironmentSetting<String> =
210210
strEnvSetting("aws.sigV4aSigningRegionSet", "AWS_SIGV4A_SIGNING_REGION_SET")
211+
212+
/**
213+
* A flag indicating whether endpoint discovery is enabled for AWS services that support it. The implicit default
214+
* value for this setting is:
215+
* * `true` for services which _require_ EP discovery (e.g., Timestream)
216+
* * `false` for services which _allow but do not require_ EP discovery (e.g., DynamoDB)
217+
*/
218+
public val AwsEndpointDiscoveryEnabled: EnvironmentSetting<Boolean> =
219+
boolEnvSetting("aws.endpointDiscoveryEnabled", "AWS_ENABLE_ENDPOINT_DISCOVERY")
211220
}
212221

213222
/**

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/endpoints/Resolvers.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,16 @@ public fun resolveAccountId(endpointMode: AccountIdEndpointMode, attributes: Att
101101
AccountIdEndpointMode.DISABLED -> null
102102
AccountIdEndpointMode.REQUIRED -> attributes.getOrNull(AwsClientOption.AccountId) ?: throw ConfigurationException("AccountIdEndpointMode is set to required but no AWS account ID found")
103103
}
104+
105+
/**
106+
* Resolve the endpoint discovery mode
107+
*/
108+
@InternalSdkApi
109+
public suspend fun resolveEndpointDiscoveryEnabled(
110+
provider: PlatformProvider = PlatformProvider.System,
111+
profile: LazyAsyncValue<AwsProfile> = asyncLazy { loadAwsSharedConfig(provider).activeProfile },
112+
serviceRequiresEpDiscovery: Boolean,
113+
): Boolean =
114+
AwsSdkSetting.AwsEndpointDiscoveryEnabled.resolve(provider)
115+
?: profile.get().endpointDiscoveryEnabled
116+
?: serviceRequiresEpDiscovery

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/profile/AwsProfile.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,14 @@ public val AwsProfile.requestMinCompressionSizeBytes: Long?
167167
public val AwsProfile.sigV4aSigningRegionSet: String?
168168
get() = getOrNull("sigv4a_signing_region_set")
169169

170+
/**
171+
* A flag indicating whether endpoint discovery should be enabled for a service that supports it. This setting has no
172+
* effect for services which _do not_ support endpoint discovery.
173+
*/
174+
@InternalSdkApi
175+
public val AwsProfile.endpointDiscoveryEnabled: Boolean?
176+
get() = getBooleanOrNull("endpoint_discovery_enabled")
177+
170178
/**
171179
* Parse a config value as a boolean, ignoring case.
172180
*/
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package aws.sdk.kotlin.runtime.config.endpoints
6+
7+
import aws.sdk.kotlin.runtime.config.profile.*
8+
import aws.sdk.kotlin.runtime.config.profile.FileType
9+
import aws.sdk.kotlin.runtime.config.profile.parse
10+
import aws.sdk.kotlin.runtime.config.profile.toSharedConfig
11+
import aws.smithy.kotlin.runtime.telemetry.logging.Logger
12+
import aws.smithy.kotlin.runtime.util.TestPlatformProvider
13+
import aws.smithy.kotlin.runtime.util.asyncLazy
14+
import kotlinx.coroutines.test.runTest
15+
import kotlin.test.Test
16+
import kotlin.test.assertEquals
17+
18+
class ResolveEndpointDiscoveryTest {
19+
@Test
20+
fun testPrecedenceSysProps() = assertEpDiscovery(
21+
sysProps = mapOf("aws.endpointDiscoveryEnabled" to "true"),
22+
env = mapOf("AWS_ENABLE_ENDPOINT_DISCOVERY" to "false"),
23+
config = """
24+
[${Literals.DEFAULT_PROFILE}]
25+
endpoint_discovery_enabled = false
26+
""".trimIndent(),
27+
serviceRequiresEpDiscovery = false,
28+
expected = true,
29+
)
30+
31+
@Test
32+
fun testPrecedenceEnvVars() = assertEpDiscovery(
33+
env = mapOf("AWS_ENABLE_ENDPOINT_DISCOVERY" to "true"),
34+
config = """
35+
[${Literals.DEFAULT_PROFILE}]
36+
endpoint_discovery_enabled = false
37+
""".trimIndent(),
38+
serviceRequiresEpDiscovery = false,
39+
expected = true,
40+
)
41+
42+
@Test
43+
fun testPrecedenceConfig() = assertEpDiscovery(
44+
config = """
45+
[${Literals.DEFAULT_PROFILE}]
46+
endpoint_discovery_enabled = true
47+
""".trimIndent(),
48+
serviceRequiresEpDiscovery = false,
49+
expected = true,
50+
)
51+
52+
@Test
53+
fun testPrecedenceDefault() = assertEpDiscovery(
54+
serviceRequiresEpDiscovery = true,
55+
expected = true,
56+
)
57+
}
58+
59+
fun assertEpDiscovery(
60+
sysProps: Map<String, String> = mapOf(),
61+
env: Map<String, String> = mapOf(),
62+
config: String = "",
63+
serviceRequiresEpDiscovery: Boolean,
64+
expected: Boolean,
65+
) = runTest {
66+
val provider = TestPlatformProvider(env, sysProps)
67+
val source = AwsConfigurationSource(Literals.DEFAULT_PROFILE, "", "")
68+
69+
val profile = asyncLazy {
70+
parse(Logger.None, FileType.CONFIGURATION, config)
71+
.toSharedConfig(source)
72+
.activeProfile
73+
}
74+
75+
val actual = resolveEndpointDiscoveryEnabled(provider, profile, serviceRequiresEpDiscovery)
76+
assertEquals(expected, actual)
77+
}

codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ object AwsRuntimeTypes {
3838

3939
object Endpoints : RuntimeTypePackage(AwsKotlinDependency.AWS_CONFIG, "config.endpoints") {
4040
val AccountIdEndpointMode = symbol("AccountIdEndpointMode")
41+
val resolveEndpointDiscoveryEnabled = symbol("resolveEndpointDiscoveryEnabled")
4142
val resolveEndpointUrl = symbol("resolveEndpointUrl")
4243
val resolveAccountId = symbol("resolveAccountId")
4344
val resolveAccountIdEndpointMode = symbol("resolveAccountIdEndpointMode")

codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/PresignerGenerator.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ class PresignerGenerator : KotlinIntegration {
4646
* signing.
4747
*/
4848
object UnsignedRequestCustomizationSection : SectionId {
49-
val CodegenContext: SectionKey<CodegenContext> = SectionKey("CodegenContext")
5049
val OperationId: SectionKey<String> = SectionKey("OperationId")
5150
val HttpBindingResolver: SectionKey<HttpBindingResolver> = SectionKey("HttpBindingResolver")
5251
val DefaultTimestampFormat: SectionKey<TimestampFormatTrait.Format> = SectionKey("DefaultTimestampFormat")
@@ -128,7 +127,6 @@ class PresignerGenerator : KotlinIntegration {
128127

129128
val contextMap: Map<SectionKey<*>, Any> = mapOf(
130129
UnsignedRequestCustomizationSection.OperationId to op.id.toString(),
131-
UnsignedRequestCustomizationSection.CodegenContext to ctx,
132130
UnsignedRequestCustomizationSection.HttpBindingResolver to httpBindingResolver,
133131
UnsignedRequestCustomizationSection.DefaultTimestampFormat to defaultTimestampFormat,
134132
)

0 commit comments

Comments
 (0)