The SmokeAWS package is a library for communicating with AWS services written in the Swift programming language. Using SwiftNIO for its networking layer, the library provides the ability to call API methods for AWS services either synchronously or asynchronously.
The support policy for this package is described here.
Each AWS service has two libraries and corresponding targets in this package-
SmokeAWS uses the Swift Package Manager. To use the framework, add the following dependency to your Package.swift-
dependencies: [
.package(url: "https://github.com/amzn/smoke-aws.git", from: "2.0.0")
]
Once you have specified the SmokeAWS package as a dependency, you can specify the targets from this package that your application needs to depend on. Swift Package Manager will compile these targets as part of your application for you to use. It will not compile the targets in the SmokeAWS package that you don't depend on.
For swift-tools version 5.2 and greater-
targets: [
.target(
name: "SampleServiceOperations", dependencies: [
.product(name: "ElasticComputeCloudClient", package: "smoke-aws"),
]),
.testTarget(
name: "SampleServiceOperationsTests", dependencies: [
.target(name: "SampleServiceOperations"),
]),
]
For swift-tools version 5.1 and prior-
targets: [
.target(
name: "SampleServiceOperations",
dependencies: ["ElasticComputeCloudClient"]),
.testTarget(
name: "SampleServiceOperationsTests",
dependencies: ["SampleServiceOperations"]),
]
While it is possible to use the AWS clients directly, in most cases you will want to use the corresponding protocol so you can unit test your code without contacting the AWS service, rather using one of the mock clients to handle service calls locally.
import ElasticComputeCloudClient
public struct SampleServiceOperationsContext {
public let ec2Client: ElasticComputeCloudClientProtocol
public init(ec2Client: ElasticComputeCloudClientProtocol) {
self.ec2Client = ec2Client
}
}
Using this protocol you can call service API methods and get results-
import ElasticComputeCloudModel
...
let request = RunInstancesRequest(
clientToken: nil,
launchTemplate: instanceLaunchTemplate,
maxCount: maxCount,
minCount: minCount,
subnetId: subnetId)
let response = try context.ec2Client.runInstancesSync(input: request)
try response.instances?.forEach { instance in ... }
When starting your application in production, you can instantiate an instance of the AWS client and pass it in the place of the protocol to contact the actual AWS service.
Each AWS service provides a Generator type that can be globally instatiated for the application and used to produce a request-specific client.
At application startup-
import ElasticComputeCloudClient
import SmokeAWSCredentials
...
guard let credentialsProvider = AwsContainerRotatingCredentials.getCredentials(fromEnvironment: environment) else {
return Log.error("Unable to obtain credentials from the container environment.")
}
// optional: for the EC2 clients, only emit the retry count metric
// only report 5XX error counts for DescribeInstances (even if additional operations are added in the future)
// only report 4XX error counts for operations other than DescribeInstances (including if they are added in the future)
let reportingConfiguration = SmokeAWSClientReportingConfiguration<ElasticComputeCloudModelOperations>(
successCounterMatchingOperations: .none,
failure5XXCounterMatchingRequests: .onlyForOperations([.describeInstances]),
failure4XXCounterMatchingRequests: .exceptForOperations([.describeInstances]),
retryCountRecorderMatchingOperations: .all,
latencyTimerMatchingOperations: .none)
self.ec2ClientGenerator = AWSElasticComputeCloudClientGenerator(
credentialsProvider: credentialsProvider,
awsRegion: region,
endpointHostName: ec2EndpointHostName,
connectionTimeoutSeconds: connectionTimeoutSeconds, // optional
retryConfiguration: retryConfiguration, // optional
eventLoopProvider: .createNew, // optional
reportingConfiguration: reportingConfiguration) // optional
The inputs to this constructor are-
dynamodb.us-west-2.amazonaws.com
.HTTPClientRetryConfiguration
to indicate how the client should handle automatic retries on failure. Default to a configuration with 5 retries starting at a 500 ms interval.SmokeAWSClientReportingConfiguration
that indicates what metrics to emit for the client. Defaults to a configuration where all metrics for all APIs are emitted. Within a request-
let ec2Client = self.ec2ClientGenerator.with(logger: logger)
Recording metrics from the AWS clients will require an metrics implementation to be instatiated for the application for swift-metrics. Currently SmokeAWS doesn't provide a default implementation for Cloudwatch.
The metrics emitted by the AWS clients are-
In unit tests, you can instantiate an instance of the mock or throwing client and pass it in the place of the protocol to verify your code acts as expected. Both mock clients allow you to optionally pass closures to override the default behavior for particular API methods, allowing you to provide custom mock behavior for some but not all API methods.
var instances: [(instanceId: String, subnetId: String)] = []
var terminatedInstanceIds: [String] = []
func runInstancesSync(_ input: ElasticComputeCloudModel.RunInstancesRequest)
throws -> ElasticComputeCloudModel.Reservation {
var instanceList: InstanceList = []
for _ in 0..<input.maxCount {
let instanceId = "instance_\(UUID().uuidString)"
let instance = ElasticComputeCloudModel.Instance(instanceId: instanceId)
instanceList.append(instance)
instances.append((instanceId: instanceId, subnetId: input.subnetId!))
}
return ElasticComputeCloudModel.Reservation(instances: instanceList)
}
func terminateInstancesSync(input: ElasticComputeCloudModel.TerminateInstancesRequest) throws
-> ElasticComputeCloudModel.TerminateInstancesResult {
terminatedInstanceIds.append(contentsOf: input.instanceIds)
return ElasticComputeCloudModel.TerminateInstancesResult()
}
let ec2Client = MockElasticComputeCloudClient(runInstancesSync: runInstancesSync,
terminateInstancesSync: terminateInstancesSync)
let context = SampleServiceOperationsContext(ec2Client: ec2Client)
The majority of this package is code generated using SmokeAWSGenerate.
This library is licensed under the Apache 2.0 License.