Skip to content

Commit 1416029

Browse files
authored
chore: implement route53 customization for hostzone trimming (#521)
1 parent d6563ff commit 1416029

File tree

6 files changed

+165
-0
lines changed

6 files changed

+165
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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: "ListResourceRecordSetsTrimHostedZone",
11+
documentation: "This test validates that that hosted zone is correctly trimmed",
12+
method: "GET",
13+
protocol: "aws.protocols#restXml",
14+
uri: "/2013-04-01/hostedzone/IDOFMYHOSTEDZONE/rrset",
15+
bodyMediaType: "application/xml",
16+
params: {
17+
"HostedZoneId": "/hostedzone/IDOFMYHOSTEDZONE"
18+
}
19+
}
20+
])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package software.amazon.smithy.aws.swift.codegen.customization.route53
2+
3+
import software.amazon.smithy.model.Model
4+
import software.amazon.smithy.model.shapes.MemberShape
5+
import software.amazon.smithy.model.shapes.OperationShape
6+
import software.amazon.smithy.model.shapes.Shape
7+
import software.amazon.smithy.model.shapes.ShapeId
8+
import software.amazon.smithy.model.traits.HttpLabelTrait
9+
import software.amazon.smithy.model.transform.ModelTransformer
10+
import software.amazon.smithy.swift.codegen.SwiftSettings
11+
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
12+
import software.amazon.smithy.swift.codegen.integration.SwiftIntegration
13+
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.MiddlewareShapeUtils
14+
import software.amazon.smithy.swift.codegen.middleware.OperationMiddleware
15+
import software.amazon.smithy.swift.codegen.model.hasTrait
16+
17+
private val Route53ShapeId: ShapeId = ShapeId.from("com.amazonaws.route53#AWSDnsV20130401")
18+
19+
class Route53TrimHostedZone : SwiftIntegration {
20+
override fun enabledForService(model: Model, settings: SwiftSettings): Boolean {
21+
return settings.service == Route53ShapeId
22+
}
23+
override fun preprocessModel(model: Model, settings: SwiftSettings): Model {
24+
return ModelTransformer.create().mapShapes(model) {
25+
if (isHostId(it)) {
26+
(it as MemberShape).toBuilder().addTrait(TrimHostedZone()).build()
27+
} else {
28+
it
29+
}
30+
}
31+
}
32+
33+
override fun customizeMiddleware(
34+
ctx: ProtocolGenerator.GenerationContext,
35+
operationShape: OperationShape,
36+
operationMiddleware: OperationMiddleware
37+
) {
38+
val inputShape = MiddlewareShapeUtils.inputShape(ctx.model, operationShape)
39+
val hostedZoneMember = inputShape.members().find { it.hasTrait<TrimHostedZone>() }
40+
if (hostedZoneMember != null) {
41+
StripHostedZoneURLPathMiddleware.renderMiddleware(ctx, operationShape)
42+
operationMiddleware.prependMiddleware(operationShape, StripHostedZoneUrlPathMiddlewareRenderable(ctx.model, ctx.symbolProvider))
43+
}
44+
}
45+
46+
private fun isHostId(shape: Shape): Boolean {
47+
return (shape is MemberShape && shape.target == ShapeId.from("com.amazonaws.route53#ResourceId")) && shape.hasTrait<HttpLabelTrait>() && shape.memberName == "HostedZoneId"
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package software.amazon.smithy.aws.swift.codegen.customization.route53
2+
3+
import software.amazon.smithy.codegen.core.Symbol
4+
import software.amazon.smithy.model.shapes.OperationShape
5+
import software.amazon.smithy.swift.codegen.Middleware
6+
import software.amazon.smithy.swift.codegen.MiddlewareGenerator
7+
import software.amazon.smithy.swift.codegen.SwiftDependency
8+
import software.amazon.smithy.swift.codegen.SwiftWriter
9+
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
10+
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.MiddlewareShapeUtils
11+
import software.amazon.smithy.swift.codegen.integration.steps.OperationInitializeStep
12+
13+
class StripHostedZoneURLPathMiddleware(
14+
inputSymbol: Symbol,
15+
outputSymbol: Symbol,
16+
outputErrorSymbol: Symbol,
17+
private val writer: SwiftWriter
18+
) : Middleware(writer, inputSymbol, OperationInitializeStep(inputSymbol, outputSymbol, outputErrorSymbol)) {
19+
20+
override val typeName = "${inputSymbol.name}StripHostedZoneMiddleware"
21+
22+
companion object {
23+
fun renderMiddleware(ctx: ProtocolGenerator.GenerationContext, op: OperationShape) {
24+
val inputSymbol = MiddlewareShapeUtils.inputSymbol(ctx.symbolProvider, ctx.model, op)
25+
val outputSymbol = MiddlewareShapeUtils.outputSymbol(ctx.symbolProvider, ctx.model, op)
26+
val outputErrorSymbol = MiddlewareShapeUtils.outputErrorSymbol(op)
27+
val rootNamespace = MiddlewareShapeUtils.rootNamespace(ctx.settings)
28+
val urlPathMiddlewareSymbol = Symbol.builder()
29+
.definitionFile("./$rootNamespace/models/${inputSymbol.name}+StripHostedZone.swift")
30+
.name(inputSymbol.name)
31+
.build()
32+
ctx.delegator.useShapeWriter(urlPathMiddlewareSymbol) { writer ->
33+
writer.addImport(SwiftDependency.CLIENT_RUNTIME.target)
34+
val urlPathMiddleware = StripHostedZoneURLPathMiddleware(inputSymbol, outputSymbol, outputErrorSymbol, writer)
35+
MiddlewareGenerator(writer, urlPathMiddleware).generate()
36+
}
37+
}
38+
}
39+
override fun generateInit() {
40+
// No-op
41+
}
42+
43+
override fun generateMiddlewareClosure() {
44+
writer.openBlock("guard let hostedZoneId = input.hostedZoneId else {", "}") {
45+
writer.write("return next.handle(context: context, input: input)")
46+
}
47+
writer.write("var copiedInput = input")
48+
writer.write("let stripped = hostedZoneId.stripFirstMatching(prefixes: [\"/hostedzone/\", \"hostedzone/\", \"/hostedzone\", \"hostedzone\"])")
49+
writer.write("copiedInput.hostedZoneId = stripped")
50+
}
51+
52+
override fun renderReturn() {
53+
writer.write("return next.handle(context: context, input: copiedInput)")
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package software.amazon.smithy.aws.swift.codegen.customization.route53
2+
3+
import software.amazon.smithy.codegen.core.SymbolProvider
4+
import software.amazon.smithy.model.Model
5+
import software.amazon.smithy.model.shapes.OperationShape
6+
import software.amazon.smithy.swift.codegen.SwiftWriter
7+
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.MiddlewareShapeUtils
8+
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
9+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
10+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
11+
12+
class StripHostedZoneUrlPathMiddlewareRenderable(
13+
val model: Model,
14+
val symbolProvider: SymbolProvider
15+
) : MiddlewareRenderable {
16+
override val name = "StripHostedZoneUrlPathMiddleware"
17+
18+
override val middlewareStep = MiddlewareStep.INITIALIZESTEP
19+
20+
override val position = MiddlewarePosition.AFTER
21+
22+
override fun render(writer: SwiftWriter, op: OperationShape, operationStackName: String) {
23+
val inputShapeName = MiddlewareShapeUtils.inputSymbol(symbolProvider, model, op).name
24+
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: ${inputShapeName}StripHostedZoneMiddleware())")
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package software.amazon.smithy.aws.swift.codegen.customization.route53
2+
3+
import software.amazon.smithy.model.node.Node
4+
import software.amazon.smithy.model.shapes.ShapeId
5+
import software.amazon.smithy.model.traits.AnnotationTrait
6+
7+
/**
8+
* Indicates that a member should have the `hostedzone` prefix stripped if needed
9+
*/
10+
class TrimHostedZone : AnnotationTrait(ID, Node.objectNode()) {
11+
companion object {
12+
val ID = ShapeId.from("aws.api.internal#trimHostedZone")
13+
}
14+
}

codegen/smithy-aws-swift-codegen/src/main/resources/META-INF/services/software.amazon.smithy.swift.codegen.integration.SwiftIntegration

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
software.amazon.smithy.aws.swift.codegen.AddProtocols
22
software.amazon.smithy.aws.swift.codegen.customization.s3.S3SigningConfig
33
software.amazon.smithy.aws.swift.codegen.customization.s3.S3ErrorIntegration
4+
software.amazon.smithy.aws.swift.codegen.customization.route53.Route53TrimHostedZone
45
software.amazon.smithy.aws.swift.codegen.customization.apigateway.ApiGatewayAddAcceptHeader
56
software.amazon.smithy.aws.swift.codegen.customization.glacier.GlacierAddVersionHeader
67
software.amazon.smithy.aws.swift.codegen.customization.glacier.GlacierAccountIdDefault

0 commit comments

Comments
 (0)