Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
79b8dbb
aws client runtime refactored to use async now
kneekey23 Nov 15, 2021
828dc60
codegen changes for async
kneekey23 Nov 16, 2021
e58ee78
linters
kneekey23 Nov 16, 2021
33749d1
fix all unit tests
kneekey23 Dec 22, 2021
b9604de
fix linters
kneekey23 Dec 22, 2021
5aa9032
update ci to account for new version of swift
kneekey23 Dec 22, 2021
f11aa11
adjust linux ci
kneekey23 Dec 22, 2021
1e511f3
fix unit tests in client runtime
kneekey23 Dec 22, 2021
22effcf
refactor linux ci to use new builder commands
kneekey23 Dec 22, 2021
5348d81
fix linux ci
kneekey23 Dec 22, 2021
ef98bb8
fix linux ci again
kneekey23 Dec 22, 2021
72362d6
add java to ci for linux
kneekey23 Dec 22, 2021
67fff2a
fix compilation of aws json and glacier
kneekey23 Dec 23, 2021
3eb8020
fix glacier middleware compilation errors
kneekey23 Dec 23, 2021
9605751
fix unit tests again
kneekey23 Dec 23, 2021
54096b0
fix yaml file
kneekey23 Dec 23, 2021
7a220be
fix yaml file again
kneekey23 Dec 23, 2021
08ffc39
add java home env variable
kneekey23 Dec 23, 2021
09bebde
fix java home issue for ubuntu
kneekey23 Dec 27, 2021
5cec422
address pr comments
kneekey23 Dec 29, 2021
9660b2d
update crt builder to use latest where ubuntu image has java on it
kneekey23 Jan 3, 2022
8713e92
trying to fix linux
kneekey23 Jan 4, 2022
b0892c5
experimentation
kneekey23 Jan 4, 2022
3b5cb76
more experimentation to find a work around
kneekey23 Jan 5, 2022
05b06f6
remove workaround while we wait for apple release
kneekey23 Jan 11, 2022
6613165
pr comments from john
kneekey23 Jan 20, 2022
78ae3c8
added todo
kneekey23 Jan 20, 2022
3c687c9
remvoe throws from signer function
kneekey23 Jan 20, 2022
996f91d
correct sig4 signer function back to non throws
kneekey23 Jan 20, 2022
3765bc6
remove extra space
kneekey23 Jan 20, 2022
b09efaf
add where
kneekey23 Jan 20, 2022
a1e074f
john is a g
kneekey23 Jan 21, 2022
c4e8073
correct swift version
kneekey23 Jan 24, 2022
ad99c07
fix tests
kneekey23 Feb 7, 2022
502f559
update bulder with new images
kneekey23 Feb 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@ on:
workflow_dispatch:

env:
BUILDER_VERSION: v0.8.19
BUILDER_VERSION: v0.9.13
BUILDER_SOURCE: releases
# host owned by CRT team to host aws-crt-builder releases. Contact their on-call with any issues
BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net
PACKAGE_NAME: aws-sdk-swift
LINUX_BASE_IMAGE: ubuntu-16-x64
RUN: ${{ github.run_id }}-${{ github.run_number }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-east-1
AWS_SDK_SWIFT_CI_DIR: /Users/runner/work/aws-sdk-swift/aws-sdk-swift
AWS_CRT_SWIFT_CI_DIR: /Users/runner/work/aws-sdk-swift/aws-sdk-swift/target/build/deps/aws-crt-swift
SMITHY_SWIFT_CI_DIR: /Users/runner/work/aws-sdk-swift/aws-sdk-swift/target/build/deps/smithy-swift

jobs:
ios-compat:
runs-on: macos-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
steps:
- name: Checkout Sources
uses: actions/checkout@v2
Expand All @@ -43,6 +48,8 @@ jobs:
AWS_CRT_SWIFT_CI_DIR="${{ env.AWS_CRT_SWIFT_CI_DIR }}" AWS_SDK_SWIFT_CI_DIR="${{ env.AWS_SDK_SWIFT_CI_DIR }}" SMITHY_SWIFT_CI_DIR="${{ env.SMITHY_SWIFT_CI_DIR }}" ./builder.pyz build -p ${{ env.PACKAGE_NAME }} --target=ios-armv8
macos-compat:
runs-on: macos-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
steps:
- name: Checkout sources
uses: actions/checkout@v2
Expand All @@ -65,21 +72,28 @@ jobs:
linux-compat:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
image:
- aws-crt-swift-5-al2-x64
- ubuntu-x64
- al2-x64
steps:
- name: Checkout Sources
uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: '11'
- name: Build and Test ${{ env.PACKAGE_NAME }}
# todo: remove the aws credentials from the below command eventually once the CRT builder no longer requires aws credentials
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u awslabs --password-stdin
export DOCKER_IMAGE=docker.pkg.github.com/awslabs/aws-crt-builder/${{ matrix.image }}:${{ env.BUILDER_VERSION }}
aws ecr get-login-password | docker login 123124136734.dkr.ecr.us-east-1.amazonaws.com -u AWS --password-stdin
export DOCKER_IMAGE=123124136734.dkr.ecr.us-east-1.amazonaws.com/aws-crt-swift-5-${{ matrix.image }}:${{ env.BUILDER_VERSION }}
docker pull $DOCKER_IMAGE
docker run --mount type=bind,source=$(pwd),target=/root/${{ env.PACKAGE_NAME }} \
--env GITHUB_REF \
--env GITHUB_HEAD_REF \
--env AWS_CRT_SWIFT_CI_DIR="/root/${{ env.PACKAGE_NAME }}/target/build/deps/aws-crt-swift" \
--env AWS_SDK_SWIFT_CI_DIR="/root/${{ env.PACKAGE_NAME }}" \
--env SMITHY_SWIFT_CI_DIR="/root/${{ env.PACKAGE_NAME }}/target/build/deps/smithy-swift" \
--env AWS_ACCESS_KEY_ID --env AWS_SECRET_ACCESS_KEY --env AWS_DEFAULT_REGION --env CXXFLAGS \
$DOCKER_IMAGE build -p ${{ env.PACKAGE_NAME }} --build-dir=/root/${{ env.PACKAGE_NAME }} --spec=downstream
2 changes: 1 addition & 1 deletion AWSClientRuntime/Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.4
// swift-tools-version:5.5

/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Expand Down
24 changes: 11 additions & 13 deletions AWSClientRuntime/Sources/Auth/AWSCredentialsProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,16 @@ public class AWSCredentialsProvider: CredentialsProvider {
return AWSCredentialsProvider(awsCredentialsProvider: credsProvider)
}

public func getCredentials() throws -> SdkFuture<AWSCredentials> {
let credentials = crtCredentialsProvider.getCredentials()
let result = try credentials.get()
guard let accessKey = result.getAccessKey(),
let secret = result.getSecret() else {
throw ClientError.authError("Unable to get credentials. Required: accessKey, secret.")
}
let future = SdkFuture<AWSCredentials>()
future.fulfill(AWSCredentials(accessKey: accessKey,
secret: secret,
expirationTimeout: result.getExpirationTimeout(),
sessionToken: result.getSessionToken()))
return future
public func getCredentials() async throws -> AWSCredentials {
let crtCredentials = try await crtCredentialsProvider.getCredentials()

guard let accessKey = crtCredentials.getAccessKey(),
let secret = crtCredentials.getSecret() else {
throw ClientError.authError("Unable to get credentials. Required: accessKey, secret.")
}
return AWSCredentials(accessKey: accessKey,
secret: secret,
expirationTimeout: crtCredentials.getExpirationTimeout(),
sessionToken: crtCredentials.getSessionToken())
}
}
2 changes: 1 addition & 1 deletion AWSClientRuntime/Sources/Auth/CredentialsProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import ClientRuntime

public protocol CredentialsProvider {
/// Resolves `AWSCredentials` through custom means
func getCredentials() throws -> SdkFuture<AWSCredentials>
func getCredentials() async throws -> AWSCredentials
}
15 changes: 3 additions & 12 deletions AWSClientRuntime/Sources/Auth/CredentialsProviderCRTAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,8 @@ struct CredentialsProviderCRTAdapter: CRTCredentialsProvider {
self.allocator = defaultAllocator
}

func getCredentials(credentialCallbackData: CRTCredentialsCallbackData) {
do {
let credentialsResult = try credentialsProvider.getCredentials()
let credentials = try credentialsResult.get()
let emptyError = AWSError(errorCode: 0)
let crtCredentials = credentials.toCRTType()
credentialCallbackData.onCredentialsResolved?(crtCredentials, CRTError.crtError(emptyError))
} catch let err {
logger.error("An error occurred with retrieving credentials from your custom credentials provider. Error: \(err)")

credentialCallbackData.onCredentialsResolved?(nil, CRTError.crtError(AWSError(errorCode: -1)))
}
func getCredentials() async throws -> CRTCredentials {
let credentials = try await credentialsProvider.getCredentials()
return credentials.toCRTType()
}
}
11 changes: 2 additions & 9 deletions AWSClientRuntime/Sources/IMDS/IMDSClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,7 @@ public class IMDSClient {
self.crtIMDSClient = CRTIMDSClient(options: crtConfig)
}

public func get(path: String, completion: @escaping (Result<String, ClientError>) -> Void) {
let callbackData = CRTIMDSClientResourceCallbackData { resource, error in
guard let resource = resource else {
completion(.failure(.crtError(error)))
return
}
completion(.success(resource))
}
crtIMDSClient.getResource(resourcePath: path, callbackData: callbackData)
public func get(path: String) async throws -> String? {
return try await crtIMDSClient.getResource(resourcePath: path)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@ public struct EndpointResolverMiddleware<OperationStackOutput: HttpResponseBindi

public func handle<H>(context: Context,
input: SdkHttpRequestBuilder,
next: H) -> Result<OperationOutput<OperationStackOutput>, MError>
next: H) async throws -> OperationOutput<OperationStackOutput>
where H: Handler,
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context,
Self.MError == H.MiddlewareError {
Self.Context == H.Context {

guard let region = context.getRegion(), !region.isEmpty else {
return .failure(.client(ClientError.unknownError(("Region is unable to be resolved"))))
throw SdkError<OperationStackError>.client(ClientError.unknownError(("Region is unable to be resolved")))
}

do {
Expand Down Expand Up @@ -56,12 +55,13 @@ public struct EndpointResolverMiddleware<OperationStackOutput: HttpResponseBindi
.withHost(host)
.withPort(awsEndpoint.endpoint.port)
.withPath(context.getPath())
// TODO: investigate if this header should be the same host value as the actual host and where this header should be set
// TODO: investigate if this header should be the same host value as
// the actual host and where this header should be set
.withHeader(name: "Host", value: host)

return next.handle(context: updatedContext, input: input)
return try await next.handle(context: updatedContext, input: input)
} catch {
return .failure(.client(ClientError.unknownError(("Endpoint is unable to be resolved"))))
throw SdkError<OperationStackError>.client(ClientError.unknownError(("Endpoint is unable to be resolved")))
}
}

Expand Down
87 changes: 44 additions & 43 deletions AWSClientRuntime/Sources/Middlewares/RetryerMiddleware.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,59 +20,60 @@ public struct RetryerMiddleware<Output: HttpResponseBinding,

public func handle<H>(context: Context,
input: SdkHttpRequestBuilder,
next: H) -> Result<OperationOutput<Output>, SdkError<OutputError>>
next: H) async throws -> OperationOutput<Output>
where H: Handler,
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context,
Self.MError == H.MiddlewareError {

guard let region = context.getRegion(), !region.isEmpty else {
return .failure(.client(ClientError.unknownError(("Region is unable to be resolved"))))
}
do {
let partitionId = "\(context.getServiceName()) - \(region))"
let token = try retryer.acquireToken(partitionId: partitionId)
return try tryRequest(token: token, partitionId: partitionId, context: context, input: input, next: next)

} catch let err {
return .failure(.client(ClientError.retryError(err)))
}
}
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context {

guard let region = context.getRegion(), !region.isEmpty else {
throw SdkError<OutputError>.client(ClientError.unknownError(("Region is unable to be resolved")))
}
do {
let partitionId = "\(context.getServiceName()) - \(region))"
let token = try await retryer.acquireToken(partitionId: partitionId)
return try await tryRequest(token: token,
partitionId: partitionId,
context: context,
input: input,
next: next)

} catch let err {
throw SdkError<OutputError>.client(ClientError.retryError(err))
}
}

func tryRequest<H>(token: RetryToken,
errorType: RetryError? = nil,
partitionId: String,
context: Context,
input: SdkHttpRequestBuilder,
next: H) throws -> Result<OperationOutput<Output>, SdkError<OutputError>>
next: H) async throws -> OperationOutput<Output>
where H: Handler,
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context,
Self.MError == H.MiddlewareError {
defer { retryer.releaseToken(token: token)}

let serviceResponse = next.handle(context: context, input: input)

switch serviceResponse {
case .failure(let error):
if retryer.isErrorRetryable(error: error) {
let errorType = retryer.getErrorType(error: error)
let newToken = try retryer.scheduleRetry(token: token, error: errorType)
// TODO: rewind the stream once streaming is properly implemented
return try tryRequest(token: newToken, partitionId: partitionId, context: context, input: input, next: next)
} else {
return serviceResponse
}
case .success:
retryer.recordSuccess(token: token)
return serviceResponse
}
}
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context {
defer { retryer.releaseToken(token: token)}
do {
let serviceResponse = try await next.handle(context: context, input: input)
retryer.recordSuccess(token: token)
return serviceResponse
} catch let error as SdkError<OutputError> where retryer.isErrorRetryable(error: error) {

let errorType = retryer.getErrorType(error: error)
let newToken = try await retryer.scheduleRetry(token: token, error: errorType)
// TODO: rewind the stream once streaming is properly implemented
return try await tryRequest(token: newToken,
partitionId: partitionId,
context: context,
input: input,
next: next)
} catch {
throw error
}
}

public typealias MInput = SdkHttpRequestBuilder
public typealias MOutput = OperationOutput<Output>
public typealias Context = HttpContext
public typealias MError = SdkError<OutputError>
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@ public struct Sha256TreeHashMiddleware<OperationStackOutput: HttpResponseBinding

public func handle<H>(context: Context,
input: MInput,
next: H) -> Result<MOutput, MError>
next: H) async throws -> MOutput
where H: Handler,
Self.MInput == H.Input,
Self.MOutput == H.Output,
Self.Context == H.Context,
Self.MError == H.MiddlewareError {
Self.Context == H.Context {
let request = input.build()

switch request.body {
case .data(let data):
guard let data = data else {
return next.handle(context: context, input: input)
return try await next.handle(context: context, input: input)
}
if !request.headers.exists(name: X_AMZ_CONTENT_SHA256_HEADER_NAME) {
let sha256 = ByteBuffer(data: data).sha256().encodeToHexString()
Expand All @@ -37,7 +36,7 @@ public struct Sha256TreeHashMiddleware<OperationStackOutput: HttpResponseBinding
case .stream(let stream):
let streamBytes = stream.toBytes()
guard streamBytes.length > 0 else {
return next.handle(context: context, input: input)
return try await next.handle(context: context, input: input)
}
let (linearHash, treeHash) = computeHashes(bytes: streamBytes)
if let treeHash = treeHash, let linearHash = linearHash {
Expand All @@ -48,7 +47,7 @@ public struct Sha256TreeHashMiddleware<OperationStackOutput: HttpResponseBinding
break
}

return next.handle(context: context, input: input)
return try await next.handle(context: context, input: input)
}

/// Computes the tree-hash and linear hash of a `ByteBuffer`.
Expand All @@ -70,8 +69,10 @@ public struct Sha256TreeHashMiddleware<OperationStackOutput: HttpResponseBinding
return (bytes.sha256().encodeToHexString(), computeTreeHash(hashes: hashes))
}

/// Builds a tree hash root node given a slice of hashes. Glacier tree hash to be derived from SHA256 hashes of 1MB chunks of the data.
/// See http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html for more information.
/// Builds a tree hash root node given a slice of hashes. Glacier tree hash to be derived from SHA256 hashes
/// of 1MB chunks of the data.
/// See http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html
/// for more information.
private func computeTreeHash(hashes: [[UInt8]]) -> String? {
guard !hashes.isEmpty else {
return nil
Expand Down
Loading