Skip to content

Commit

Permalink
fix: Route 53 TrimHostedZone customization is incomplete (#1445)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbelkins authored Apr 23, 2024
1 parent 6820186 commit f8cbbab
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 427 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import XCTest
import AWSRoute53

class AWSRoute53Tests: XCTestCase {
var client: Route53Client!
var hostedZoneID: String?

override func setUp() async throws {
try await super.setUp()
client = try Route53Client(region: "us-east-1")
}

override func tearDown() async throws {

// Delete the hosted zone that was created in the test.
// Note that the member with the hosted zone ID is just named 'id'
// here while it is 'hostedZoneId' below; the customization has
// been adapted to handle any member name.
let input = DeleteHostedZoneInput(id: hostedZoneID)
_ = try await client.deleteHostedZone(input: input)
client = nil
hostedZoneID = nil
}

// Tests the 'TrimHostedZone' customization by performing operations on
// AWS Route 53 that will fail if the zone ID is not correctly trimmed.
func test_route53_createsAndDeletesZoneAndRecords() async throws {

// Create reference string that is used for idempotency, and
// also use it to create a bogus web domain that is used in the test.
let ref = UUID().uuidString
let hostedZoneName = "\(ref).com."

// Create a hosted zone for the zone name created above.
// Store the hosted zone ID for future reference.
// The ID will be in the form '/hostedzone/<alphanumeric ID>'.
// The '/hostedzone/' portion of the ID at the beginning is what must be
// trimmed by the customization, and only the alphanumeric portion
// of the ID is used in the operation's request URL.
let input0 = CreateHostedZoneInput(callerReference: ref, name: hostedZoneName)
let output0 = try await client.createHostedZone(input: input0)
hostedZoneID = output0.hostedZone?.id

// Create an A record on the zone that was just made.
// ChangeResourceRecordSetsInput includes the hosted zone ID in a URL
// component.
let createBatch = Route53ClientTypes.ChangeBatch(changes:
[
Route53ClientTypes.Change(
action: .create,
resourceRecordSet: Route53ClientTypes.ResourceRecordSet(
name: "abc.\(hostedZoneName)", resourceRecords: [Route53ClientTypes.ResourceRecord(value: "1.1.1.1")], ttl: 3600, type: .a
)
),
]
)
let input1 = ChangeResourceRecordSetsInput(changeBatch: createBatch, hostedZoneId: hostedZoneID)
let output1 = try await client.changeResourceRecordSets(input: input1)

// Now delete the A record that was just created; this is necessary for the
// hosted zone to be deleted in test teardown.
let deleteBatch = Route53ClientTypes.ChangeBatch(changes:
[
Route53ClientTypes.Change(
action: .delete,
resourceRecordSet: Route53ClientTypes.ResourceRecordSet(
name: "abc.\(hostedZoneName)", resourceRecords: [Route53ClientTypes.ResourceRecord(value: "1.1.1.1")], ttl: 3600, type: .a
)
),
]
)
let input2 = ChangeResourceRecordSetsInput(changeBatch: deleteBatch, hostedZoneId: hostedZoneID)
let output2 = try await client.changeResourceRecordSets(input: input2)
}
}
Empty file.
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ let servicesWithIntegrationTests: [String] = [
"AWSEventBridge",
"AWSKinesis",
"AWSMediaConvert",
"AWSRoute53",
"AWSS3",
"AWSSQS",
"AWSSTS",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import ClientRuntime

public struct Route53TrimHostedZoneMiddleware<Input, Output>: ClientRuntime.Middleware {
public let id: Swift.String = "Route53TrimHostedZoneMiddleware"
private let prefixes = ["/hostedzone/", "hostedzone/", "/hostedzone", "hostedzone"]

private let hostedZoneIDKeyPath: WritableKeyPath<Input, String?>

public init(_ hostedZoneIDKeyPath: WritableKeyPath<Input, String?>) {
self.hostedZoneIDKeyPath = hostedZoneIDKeyPath
}

public func handle<H>(context: Context,
input: Input,
next: H) async throws -> ClientRuntime.OperationOutput<Output>
where H: Handler,
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context {
guard let hostedZoneId = input[keyPath: hostedZoneIDKeyPath] else {
return try await next.handle(context: context, input: input)
}
var copiedInput = input
let stripped = hostedZoneId.stripFirstMatching(prefixes: prefixes)
copiedInput[keyPath: hostedZoneIDKeyPath] = stripped
return try await next.handle(context: context, input: copiedInput)
}

public typealias MInput = Input
public typealias MOutput = ClientRuntime.OperationOutput<Output>
public typealias Context = ClientRuntime.HttpContext
}
Loading

0 comments on commit f8cbbab

Please sign in to comment.