-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Support custom error format for Route53 ChangeResourceRecordSets…
… operation (#791) * Updates CRT to 0.5.0 * Updates CRT to 0.5.0 * Bumps CRT to 0.5.2 * Updates tests * Cleans up and adds tests * Adds tests * Addresses PR feedback * Logs when we fail to resolve a region * Updates codegen tests * Updates codegen and error models * Updates codegen * Adds customization for Route53 ChangeResourceRecordSets to handle InvalidBatchError * ktlintformat
- Loading branch information
Showing
6 changed files
with
216 additions
and
3 deletions.
There are no files selected for viewing
90 changes: 90 additions & 0 deletions
90
...zon/smithy/aws/swift/codegen/customization/route53/Route53InvalidBatchErrorIntegration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package software.amazon.smithy.aws.swift.codegen.customization.route53 | ||
|
||
import software.amazon.smithy.aws.swift.codegen.restxml.AWSRestXMLHttpResponseBindingErrorGenerator | ||
import software.amazon.smithy.model.Model | ||
import software.amazon.smithy.model.shapes.ServiceShape | ||
import software.amazon.smithy.swift.codegen.SwiftDelegator | ||
import software.amazon.smithy.swift.codegen.SwiftDependency | ||
import software.amazon.smithy.swift.codegen.SwiftSettings | ||
import software.amazon.smithy.swift.codegen.SwiftWriter | ||
import software.amazon.smithy.swift.codegen.core.CodegenContext | ||
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator | ||
import software.amazon.smithy.swift.codegen.integration.SectionWriter | ||
import software.amazon.smithy.swift.codegen.integration.SectionWriterBinding | ||
import software.amazon.smithy.swift.codegen.integration.SwiftIntegration | ||
import software.amazon.smithy.swift.codegen.model.expectShape | ||
|
||
class Route53InvalidBatchErrorIntegration : SwiftIntegration { | ||
override fun enabledForService(model: Model, settings: SwiftSettings): Boolean { | ||
return model.expectShape<ServiceShape>(settings.service).isRoute53 | ||
} | ||
|
||
override val sectionWriters: List<SectionWriterBinding> | ||
get() = listOf( | ||
SectionWriterBinding(AWSRestXMLHttpResponseBindingErrorGenerator.RestXMLResponseBindingSectionId, httpResponseBindingErrorGenerator) | ||
) | ||
|
||
private val httpResponseBindingErrorGenerator = SectionWriter { writer, previousCode -> | ||
val operationErrorName = writer.getContext("operationErrorName") as String | ||
if (operationErrorName == "ChangeResourceRecordSetsOutputError") { | ||
writer.openBlock("if let customBatchError = CustomInvalidBatchError.makeFromHttpResponse(httpResponse) {", "}") { | ||
writer.openBlock("let invalidChangeBatchError = InvalidChangeBatch(", ")") { | ||
writer.write("customError: customBatchError,") | ||
writer.write("headers: httpResponse.headers,") | ||
writer.write("statusCode: httpResponse.statusCode") | ||
} | ||
writer.write("self = .invalidChangeBatch(invalidChangeBatchError)") | ||
writer.write("return") | ||
} | ||
} | ||
writer.write(previousCode) | ||
} | ||
|
||
override fun writeAdditionalFiles(ctx: CodegenContext, protocolGenerationContext: ProtocolGenerator.GenerationContext, delegator: SwiftDelegator) { | ||
delegator.useFileWriter("${ctx.settings.moduleName}/models/ChangeResourceRecordSetsOutputError+Customization.swift") { writer -> | ||
writer.addImport(SwiftDependency.CLIENT_RUNTIME.target) | ||
renderCustomInvalidBatchError(writer) | ||
renderInvalidChangeBatch(writer) | ||
} | ||
} | ||
|
||
private fun renderCustomInvalidBatchError(writer: SwiftWriter) { | ||
writer.openBlock("struct CustomInvalidBatchError: Decodable {", "}") { | ||
writer.openBlock("struct Message: Decodable {", "}") { | ||
writer.write("let message: String") | ||
writer.openBlock("enum CodingKeys: String, CodingKey {", "}") { | ||
writer.write("case message = \"Message\"") | ||
} | ||
} | ||
writer.write("let requestId: String") | ||
writer.write("let messages: [String]?") | ||
writer.openBlock("enum CodingKeys: String, CodingKey {", "}") { | ||
writer.write("case messages = \"Messages\"") | ||
writer.write("case requestId = \"RequestId\"") | ||
} | ||
writer.openBlock("init(from decoder: Decoder) throws {", "}") { | ||
writer.write("let container = try decoder.container(keyedBy: CodingKeys.self)") | ||
writer.write("self.requestId = try container.decode(String.self, forKey: .requestId)") | ||
writer.write("let messages = try container.decodeIfPresent([Message].self, forKey: .messages)") | ||
writer.write("self.messages = messages?.map(\\.message)") | ||
} | ||
writer.openBlock("static func makeFromHttpResponse(_ httpResponse: ClientRuntime.HttpResponse) -> CustomInvalidBatchError? {", "}") { | ||
writer.openBlock("guard let data = httpResponse.body.toBytes()?.getData() else {", "}") { | ||
writer.write("return nil") | ||
} | ||
writer.write("return try? XMLDecoder().decode(CustomInvalidBatchError.self, from: data)") | ||
} | ||
} | ||
} | ||
|
||
private fun renderInvalidChangeBatch(writer: SwiftWriter) { | ||
writer.openBlock("extension InvalidChangeBatch {", "}") { | ||
writer.openBlock("init(customError: CustomInvalidBatchError, headers: Headers?, statusCode: HttpStatusCode?) {", "}") { | ||
writer.write("self.init(messages: customError.messages)") | ||
writer.write("self._requestID = customError.requestId") | ||
writer.write("self._headers = headers") | ||
writer.write("self._statusCode = statusCode") | ||
} | ||
} | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...otlin/software/amazon/smithy/aws/swift/codegen/customization/route53/Route53ModelUtils.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package software.amazon.smithy.aws.swift.codegen.customization.route53 | ||
|
||
import software.amazon.smithy.aws.swift.codegen.sdkId | ||
import software.amazon.smithy.model.shapes.ServiceShape | ||
|
||
val ServiceShape.isRoute53: Boolean | ||
get() = sdkId.lowercase() == "route53" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
...mazon/smithy/aws/swift/codegen/customizations/Route53InvalidBatchErrorIntegrationTests.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package software.amazon.smithy.aws.swift.codegen.customizations | ||
|
||
import io.kotest.matchers.string.shouldContainOnlyOnce | ||
import org.junit.jupiter.api.Test | ||
import software.amazon.smithy.aws.swift.codegen.TestContext | ||
import software.amazon.smithy.aws.swift.codegen.TestContextGenerator | ||
import software.amazon.smithy.aws.swift.codegen.shouldSyntacticSanityCheck | ||
import software.amazon.smithy.aws.traits.protocols.RestXmlTrait | ||
|
||
class Route53InvalidBatchErrorIntegrationTests { | ||
|
||
@Test | ||
fun `001 test additional structs and extensions are generated`() { | ||
val context = setupTests("route53-invalidbatch.smithy", "com.amazonaws.route53#Route53") | ||
val contents = TestContextGenerator.getFileContents(context.manifest, "/Example/models/ChangeResourceRecordSetsOutputError+Customization.swift") | ||
contents.shouldSyntacticSanityCheck() | ||
val expectedContents = | ||
""" | ||
struct CustomInvalidBatchError: Decodable { | ||
struct Message: Decodable { | ||
let message: String | ||
enum CodingKeys: String, CodingKey { | ||
case message = "Message" | ||
} | ||
} | ||
let requestId: String | ||
let messages: [String]? | ||
enum CodingKeys: String, CodingKey { | ||
case messages = "Messages" | ||
case requestId = "RequestId" | ||
} | ||
init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
self.requestId = try container.decode(String.self, forKey: .requestId) | ||
let messages = try container.decodeIfPresent([Message].self, forKey: .messages) | ||
self.messages = messages?.map(\.message) | ||
} | ||
static func makeFromHttpResponse(_ httpResponse: ClientRuntime.HttpResponse) -> CustomInvalidBatchError? { | ||
guard let data = httpResponse.body.toBytes()?.getData() else { | ||
return nil | ||
} | ||
return try? XMLDecoder().decode(CustomInvalidBatchError.self, from: data) | ||
} | ||
} | ||
extension InvalidChangeBatch { | ||
init(customError: CustomInvalidBatchError, headers: Headers?, statusCode: HttpStatusCode?) { | ||
self.init(messages: customError.messages) | ||
self._requestID = customError.requestId | ||
self._headers = headers | ||
self._statusCode = statusCode | ||
} | ||
} | ||
""".trimIndent() | ||
contents.shouldContainOnlyOnce(expectedContents) | ||
} | ||
|
||
@Test | ||
fun `002 test ChangeResourceRecordSetsOutputError+HttpResponseBinding is customized`() { | ||
val context = setupTests("route53-invalidbatch.smithy", "com.amazonaws.route53#Route53") | ||
val contents = TestContextGenerator.getFileContents(context.manifest, "/Example/models/ChangeResourceRecordSetsOutputError+HttpResponseBinding.swift") | ||
contents.shouldSyntacticSanityCheck() | ||
val expectedContents = | ||
""" | ||
extension ChangeResourceRecordSetsOutputError: ClientRuntime.HttpResponseBinding { | ||
public init(httpResponse: ClientRuntime.HttpResponse, decoder: ClientRuntime.ResponseDecoder? = nil) throws { | ||
if let customBatchError = CustomInvalidBatchError.makeFromHttpResponse(httpResponse) { | ||
let invalidChangeBatchError = InvalidChangeBatch( | ||
customError: customBatchError, | ||
headers: httpResponse.headers, | ||
statusCode: httpResponse.statusCode | ||
) | ||
self = .invalidChangeBatch(invalidChangeBatchError) | ||
return | ||
} | ||
let errorDetails = try AWSClientRuntime.RestXMLError(httpResponse: httpResponse) | ||
try self.init(errorType: errorDetails.errorCode, httpResponse: httpResponse, decoder: decoder, message: errorDetails.message, requestID: errorDetails.requestId) | ||
} | ||
} | ||
""".trimIndent() | ||
contents.shouldContainOnlyOnce(expectedContents) | ||
} | ||
|
||
private fun setupTests(smithyFile: String, serviceShapeId: String): TestContext { | ||
val context = TestContextGenerator.initContextFrom(smithyFile, serviceShapeId, RestXmlTrait.ID) | ||
return context | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
...n/src/test/resources/software.amazon.smithy.aws.swift.codegen/route53-invalidbatch.smithy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
$version: "1.0" | ||
namespace com.amazonaws.route53 | ||
|
||
use aws.api#service | ||
use aws.protocols#restXml | ||
|
||
@service(sdkId: "Route53") | ||
@restXml | ||
service Route53 { | ||
version: "2019-12-16", | ||
operations: [ChangeResourceRecordSets] | ||
} | ||
|
||
@http(uri: "/ChangeResourceRecordSets", method: "POST") | ||
operation ChangeResourceRecordSets { | ||
input: InputOutput | ||
output: InputOutput | ||
errors: [InvalidChangeBatch] | ||
} | ||
|
||
structure InputOutput { | ||
foo: String | ||
} | ||
|
||
@error("client") | ||
structure InvalidChangeBatch { | ||
message: String | ||
} |