Build - Main Branch Swift 5.7, 5.8 and 5.9 Tested Ubuntu 20.04 and 22.04 Tested Join the Smoke Server Side community on gitter Apache 2

SmokeAWS

SmokeAWS 软件包是一个使用 Swift 编程语言编写的,用于与 AWS 服务通信的库。该库使用 SwiftNIO 作为其网络层,提供了同步或异步调用 AWS 服务 API 方法的能力。

支持策略

此软件包的支持策略在此处描述:here

概念概述

每个 AWS 服务在此软件包中都有两个库和对应的目标:

入门指南

步骤 1:添加 SmokeAWS 依赖

SmokeAWS 使用 Swift Package Manager。 要使用该框架,请将以下依赖项添加到您的 Package.swift:

dependencies: [
    .package(url: "https://github.com/amzn/smoke-aws.git", from: "2.0.0")
]

步骤 2:依赖于您需要使用的 SmokeAWS 客户端库

指定 SmokeAWS 软件包作为依赖项后,您可以指定您的应用程序需要依赖于此软件包中的哪些目标。 Swift Package Manager 将编译这些目标作为您应用程序的一部分以供您使用。 它不会编译您不依赖的 SmokeAWS 软件包中的目标。

对于 swift-tools 版本 5.2 及更高版本:

    targets: [
        .target(
            name: "SampleServiceOperations", dependencies: [
                .product(name: "ElasticComputeCloudClient", package: "smoke-aws"),
            ]),
        .testTarget(
            name: "SampleServiceOperationsTests", dependencies: [
                .target(name: "SampleServiceOperations"),
            ]),
    ]

对于 swift-tools 版本 5.1 及更早版本:

    targets: [
        .target(
            name: "SampleServiceOperations",
            dependencies: ["ElasticComputeCloudClient"]),
        .testTarget(
            name: "SampleServiceOperationsTests",
            dependencies: ["SampleServiceOperations"]),
    ]

步骤 3:使用客户端协议

虽然可以直接使用 AWS 客户端,但在大多数情况下,您需要使用相应的协议,以便您可以进行单元测试,而无需连接到 AWS 服务,而是使用其中一个模拟客户端在本地处理服务调用。

import ElasticComputeCloudClient

public struct SampleServiceOperationsContext {
    public let ec2Client: ElasticComputeCloudClientProtocol

    public init(ec2Client: ElasticComputeCloudClientProtocol) {
        self.ec2Client = ec2Client
    }
}

使用此协议,您可以调用服务 API 方法并获取结果:

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 ... }

步骤 4:实例化用于生产环境的 AWS 客户端

在生产环境中启动应用程序时,您可以实例化一个 AWS 客户端实例,并将其传递到协议的位置,以连接到实际的 AWS 服务。

每个 AWS 服务都提供一个 Generator 类型,可以为应用程序全局实例化,并用于生成特定于请求的客户端。

在应用程序启动时:

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

此构造函数的输入为:

  1. credentialsProvider:用于此客户端的凭证提供程序。
  1. awsRegion:用于此客户端的 AWS 区域。
  2. endpointHostName:此客户端进行的调用要连接的主机名。 不包括协议或端口。
  1. connectionTimeoutSeconds:此客户端发出的请求的超时时间(以秒为单位)。
  2. retryConfiguration:类型为 HTTPClientRetryConfiguration 的实例,用于指示客户端应如何处理失败时的自动重试。 默认为一个配置,其中包含 5 次重试,从 500 毫秒的间隔开始。
  3. eventLoopProvider:此客户端的事件循环提供程序。 默认为创建一个新的事件循环。
  4. reportingConfigurationSmokeAWSClientReportingConfiguration 的一个实例,指示要为客户端发出哪些指标。 默认为一个配置,其中发出所有 API 的所有指标。

在请求中:

    let ec2Client = self.ec2ClientGenerator.with(logger: logger)

从 AWS 客户端记录指标将需要为应用程序实例化一个指标实现,以用于 swift-metrics。 目前,SmokeAWS 没有为 Cloudwatch 提供默认实现。

AWS 客户端发出的指标为:

  1. success:成功调用的计数。
  2. failure5XX:客户端返回 5xx 响应代码的不成功调用的计数。
  3. failure4XX:客户端返回 4xx 响应代码的不成功调用的计数。
  4. retryCount:客户端调用的重试计数。
  5. latency:来自客户端调用的延迟。

步骤 5:实例化一个用于测试的模拟客户端

在单元测试中,您可以实例化一个模拟或抛出异常的客户端实例,并将其传递到协议的位置,以验证您的代码是否按预期运行。 两个模拟客户端都允许您选择性地传递闭包以覆盖特定 API 方法的默认行为,从而允许您为某些但并非所有 API 方法提供自定义模拟行为。

    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)

进一步的概念

包生成

此软件包的大部分代码是使用 SmokeAWSGenerate 生成的。

许可证

此库是在 Apache 2.0 许可证下获得许可的。