From 472958442b2f1bcbe498bcf2101f1fa48d459c47 Mon Sep 17 00:00:00 2001 From: 0marperez Date: Wed, 6 Nov 2024 02:22:15 -0500 Subject: [PATCH 1/9] misc: add rules engine codegen tests --- settings.gradle.kts | 1 + tests/codegen/rules-engine/build.gradle.kts | 158 ++++++++++++++++++ .../operation-context-params.smithy | 58 +++++++ 3 files changed, 217 insertions(+) create mode 100644 tests/codegen/rules-engine/build.gradle.kts create mode 100644 tests/codegen/rules-engine/operation-context-params.smithy diff --git a/settings.gradle.kts b/settings.gradle.kts index 203fcef7b8d..6f53bf06951 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -53,6 +53,7 @@ include(":hll:hll-mapping-core") include(":services") include(":tests") include(":tests:codegen:event-stream") +include("tests:codegen:rules-engine") include(":tests:e2e-test-util") // generated services diff --git a/tests/codegen/rules-engine/build.gradle.kts b/tests/codegen/rules-engine/build.gradle.kts new file mode 100644 index 00000000000..ef35526b380 --- /dev/null +++ b/tests/codegen/rules-engine/build.gradle.kts @@ -0,0 +1,158 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +import aws.sdk.kotlin.gradle.codegen.dsl.generateSmithyProjections +import aws.sdk.kotlin.gradle.codegen.dsl.smithyKotlinPlugin +import aws.sdk.kotlin.gradle.codegen.smithyKotlinProjectionSrcDir + +plugins { + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.aws.kotlin.repo.tools.smithybuild) +} + +description = "Smithy rules engine codegen integration test suite" + +data class Test( + val projectionName: String, + val protocolName: String, + val modelTemplate: File, +) { + val model: File + get() = layout.buildDirectory.file("$projectionName/model.smithy").get().asFile +} + +val tests = listOf( + Test("operationContextParams", "operationContextParams", file("operation-context-params.smithy")), +) + +fun fillInModel(output: File, protocolName: String, template: File) { + val input = template.readText() + val opTraits = when (protocolName) { + "restJson1", "restXml" -> """@http(method: "POST", uri: "/test-eventstream", code: 200)""" + else -> "" + } + val replaced = input + .replace("{protocol-name}", protocolName) + .replace("{op-traits}", opTraits) + + output.parentFile.mkdirs() + output.writeText(replaced) +} + +val testServiceShapeId = "aws.sdk.kotlin.test#TestService" +smithyBuild { + tests.forEach { test -> + + projections.register(test.projectionName) { + imports = listOf(test.model.absolutePath) + transforms = listOf( + """ + { + "name": "includeServices", + "args": { + "services": ["$testServiceShapeId"] + } + } + """, + ) + + smithyKotlinPlugin { + serviceShapeId = testServiceShapeId + packageName = "aws.sdk.kotlin.test.${test.projectionName.lowercase()}" + packageVersion = "1.0" + buildSettings { + generateFullProject = false + generateDefaultBuildFiles = false + optInAnnotations = listOf( + "aws.smithy.kotlin.runtime.InternalApi", + "aws.sdk.kotlin.runtime.InternalSdkApi", + ) + } + } + } + } +} + +val codegen by configurations.getting +dependencies { + codegen(project(":codegen:aws-sdk-codegen")) + codegen(libs.smithy.cli) + codegen(libs.smithy.model) +} + +tasks.generateSmithyBuild { + doFirst { + tests.forEach { test -> fillInModel(test.model, test.protocolName, test.modelTemplate) } + } +} + +tasks.generateSmithyProjections { + doFirst { + // ensure the generated tests use the same version of the runtime as the aws aws-runtime + val smithyKotlinRuntimeVersion = libs.versions.smithy.kotlin.runtime.version.get() + System.setProperty("smithy.kotlin.codegen.clientRuntimeVersion", smithyKotlinRuntimeVersion) + } +} + +val optinAnnotations = listOf( + "kotlin.RequiresOptIn", + "aws.smithy.kotlin.runtime.InternalApi", + "aws.sdk.kotlin.runtime.InternalSdkApi", +) + +kotlin.sourceSets.all { + optinAnnotations.forEach { languageSettings.optIn(it) } +} + +kotlin.sourceSets.getByName("test") { + smithyBuild.projections.forEach { + kotlin.srcDir(smithyBuild.smithyKotlinProjectionSrcDir(it.name)) + } +} + +tasks.withType { + dependsOn(tasks.generateSmithyProjections) + // generated clients have quite a few warnings + kotlinOptions.allWarningsAsErrors = false +} + +tasks.test { + useJUnitPlatform() + testLogging { + events("passed", "skipped", "failed") + showStandardStreams = true + showStackTraces = true + showExceptions = true + exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL + } +} + +dependencies { + + implementation(libs.kotlinx.coroutines.core) + + testImplementation(libs.kotlin.test) + testImplementation(libs.kotlin.test.junit5) + testImplementation(libs.kotlinx.coroutines.test) + + testImplementation(libs.smithy.kotlin.smithy.test) + testImplementation(libs.smithy.kotlin.aws.signing.default) + testImplementation(libs.smithy.kotlin.telemetry.api) + + // have to manually add all the dependencies of the generated client(s) + // doing it this way (as opposed to doing what we do for protocol-tests) allows + // the tests to work without a publish to maven-local step at the cost of maintaining + // this set of dependencies manually + // <-- BEGIN GENERATED DEPENDENCY LIST --> + implementation(libs.bundles.smithy.kotlin.service.client) + implementation(libs.smithy.kotlin.aws.event.stream) + implementation(project(":aws-runtime:aws-http")) + implementation(libs.smithy.kotlin.aws.json.protocols) + implementation(libs.smithy.kotlin.serde.json) + api(project(":aws-runtime:aws-config")) + api(project(":aws-runtime:aws-core")) + api(project(":aws-runtime:aws-endpoint")) + // <-- END GENERATED DEPENDENCY LIST --> +} diff --git a/tests/codegen/rules-engine/operation-context-params.smithy b/tests/codegen/rules-engine/operation-context-params.smithy new file mode 100644 index 00000000000..c63a2756e39 --- /dev/null +++ b/tests/codegen/rules-engine/operation-context-params.smithy @@ -0,0 +1,58 @@ +$version: "2.0" +namespace aws.sdk.kotlin.test + +use aws.protocols#awsJson1_0 +use smithy.rules#operationContextParams +use smithy.rules#endpointRuleSet +use aws.api#service + +@awsJson1_0 +@service(sdkId: "OperationContextParamsTest") +@endpointRuleSet( + version: "1.0", + parameters: { + "ObjectKeys": { + "type": "stringArray", + "documentation": "A string array.", + "required": true + } + }, + rules: [ + { + "type": "endpoint", + "conditions": [], + "endpoint": { + "url": "https://static.endpoint" + } + } + ] +) +service TestService { + operations: [DeleteObjects], + version: "1" +} + +@operationContextParams( + ObjectKeys: { + path: "Delete.Objects[*].[Key][]" + } +) +operation DeleteObjects { + input: DeleteObjectsRequest +} + +structure DeleteObjectsRequest { + Delete: Delete +} + +structure Delete { + Objects: ObjectIdentifierList +} + +list ObjectIdentifierList { + member: ObjectIdentifier +} + +structure ObjectIdentifier { + Key: String +} From 7b7308836e00da347a3a3d2673127cdc0c631a13 Mon Sep 17 00:00:00 2001 From: 0marperez Date: Wed, 6 Nov 2024 10:32:10 -0500 Subject: [PATCH 2/9] Use snapshot version of smithy kotlin --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d86529cab72..533963fcac2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,8 +11,8 @@ coroutines-version = "1.9.0" atomicfu-version = "0.25.0" # smithy-kotlin codegen and runtime are versioned separately -smithy-kotlin-runtime-version = "1.3.19" -smithy-kotlin-codegen-version = "0.33.19" +smithy-kotlin-runtime-version = "1.3.20-SNAPSHOT" +smithy-kotlin-codegen-version = "0.33.20-SNAPSHOT" # codegen smithy-version = "1.51.0" From dbfb9735643e8201a053cba5bd2a0fe081857ded Mon Sep 17 00:00:00 2001 From: 0marperez Date: Wed, 6 Nov 2024 11:32:03 -0500 Subject: [PATCH 3/9] debugging: throw exception to see what metrics are strings --- .../runtime/http/interceptors/BusinessMetricsInterceptor.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt b/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt index 45acf59e5d4..ddfe0ab7808 100644 --- a/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt +++ b/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt @@ -20,6 +20,7 @@ import aws.smithy.kotlin.runtime.http.request.toBuilder public class BusinessMetricsInterceptor : HttpInterceptor { override suspend fun modifyBeforeTransmit(context: ProtocolRequestInterceptorContext): HttpRequest { context.executionContext.getOrNull(BusinessMetrics)?.let { metrics -> + throw Exception("Metrics: $metrics") val metricsString = formatMetrics(metrics) val currentUserAgentHeader = context.protocolRequest.headers[USER_AGENT] val modifiedRequest = context.protocolRequest.toBuilder() From b15358b8eff089c36c8b9aad579c5f586c0c1160 Mon Sep 17 00:00:00 2001 From: 0marperez Date: Wed, 6 Nov 2024 11:39:05 -0500 Subject: [PATCH 4/9] debugging: remove exception --- .../runtime/http/interceptors/BusinessMetricsInterceptor.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt b/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt index ddfe0ab7808..45acf59e5d4 100644 --- a/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt +++ b/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/BusinessMetricsInterceptor.kt @@ -20,7 +20,6 @@ import aws.smithy.kotlin.runtime.http.request.toBuilder public class BusinessMetricsInterceptor : HttpInterceptor { override suspend fun modifyBeforeTransmit(context: ProtocolRequestInterceptorContext): HttpRequest { context.executionContext.getOrNull(BusinessMetrics)?.let { metrics -> - throw Exception("Metrics: $metrics") val metricsString = formatMetrics(metrics) val currentUserAgentHeader = context.protocolRequest.headers[USER_AGENT] val modifiedRequest = context.protocolRequest.toBuilder() From dacc3458ed2ad86a5f74b2b1db6105bc1197cbda Mon Sep 17 00:00:00 2001 From: 0marperez Date: Wed, 6 Nov 2024 12:19:53 -0500 Subject: [PATCH 5/9] Don't depend on snapshot version of smithy kotlin --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 533963fcac2..d003593d62b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,8 +11,8 @@ coroutines-version = "1.9.0" atomicfu-version = "0.25.0" # smithy-kotlin codegen and runtime are versioned separately -smithy-kotlin-runtime-version = "1.3.20-SNAPSHOT" -smithy-kotlin-codegen-version = "0.33.20-SNAPSHOT" +smithy-kotlin-runtime-version = "1.3.20" +smithy-kotlin-codegen-version = "0.33.20" # codegen smithy-version = "1.51.0" From bbafc3fac438d014c592564aa04a1d25c65e668d Mon Sep 17 00:00:00 2001 From: 0marperez Date: Wed, 6 Nov 2024 12:20:40 -0500 Subject: [PATCH 6/9] Use released version --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d003593d62b..d86529cab72 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,8 +11,8 @@ coroutines-version = "1.9.0" atomicfu-version = "0.25.0" # smithy-kotlin codegen and runtime are versioned separately -smithy-kotlin-runtime-version = "1.3.20" -smithy-kotlin-codegen-version = "0.33.20" +smithy-kotlin-runtime-version = "1.3.19" +smithy-kotlin-codegen-version = "0.33.19" # codegen smithy-version = "1.51.0" From a79aa1ea29244733565c1b07d1f3ed1cb9794d01 Mon Sep 17 00:00:00 2001 From: 0marperez Date: Wed, 6 Nov 2024 13:16:25 -0500 Subject: [PATCH 7/9] PR feedback --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 6f53bf06951..c686feb4989 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -53,7 +53,7 @@ include(":hll:hll-mapping-core") include(":services") include(":tests") include(":tests:codegen:event-stream") -include("tests:codegen:rules-engine") +include(":tests:codegen:rules-engine") include(":tests:e2e-test-util") // generated services From 91abbb68fd6b7f958d9616ba31934b9be9a50581 Mon Sep 17 00:00:00 2001 From: 0marperez Date: Fri, 13 Dec 2024 16:40:47 -0500 Subject: [PATCH 8/9] Trigger CI From 4ddf8f7af38e29cc2948ceb24ce2d8a0fabdf49b Mon Sep 17 00:00:00 2001 From: 0marperez <60363173+0marperez@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:27:21 -0500 Subject: [PATCH 9/9] smithy kotlin version bump --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2e086d1301c..b0713cf239f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,8 +11,8 @@ coroutines-version = "1.9.0" atomicfu-version = "0.25.0" # smithy-kotlin codegen and runtime are versioned separately -smithy-kotlin-runtime-version = "1.3.29" -smithy-kotlin-codegen-version = "0.33.29" +smithy-kotlin-runtime-version = "1.3.30" +smithy-kotlin-codegen-version = "0.33.30" # codegen smithy-version = "1.51.0"