Skip to content

Commit f204447

Browse files
authored
feat: autofill Glacier accountId (#301)
1 parent 28d4008 commit f204447

File tree

11 files changed

+167
-29
lines changed

11 files changed

+167
-29
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import Builder
2+
import argparse
3+
import os
4+
import sys
5+
6+
class SetUpstreamVersions(Builder.Action):
7+
"""
8+
Inspects the upstream dependencies for their actual versions and replaces them in `aws-sdk-kotlin/gradle.properties`.
9+
10+
This ensures that when `aws-sdk-kotlin` is built with a dependency from a branch that has declared a different version
11+
than what is set in `gradle.properties` that it works correctly.
12+
"""
13+
14+
def run(self, env):
15+
if env.project.name != "aws-sdk-kotlin":
16+
# not the root project, probably building as a consumer
17+
proj = Builder.Project.find_project("aws-sdk-kotlin")
18+
else:
19+
proj = env.project
20+
21+
deps = proj.config.get("upstream")
22+
23+
discovered_versions = {}
24+
for d in deps:
25+
dep_version = _get_dependency_version(env, d)
26+
if dep_version is not None:
27+
discovered_versions[d.name] = dep_version
28+
29+
print("discovered dependency versions: {}".format(discovered_versions))
30+
if "smithy-kotlin" in discovered_versions:
31+
_replace_gradle_property(proj, "smithyKotlinVersion", discovered_versions["smithy-kotlin"])
32+
33+
if "aws-crt-kotlin" in discovered_versions:
34+
_replace_gradle_property(proj, "crtKotlinVersion", discovered_versions["aws-crt-kotlin"])
35+
36+
37+
def _replace_gradle_property(proj, prop_name, new_value):
38+
"""
39+
Replaces the named property with the value if property name exists in gradle.properties
40+
"""
41+
gradle_props = os.path.join(proj.path, "gradle.properties")
42+
43+
with open(gradle_props, "r") as f:
44+
lines = f.readlines()
45+
46+
with open(gradle_props, "w") as f:
47+
for line in lines:
48+
needle = "{}=".format(prop_name)
49+
if needle in line:
50+
replacement = "{}={}\n".format(prop_name, new_value)
51+
f.write(replacement)
52+
print("replaced {} with {}".format(line.strip(), replacement.strip()))
53+
else:
54+
f.write(line)
55+
56+
57+
def _get_dependency_version(env, dep):
58+
"""
59+
Gets the version of the dependency actually used. This may be different than what
60+
we have set in our gradle.properties. We need to use the version of the dependency
61+
actually downloaded
62+
"""
63+
dep_root = os.path.join(env.deps_dir, dep.name)
64+
dep_gradle_props = os.path.join(dep_root, "gradle.properties")
65+
if not os.path.exists(dep_gradle_props):
66+
dep_proj = Builder.Project.find_project(dep.name)
67+
dep_gradle_props = os.path.join(dep_proj.path, "gradle.properties")
68+
if not os.path.exists(dep_gradle_props):
69+
return None
70+
71+
with open(dep_gradle_props, "r") as f:
72+
lines = f.readlines()
73+
version = next(filter(lambda x: "sdkVersion=" in x, lines), None)
74+
75+
if version is None:
76+
return None
77+
78+
return version.split("=")[1].strip()

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ workspace.xml
1010
build/
1111
*.iml
1212
.idea/
13+
__pycache__/
1314
local.properties
1415
# ignore generated files
1516
services/*/generated-src

builder.json

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
"variables": {
66
"gradlew": "{source_dir}/gradlew -p {source_dir}"
77
},
8+
"build_dir": "target/build",
9+
"imports": [
10+
"JDK8"
11+
],
12+
"env": {
13+
"JAVA_HOME": "{java_home}"
14+
},
15+
"_comment": "prebuild step defined in .builder/actions/set_upstream_versions.py",
16+
"pre_build_steps": [
17+
"set-upstream-versions"
18+
],
819
"build_steps": [
920
"{gradlew} assemble --parallel"
1021
],
@@ -13,13 +24,6 @@
1324
"{gradlew} test allTests",
1425
"{gradlew} testAllProtocols"
1526
],
16-
"imports": [
17-
"JDK8"
18-
],
19-
"build_dir": "target/build",
20-
"env": {
21-
"JAVA_HOME": "{java_home}"
22-
},
2327
"upstream": [
2428
{
2529
"name": "smithy-kotlin"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
6+
package aws.sdk.kotlin.codegen.customization.glacier
7+
8+
import aws.sdk.kotlin.codegen.sdkId
9+
import software.amazon.smithy.kotlin.codegen.KotlinSettings
10+
import software.amazon.smithy.kotlin.codegen.core.*
11+
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration
12+
import software.amazon.smithy.kotlin.codegen.model.expectShape
13+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
14+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
15+
import software.amazon.smithy.kotlin.codegen.utils.getOrNull
16+
import software.amazon.smithy.model.Model
17+
import software.amazon.smithy.model.shapes.*
18+
19+
/**
20+
* Adds a middleware for Glacier to autofill accountId when not set
21+
* See: https://github.com/awslabs/aws-sdk-kotlin/issues/246
22+
*/
23+
class GlacierAccountIdDefault : KotlinIntegration {
24+
override fun enabledForService(model: Model, settings: KotlinSettings): Boolean =
25+
model.expectShape<ServiceShape>(settings.service).sdkId.equals("Glacier", ignoreCase = true)
26+
27+
override fun customizeMiddleware(
28+
ctx: ProtocolGenerator.GenerationContext,
29+
resolved: List<ProtocolMiddleware>
30+
): List<ProtocolMiddleware> {
31+
return resolved + GlacierAccountIdMiddleware()
32+
}
33+
}
34+
35+
private class GlacierAccountIdMiddleware : ProtocolMiddleware {
36+
override val name: String
37+
get() = "GlacierAccountIdAutoFill"
38+
39+
override val order: Byte = -100
40+
41+
override fun isEnabledFor(ctx: ProtocolGenerator.GenerationContext, op: OperationShape): Boolean {
42+
val input = op.input.getOrNull()?.let { ctx.model.expectShape<StructureShape>(it) }
43+
return input?.memberNames?.any { it.lowercase() == "accountid" } ?: false
44+
}
45+
46+
override fun render(ctx: ProtocolGenerator.GenerationContext, op: OperationShape, writer: KotlinWriter) {
47+
val accountId = ctx.model.expectShape<StructureShape>(op.input.get()).members().first { it.memberName.lowercase() == "accountid" }
48+
writer.addImport(RuntimeTypes.Http.Operation.OperationRequest)
49+
50+
writer.withBlock("execution.initialize.intercept { req, next -> ", "}") {
51+
openBlock("if (req.subject.#L.isNullOrEmpty()) {", accountId.defaultName())
52+
.write("val updated = req.subject.copy { #L = #S }", accountId.defaultName(), "-")
53+
.write("next.call(#T(req.context, updated))", RuntimeTypes.Http.Operation.OperationRequest)
54+
.closeAndOpenBlock("} else {")
55+
.write("next.call(req)")
56+
.closeBlock("}")
57+
}
58+
}
59+
}

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/protocols/core/AwsHttpBindingProtocolGenerator.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ abstract class AwsHttpBindingProtocolGenerator : HttpBindingProtocolGenerator()
7676
"PutAndGetInlineDocumentsInput",
7777

7878
// Glacier customizations
79-
"GlacierAccountId", // smithy-kotlin#163
8079
"GlacierChecksums", // smithy-kotlin#164
8180
"GlacierMultipartChecksums", // smithy-kotlin#164
8281
),

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/protocols/json/AwsJsonProtocolMiddleware.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import aws.sdk.kotlin.codegen.AwsKotlinDependency
99
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
1010
import software.amazon.smithy.kotlin.codegen.model.buildSymbol
1111
import software.amazon.smithy.kotlin.codegen.model.namespace
12-
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
12+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpFeatureMiddleware
1313
import software.amazon.smithy.model.shapes.ShapeId
1414

1515
/**
@@ -19,20 +19,17 @@ import software.amazon.smithy.model.shapes.ShapeId
1919
class AwsJsonProtocolMiddleware(
2020
private val serviceShapeId: ShapeId,
2121
private val protocolVersion: String
22-
) : ProtocolMiddleware {
22+
) : HttpFeatureMiddleware() {
2323
override val name: String = "AwsJsonProtocol"
24+
override val order: Byte = 10
2425

25-
override fun addImportsAndDependencies(writer: KotlinWriter) {
26-
super.addImportsAndDependencies(writer)
26+
override fun renderConfigure(writer: KotlinWriter) {
2727
val awsJsonProtocolSymbol = buildSymbol {
2828
name = "AwsJsonProtocol"
2929
namespace(AwsKotlinDependency.AWS_JSON_PROTOCOLS)
3030
}
3131

3232
writer.addImport(awsJsonProtocolSymbol)
33-
}
34-
35-
override fun renderConfigure(writer: KotlinWriter) {
3633
writer.write("serviceShapeName = #S", serviceShapeId.name)
3734
writer.write("version = #S", protocolVersion)
3835
}

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/protocols/middleware/AwsSignatureVersion4.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import software.amazon.smithy.kotlin.codegen.core.addImport
1313
import software.amazon.smithy.kotlin.codegen.model.expectShape
1414
import software.amazon.smithy.kotlin.codegen.model.expectTrait
1515
import software.amazon.smithy.kotlin.codegen.model.hasTrait
16+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpFeatureMiddleware
1617
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
17-
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
1818
import software.amazon.smithy.model.Model
1919
import software.amazon.smithy.model.knowledge.ServiceIndex
2020
import software.amazon.smithy.model.shapes.OperationShape
@@ -26,8 +26,9 @@ import software.amazon.smithy.model.traits.OptionalAuthTrait
2626
* @param signingServiceName The credential scope service name to sign for
2727
* See the `name` property of: https://awslabs.github.io/smithy/1.0/spec/aws/aws-auth.html#aws-auth-sigv4-trait
2828
*/
29-
open class AwsSignatureVersion4(private val signingServiceName: String) : ProtocolMiddleware {
29+
open class AwsSignatureVersion4(private val signingServiceName: String) : HttpFeatureMiddleware() {
3030
override val name: String = AwsRuntimeTypes.Auth.AwsSigV4SigningMiddleware.name
31+
override val order: Byte = 127
3132

3233
init {
3334
require(signingServiceName.isNotEmpty()) { "signingServiceName must be specified" }
@@ -38,12 +39,10 @@ open class AwsSignatureVersion4(private val signingServiceName: String) : Protoc
3839
return hasSigV4AuthScheme(ctx.model, service, op)
3940
}
4041

41-
override fun addImportsAndDependencies(writer: KotlinWriter) {
42+
override fun renderConfigure(writer: KotlinWriter) {
4243
writer.addImport(AwsRuntimeTypes.Auth.AwsSigV4SigningMiddleware)
4344
writer.addImport("DefaultChainCredentialsProvider", AwsKotlinDependency.AWS_AUTH)
44-
}
4545

46-
override fun renderConfigure(writer: KotlinWriter) {
4746
writer.write("credentialsProvider = config.credentialsProvider ?: DefaultChainCredentialsProvider()")
4847
writer.write("signingService = #S", signingServiceName)
4948
}

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/protocols/middleware/EndpointResolverMiddleware.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ import aws.sdk.kotlin.codegen.AwsKotlinDependency
99
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
1010
import software.amazon.smithy.kotlin.codegen.model.buildSymbol
1111
import software.amazon.smithy.kotlin.codegen.model.namespace
12+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpFeatureMiddleware
1213
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
13-
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
1414

1515
/**
1616
* HTTP client interceptor that resolves service endpoints for a single service
1717
*/
18-
class EndpointResolverMiddleware(private val ctx: ProtocolGenerator.GenerationContext) : ProtocolMiddleware {
18+
class EndpointResolverMiddleware(private val ctx: ProtocolGenerator.GenerationContext) : HttpFeatureMiddleware() {
1919
override val name: String = "ServiceEndpointResolver"
20-
override fun addImportsAndDependencies(writer: KotlinWriter) {
20+
override fun renderConfigure(writer: KotlinWriter) {
2121
val resolverFeatureSymbol = buildSymbol {
2222
name = "ServiceEndpointResolver"
2323
namespace(AwsKotlinDependency.AWS_HTTP, subpackage = "middleware")
@@ -31,9 +31,7 @@ class EndpointResolverMiddleware(private val ctx: ProtocolGenerator.GenerationCo
3131

3232
writer.addImport(resolverFeatureSymbol)
3333
writer.addImport(defaultResolverSymbol)
34-
}
3534

36-
override fun renderConfigure(writer: KotlinWriter) {
3735
writer.write("serviceId = ServiceId")
3836
writer.write("resolver = config.endpointResolver ?: DefaultEndpointResolver()")
3937
}

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/protocols/middleware/MutateHeadersMiddleware.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ package aws.sdk.kotlin.codegen.protocols.middleware
77

88
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
99
import software.amazon.smithy.kotlin.codegen.core.RuntimeTypes
10-
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
10+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpFeatureMiddleware
1111

1212
/**
1313
* General purpose middleware that allows mutation of headers
@@ -16,8 +16,9 @@ class MutateHeadersMiddleware(
1616
val extraHeaders: Map<String, String> = emptyMap(),
1717
val overrideHeaders: Map<String, String> = emptyMap(),
1818
val addMissingHeaders: Map<String, String> = emptyMap(),
19-
) : ProtocolMiddleware {
19+
) : HttpFeatureMiddleware() {
2020
override val name: String = "MutateHeaders"
21+
override val order: Byte = 10
2122
override fun renderConfigure(writer: KotlinWriter) {
2223
writer.addImport(RuntimeTypes.Http.MutateHeadersMiddleware)
2324
overrideHeaders.forEach {

codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/protocols/middleware/UserAgentMiddleware.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import aws.sdk.kotlin.codegen.AwsKotlinDependency
99
import software.amazon.smithy.kotlin.codegen.core.KotlinWriter
1010
import software.amazon.smithy.kotlin.codegen.model.buildSymbol
1111
import software.amazon.smithy.kotlin.codegen.model.namespace
12-
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
12+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpFeatureMiddleware
1313

1414
/**
1515
* Middleware that sets the User-Agent and x-amz-user-agent headers
1616
*/
17-
class UserAgentMiddleware : ProtocolMiddleware {
17+
class UserAgentMiddleware : HttpFeatureMiddleware() {
1818
override val name: String = "UserAgent"
19+
override val order: Byte = 20
1920

2021
private val uaSymbol = buildSymbol {
2122
name = "AwsUserAgentMetadata"

0 commit comments

Comments
 (0)