-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat!: Account ID-based endpoints (#1841)
- Loading branch information
Showing
26 changed files
with
515 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
149 changes: 149 additions & 0 deletions
149
IntegrationTests/Services/AWSDynamoDBIntegrationTests/AccountIDEndpointModeTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import XCTest | ||
import AWSDynamoDB | ||
import SmithyTestUtil | ||
import SmithyIdentity | ||
import enum AWSClientRuntime.AccountIDEndpointMode | ||
import enum ClientRuntime.EndpointError | ||
|
||
final class AccountIDEndpointModeTests: XCTestCase { | ||
private let accountID = "0123456789" | ||
|
||
// MARK: - Tests | ||
|
||
// MARK: nil | ||
|
||
func test_nilMode_prefersByDefault() async throws { | ||
let subject = try await subject(accountIDEndpointMode: nil, setAccountID: true) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch TestCheckError.actual(let request) { | ||
XCTAssert(request.endpoint.host.contains(accountID)) | ||
} catch { | ||
XCTFail("Request should have succeeded, threw error: \(error)") | ||
} | ||
} | ||
|
||
func test_nilMode_createsEndpointWithoutAccountID() async throws { | ||
let subject = try await subject(accountIDEndpointMode: nil, setAccountID: false) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch TestCheckError.actual(let request) { | ||
XCTAssertFalse(request.endpoint.host.contains(accountID)) | ||
} catch { | ||
XCTFail("Request failed on unexpected error") | ||
} | ||
} | ||
|
||
// MARK: preferred | ||
|
||
func test_preferredMode_prefersByDefault() async throws { | ||
let subject = try await subject(accountIDEndpointMode: .preferred, setAccountID: true) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch TestCheckError.actual(let request) { | ||
XCTAssert(request.endpoint.host.contains(accountID)) | ||
} catch { | ||
XCTFail("Request should have succeeded, threw error: \(error)") | ||
} | ||
} | ||
|
||
func test_preferredMode_createsEndpointWithoutAccountID() async throws { | ||
let subject = try await subject(accountIDEndpointMode: .preferred, setAccountID: false) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch TestCheckError.actual(let request) { | ||
XCTAssertFalse(request.endpoint.host.contains(accountID)) | ||
} catch { | ||
XCTFail("Request failed on unexpected error") | ||
} | ||
} | ||
|
||
// MARK: required | ||
|
||
func test_requiredMode_createsEndpointWithAccountID() async throws { | ||
let subject = try await subject(accountIDEndpointMode: .required, setAccountID: true) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch TestCheckError.actual(let request) { | ||
XCTAssert(request.endpoint.host.contains(accountID)) | ||
} catch { | ||
XCTFail("Request should have succeeded, threw error: \(error)") | ||
} | ||
} | ||
|
||
func test_requiredMode_failsWhenRequiredButNotPresent() async throws { | ||
let subject = try await subject(accountIDEndpointMode: .required, setAccountID: false) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch EndpointError.unresolved { | ||
// No action, test succeeded | ||
} catch { | ||
XCTFail("Request failed on unexpected error") | ||
} | ||
} | ||
|
||
// MARK: disabled | ||
|
||
func test_disabledMode_createsEndpointWithoutAccountIDWhenNil() async throws { | ||
let subject = try await subject(accountIDEndpointMode: .disabled, setAccountID: false) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch TestCheckError.actual(let request) { | ||
XCTAssertFalse(request.endpoint.host.contains(accountID)) | ||
} catch { | ||
XCTFail("Request failed on unexpected error") | ||
} | ||
} | ||
|
||
func test_disabledMode_createsEndpointWithoutAccountIDWhenSupplied() async throws { | ||
let subject = try await subject(accountIDEndpointMode: .disabled, setAccountID: true) | ||
|
||
do { | ||
_ = try await subject.getItem(input: GetItemInput()) | ||
XCTFail("Request should have thrown") | ||
} catch TestCheckError.actual(let request) { | ||
XCTAssertFalse(request.endpoint.host.contains(accountID)) | ||
} catch { | ||
XCTFail("Request failed on unexpected error") | ||
} | ||
} | ||
|
||
// MARK: - Private methods | ||
|
||
private func subject( | ||
accountIDEndpointMode: AccountIDEndpointMode?, | ||
setAccountID: Bool | ||
) async throws -> DynamoDBClient { | ||
let accountID = setAccountID ? self.accountID : nil | ||
let credentials = AWSCredentialIdentity(accessKey: "abc", secret: "def", accountID: accountID) | ||
let resolver = try StaticAWSCredentialIdentityResolver(credentials) | ||
let config = try await DynamoDBClient.Config( | ||
awsCredentialIdentityResolver: resolver, | ||
region: "us-east-1", | ||
accountIdEndpointMode: accountIDEndpointMode, | ||
httpClientEngine: ProtocolTestClient() | ||
) | ||
return DynamoDBClient(config: config) | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
1.1.2 | ||
1.2.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
Sources/Core/AWSClientRuntime/Sources/AWSClientRuntime/Endpoints/AccountIDEndpointMode.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
/// Determines how & whether an account ID-based endpoint will be used for requests. | ||
public enum AccountIDEndpointMode: String, Equatable { | ||
// Note : these case names match string values for the accountIdEndpointMode endpoint param. | ||
// Do not rename them | ||
|
||
/// An account ID-based endpoint will be used if an account ID is available. | ||
/// | ||
/// This is the default mode. | ||
case preferred // the default case | ||
|
||
/// An account ID-based endpoint will never be used. | ||
/// | ||
/// The request will fail if a non-account ID-based endpoint is not available. | ||
case disabled | ||
|
||
/// An account ID-based endpoint will always be used. | ||
/// | ||
/// The request will fail if an account ID-based endpoint cannot be constructed. | ||
case required | ||
} |
30 changes: 30 additions & 0 deletions
30
...e/AWSClientRuntime/Sources/AWSClientRuntime/Endpoints/Context+AccountIDEndpointMode.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import struct Smithy.Attributes | ||
import struct Smithy.AttributeKey | ||
import class Smithy.Context | ||
import class Smithy.ContextBuilder | ||
|
||
public extension Context { | ||
|
||
var accountIDEndpointMode: AccountIDEndpointMode? { | ||
get { get(key: accountIDEndpointModeKey) } | ||
set { set(key: accountIDEndpointModeKey, value: newValue) } | ||
} | ||
} | ||
|
||
public extension ContextBuilder { | ||
|
||
@discardableResult | ||
func withAccountIDEndpointMode(value: AccountIDEndpointMode?) -> Self { | ||
attributes.set(key: accountIDEndpointModeKey, value: value) | ||
return self | ||
} | ||
} | ||
|
||
private let accountIDEndpointModeKey = AttributeKey<AccountIDEndpointMode>(name: "AccountIDEndpointMode") |
Oops, something went wrong.