Skip to content

Commit 8d422e1

Browse files
authored
feat: Account ID-based endpoints (#880)
1 parent c1adba4 commit 8d422e1

File tree

12 files changed

+58
-66
lines changed

12 files changed

+58
-66
lines changed

Sources/SmithyIdentity/AWSCredentialIdentity.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import struct Foundation.Date
1414
public struct AWSCredentialIdentity: Identity {
1515
public let accessKey: String
1616
public let secret: String
17+
public let accountID: String?
1718
public let sessionToken: String?
1819
public let expiration: Date?
1920

@@ -22,16 +23,19 @@ public struct AWSCredentialIdentity: Identity {
2223
/// - Parameters:
2324
/// - accessKey: The access key
2425
/// - secret: The secret for the provided access key
26+
/// - accountID: The account ID for the credentials, if known. Defaults to `nil`.
2527
/// - expiration: The date when the credentials will expire and no longer be valid. If value is `nil` then the credentials never expire. Defaults to `nil`
2628
/// - sessionToken: A session token for this session. Defaults to `nil`
2729
public init(
2830
accessKey: String,
2931
secret: String,
32+
accountID: String? = nil,
3033
expiration: Date? = nil,
3134
sessionToken: String? = nil
3235
) {
3336
self.accessKey = accessKey
3437
self.secret = secret
38+
self.accountID = accountID
3539
self.expiration = expiration
3640
self.sessionToken = sessionToken
3741
}

Sources/SmithyIdentity/AWSCredentialIdentityResolvers/StaticAWSCredentialIdentityResolver.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// SPDX-License-Identifier: Apache-2.0
66
//
77

8-
import class AwsCommonRuntimeKit.CredentialsProvider
8+
@_spi(AccountIDTempSupport) import class AwsCommonRuntimeKit.CredentialsProvider
99

1010
/// A credential identity resolver that provides a fixed set of credentials
1111
public struct StaticAWSCredentialIdentityResolver: AWSCredentialIdentityResolvedByCRT {
@@ -23,6 +23,6 @@ public struct StaticAWSCredentialIdentityResolver: AWSCredentialIdentityResolved
2323
accessKey: credentials.accessKey,
2424
secret: credentials.secret,
2525
sessionToken: credentials.sessionToken
26-
))
26+
), accountId: credentials.accountID)
2727
}
2828
}

Sources/SmithyIdentity/CRTAdapters/AWSCredentialIdentityUtilityInitializers.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public extension AWSCredentialIdentity {
2323
self.init(
2424
accessKey: accessKey,
2525
secret: secret,
26+
accountID: crtAWSCredentialIdentity.getAccountId(),
2627
expiration: crtAWSCredentialIdentity.getExpiration(),
2728
sessionToken: crtAWSCredentialIdentity.getSessionToken()
2829
)

Tests/SmithyIdentityTests/CustomAWSCredentialIdentityResolverTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import XCTest
99
import struct SmithyIdentity.CustomAWSCredentialIdentityResolver
1010

1111
class CustomAWSCredentialIdentityResolverTests: XCTestCase {
12+
1213
func testGetCredentials() async throws {
1314
let mockProvider = MockAWSCredentialIdentityResolver()
1415
let subject = try CustomAWSCredentialIdentityResolver(mockProvider)
1516
let credentials = try await subject.getIdentity()
1617

17-
XCTAssertEqual(credentials.accessKey, "some_access_key")
18-
XCTAssertEqual(credentials.secret, "some_secret")
18+
XCTAssertEqual(credentials.accessKey, "mock_access_key")
19+
XCTAssertEqual(credentials.secret, "mock_secret")
1920
}
2021
}

Tests/SmithyIdentityTests/MockAWSCredentialIdentityResolver.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@ import struct SmithyIdentity.AWSCredentialIdentity
1111

1212
struct MockAWSCredentialIdentityResolver: AWSCredentialIdentityResolver {
1313
let _getIdentity: () async throws -> AWSCredentialIdentity
14+
1415
init(_ _getIdentity: @escaping () async throws -> AWSCredentialIdentity) {
1516
self._getIdentity = _getIdentity
1617
}
18+
1719
init() {
1820
self._getIdentity = {
1921
AWSCredentialIdentity(
20-
accessKey: "some_access_key",
21-
secret: "some_secret"
22+
accessKey: "mock_access_key",
23+
secret: "mock_secret",
24+
accountID: "mock_account_id"
2225
)
2326
}
2427
}

Tests/SmithyIdentityTests/StaticAWSCredentialIdentityResolverTests.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ import XCTest
99
import struct SmithyIdentity.StaticAWSCredentialIdentityResolver
1010

1111
class StaticAWSCredentialIdentityResolverTests: XCTestCase {
12+
1213
func testGetCredentials() async throws {
1314
let subject = try StaticAWSCredentialIdentityResolver(.init(
14-
accessKey: "some_access_key",
15-
secret: "some_secret"
15+
accessKey: "static_access_key",
16+
secret: "static_secret",
17+
accountID: "static_account_id"
1618
))
1719
let credentials = try await subject.getIdentity()
1820

19-
XCTAssertEqual(credentials.accessKey, "some_access_key")
20-
XCTAssertEqual(credentials.secret, "some_secret")
21+
XCTAssertEqual(credentials.accessKey, "static_access_key")
22+
XCTAssertEqual(credentials.secret, "static_secret")
23+
XCTAssertEqual(credentials.accountID, "static_account_id")
2124
}
2225
}

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/endpoints/EndpointResolverGenerator.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ class EndpointResolverGenerator(
3030
it.write("")
3131
renderResolver(it, ruleSet)
3232
renderStaticResolver(it)
33-
val inputSymbol = Symbol.builder().name("HTTPRequestBuilder").build()
34-
val outputSymbol = Symbol.builder().name("OperationStackOutput").build()
35-
val outputErrorSymbol = Symbol.builder().name("OperationStackError").build()
3633
it.write("")
3734
}
3835
}

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/endpoints/EndpointTypes.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import software.amazon.smithy.swift.codegen.model.buildSymbol
66
object EndpointTypes {
77
val EndpointResolver = symbol("EndpointResolver")
88
val EndpointParams = symbol("EndpointParams")
9-
val EndpointResolverMiddleware = symbol("EndpointResolverMiddleware")
109
val DefaultEndpointResolver = symbol("DefaultEndpointResolver")
1110

1211
private fun symbol(name: String): Symbol = buildSymbol {

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/HttpProtocolClientGenerator.kt

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import software.amazon.smithy.swift.codegen.SwiftWriter
1313
import software.amazon.smithy.swift.codegen.middleware.MiddlewareExecutionGenerator
1414
import software.amazon.smithy.swift.codegen.middleware.OperationMiddleware
1515
import software.amazon.smithy.swift.codegen.model.toUpperCamelCase
16-
import software.amazon.smithy.swift.codegen.swiftmodules.SmithyTypes
1716
import software.amazon.smithy.swift.codegen.utils.toUpperCamelCase
1817

1918
/**
@@ -52,14 +51,7 @@ open class HttpProtocolClientGenerator(
5251
writer.openBlock(" {", "}") {
5352
val operationStackName = "operation"
5453
val generator = MiddlewareExecutionGenerator(ctx, writer, httpBindingResolver, httpProtocolCustomizable, operationMiddleware, operationStackName)
55-
generator.render(serviceShape, it) { writer, labelMemberName ->
56-
writer.write(
57-
"throw \$N.unknownError(\"uri component \$L unexpectedly nil\")",
58-
SmithyTypes.ClientError,
59-
labelMemberName,
60-
)
61-
}
62-
54+
generator.render(serviceShape, it)
6355
writer.write("return try await op.execute(input: input)")
6456
}
6557
writer.write("")

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/HttpProtocolServiceClient.kt

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,11 @@ open class HttpProtocolServiceClient(
158158
private fun renderEmptyAsynchronousConfigInitializer(properties: List<ConfigProperty>) {
159159
writer.openBlock("public convenience required init() async throws {", "}") {
160160
writer.openBlock("try await self.init(", ")") {
161-
renderProperties(properties, true) {
162-
writer.format("\$L: nil", it.name)
161+
properties.forEach { property ->
162+
writer.write("\$L: nil,", property.name)
163163
}
164+
writer.unwrite(",\n")
165+
writer.write("")
164166
}
165167
}
166168
writer.write("")
@@ -190,13 +192,15 @@ open class HttpProtocolServiceClient(
190192

191193
private fun renderConfigInitializer(serviceSymbol: Symbol, properties: List<ConfigProperty>) {
192194
writer.openBlock("private init(", ") {") {
193-
renderProperties(properties, true) {
194-
writer.format("_ \$L: \$L", it.name, it.type.renderSwiftType(writer))
195+
properties.forEach { property ->
196+
writer.write("_ \$L: \$L,", property.name, property.type.renderSwiftType(writer))
195197
}
198+
writer.unwrite(",\n")
199+
writer.write("")
196200
}
197201
writer.indent {
198-
renderProperties(properties, false) {
199-
writer.format("self.\$L = \$L", it.name, it.name)
202+
properties.forEach { property ->
203+
writer.write("self.\$L = \$L", property.name, property.name)
200204
}
201205
writer.injectSection(ConfigInitializerCustomization(serviceSymbol))
202206
}
@@ -206,19 +210,23 @@ open class HttpProtocolServiceClient(
206210

207211
private fun renderSynchronousConfigInitializer(properties: List<ConfigProperty>) {
208212
writer.openBlock("public convenience init(", ") throws {") {
209-
renderProperties(properties, true) {
210-
writer.format("\$L: \$N = nil", it.name, it.type.toOptional())
213+
properties.forEach { property ->
214+
writer.write("\$L: \$N = nil,", property.name, property.type.toOptional())
211215
}
216+
writer.unwrite(",\n")
217+
writer.write("")
212218
}
213219
writer.indent {
214220
writer.openBlock("self.init(", ")") {
215-
renderProperties(properties, true) {
216-
if (it.default?.isAsync == true) {
217-
it.name
221+
properties.forEach { property ->
222+
if (property.default?.isAsync == true) {
223+
writer.write("\$L,", property.name)
218224
} else {
219-
it.default?.render(writer, it.name) ?: it.name
225+
writer.write("\$L,", property.default?.render(writer, property.name) ?: property.name)
220226
}
221227
}
228+
writer.unwrite(",\n")
229+
writer.write("")
222230
}
223231
}
224232
writer.write("}")
@@ -229,19 +237,23 @@ open class HttpProtocolServiceClient(
229237
if (properties.none { it.default?.isAsync == true }) return
230238

231239
writer.openBlock("public convenience init(", ") async throws {") {
232-
renderProperties(properties, true) {
233-
writer.format("\$L: \$L = nil", it.name, it.type.toOptional().renderSwiftType(writer))
240+
properties.forEach { property ->
241+
writer.write("\$L: \$L = nil,", property.name, property.type.toOptional().renderSwiftType(writer))
234242
}
243+
writer.unwrite(",\n")
244+
writer.write("")
235245
}
236246
writer.indent {
237247
writer.openBlock("self.init(", ")") {
238-
renderProperties(properties, true) {
239-
if (it.default?.isAsync == true) {
240-
it.default.render(writer)
248+
properties.forEach { property ->
249+
if (property.default?.isAsync == true) {
250+
writer.write("\$L,", property.default.render(writer))
241251
} else {
242-
it.default?.render(writer, it.name) ?: it.name
252+
writer.write("\$L,", property.default?.render(writer, property.name) ?: property.name)
243253
}
244254
}
255+
writer.unwrite(",\n")
256+
writer.write("")
245257
}
246258
}
247259
writer.write("}")
@@ -255,18 +267,4 @@ open class HttpProtocolServiceClient(
255267
.onEach { it.render(ctx, writer) }
256268
}
257269
}
258-
259-
// Renders the passed properties using the passed block to generate text,
260-
// optionally comma-separating the lines as they are rendered.
261-
protected fun renderProperties(
262-
properties: List<ConfigProperty>,
263-
commaSeparated: Boolean,
264-
block: (ConfigProperty) -> String
265-
) {
266-
val commaOrBlank = ",".takeIf { commaSeparated } ?: ""
267-
properties.forEach { property ->
268-
val separator = commaOrBlank.takeIf { property != properties.last() } ?: ""
269-
writer.write("\$L\$L", block(property), separator)
270-
}
271-
}
272270
}

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/middleware/MiddlewareExecutionGenerator.kt

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package software.amazon.smithy.swift.codegen.middleware
22

33
import software.amazon.smithy.aws.traits.auth.UnsignedPayloadTrait
4-
import software.amazon.smithy.model.Model
54
import software.amazon.smithy.model.shapes.OperationShape
65
import software.amazon.smithy.model.shapes.ServiceShape
76
import software.amazon.smithy.swift.codegen.SwiftWriter
87
import software.amazon.smithy.swift.codegen.integration.HTTPProtocolCustomizable
98
import software.amazon.smithy.swift.codegen.integration.HttpBindingResolver
109
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
1110
import software.amazon.smithy.swift.codegen.integration.middlewares.handlers.MiddlewareShapeUtils
11+
import software.amazon.smithy.swift.codegen.model.hasTrait
1212
import software.amazon.smithy.swift.codegen.model.toLowerCamelCase
13-
import software.amazon.smithy.swift.codegen.model.toUpperCamelCase
1413
import software.amazon.smithy.swift.codegen.swiftFunctionParameterIndent
1514
import software.amazon.smithy.swift.codegen.swiftmodules.ClientRuntimeTypes
1615
import software.amazon.smithy.swift.codegen.swiftmodules.SmithyHTTPAPITypes
@@ -26,16 +25,13 @@ class MiddlewareExecutionGenerator(
2625
private val operationStackName: String,
2726
private val httpMethodCallback: HttpMethodCallback? = null
2827
) {
29-
private val model: Model = ctx.model
3028
private val symbolProvider = ctx.symbolProvider
3129

3230
fun render(
3331
serviceShape: ServiceShape,
3432
op: OperationShape,
3533
flowType: ContextAttributeCodegenFlowType = ContextAttributeCodegenFlowType.NORMAL,
36-
onError: (SwiftWriter, String) -> Unit,
3734
) {
38-
val operationErrorName = "${op.toUpperCamelCase()}OutputError"
3935
val inputShape = MiddlewareShapeUtils.inputSymbol(symbolProvider, ctx.model, op)
4036
val outputShape = MiddlewareShapeUtils.outputSymbol(symbolProvider, ctx.model, op)
4137
writer.write("let context = \$N()", SmithyTypes.ContextBuilder)
@@ -91,15 +87,15 @@ class MiddlewareExecutionGenerator(
9187

9288
// FIXME it over indents if i add another indent, come up with better way to properly indent or format for swift
9389

94-
writer.write(" .withMethod(value: .$httpMethod)")
90+
writer.write(" .withMethod(value: .\$L)", httpMethod)
9591
writer.write(" .withServiceName(value: serviceName)")
96-
writer.write(" .withOperation(value: \"${op.toLowerCamelCase()}\")")
92+
writer.write(" .withOperation(value: \$S)", op.toLowerCamelCase())
9793
writer.write(" .withIdempotencyTokenGenerator(value: config.idempotencyTokenGenerator)")
9894
writer.write(" .withLogger(value: config.logger)")
9995
writer.write(" .withPartitionID(value: config.partitionID)")
10096
writer.write(" .withAuthSchemes(value: config.authSchemes ?? [])")
10197
writer.write(" .withAuthSchemeResolver(value: config.authSchemeResolver)")
102-
writer.write(" .withUnsignedPayloadTrait(value: ${op.hasTrait(UnsignedPayloadTrait::class.java)})")
98+
writer.write(" .withUnsignedPayloadTrait(value: \$L)", op.hasTrait<UnsignedPayloadTrait>())
10399
writer.write(" .withSocketTimeout(value: config.httpClientConfiguration.socketTimeout)")
104100
writer.write(" .withIdentityResolver(value: config.bearerTokenIdentityResolver, schemeID: \$S)", "smithy.api#httpBearerAuth")
105101

@@ -114,6 +110,7 @@ class MiddlewareExecutionGenerator(
114110
writer.write(" .withExpiration(value: expiration)")
115111
}
116112

113+
// Add context values for config fields
117114
val serviceShape = ctx.service
118115
httpProtocolCustomizable.renderContextAttributes(ctx, writer, serviceShape, op)
119116
writer.write(" .build()")

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/swiftmodules/ClientRuntimeTypes.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ object ClientRuntimeTypes {
6868
val EndpointsRequestContextProviding = runtimeSymbol("EndpointsRequestContextProviding", SwiftDeclaration.PROTOCOL)
6969
val EndpointError = runtimeSymbol("EndpointError", SwiftDeclaration.ENUM)
7070
val PartitionDefinition = runtimeSymbol("partitionJSON", SwiftDeclaration.LET)
71-
val EndpointsAuthSchemeResolver = runtimeSymbol("EndpointsAuthSchemeResolver", SwiftDeclaration.PROTOCOL)
72-
val DefaultEndpointsAuthSchemeResolver = runtimeSymbol("DefaultEndpointsAuthSchemeResolver", SwiftDeclaration.STRUCT)
7371
val EndpointsAuthScheme = runtimeSymbol("EndpointsAuthScheme", SwiftDeclaration.ENUM)
7472
val DefaultEndpointResolver = runtimeSymbol("DefaultEndpointResolver", SwiftDeclaration.STRUCT)
7573
val StaticEndpointResolver = runtimeSymbol("StaticEndpointResolver", SwiftDeclaration.STRUCT)
@@ -90,7 +88,6 @@ object ClientRuntimeTypes {
9088
val OrchestratorBuilder = runtimeSymbol("OrchestratorBuilder", SwiftDeclaration.CLASS)
9189
val InterceptorProvider = runtimeSymbol("InterceptorProvider", SwiftDeclaration.PROTOCOL)
9290
val HttpInterceptorProvider = runtimeSymbol("HttpInterceptorProvider", SwiftDeclaration.PROTOCOL)
93-
val HttpInterceptor = runtimeSymbol("HttpInterceptor", SwiftDeclaration.PROTOCOL)
9491
val SDKLoggingSystem = runtimeSymbol("SDKLoggingSystem", SwiftDeclaration.CLASS)
9592
}
9693

0 commit comments

Comments
 (0)