Skip to content

Commit b1139cf

Browse files
authored
fix: aws client config redesign (#274)
1 parent 4ef1f2a commit b1139cf

18 files changed

+184
-104
lines changed

AWSClientRuntime/Sources/AWSClientConfiguration.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

66
import ClientRuntime
77

8-
public protocol AWSClientConfiguration {
8+
public protocol AWSRuntimeConfiguration {
99
var credentialsProvider: AWSCredentialsProvider { get set }
1010
var region: String { get set }
1111
var signingRegion: String {get set}
1212
var endpointResolver: EndpointResolver {get set}
1313
}
14+
15+
public typealias AWSClientConfiguration = SDKRuntimeConfiguration & AWSRuntimeConfiguration

AWSClientRuntime/Sources/Auth/AWSCredentialsProvider.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ public class AWSCredentialsProvider {
4646
return AWSCredentialsProvider(awsCredentialsProvider: credsProvider)
4747
}
4848

49-
public static func fromChain(_ config: AWSCredentialsProviderChainDefaultConfig) throws -> AWSCredentialsProvider {
49+
public static func fromChain(shutDownCallback: ShutDownCallback? = nil) throws -> AWSCredentialsProvider {
50+
let config = AWSCredentialsProviderChainDefaultConfig(shutDownCallback: shutDownCallback)
5051
let credsProvider = try CRTAWSCredentialsProvider(fromChainDefault: config.toCRTType())
5152
return AWSCredentialsProvider(awsCredentialsProvider: credsProvider)
5253
}

AWSClientRuntime/Sources/Auth/AWSCredentialsProviderChainDefaultConfig.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ import ClientRuntime
99

1010
public struct AWSCredentialsProviderChainDefaultConfig {
1111
let shutDownCallback: ShutDownCallback?
12-
let client: CRTClientEngine
12+
13+
public init(shutDownCallback: ShutDownCallback? = nil) {
14+
self.shutDownCallback = shutDownCallback
15+
}
1316
}
1417

1518
extension AWSCredentialsProviderChainDefaultConfig {
1619
func toCRTType() -> CRTCredentialsProviderChainDefaultConfig {
17-
return CredentialsProviderChainDefaultConfig(bootstrap: client.bootstrap, shutDownOptions: shutDownCallback)
20+
return CredentialsProviderChainDefaultConfig(bootstrap: SDKDefaultIO.shared.clientBootstrap, shutDownOptions: shutDownCallback)
1821
}
1922
}
2023

README.md

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,25 +95,13 @@ let package = Package(
9595
)
9696
```
9797

98-
Update the scheme in Xcode to put your AWS credentials in env variables (we don’t have auto credential resolution quite finished yet, only 3/4 done sry)
99-
100-
Variable names are:*
101-
```
102-
AWS_ACCESS_KEY_ID
103-
AWS_SECRET_ACCESS_KEY
104-
```
105-
(if you need help with getting these values, talk to wooj@ or nickik@
106-
10798
Then you can open up main.swift, and instantiate CognitoIdentity as follows:
10899

109100
```swift
110101
import CognitoIdentity
111102
import Foundation
112103

113-
//this config file will be moved out of the client,
114-
// I realize this is a pain right now and we have an open ticket for it.
115-
let config = try! CognitoIdentityClient.CognitoIdentityClientConfiguration.default()
116-
let cognitoIdentityClient = CognitoIdentityClient(config: config)
104+
let cognitoIdentityClient = CognitoIdentityClient()
117105
let cognitoInputCall = CreateIdentityPoolInput(allowClassicFlow: nil,
118106
allowUnauthenticatedIdentities: true,
119107
cognitoIdentityProviders: nil,
@@ -136,7 +124,7 @@ cognitoIdentityClient.createIdentityPool(input: cognitoInputCall) { (result) in
136124

137125
As a result, you should be able to:
138126

139-
1. Log into your AWS console, go to us-east-1 (we default region to us-east-1, no region resolver yet)
127+
1. Log into your AWS console, go to us-east-1 (we default region to us-east-1 but you can pass in a region, no region resolver yet)
140128
2. Click on cognito
141129
3. click on cognito identity pools
142130
4. Verify that you see the newly created identity pool name: identityPoolMadeWithSwiftSDK

TestLambdaSdk/Sources/TestSdk/main.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import ClientRuntime
44

55
do {
66

7-
let config = try S3Client.S3ClientConfiguration.default()
8-
let s3Client = S3Client(config: config)
7+
let s3Client = try S3Client(region: "us-east-1")
98
guard let data = "hello".data(using: .utf8) else {
109
print("why is data empty")
1110
fatalError()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package software.amazon.smithy.aws.swift.codegen
2+
3+
import software.amazon.smithy.codegen.core.Symbol
4+
import software.amazon.smithy.swift.codegen.model.buildSymbol
5+
6+
object AWSClientRuntimeTypes {
7+
object Core {
8+
val EndpointResolver = runtimeSymbol("EndpointResolver", AWSSwiftDependency.AWS_CLIENT_RUNTIME)
9+
val CredentialsProvider = runtimeSymbol("AWSCredentialsProvider", AWSSwiftDependency.AWS_CLIENT_RUNTIME)
10+
}
11+
}
12+
13+
private fun runtimeSymbol(name: String, dependency: AWSSwiftDependency): Symbol = buildSymbol {
14+
this.name = name
15+
dependency(dependency)
16+
}

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/AWSHttpProtocolClientGeneratorFactory.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class AWSHttpProtocolClientGeneratorFactory : HttpProtocolClientGeneratorFactory
1818
): HttpProtocolClientGenerator {
1919
val serviceName = ctx.symbolProvider.toSymbol(ctx.service).name
2020
val config = AWSServiceConfig(writer, serviceName)
21-
val clientProperties = httpProtocolCustomizable.getClientProperties()
22-
return HttpProtocolClientGenerator(ctx, writer, clientProperties, config, httpBindingResolver, defaultContentType, httpProtocolCustomizable)
21+
return HttpProtocolClientGenerator(ctx, writer, config, httpBindingResolver, defaultContentType, httpProtocolCustomizable)
2322
}
2423
}

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/AWSHttpProtocolCustomizations.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import software.amazon.smithy.model.shapes.ServiceShape
1010
import software.amazon.smithy.swift.codegen.SwiftWriter
1111
import software.amazon.smithy.swift.codegen.integration.ClientProperty
1212
import software.amazon.smithy.swift.codegen.integration.DefaultHttpProtocolCustomizations
13+
import software.amazon.smithy.swift.codegen.integration.HttpProtocolServiceClient
1314
import software.amazon.smithy.swift.codegen.integration.OperationMiddlewareRenderable
1415
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
16+
import software.amazon.smithy.swift.codegen.integration.ServiceConfig
1517

1618
abstract class AWSHttpProtocolCustomizations : DefaultHttpProtocolCustomizations() {
1719
override fun baseMiddlewares(ctx: ProtocolGenerator.GenerationContext, op: OperationShape): List<OperationMiddlewareRenderable> {
@@ -57,4 +59,14 @@ abstract class AWSHttpProtocolCustomizations : DefaultHttpProtocolCustomizations
5759
properties.add(AWSHttpResponseJsonDecoder(responseDecoderOptions))
5860
return properties
5961
}
62+
63+
override fun serviceClient(
64+
ctx: ProtocolGenerator.GenerationContext,
65+
writer: SwiftWriter,
66+
serviceConfig: ServiceConfig
67+
): HttpProtocolServiceClient {
68+
writer.addImport(AWSSwiftDependency.AWS_CLIENT_RUNTIME.target)
69+
val clientProperties = getClientProperties()
70+
return AWSHttpProtocolServiceClient(ctx, writer, clientProperties, serviceConfig)
71+
}
6072
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package software.amazon.smithy.aws.swift.codegen
2+
3+
import software.amazon.smithy.codegen.core.Symbol
4+
import software.amazon.smithy.swift.codegen.SwiftWriter
5+
import software.amazon.smithy.swift.codegen.integration.ClientProperty
6+
import software.amazon.smithy.swift.codegen.integration.HttpProtocolServiceClient
7+
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
8+
import software.amazon.smithy.swift.codegen.integration.ServiceConfig
9+
10+
class AWSHttpProtocolServiceClient(
11+
ctx: ProtocolGenerator.GenerationContext,
12+
private val writer: SwiftWriter,
13+
properties: List<ClientProperty>,
14+
private val serviceConfig: ServiceConfig
15+
) : HttpProtocolServiceClient(ctx, writer, properties, serviceConfig) {
16+
override fun renderConvenienceInit(serviceSymbol: Symbol) {
17+
writer.openBlock("public convenience init(region: String? = nil) throws {", "}") {
18+
writer.write("let unwrappedRegion = region ?? \"us-east-1\"") // TODO: replace with call to region resolver
19+
writer.write("let config = try ${serviceConfig.typeName}(region: unwrappedRegion)")
20+
writer.write("self.init(config: config)")
21+
}
22+
}
23+
}

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/AWSServiceConfig.kt

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,78 @@ import software.amazon.smithy.codegen.core.Symbol
44
import software.amazon.smithy.swift.codegen.SwiftWriter
55
import software.amazon.smithy.swift.codegen.integration.ConfigField
66
import software.amazon.smithy.swift.codegen.integration.ServiceConfig
7+
import software.amazon.smithy.swift.codegen.model.buildSymbol
78

89
const val REGION_CONFIG_NAME = "region"
910
const val CREDENTIALS_PROVIDER_CONFIG_NAME = "credentialsProvider"
1011
const val SIGNING_REGION_CONFIG_NAME = "signingRegion"
1112
const val ENDPOINT_RESOLVER = "endpointResolver"
1213

13-
val AWS_CONFIG_FIELDS = listOf(
14-
ConfigField(REGION_CONFIG_NAME, "String", "The region to send requests to. (Required)"),
15-
ConfigField(
16-
CREDENTIALS_PROVIDER_CONFIG_NAME, "AWSCredentialsProvider",
17-
"The credentials provider to use to authenticate requests."
18-
),
19-
ConfigField(SIGNING_REGION_CONFIG_NAME, "String", "The region to sign requests in. (Required)"),
20-
ConfigField(
21-
ENDPOINT_RESOLVER, "EndpointResolver",
22-
"The endpoint resolver used to resolve endpoints."
23-
)
24-
)
25-
2614
class AWSServiceConfig(writer: SwiftWriter, serviceName: String) : ServiceConfig(writer, serviceName) {
2715
override val typesToConformConfigTo: List<String>
28-
get() = super.typesToConformConfigTo + listOf("AWSClientConfiguration")
16+
get() = listOf("AWSClientConfiguration")
2917

30-
override fun renderStaticDefaultImplementation(serviceSymbol: Symbol) {
31-
writer.openBlock("public static func `default`() throws -> ${serviceSymbol.name}Configuration {", "}") {
32-
writer.write("let awsCredsProvider = try AWSCredentialsProvider.fromEnv()") // TODO: should be this be the default creds provider?
33-
writer.write("return try ${serviceSymbol.name}Configuration(credentialsProvider: awsCredsProvider)")
18+
override fun renderInitializers(serviceSymbol: Symbol) {
19+
val awsConfigFields = otherRuntimeConfigProperties()
20+
writer.openBlock("public init(", ") throws {") {
21+
awsConfigFields.forEach {
22+
writer.write("${it.memberName}: \$D, ", it.type)
23+
}
24+
writer.write("runtimeConfig: SDKRuntimeConfiguration")
3425
}
35-
}
26+
writer.indent()
27+
writer.write("self.region = region")
28+
writer.write("self.signingRegion = signingRegion ?? region")
29+
writer.write("self.endpointResolver = endpointResolver ?? DefaultEndpointResolver()")
30+
writer.openBlock("if let credProvider = credentialsProvider {", "} else {") {
31+
writer.write("self.credentialsProvider = credProvider")
32+
}
33+
writer.indent().write("self.credentialsProvider = try AWSCredentialsProvider.fromChain()")
34+
writer.dedent().write("}")
35+
val runtimeTimeConfigFields = sdkRuntimeConfigProperties()
36+
runtimeTimeConfigFields.forEach {
37+
writer.write("self.${it.memberName} = runtimeConfig.${it.memberName}")
38+
}
39+
writer.dedent().write("}")
40+
writer.write("")
3641

37-
override fun getConfigFields(): List<ConfigField> {
38-
return AWS_CONFIG_FIELDS
39-
}
42+
writer.openBlock("public convenience init(", ") throws {") {
4043

41-
override fun renderConvenienceInits(serviceSymbol: Symbol) {
42-
writer.addImport("AWSClientRuntime")
43-
writer.openBlock("public convenience init(credentialsProvider: AWSCredentialsProvider) throws {", "}") {
44-
writer.write("let region = \"us-east-1\"") // FIXME: get region from a region resolver
45-
writer.write("let signingRegion = \"us-east-1\"") // FIXME: get region from a region resolver
46-
writer.write("let endpointResolver = DefaultEndpointResolver()")
47-
writer.openBlock("try self.init(", ")") {
48-
val configFieldsSortedByName = getConfigFields().sortedBy { it.name }
49-
for ((index, member) in configFieldsSortedByName.withIndex()) {
50-
val memberName = member.name
51-
val terminator = if (index == configFieldsSortedByName.size - 1) "" else ","
52-
writer.write("\$L: \$L$terminator", memberName, memberName)
53-
}
44+
awsConfigFields.forEachIndexed { index, configField ->
45+
val terminator = if (index != awsConfigFields.lastIndex) ", " else ""
46+
writer.write("${configField.memberName}: \$D$terminator", configField.type)
5447
}
5548
}
49+
50+
var configParamValues = ""
51+
awsConfigFields.forEach {
52+
configParamValues += "${it.memberName}: ${it.memberName}, "
53+
}
54+
writer.indent()
55+
writer.write("let defaultRuntimeConfig = try DefaultSDKRuntimeConfiguration(\"${serviceName}\")")
56+
writer.write("try self.init(${configParamValues}runtimeConfig: defaultRuntimeConfig)")
57+
writer.dedent().write("}")
58+
}
59+
60+
override fun otherRuntimeConfigProperties(): List<ConfigField> {
61+
return listOf(
62+
ConfigField(
63+
REGION_CONFIG_NAME,
64+
buildSymbol {
65+
this.name = "String"
66+
this.nullable = false
67+
},
68+
"The region to send requests to. (Required)"
69+
),
70+
ConfigField(
71+
CREDENTIALS_PROVIDER_CONFIG_NAME, AWSClientRuntimeTypes.Core.CredentialsProvider,
72+
"The credentials provider to use to authenticate requests."
73+
),
74+
ConfigField(SIGNING_REGION_CONFIG_NAME, buildSymbol { this.name = "String" }, "The region to sign requests in. (Required)"),
75+
ConfigField(
76+
ENDPOINT_RESOLVER, AWSClientRuntimeTypes.Core.EndpointResolver,
77+
"The endpoint resolver used to resolve endpoints."
78+
)
79+
).sortedBy { it.memberName }
5680
}
5781
}

0 commit comments

Comments
 (0)