Skip to content

Commit c8b6844

Browse files
authored
feat: implement automatic prefix trimming for route53 resource ids (#655)
1 parent 9303e68 commit c8b6844

File tree

4 files changed

+155
-0
lines changed

4 files changed

+155
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "8fa79617-cfb4-48f2-a031-32ee2f0341b3",
3+
"type": "feature",
4+
"description": "Implement ID prefix trimming for route53 resources.",
5+
"issues": [
6+
"awslabs/aws-sdk-kotlin#509"
7+
]
8+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package aws.sdk.kotlin.codegen.customization.route53
2+
3+
import aws.sdk.kotlin.codegen.sdkId
4+
import software.amazon.smithy.kotlin.codegen.KotlinSettings
5+
import software.amazon.smithy.kotlin.codegen.core.*
6+
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration
7+
import software.amazon.smithy.kotlin.codegen.model.expectShape
8+
import software.amazon.smithy.kotlin.codegen.model.hasTrait
9+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
10+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolMiddleware
11+
import software.amazon.smithy.kotlin.codegen.utils.getOrNull
12+
import software.amazon.smithy.model.Model
13+
import software.amazon.smithy.model.shapes.MemberShape
14+
import software.amazon.smithy.model.shapes.OperationShape
15+
import software.amazon.smithy.model.shapes.ServiceShape
16+
import software.amazon.smithy.model.shapes.StructureShape
17+
import software.amazon.smithy.model.traits.HttpLabelTrait
18+
19+
class TrimResourcePrefix : KotlinIntegration {
20+
override fun enabledForService(model: Model, settings: KotlinSettings) =
21+
model.expectShape<ServiceShape>(settings.service).sdkId.equals("route 53", ignoreCase = true)
22+
23+
override fun customizeMiddleware(
24+
ctx: ProtocolGenerator.GenerationContext,
25+
resolved: List<ProtocolMiddleware>
26+
): List<ProtocolMiddleware> =
27+
resolved + TrimResourcePrefixMiddleware()
28+
}
29+
30+
private class TrimResourcePrefixMiddleware : ProtocolMiddleware {
31+
override val name: String
32+
get() = "TrimResourcePrefix"
33+
34+
override val order: Byte = -128
35+
36+
override fun isEnabledFor(ctx: ProtocolGenerator.GenerationContext, op: OperationShape): Boolean {
37+
val input = op.input.getOrNull()?.let { ctx.model.expectShape<StructureShape>(it) }
38+
return input?.members()?.any(MemberShape::shouldTrimResourcePrefix) ?: false
39+
}
40+
41+
override fun render(ctx: ProtocolGenerator.GenerationContext, op: OperationShape, writer: KotlinWriter) {
42+
val pathMember = ctx.model.expectShape<StructureShape>(op.input.get()).members().first(
43+
MemberShape::shouldTrimResourcePrefix
44+
).defaultName()
45+
46+
writer.withBlock("op.execution.initialize.intercept { req, next -> ", "}") {
47+
write("""val prefix = "^/?.*?/".toRegex()""")
48+
withBlock("if (req.subject.#L?.contains(prefix) == true) {", "}", pathMember) {
49+
write(
50+
"""val updated = req.subject.copy { #L = req.subject.#L?.replace(prefix, "") }""",
51+
pathMember,
52+
pathMember,
53+
)
54+
write("next.call(#T(req.context, updated))", RuntimeTypes.Http.Operation.OperationRequest)
55+
}
56+
withBlock("else {", "}") {
57+
write("next.call(req)")
58+
}
59+
}
60+
}
61+
}
62+
63+
private fun MemberShape.shouldTrimResourcePrefix(): Boolean =
64+
(target.name == "ResourceId" || target.name == "ChangeId") &&
65+
hasTrait<HttpLabelTrait>()

codegen/smithy-aws-kotlin-codegen/src/main/resources/META-INF/services/software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ aws.sdk.kotlin.codegen.customization.machinelearning.MachineLearningEndpointCust
1919
aws.sdk.kotlin.codegen.customization.BackfillOptionalAuth
2020
aws.sdk.kotlin.codegen.customization.RemoveEventStreamOperations
2121
aws.sdk.kotlin.codegen.customization.RemoveChecksumSelectionFields
22+
aws.sdk.kotlin.codegen.customization.route53.TrimResourcePrefix
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
$version: "1.0"
2+
3+
namespace com.amazonaws.route53
4+
5+
use smithy.test#httpRequestTests
6+
7+
8+
apply ListResourceRecordSets @httpRequestTests([
9+
{
10+
id: "ListResourceRecordSetsNoTrim",
11+
documentation: "Validates that HostedZoneId isn't trimmed when not prefixed.",
12+
method: "GET",
13+
protocol: "aws.protocols#restXml",
14+
uri: "/2013-04-01/hostedzone/IDOFMYHOSTEDZONE/rrset",
15+
bodyMediaType: "application/xml",
16+
params: {
17+
"HostedZoneId": "IDOFMYHOSTEDZONE"
18+
}
19+
},
20+
{
21+
id: "ListResourceRecordSetsTrim",
22+
documentation: "Validates that HostedZoneId is trimmed.",
23+
method: "GET",
24+
protocol: "aws.protocols#restXml",
25+
uri: "/2013-04-01/hostedzone/IDOFMYHOSTEDZONE/rrset",
26+
bodyMediaType: "application/xml",
27+
params: {
28+
"HostedZoneId": "hostedzone/IDOFMYHOSTEDZONE"
29+
}
30+
},
31+
{
32+
id: "ListResourceRecordSetsTrimLeadingSlash",
33+
documentation: "Validates that HostedZoneId is trimmed even with a leading slash.",
34+
method: "GET",
35+
protocol: "aws.protocols#restXml",
36+
uri: "/2013-04-01/hostedzone/IDOFMYHOSTEDZONE/rrset",
37+
bodyMediaType: "application/xml",
38+
params: {
39+
"HostedZoneId": "/hostedzone/IDOFMYHOSTEDZONE"
40+
}
41+
},
42+
{
43+
id: "ListResourceRecordSetsTrimMultislash",
44+
documentation: "Validates that HostedZoneId isn't over-trimmed.",
45+
method: "GET",
46+
protocol: "aws.protocols#restXml",
47+
uri: "/2013-04-01/hostedzone/IDOFMY%2FHOSTEDZONE/rrset",
48+
bodyMediaType: "application/xml",
49+
params: {
50+
"HostedZoneId": "/hostedzone/IDOFMY/HOSTEDZONE"
51+
}
52+
},
53+
])
54+
55+
apply GetChange @httpRequestTests([
56+
{
57+
id: "GetChangeTrimChangeId",
58+
documentation: "This test validates that change id is correctly trimmed",
59+
method: "GET",
60+
protocol: "aws.protocols#restXml",
61+
uri: "/2013-04-01/change/SOMECHANGEID",
62+
bodyMediaType: "application/xml",
63+
params: {
64+
"Id": "/change/SOMECHANGEID"
65+
}
66+
},
67+
])
68+
69+
apply GetReusableDelegationSet @httpRequestTests([
70+
{
71+
id: "GetReusableDelegationSetTrimDelegationSetId",
72+
documentation: "This test validates that delegation set id is correctly trimmed",
73+
method: "GET",
74+
protocol: "aws.protocols#restXml",
75+
uri: "/2013-04-01/delegationset/DELEGATIONSETID",
76+
bodyMediaType: "application/xml",
77+
params: {
78+
"Id": "/delegationset/DELEGATIONSETID"
79+
}
80+
},
81+
])

0 commit comments

Comments
 (0)