Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import aws.sdk.kotlin.runtime.auth.credentials.internal.credentials
import aws.sdk.kotlin.runtime.config.AwsSdkSetting
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric
import aws.smithy.kotlin.runtime.IgnoreNative
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProviderException
import aws.smithy.kotlin.runtime.http.Headers
Expand Down Expand Up @@ -144,9 +143,6 @@ class EcsCredentialsProviderTest {
engine.assertRequests()
}

// FIXME iosSimulator fails with a different exception: "Failed to resolve host amazonaws.com: nodename nor servname provided, or not known"
// Need to fix this by applying the same --standalone removal that we do in smithy-kotlin, aws-crt-kotlin. See `configureIosSimulatorTasks` in aws-kotlin-repo-tools.
@IgnoreNative
@Test
fun testNonLocalFullUri() = runTest {
val uri = "http://amazonaws.com/full"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,15 @@
package aws.sdk.kotlin.runtime.region

import aws.sdk.kotlin.runtime.util.TestInstanceMetadataProvider
import aws.smithy.kotlin.runtime.IgnoreNative
import aws.smithy.kotlin.runtime.util.TestPlatformProvider
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.*
import kotlin.test.Test
import kotlin.test.assertEquals

class DefaultRegionProviderChainTest {
private data class RegionProviderChainTest(
val name: String,
val platformProvider: TestPlatformProvider,
val instanceMetadataProvider: TestInstanceMetadataProvider,
val region: String?,
val targets: List<String> = emptyList(),
)

// FIXME "jvm property is favored" tests need to be made JVM-only. Native does not have system properties, so those tests will always fail.
@IgnoreNative
@Test
fun testSuite() = runTest {
val tests = Json.parseToJsonElement(REGION_PROVIDER_CHAIN_TEST_SUITE).jsonArray
.map { it.jsonObject }
.map {
val name = it["name"]!!.jsonPrimitive.content
val platform = TestPlatformProvider.fromJsonNode(it["platform"]!!.jsonObject)
val instanceMetadata = TestInstanceMetadataProvider.fromJsonNode(it["imds"]!!.jsonObject)
val region = it["region"]!!.jsonPrimitive.contentOrNull
RegionProviderChainTest(name, platform, instanceMetadata, region)
}

tests.forEach { test ->
val provider = DefaultRegionProviderChain(
platformProvider = test.platformProvider,
imdsClient = lazy { test.instanceMetadataProvider },
)
val actual = provider.getRegion()
assertEquals(test.region, actual, test.name)
}
}
}

/**
* Construct a [TestPlatformProvider] from a JSON node like:
*
* ```json
* {
* "env": {
* "ENV_VAR": "value"
* },
* "props": {
* "aws.property": "value"
* },
* "fs": {
* "filename": "contents"
* }
* }
* ```
*/
fun TestPlatformProvider.Companion.fromJsonNode(obj: JsonObject): TestPlatformProvider {
val env = obj["env"]?.jsonObject?.mapValues { it.value.jsonPrimitive.content } ?: emptyMap()
val props = obj["props"]?.jsonObject?.mapValues { it.value.jsonPrimitive.content } ?: emptyMap()
val fs = obj["fs"]?.jsonObject?.mapValues { it.value.jsonPrimitive.content } ?: emptyMap()
return TestPlatformProvider(env, props, fs)
}

/**
* Construct a [TestInstanceMetadataProvider] from a JSON object containing metadata as key-value pairs.
*/
fun TestInstanceMetadataProvider.Companion.fromJsonNode(obj: JsonObject): TestInstanceMetadataProvider {
val metadata = obj.jsonObject.mapValues { it.value.jsonPrimitive.content }
return TestInstanceMetadataProvider(metadata)
fun testSuite() = runRegionProviderChainTestSuite(REGION_PROVIDER_CHAIN_TEST_SUITE)
}

// language=JSON
Expand Down Expand Up @@ -104,20 +42,6 @@ private const val REGION_PROVIDER_CHAIN_TEST_SUITE = """
"imds": {},
"region": "us-east-2"
},
{
"name": "jvm property is favored",
"platform": {
"env": {
"AWS_REGION": "us-east-2"
},
"props": {
"aws.region": "us-west-1"
},
"fs": {}
},
"imds": {},
"region": "us-west-1"
},
{
"name": "default profile",
"platform": {
Expand Down Expand Up @@ -160,31 +84,17 @@ private const val REGION_PROVIDER_CHAIN_TEST_SUITE = """
"region": "us-east-1"
},
{
"name": "jvm system properties are favored over imds",
"name": "environment variables are favored over imds",
"platform": {
"env": {
"AWS_REGION": "us-east-2"
"AWS_REGION": "us-west-1"
},
"props": {},
"fs": {}
},
"imds": {
"/latest/meta-data/placement/region": "us-east-1"
},
"region": "us-east-2"
},
{
"name": "environment variables are favored over imds",
"platform": {
"env": {},
"props": {
"aws.region": "us-west-1"
},
"fs": {}
},
"imds": {
"/latest/meta-data/placement/region": "us-east-1"
},
"region": "us-west-1"
},
{
Expand All @@ -205,3 +115,84 @@ private const val REGION_PROVIDER_CHAIN_TEST_SUITE = """
}
]
"""

private data class RegionProviderChainTest(
val name: String,
val platformProvider: TestPlatformProvider,
val instanceMetadataProvider: TestInstanceMetadataProvider,
val region: String?,
val targets: List<String> = emptyList(),
)

/**
* Construct a [TestPlatformProvider] from a JSON node like:
*
* ```json
* {
* "env": {
* "ENV_VAR": "value"
* },
* "props": {
* "aws.property": "value"
* },
* "fs": {
* "filename": "contents"
* }
* }
* ```
*/
/**
* Construct a [TestPlatformProvider] from a JSON node like:
*
* ```json
* {
* "env": {
* "ENV_VAR": "value"
* },
* "props": {
* "aws.property": "value"
* },
* "fs": {
* "filename": "contents"
* }
* }
* ```
*/
private fun TestPlatformProvider.Companion.fromJsonNode(obj: JsonObject): TestPlatformProvider {
val env = obj["env"]?.jsonObject?.mapValues { it.value.jsonPrimitive.content } ?: emptyMap()
val props = obj["props"]?.jsonObject?.mapValues { it.value.jsonPrimitive.content } ?: emptyMap()
val fs = obj["fs"]?.jsonObject?.mapValues { it.value.jsonPrimitive.content } ?: emptyMap()
return TestPlatformProvider(env, props, fs)
}

/**
* Construct a [TestInstanceMetadataProvider] from a JSON object containing metadata as key-value pairs.
*/
/**
* Construct a [TestInstanceMetadataProvider] from a JSON object containing metadata as key-value pairs.
*/
private fun TestInstanceMetadataProvider.Companion.fromJsonNode(obj: JsonObject): TestInstanceMetadataProvider {
val metadata = obj.jsonObject.mapValues { it.value.jsonPrimitive.content }
return TestInstanceMetadataProvider(metadata)
}

internal fun runRegionProviderChainTestSuite(testSuite: String) = runBlocking {
val tests = Json.parseToJsonElement(testSuite).jsonArray
.map { it.jsonObject }
.map {
val name = it["name"]!!.jsonPrimitive.content
val platform = TestPlatformProvider.fromJsonNode(it["platform"]!!.jsonObject)
val instanceMetadata = TestInstanceMetadataProvider.fromJsonNode(it["imds"]!!.jsonObject)
val region = it["region"]!!.jsonPrimitive.contentOrNull
RegionProviderChainTest(name, platform, instanceMetadata, region)
}

tests.forEach { test ->
val provider = DefaultRegionProviderChain(
platformProvider = test.platformProvider,
imdsClient = lazy { test.instanceMetadataProvider },
)
val actual = provider.getRegion()
assertEquals(test.region, actual, test.name)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package aws.sdk.kotlin.runtime.region

import kotlin.test.Test

class DefaultRegionProviderChainTestJVM {
@Test
fun testSuite() = runRegionProviderChainTestSuite(JVM_REGION_PROVIDER_CHAIN_TEST_SUITE)
}

// language=JSON
private const val JVM_REGION_PROVIDER_CHAIN_TEST_SUITE = """
[
{
"name": "jvm property is favored",
"platform": {
"env": {
"AWS_REGION": "us-east-2"
},
"props": {
"aws.region": "us-west-1"
},
"fs": {}
},
"imds": {},
"region": "us-west-1"
},
{
"name": "jvm system properties are favored over imds",
"platform": {
"env": {},
"props": {
"aws.region": "us-east-2"
},
"fs": {}
},
"imds": {
"/latest/meta-data/placement/region": "us-east-1"
},
"region": "us-east-2"
}
]
"""
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,19 @@ internal actual suspend fun executeCommand(
}

val shell = when (platformProvider.osInfo().family) {
OsFamily.Windows -> "cmd.exe"
else -> "sh"
OsFamily.Windows -> "C:\\Windows\\System32\\cmd.exe"
else -> "/bin/sh"
}

val shellArg = when (platformProvider.osInfo().family) {
OsFamily.Windows -> "/C"
else -> "-c"
}

val argv = memScoped { (arrayOf(shell, shellArg, command).map { it.cstr.ptr } + null).toCValues() }
execvp(shell, argv)
memScoped {
val argv = (arrayOf(shell, shellArg, command).map { it.cstr.ptr } + null).toCValues()
execvp(shell, argv)
}
_exit(127) // If exec fails
}

Expand Down
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
import aws.sdk.kotlin.gradle.dsl.configureLinting
import aws.sdk.kotlin.gradle.dsl.configureNexus
import aws.sdk.kotlin.gradle.kmp.configureIosSimulatorTasks
import aws.sdk.kotlin.gradle.util.typedProp
import java.net.URL

Expand All @@ -23,6 +24,7 @@ plugins {
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.aws.kotlin.repo.tools.artifactsizemetrics)
alias(libs.plugins.aws.kotlin.repo.tools.kmp)
}

artifactSizeMetrics {
Expand Down Expand Up @@ -116,6 +118,8 @@ allprojects {

// Enables running `./gradlew allDeps` to get a comprehensive list of dependencies for every subproject
tasks.register<DependencyReportTask>("allDeps") { }

configureIosSimulatorTasks()
}

project.afterEvaluate {
Expand Down
Loading