diff --git a/.doc_gen/metadata/sfn_metadata.yaml b/.doc_gen/metadata/sfn_metadata.yaml
index 75a96e309fc..f79a68b4985 100644
--- a/.doc_gen/metadata/sfn_metadata.yaml
+++ b/.doc_gen/metadata/sfn_metadata.yaml
@@ -81,6 +81,14 @@ sfn_CreateStateMachine:
snippet_tags:
- python.example_code.sfn.StateMachine_decl
- python.example_code.sfn.CreateStateMachine
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.CreateStateMachine
services:
sfn: {CreateStateMachine}
sfn_DeleteStateMachine:
@@ -122,6 +130,14 @@ sfn_DeleteStateMachine:
snippet_tags:
- python.example_code.sfn.StateMachine_decl
- python.example_code.sfn.DeleteStateMachine
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.DeleteStateMachine
services:
sfn: {DeleteStateMachine}
sfn_ListStateMachines:
@@ -163,6 +179,14 @@ sfn_ListStateMachines:
snippet_tags:
- python.example_code.sfn.StateMachine_decl
- python.example_code.sfn.ListStateMachines
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.ListStateMachines
services:
sfn: {ListStateMachines}
sfn_DescribeStateMachine:
@@ -204,6 +228,14 @@ sfn_DescribeStateMachine:
snippet_tags:
- python.example_code.sfn.StateMachine_decl
- python.example_code.sfn.DescribeStateMachine
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.DescribeStateMachine
services:
sfn: {DescribeStateMachine}
sfn_StartExecution:
@@ -254,6 +286,14 @@ sfn_StartExecution:
- description:
snippet_files:
- javascriptv3/example_code/sfn/actions/start-execution.js
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.StartExecution
services:
sfn: {StartExecution}
sfn_ListExecutions:
@@ -325,6 +365,14 @@ sfn_DescribeExecution:
- description:
snippet_tags:
- python.example_code.sfn.DescribeExecution
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.DescribeExecution
services:
sfn: {DescribeExecution}
sfn_CreateActivity:
@@ -366,6 +414,14 @@ sfn_CreateActivity:
snippet_tags:
- python.example_code.sfn.Activity_decl
- python.example_code.sfn.CreateActivity
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.CreateActivity
services:
sfn: {CreateActivity}
sfn_ListActivities:
@@ -407,6 +463,14 @@ sfn_ListActivities:
snippet_tags:
- python.example_code.sfn.Activity_decl
- python.example_code.sfn.ListActivities
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.CreateActivity
services:
sfn: {ListActivities}
sfn_GetActivityTask:
@@ -447,6 +511,14 @@ sfn_GetActivityTask:
snippet_tags:
- python.example_code.sfn.Activity_decl
- python.example_code.sfn.GetActivityTask
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.GetActivityTask
services:
sfn: {GetActivityTask}
sfn_SendTaskSuccess:
@@ -488,6 +560,14 @@ sfn_SendTaskSuccess:
snippet_tags:
- python.example_code.sfn.Activity_decl
- python.example_code.sfn.SendTaskSuccess
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.SendTaskSuccess
services:
sfn: {SendTaskSuccess}
sfn_DeleteActivity:
@@ -529,6 +609,14 @@ sfn_DeleteActivity:
snippet_tags:
- python.example_code.sfn.Activity_decl
- python.example_code.sfn.DeleteActivity
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - snippet_tags:
+ - swift.sfn.import
+ - swift.sfn.DeleteActivity
services:
sfn: {DeleteActivity}
sfn_Scenario_GetStartedStateMachines:
@@ -586,6 +674,21 @@ sfn_Scenario_GetStartedStateMachines:
- description: Define a class that wraps activity actions.
snippet_tags:
- python.example_code.sfn.Activity_full
+ Swift:
+ versions:
+ - sdk_version: 1
+ github: swift/example_code/sfn/scenario
+ excerpts:
+ - description: The main program, entry.swift.
+ snippet_tags:
+ - swift.sfn.scenario
+ - description: The activity manager, Activity.swift.
+ snippet_tags:
+ - swift.sfn.scenario.activity
+ - description: The state machine manager, StateMachine.swift.
+ snippet_tags:
+ - swift.sfn.scenario.statemachine
+
services:
sfn: {CreateActivity, CreateStateMachine, DeleteActivity, DeleteStateMachine, DescribeExecution, DescribeStateMachine,
GetActivityTask, ListActivities, ListStateMachines, SendTaskSuccess, StartExecution, StopExecution}
diff --git a/swift/example_code/identity-resolvers/cognito-resolver/Package.swift b/swift/example_code/identity-resolvers/cognito-resolver/Package.swift
new file mode 100644
index 00000000000..458af4b323c
--- /dev/null
+++ b/swift/example_code/identity-resolvers/cognito-resolver/Package.swift
@@ -0,0 +1,42 @@
+// swift-tools-version:5.9
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+// The swift-tools-version declares the minimum version of Swift required to
+// build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "cognito-resolver",
+ // Let Xcode know the minimum Apple platforms supported.
+ platforms: [
+ .macOS(.v11),
+ .iOS(.v13)
+ ],
+ dependencies: [
+ // Dependencies declare other packages that this package depends on.
+ .package(
+ url: "https://github.com/awslabs/aws-sdk-swift",
+ from: "1.0.0"
+ ),
+ .package(
+ url: "https://github.com/apple/swift-argument-parser.git",
+ branch: "main"
+ ),
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package, defining a module or a test suite.
+ // Targets can depend on other targets in this package and products from dependencies.
+ .executableTarget(
+ name: "cognito-resolver",
+ dependencies: [
+ .product(name: "AWSCognitoIdentity", package: "aws-sdk-swift"),
+ .product(name: "AWSIAM", package: "aws-sdk-swift"),
+ .product(name: "AWSSTS", package: "aws-sdk-swift"),
+ .product(name: "AWSS3", package: "aws-sdk-swift"),
+ .product(name: "ArgumentParser", package: "swift-argument-parser"),
+ ],
+ path: "Sources"),
+ ]
+)
diff --git a/swift/example_code/identity-resolvers/cognito-resolver/Sources/Example.swift b/swift/example_code/identity-resolvers/cognito-resolver/Sources/Example.swift
new file mode 100644
index 00000000000..ea3f95c0e16
--- /dev/null
+++ b/swift/example_code/identity-resolvers/cognito-resolver/Sources/Example.swift
@@ -0,0 +1,255 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+// snippet-start:[swift.identity.cognito.imports]
+import AWSCognitoIdentity
+import AWSSDKIdentity
+import AWSSTS
+// snippet-end:[swift.identity.cognito.imports]
+import AWSIAM
+import AWSS3
+import Foundation
+
+/// Contains the data and code for the main body of the example.
+class Example {
+ let region: String
+
+ var cognitoIdentityClient: CognitoIdentityClient!
+ var iamClient: IAMClient!
+ var roleName: String
+
+ /// The name of the AWS Cognito Identity Pool to use.
+ let identityPoolName: String
+ /// The ID of the Identity Pool.
+ var identityPoolID: String!
+
+ /// The name of the managed policy granting Amazon S3 permissions.
+ let managedPolicyName: String
+ /// The ARN of the managed policy granting S3 permissions.
+ var managedPolicyArn: String?
+
+ /// Initialize the example.
+ ///
+ /// - Parameter region: The AWS Region to operate in.
+ ///
+ /// - Throws: Any AWS errors thrown by IAM or Cognito.
+ ///
+ /// ^ Note: IAM must always use `us-east-1`, so it doesn't use the value
+ /// of the `region` parameter.
+ init(region: String) throws {
+ self.region = region
+
+ self.identityPoolName = "cognito-resolver-example-\(UUID().uuidString.split(separator: "-").first!.lowercased())"
+ cognitoIdentityClient = try CognitoIdentityClient(region: region)
+
+ self.roleName = "cognito-unauth-\(identityPoolName)"
+ iamClient = try IAMClient(region: "us-east-1")
+
+ self.managedPolicyName = "cognito-policy-\(identityPoolName)"
+ }
+
+ /// The body of the example.
+ ///
+ /// - Throws: Errors from IAM, STS, or Cognito.
+ func run() async throws {
+ // Set up the cleanup function to run automatically when this object
+ // is discarded. This way, we clean up AWS artifacts whether the run
+ // is successful or an error occurs.
+
+ defer {
+ blocking {
+ await self.cleanup()
+ }
+ }
+
+ // Create an identity pool to use for this example.
+
+ print("Creating a Cognito identity pool named \(identityPoolName)...")
+ identityPoolID = try await cognitoIdentityClient.createIdentityPool(
+ input: CreateIdentityPoolInput(
+ allowUnauthenticatedIdentities: true,
+ identityPoolName: identityPoolName
+ )
+ ).identityPoolId
+
+ // Create an IAM role for unauthenticated users.
+
+ let trustPolicy = """
+ {
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Principal": {"Federated": "cognito-identity.amazonaws.com"},
+ "Action": "sts:AssumeRoleWithWebIdentity",
+ "Condition": {
+ "StringEquals": {"cognito-identity.amazonaws.com:aud": "\(identityPoolID!)"},
+ "ForAnyValue:StringLike": {"cognito-identity.amazonaws.com:amr": "unauthenticated"}
+ }
+ }]
+ }
+ """
+
+ print("Creating an IAM role named \(roleName)...")
+ let createRoleInput = CreateRoleInput(
+ assumeRolePolicyDocument: trustPolicy,
+ roleName: roleName
+ )
+ let createRoleOutput = try await iamClient.createRole(input: createRoleInput)
+
+ guard let role = createRoleOutput.role else {
+ print("*** No role returned by CreateRole!")
+ return
+ }
+
+ // Wait for the role to be available.
+
+ print("Waiting for the role to be available...")
+ try await Task.sleep(nanoseconds: 10_000_000_000) // Wait 10 seconds
+
+ // Assign the role to the identity pool.
+
+ print("Setting the identity pool's roles...")
+ _ = try await cognitoIdentityClient.setIdentityPoolRoles(
+ input: SetIdentityPoolRolesInput(
+ identityPoolId: identityPoolID,
+ roles: ["unauthenticated": role.arn!]
+ )
+ )
+
+ //======================================================================
+ // Resolve an identity using the Cognito credential identity resolver
+ // with the AWS STS function getCallerIdentity(input:). This is done
+ // by configuring the STS client to use the Cognito credentials
+ // resolver.
+ //======================================================================
+
+ // snippet-start:[swift.identity.cognito.resolve]
+ // Create a Cognito credential resolver that uses the Cognito Identity
+ // Pool created above.
+ let cognitoCredentialResolver = try CognitoAWSCredentialIdentityResolver(
+ identityPoolId: identityPoolID,
+ identityPoolRegion: region
+ )
+
+ // Create an AWS STS client that uses the new Cognito credential
+ // resolver to do credential identity resolution.
+ let cognitoSTSConfig = try await STSClient.STSClientConfiguration(
+ awsCredentialIdentityResolver: cognitoCredentialResolver,
+ region: "us-east-1"
+ )
+ let cognitoSTSClient = STSClient(config: cognitoSTSConfig)
+
+ let output = try await cognitoSTSClient.getCallerIdentity(
+ input: GetCallerIdentityInput()
+ )
+
+ print("Authenticated with AWS using Cognito!")
+ print(" ARN: \(output.arn ?? "")")
+ print(" Account ID: \(output.account ?? "")")
+ print(" User ID: \(output.userId ?? "")")
+ // snippet-end:[swift.identity.cognito.resolve]
+
+ //======================================================================
+ // Add a managed policy to the role to allow access to the AWS S3
+ // function ListBuckets.
+ //======================================================================
+
+ print("Creating a managed policy to allow listing S3 buckets...")
+ let createPolicyOutput = try await iamClient.createPolicy(
+ input: CreatePolicyInput(
+ policyDocument: """
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "s3:ListAllMyBuckets",
+ "Resource": "arn:aws:s3:::*"
+ }
+ ]
+ }
+ """,
+ policyName: managedPolicyName
+ )
+ )
+
+ guard let managedPolicy = createPolicyOutput.policy else {
+ print("No policy returned by CreatePolicy!")
+ return
+ }
+
+ managedPolicyArn = managedPolicy.arn
+
+ print("Attaching the policy to the IAM role...")
+ _ = try await iamClient.attachRolePolicy(
+ input: AttachRolePolicyInput(
+ policyArn: managedPolicy.arn,
+ roleName: roleName
+ )
+ )
+
+ // Wait for the policy to attach.
+
+ print("Waiting for the policy to attach to the role...")
+ try await Task.sleep(nanoseconds: 10_000_000_000) // Wait 10 seconds
+
+ //======================================================================
+ // This is where you can do tasks using the returned AWS credentials.
+ // In this example, we list S3 buckets.
+ //======================================================================
+
+ // snippet-start:[swift.identity.cognito.s3]
+ let s3Config = try await S3Client.S3ClientConfiguration(
+ awsCredentialIdentityResolver: cognitoCredentialResolver,
+ region: region
+ )
+ let s3Client = S3Client(config: s3Config)
+
+ let listBucketsOutput = try await s3Client.listBuckets(
+ input: ListBucketsInput()
+ )
+ // snippet-end:[swift.identity.cognito.s3]
+ guard let buckets = listBucketsOutput.buckets else {
+ print("No buckets returned by S3!")
+ return
+ }
+
+ print("Found \(buckets.count) S3 buckets:")
+ for bucket in buckets {
+ print(" \(bucket.name ?? "")")
+ }
+ }
+
+ /// Clean up by deleting AWS assets created by the example. Ignores
+ /// errors since this is just simple cleanup work.
+ func cleanup() async {
+ print("Deleting the identity pool...")
+ _ = try? await cognitoIdentityClient.deleteIdentityPool(
+ input: DeleteIdentityPoolInput(identityPoolId: identityPoolID)
+ )
+
+ print("Deleting the policy...")
+ if managedPolicyArn != nil {
+ _ = try? await iamClient.deletePolicy(
+ input: DeletePolicyInput(policyArn: managedPolicyArn)
+ )
+ }
+
+ print ("Deleting the IAM role...")
+ _ = try? await iamClient.deleteRole(
+ input: DeleteRoleInput(roleName: roleName)
+ )
+ }
+
+ /// Create a function that blocks the caller until execution is complete.
+ ///
+ /// - Parameter block: The function to call and wait for its return.
+ private func blocking(_ block: @escaping @Sendable () async -> Void) {
+ let semaphore = DispatchSemaphore(value: 0)
+ Task {
+ await block()
+ semaphore.signal()
+ }
+ semaphore.wait()
+ }
+}
\ No newline at end of file
diff --git a/swift/example_code/identity-resolvers/cognito-resolver/Sources/entry.swift b/swift/example_code/identity-resolvers/cognito-resolver/Sources/entry.swift
new file mode 100644
index 00000000000..917861d533e
--- /dev/null
+++ b/swift/example_code/identity-resolvers/cognito-resolver/Sources/entry.swift
@@ -0,0 +1,57 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+/// A simple example that shows how to use the AWS SDK for Swift to
+/// authenticate using Amazon Cognito.
+
+// snippet-start:[swift.identity.cognito.imports]
+import ArgumentParser
+import AWSCognitoIdentity
+import AWSIAM
+import AWSS3
+import AWSSDKIdentity
+import AWSSTS
+import Foundation
+import SmithyIdentity
+// snippet-end:[swift.identity.cognito.imports]
+
+struct ExampleCommand: ParsableCommand {
+ @Option(help: "AWS Region name")
+ var region = "us-east-1"
+
+ static var configuration = CommandConfiguration(
+ commandName: "cognito-resolver",
+ abstract: """
+ Demonstrates how to use a Cognito credential identity resolver with the
+ AWS SDK for Swift.
+ """,
+ discussion: """
+ """
+ )
+
+ /// Called by ``main()`` to do the actual running of the AWS
+ /// example.
+ func runAsync() async throws {
+ let example = try Example(region: region)
+
+ try await example.run()
+ }
+}
+
+/// The program's asynchronous entry point.
+@main
+struct Main {
+ /// The function that serves as the main asynchronous entry point for the
+ /// example. It parses the command line using the Swift Argument Parser,
+ /// then calls the `runAsync()` function to run the example itself.
+ static func main() async {
+ let args = Array(CommandLine.arguments.dropFirst())
+
+ do {
+ let command = try ExampleCommand.parse(args)
+ try await command.runAsync()
+ } catch {
+ ExampleCommand.exit(withError: error)
+ }
+ }
+}
diff --git a/swift/example_code/sfn/README.md b/swift/example_code/sfn/README.md
new file mode 100644
index 00000000000..ecdac41c071
--- /dev/null
+++ b/swift/example_code/sfn/README.md
@@ -0,0 +1,122 @@
+# Step Functions code examples for the SDK for Swift
+
+## Overview
+
+Shows how to use the AWS SDK for Swift to work with AWS Step Functions.
+
+
+
+
+_Step Functions makes it easy to coordinate the components of distributed applications as a series of steps in a visual workflow._
+
+## ⚠ Important
+
+* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/).
+* Running the tests might result in charges to your AWS account.
+* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
+* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
+
+
+
+
+## Code examples
+
+### Prerequisites
+
+For prerequisites, see the [README](../../README.md#Prerequisites) in the `swift` folder.
+
+
+
+
+
+### Basics
+
+Code examples that show you how to perform the essential operations within a service.
+
+- [Learn the basics](scenario/Sources/entry.swift)
+
+
+### Single actions
+
+Code excerpts that show you how to call individual service functions.
+
+- [CreateActivity](scenario/Sources/Activity.swift#L42)
+- [CreateStateMachine](scenario/Sources/StateMachine.swift#L133)
+- [DeleteActivity](scenario/Sources/Activity.swift#L102)
+- [DeleteStateMachine](scenario/Sources/StateMachine.swift#L308)
+- [DescribeExecution](scenario/Sources/StateMachine.swift#L263)
+- [DescribeStateMachine](scenario/Sources/StateMachine.swift#L180)
+- [GetActivityTask](scenario/Sources/StateMachine.swift#L228)
+- [ListActivities](scenario/Sources/Activity.swift#L42)
+- [ListStateMachines](scenario/Sources/StateMachine.swift#L105)
+- [SendTaskSuccess](scenario/Sources/Activity.swift#L115)
+- [StartExecution](scenario/Sources/StateMachine.swift#L205)
+
+
+
+
+
+## Run the examples
+
+### Instructions
+
+To build any of these examples from a terminal window, navigate into its
+directory, then use the following command:
+
+```
+$ swift build
+```
+
+To build one of these examples in Xcode, navigate to the example's directory
+(such as the `ListUsers` directory, to build that example). Then type `xed.`
+to open the example directory in Xcode. You can then use standard Xcode build
+and run commands.
+
+
+
+
+
+#### Learn the basics
+
+This example shows you how to do the following:
+
+- Create an activity.
+- Create a state machine from an Amazon States Language definition that contains the previously created activity as a step.
+- Run the state machine and respond to the activity with user input.
+- Get the final status and output after the run completes, then clean up resources.
+
+
+
+
+
+
+
+
+
+### Tests
+
+⚠ Running tests might result in charges to your AWS account.
+
+
+To find instructions for running these tests, see the [README](../../README.md#Tests)
+in the `swift` folder.
+
+
+
+
+
+
+## Additional resources
+
+- [Step Functions Developer Guide](https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html)
+- [Step Functions API Reference](https://docs.aws.amazon.com/step-functions/latest/apireference/Welcome.html)
+- [SDK for Swift Step Functions reference](https://sdk.amazonaws.com/swift/api/awssfn/latest/documentation/awssfn)
+
+
+
+
+---
+
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0
diff --git a/swift/example_code/sfn/hello/Package.swift b/swift/example_code/sfn/hello/Package.swift
new file mode 100644
index 00000000000..c2013d449a3
--- /dev/null
+++ b/swift/example_code/sfn/hello/Package.swift
@@ -0,0 +1,47 @@
+// swift-tools-version: 5.9
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+// (swift-tools-version has two lines here because it needs to be the first
+// line in the file, but it should also appear in the snippet below)
+//
+// snippet-start:[swift.sfn.hello.package]
+// swift-tools-version: 5.9
+//
+// The swift-tools-version declares the minimum version of Swift required to
+// build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "hello-sfn",
+ // Let Xcode know the minimum Apple platforms supported.
+ platforms: [
+ .macOS(.v13),
+ .iOS(.v15)
+ ],
+ dependencies: [
+ // Dependencies declare other packages that this package depends on.
+ .package(
+ url: "https://github.com/awslabs/aws-sdk-swift",
+ from: "1.0.0"),
+ .package(
+ url: "https://github.com/apple/swift-argument-parser.git",
+ branch: "main"
+ )
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package, defining a module or a test suite.
+ // Targets can depend on other targets in this package and products
+ // from dependencies.
+ .executableTarget(
+ name: "hello-sfn",
+ dependencies: [
+ .product(name: "AWSSFN", package: "aws-sdk-swift"),
+ .product(name: "ArgumentParser", package: "swift-argument-parser")
+ ],
+ path: "Sources")
+
+ ]
+)
+// snippet-end:[swift.sfn.hello.package]
diff --git a/swift/example_code/sfn/hello/Sources/entry.swift b/swift/example_code/sfn/hello/Sources/entry.swift
new file mode 100644
index 00000000000..c753654c391
--- /dev/null
+++ b/swift/example_code/sfn/hello/Sources/entry.swift
@@ -0,0 +1,74 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+// snippet-start:[swift.sfn.hello]
+// An example that shows how to use the AWS SDK for Swift to perform a simple
+// operation using Amazon Elastic Compute Cloud (EC2).
+//
+
+import ArgumentParser
+import Foundation
+
+// snippet-start:[swift.sfn.import]
+import AWSSFN
+// snippet-end:[swift.sfn.import]
+
+struct ExampleCommand: ParsableCommand {
+ @Option(help: "The AWS Region to run AWS API calls in.")
+ var awsRegion = "us-east-1"
+
+ static var configuration = CommandConfiguration(
+ commandName: "hello-sfn",
+ abstract: """
+ Demonstrates a simple operation using AWS Step Functions.
+ """,
+ discussion: """
+ An example showing how to make a call to AWS Step Functions using the
+ AWS SDK for Swift.
+ """
+ )
+
+ /// Called by ``main()`` to run the bulk of the example.
+ func runAsync() async throws {
+ let sfnConfig = try await SFNClient.SFNClientConfiguration(region: awsRegion)
+ let sfnClient = SFNClient(config: sfnConfig)
+
+ // snippet-start:[swift.sfn.hello.ListStateMachines]
+ do {
+ let output = try await sfnClient.listStateMachines(
+ input: ListStateMachinesInput(
+ maxResults: 10
+ )
+ )
+
+ guard let stateMachines = output.stateMachines else {
+ print("*** No state machines found.")
+ return
+ }
+
+ print("Found \(stateMachines.count) state machines (capped to 10)...")
+ for machine in stateMachines {
+ print(" \(machine.name ?? ""): \(machine.stateMachineArn ?? "")")
+ }
+ } catch {
+ print("*** Error fetching state machine list: \(error.localizedDescription)")
+ }
+ // snippet-end:[swift.sfn.hello.ListStateMachines]
+ }
+}
+
+/// The program's asynchronous entry point.
+@main
+struct Main {
+ static func main() async {
+ let args = Array(CommandLine.arguments.dropFirst())
+
+ do {
+ let command = try ExampleCommand.parse(args)
+ try await command.runAsync()
+ } catch {
+ ExampleCommand.exit(withError: error)
+ }
+ }
+}
+// snippet-end:[swift.sfn.hello]
diff --git a/swift/example_code/sfn/scenario/Package.swift b/swift/example_code/sfn/scenario/Package.swift
new file mode 100644
index 00000000000..ef21eeb8a90
--- /dev/null
+++ b/swift/example_code/sfn/scenario/Package.swift
@@ -0,0 +1,48 @@
+// swift-tools-version: 5.9
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+// (swift-tools-version has two lines here because it needs to be the first
+// line in the file, but it should also appear in the snippet below)
+//
+// snippet-start:[swift.sfn.hello.package]
+// swift-tools-version: 5.9
+//
+// The swift-tools-version declares the minimum version of Swift required to
+// build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "sfn-scenario",
+ // Let Xcode know the minimum Apple platforms supported.
+ platforms: [
+ .macOS(.v13),
+ .iOS(.v15)
+ ],
+ dependencies: [
+ // Dependencies declare other packages that this package depends on.
+ .package(
+ url: "https://github.com/awslabs/aws-sdk-swift",
+ from: "1.0.0"),
+ .package(
+ url: "https://github.com/apple/swift-argument-parser.git",
+ branch: "main"
+ )
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package, defining a module or a test suite.
+ // Targets can depend on other targets in this package and products
+ // from dependencies.
+ .executableTarget(
+ name: "sfn-scenario",
+ dependencies: [
+ .product(name: "AWSIAM", package: "aws-sdk-swift"),
+ .product(name: "AWSSFN", package: "aws-sdk-swift"),
+ .product(name: "ArgumentParser", package: "swift-argument-parser")
+ ],
+ path: "Sources")
+
+ ]
+)
+// snippet-end:[swift.sfn.hello.package]
diff --git a/swift/example_code/sfn/scenario/Sources/Activity.swift b/swift/example_code/sfn/scenario/Sources/Activity.swift
new file mode 100644
index 00000000000..375a0b0100c
--- /dev/null
+++ b/swift/example_code/sfn/scenario/Sources/Activity.swift
@@ -0,0 +1,137 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+// snippet-start:[swift.sfn.scenario.activity]
+import Foundation
+import AWSSFN
+
+/// Describes errors that occur on Step Functions activities.
+enum ActivityError: Error {
+ /// The ARN is missing from the returned activity.
+ case missingArnError
+ /// The activity list is missing from the response.
+ case missingActivityListError
+ /// No matching activity was found.
+ case activityNotFoundError
+
+ var errorDescription: String {
+ switch self {
+ case .missingArnError:
+ return "The ARN is missing from the returned activity"
+ case .missingActivityListError:
+ return "The activity list is missing from the response"
+ case .activityNotFoundError:
+ return "No activity with the specified name was found"
+ }
+ }
+}
+
+/// Manage a Step Functions activity.
+class Activity {
+ let sfnClient: SFNClient
+ let activityName: String
+ var activityArn = ""
+
+ init(client: SFNClient, name: String) async throws {
+ sfnClient = client
+ self.activityName = name
+
+ try await self.findOrCreateActivity()
+ }
+
+ // snippet-start:[swift.sfn.CreateActivity]
+ /// Create a new Step Functions activity.
+ ///
+ /// - Throws: `ActivityError` and appropriate AWS errors.
+ private func createActivity() async throws {
+ let output = try await sfnClient.createActivity(
+ input: CreateActivityInput(name: activityName)
+ )
+
+ guard let arn = output.activityArn else {
+ throw ActivityError.missingArnError
+ }
+
+ activityArn = arn
+ }
+ // snippet-end:[swift.sfn.CreateActivity]
+
+ // snippet-start:[swift.sfn.ListActivitiesPaginated]
+ // snippet-start:[swift.sfn.ListActivities]
+ /// Find an activity with the name specified when initializing the
+ /// `Activity` object.
+ ///
+ /// - Throws: `ActivityError` and appropriate AWS errors.
+ private func findActivity() async throws {
+ let pages = sfnClient.listActivitiesPaginated(
+ input: ListActivitiesInput()
+ )
+
+ for try await page in pages {
+ guard let activities = page.activities else {
+ throw ActivityError.missingActivityListError
+ }
+
+ for activity in activities {
+ if activity.name == activityName {
+ guard let arn = activity.activityArn else {
+ throw ActivityError.missingArnError
+ }
+ self.activityArn = arn
+ }
+ }
+ }
+
+ throw ActivityError.activityNotFoundError
+ }
+ // snippet-end:[swift.sfn.ListActivities]
+ // snippet-end:[swift.sfn.ListActivitiesPaginated]
+
+ /// Finds an existing activity with the name given when initializing
+ /// the `Activity`. If one isn't found, a new one is created.
+ ///
+ /// - Throws: `ActivityError` and appropriate AWS errors.
+ private func findOrCreateActivity() async throws {
+ do {
+ try await findActivity()
+ } catch {
+ try await createActivity()
+ }
+ }
+
+ // snippet-start:[swift.sfn.DeleteActivity]
+ /// Delete the activity described by this object.
+ public func delete() async {
+ do {
+ _ = try await sfnClient.deleteActivity(
+ input: DeleteActivityInput(activityArn: activityArn)
+ )
+ } catch {
+ print("*** Error deleting the activity: \(error.localizedDescription)")
+ }
+ }
+ // snippet-end:[swift.sfn.DeleteActivity]
+
+ // snippet-start:[swift.sfn.SendTaskSuccess]
+ /// Sends a task success notification to the activity.
+ ///
+ /// - Parameters:
+ /// - taskToken: The task's token.
+ /// - response: The task response.
+ ///
+ /// - Returns: `ActivityError` and appropriate AWS errors.
+ public func sendTaskSuccess(taskToken: String, response: String) async -> Bool {
+ do {
+ _ = try await sfnClient.sendTaskSuccess(
+ input: SendTaskSuccessInput(output: response, taskToken: taskToken)
+ )
+
+ return true
+ } catch {
+ print("*** Error sending task success: \(error.localizedDescription)")
+ return false
+ }
+ }
+ // snippet-end:[swift.sfn.SendTaskSuccess]
+}
+// snippet-end:[swift.sfn.scenario.activity]
diff --git a/swift/example_code/sfn/scenario/Sources/Example.swift b/swift/example_code/sfn/scenario/Sources/Example.swift
new file mode 100644
index 00000000000..43113be53e1
--- /dev/null
+++ b/swift/example_code/sfn/scenario/Sources/Example.swift
@@ -0,0 +1,252 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import Foundation
+import AWSIAM
+import AWSSFN
+
+class Example {
+ let sfnClient: SFNClient
+ let iamClient: IAMClient
+
+ let username: String
+ let activityName: String
+ var activity: Activity?
+ var stateMachineName: String
+ var stateMachinei: StateMachine?
+ var stateMachine: StateMachine?
+ var definitionPath: String
+ var runArn: String? = nil
+ var iamRole: IAMClientTypes.Role?
+
+ init(region: String, username: String, activityName: String, stateMachineName: String,
+ definitionPath: String) async throws {
+ let sfnConfig = try await SFNClient.SFNClientConfiguration(region: region)
+ sfnClient = SFNClient(config: sfnConfig)
+
+ let iamConfig = try await IAMClient.IAMClientConfiguration(region: region)
+ iamClient = IAMClient(config: iamConfig)
+
+ self.username = username
+ self.activityName = activityName
+ self.stateMachineName = stateMachineName
+ self.definitionPath = definitionPath
+ }
+
+ /// Clean up artifacts created by the program.
+ func cleanUp() async {
+ if iamRole != nil {
+ print("Deleting the IAM role: \(iamRole?.roleName ?? "")...")
+ do {
+ _ = try await iamClient.deleteRole(
+ input: DeleteRoleInput(roleName: iamRole?.roleName)
+ )
+ } catch {
+ print("*** Unable to delete the IAM role: \(error.localizedDescription)")
+ }
+ }
+
+ if activity != nil {
+ await activity?.delete()
+ }
+
+ if stateMachine != nil {
+ print("Deleting the State Machine...")
+ await stateMachine?.delete()
+ }
+ }
+
+ /// Create a new IAM role.
+ ///
+ /// - Returns: The `IAMClientTypes.Role` that was created, or `nil` if it
+ /// couldn't be created.
+ func createIAMRole() async -> IAMClientTypes.Role? {
+ let trustPolicy = """
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "",
+ "Effect": "Allow",
+ "Principal": {"Service": "states.amazonaws.com"},
+ "Action": "sts:AssumeRole"
+ }
+ ]
+ }
+ """
+
+ do {
+ let output = try await iamClient.createRole(
+ input: CreateRoleInput(
+ assumeRolePolicyDocument: trustPolicy,
+ roleName: tempName(prefix: "state-machine-demo-role")
+ )
+ )
+
+ return output.role
+ } catch {
+ print("*** Error creating the IAM role: \(error.localizedDescription)")
+ return nil
+ }
+ }
+
+ /// Delete the IAM role.
+ ///
+ /// - Throws: The AWS error, if any.
+ func deleteIAMRole() async throws {
+ guard let iamRole = self.iamRole else {
+ return
+ }
+
+ print("Deleting the IAM role: \(iamRole.roleName ?? "")")
+
+ _ = try await iamClient.deleteRole(
+ input: DeleteRoleInput(roleName: iamRole.roleName)
+ )
+ }
+
+ /// Generate and return a unique file name that begins with the specified
+ /// string.
+ ///
+ /// - Parameters:
+ /// - prefix: Text to use at the beginning of the returned name.
+ ///
+ /// - Returns: A string containing a unique filename that begins with the
+ /// specified `prefix`.
+ ///
+ /// The returned name uses a random number between 1 million and 1 billion to
+ /// provide reasonable certainty of uniqueness for the purposes of this
+ /// example.
+ func tempName(prefix: String) -> String {
+ return "\(prefix)-\(Int.random(in: 1000000..<1000000000))"
+ }
+
+ /// Run the example.
+ func run() async {
+ print("Creating the IAM role...")
+ iamRole = await createIAMRole()
+
+ if iamRole == nil {
+ print("Unable to create the IAM role. Exiting.")
+ return
+ }
+
+ print("Created role: \(iamRole?.roleName ?? "")")
+
+ // Find or create a Step Functions activity.
+
+ print("Finding or creating a Step Functions activity...")
+
+ do {
+ activity = try await Activity(client: sfnClient, name: activityName)
+ } catch let error as ActivityError {
+ print("Unable to create the activity. \(error.errorDescription)")
+ await cleanUp()
+ return
+ } catch {
+ print("An AWS error occurred: \(error.localizedDescription)")
+ await cleanUp()
+ return
+ }
+
+ guard let activity = activity else {
+ print("No activity available.")
+ await cleanUp()
+ return
+ }
+
+ print("Created Step Functions activity with ARN \(activity.activityArn).")
+
+ // Find or create a State Machine.
+
+ print("Finding or creating a State Machine...")
+ do {
+ stateMachine = try await StateMachine(
+ sfnClient: sfnClient,
+ name: stateMachineName,
+ iamRole: iamRole!,
+ definitionPath: definitionPath,
+ activity: activity
+ )
+ } catch let error as StateMachineError {
+ print("Unable to create the state machine: \(error.errorDescription)")
+ await cleanUp()
+ return
+ } catch {
+ print("An AWS error occurred while creating the state machine: \(error.localizedDescription)")
+ await cleanUp()
+ return
+ }
+
+ guard let stateMachine = stateMachine else {
+ print("No state machine available.")
+ await cleanUp()
+ return
+ }
+
+ // Display information about the State Machine.
+
+ do {
+ try await stateMachine.describe()
+ } catch let error as StateMachineError {
+ print("Unable to describe the state machine: \(error.errorDescription)")
+ await cleanUp()
+ return
+ } catch {
+ print("An AWS error occurred getting state machine details: \(error.localizedDescription)")
+ await cleanUp()
+ return
+ }
+
+ // Run the state machine.
+
+ do {
+ runArn = try await stateMachine.start(username: username)
+ } catch let error as StateMachineError {
+ print("Unable to start the state machine: \(error.errorDescription)")
+ await cleanUp()
+ return
+ } catch {
+ print("An AWS error occurred while starting the state machine: \(error.localizedDescription)")
+ await cleanUp()
+ return
+ }
+
+ guard let runArn else {
+ print("Unable to run the state machine. Exiting.")
+ await cleanUp()
+ return
+ }
+
+ // Step through the state machine. This function runs until the state
+ // machine enters its "done" state.
+
+ do {
+ try await stateMachine.execute()
+ } catch let error as StateMachineError {
+ print("Error executing the state machine: \(error.errorDescription)")
+ await cleanUp()
+ return
+ } catch {
+ print("AWS error while executing the state machine: \(error.localizedDescription)")
+ await cleanUp()
+ return
+ }
+
+ // Finish running the state machine.
+
+ do {
+ try await stateMachine.finishExecution(arn: runArn)
+ } catch let error as StateMachineError {
+ print("Error while stopping the state machine: \(error.errorDescription)")
+ await cleanUp()
+ return
+ } catch {
+ print("AWS error while stopping the state machine: \(error.localizedDescription)")
+ await cleanUp()
+ return
+ }
+
+ await cleanUp()
+ }
+}
diff --git a/swift/example_code/sfn/scenario/Sources/StateMachine.swift b/swift/example_code/sfn/scenario/Sources/StateMachine.swift
new file mode 100644
index 00000000000..b18bf61c2ec
--- /dev/null
+++ b/swift/example_code/sfn/scenario/Sources/StateMachine.swift
@@ -0,0 +1,371 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+// snippet-start:[swift.sfn.scenario.statemachine]
+import Foundation
+import AWSSFN
+import AWSIAM
+
+/// Describes an error the occurred while managing the state machine.
+enum StateMachineError: Error {
+ /// No matching role was found.
+ case roleNotFoundError
+ /// The ARN is missing from the returned state machine.
+ case missingArnError
+ /// The state machine list is missing from the response.
+ case missingStateMachineListError
+ /// No matching state machine was found.
+ case stateMachineNotFoundError
+ /// Unable to read the state machine definition file.
+ case definitionFileReadError
+ /// A state machine's details are missing
+ case stateMachineDetailsMissingError
+ /// The task token is missing from the activity task.
+ case taskTokenMissingError
+ /// The input is missing from the activity task.
+ case inputMissingError
+ /// The state machine's output is missing.
+ case outputMissingError
+ /// The state machine's execution has been aborted.
+ case executionAborted
+ /// The state machine's execution failed.
+ case executionFailed
+ /// The state machine timed out.
+ case executionTimedOut
+ /// The state machine's status is unrecognized.
+ case executionStatusUnknown
+
+ var errorDescription: String {
+ switch self {
+ case .roleNotFoundError:
+ return "The specified role was not found or could not be created"
+ case .missingArnError:
+ return "The ARN is missing from the returned activity"
+ case .missingStateMachineListError:
+ return "The state machine list is missing from the response"
+ case .stateMachineNotFoundError:
+ return "No state machine with the specified name was found"
+ case .definitionFileReadError:
+ return "Unable to read the state machine definition file"
+ case .stateMachineDetailsMissingError:
+ return "The state machine's details are missing"
+ case .taskTokenMissingError:
+ return "The task token is missing from the activity task."
+ case .inputMissingError:
+ return "The input is missing from the activity task."
+ case .outputMissingError:
+ return "The state machine's output is missing."
+ case .executionAborted:
+ return "The state machine's execution was aborted."
+ case .executionFailed:
+ return "The state machine's execution failed."
+ case .executionTimedOut:
+ return "The state machine's execution timed out."
+ case .executionStatusUnknown:
+ return "The state machine has entered an unknown status."
+ }
+ }
+}
+
+/// Describes a message and a list of actions that can be taken in response
+/// to that message.
+struct ActionList: Decodable {
+ let message: String
+ let actions: [String]
+}
+
+/// Describes a message returned by an action.
+struct Output: Decodable {
+ let message: String
+}
+
+/// Encapsulates an AWS Step Functions state machine.
+class StateMachine {
+ let sfnClient: SFNClient
+ let iamRole: IAMClientTypes.Role
+ let activity: Activity
+ let stateMachineName: String
+ let definitionPath: String
+ var stateMachineArn = ""
+
+ init(sfnClient: SFNClient, name: String,
+ iamRole: IAMClientTypes.Role, definitionPath: String,
+ activity: Activity) async throws {
+
+ self.sfnClient = sfnClient
+ self.iamRole = iamRole
+ self.stateMachineName = name
+ self.definitionPath = definitionPath
+ self.activity = activity
+
+ try await findOrCreateStateMachine()
+ }
+
+ // snippet-start:[swift.sfn.ListStateMachinesPaginated]
+ // snippet-start:[swift.sfn.ListStateMachines]
+ /// Finds a state machine matching the name specified when initializing the `StateMachine`.
+ /// - Throws: `StateMachineError` and appropriate AWS errors.
+ private func findStateMachine() async throws {
+ let pages = sfnClient.listStateMachinesPaginated(
+ input: ListStateMachinesInput()
+ )
+
+ for try await page in pages {
+ guard let stateMachines = page.stateMachines else {
+ throw StateMachineError.missingStateMachineListError
+ }
+
+ for stateMachine in stateMachines {
+ if stateMachine.name == stateMachineName {
+ guard let arn = stateMachine.stateMachineArn else {
+ throw StateMachineError.missingArnError
+ }
+ stateMachineArn = arn
+ }
+ }
+ }
+
+ throw StateMachineError.stateMachineNotFoundError
+ }
+ // snippet-end:[swift.sfn.ListStateMachines]
+ // snippet-end:[swift.sfn.ListStateMachinesPaginated]
+
+ // snippet-start:[swift.sfn.CreateStateMachine]
+ /// Create a new state machine with the name given when initializing the
+ /// `StateMachine` object.
+ ///
+ /// - Throws: `StateMachineError` and appropriate AWS errors.
+ private func createStateMachine() async throws {
+ var definition: String
+
+ print("Reading the state machine file from \(definitionPath)...")
+ do {
+ definition = try String(contentsOfFile: definitionPath, encoding: .utf8)
+ } catch {
+ throw StateMachineError.definitionFileReadError
+ }
+
+ // Swap in the activity's ARN into the definition string.
+
+ definition.replace("{{DOC_EXAMPLE_ACTIVITY_ARN}}", with: activity.activityArn)
+
+ let output = try await sfnClient.createStateMachine(
+ input: CreateStateMachineInput(
+ definition: definition,
+ name: stateMachineName,
+ roleArn: iamRole.arn
+ )
+ )
+
+ guard let arn = output.stateMachineArn else {
+ throw StateMachineError.missingArnError
+ }
+
+ stateMachineArn = arn
+ }
+ // snippet-end:[swift.sfn.CreateStateMachine]
+
+ /// Finds a state machine matching the name given when initializing the
+ /// `StateMachine` object. If it doesn't exist, a new one is created.
+ ///
+ /// - Throws: `StateMachineError` and appropriate AWS errors.
+ private func findOrCreateStateMachine() async throws {
+ do {
+ try await findStateMachine()
+ } catch {
+ try await createStateMachine()
+ }
+ }
+
+ // snippet-start:[swift.sfn.DescribeStateMachine]
+ /// Outputs a description of the state machine.
+ ///
+ /// - Throws: `StateMachineError` and appropriate AWS errors.
+ func describe() async throws {
+ let output = try await sfnClient.describeStateMachine(
+ input: DescribeStateMachineInput(
+ stateMachineArn: stateMachineArn
+ )
+ )
+
+ guard let name = output.name,
+ let status = output.status else {
+ throw StateMachineError.stateMachineDetailsMissingError
+ }
+
+ print()
+ print("State machine details: ")
+ print(" Name: \(name)")
+ print(" ARN: \(stateMachineArn)")
+ print(" Status: \(status)")
+ print()
+ }
+ // snippet-end:[swift.sfn.DescribeStateMachine]
+
+ // snippet-start:[swift.sfn.StartExecution]
+ /// Start up the state machine.
+ ///
+ /// - Parameter username: The username to use for the conversation.
+ ///
+ /// - Throws: `StateMachineError` and appropriate AWS errors.
+ /// - Returns: The execution ARN of the running state machine.
+ func start(username: String) async throws -> String? {
+ let runInput = """
+ { "name": "\(username)" }
+ """
+
+ let output = try await sfnClient.startExecution(
+ input: StartExecutionInput(
+ input: runInput,
+ stateMachineArn: stateMachineArn
+ )
+ )
+
+ return output.executionArn
+ }
+ // snippet-end:[swift.sfn.StartExecution]
+
+ // snippet-start:[swift.sfn.GetActivityTask]
+ /// Execute the steps of the state machine until it exits.
+ ///
+ /// - Throws: `StateMachineError` and appropriate AWS errors.
+ func execute() async throws {
+ var action: String = ""
+
+ while action != "done" {
+ let getTaskOutput = try await sfnClient.getActivityTask(
+ input: GetActivityTaskInput(
+ activityArn: activity.activityArn
+ )
+ )
+
+ guard let token = getTaskOutput.taskToken else {
+ throw StateMachineError.taskTokenMissingError
+ }
+ guard let input = getTaskOutput.input else {
+ throw StateMachineError.inputMissingError
+ }
+
+ let inputData = input.data(using: .utf8)!
+ let inputObject = try! JSONDecoder().decode(ActionList.self, from: inputData)
+
+ print("Task message: \(inputObject.message)")
+
+ action = menuRequest(prompt: "Choose an action:", options: inputObject.actions)
+ _ = await activity.sendTaskSuccess(taskToken: token, response: """
+ { "action": "\(action)" }
+ """
+ )
+ }
+ }
+ // snippet-end:[swift.sfn.GetActivityTask]
+
+ // snippet-start:[swift.sfn.DescribeExecution]
+ /// Wait for the execution to end, then output its final message.
+ ///
+ /// - Parameter arn: The execution ARN to finish.
+ ///
+ /// - Throws: `StateMachineError` and appropriate AWS errors.
+ func finishExecution(arn: String) async throws {
+ var status: SFNClientTypes.ExecutionStatus = .running
+
+ while status == .running {
+ let output = try await sfnClient.describeExecution(
+ input: DescribeExecutionInput(
+ executionArn: arn
+ )
+ )
+
+ status = output.status ?? .aborted
+
+ switch status {
+ case .running:
+ print("The state machine is still running. Waiting for it to finish.")
+ await sleep(forSeconds: 1)
+ case .succeeded:
+ guard let outputString = output.output else {
+ throw StateMachineError.outputMissingError
+ }
+
+ let outputData = outputString.data(using: .utf8)!
+ let outputObject = try! JSONDecoder().decode(Output.self, from: outputData)
+ print("""
+ Execution completed with final message: \(outputObject.message)
+ """)
+ case .aborted:
+ throw StateMachineError.executionAborted
+ case .failed:
+ throw StateMachineError.executionFailed
+ case .timedOut:
+ throw StateMachineError.executionTimedOut
+ default:
+ throw StateMachineError.executionStatusUnknown
+ }
+ }
+ }
+ // snippet-end:[swift.sfn.DescribeExecution]
+
+ // snippet-start:[swift.sfn.DeleteStateMachine]
+ /// Delete the state machine.
+ func delete() async {
+ do {
+ _ = try await sfnClient.deleteStateMachine(
+ input: DeleteStateMachineInput(stateMachineArn: stateMachineArn)
+ )
+ } catch {
+ print("*** Error deleting the state machine: \(error.localizedDescription)")
+ }
+ }
+ // snippet-end:[swift.sfn.DeleteStateMachine]
+
+ /// Sleep for the specified number of seconds.
+ ///
+ /// - Parameter seconds: The number of seconds to sleep, as a floating
+ /// point value.
+ func sleep(forSeconds seconds: Double) async {
+ do {
+ try await Task.sleep(for: .seconds(seconds))
+ } catch {
+ return
+ }
+
+ }
+
+ /// Display a menu of options then request a selection.
+ ///
+ /// - Parameters:
+ /// - prompt: A prompt string to display before the menu.
+ /// - options: An array of strings giving the menu options.
+ ///
+ /// - Returns: The string value of the selected option.
+ func menuRequest(prompt: String, options: [String]) -> String {
+ let numOptions = options.count
+
+ if numOptions == 0 {
+ return "done"
+ }
+
+ print(prompt)
+
+ for (index, value) in options.enumerated() {
+ print("(\(index+1)) \(value)")
+ }
+
+ repeat {
+ print("Enter your selection (1 - \(numOptions)): ", terminator: "")
+ if let answer = readLine() {
+ guard let answer = Int(answer) else {
+ print("Please enter the number matching your selection.")
+ continue
+ }
+
+ if answer > 0 && answer <= numOptions {
+ return options[answer-1]
+ } else {
+ print("Please enter the number matching your selection.")
+ }
+ }
+ } while true
+ }
+}
+// snippet-end:[swift.sfn.scenario.statemachine]
diff --git a/swift/example_code/sfn/scenario/Sources/entry.swift b/swift/example_code/sfn/scenario/Sources/entry.swift
new file mode 100644
index 00000000000..c9ce063ae97
--- /dev/null
+++ b/swift/example_code/sfn/scenario/Sources/entry.swift
@@ -0,0 +1,62 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
+// snippet-start:[swift.sfn.scenario]
+// An example that shows how to use the AWS SDK for Swift to perform a simple
+// operation using Amazon Elastic Compute Cloud (EC2).
+//
+
+import ArgumentParser
+import Foundation
+
+struct ExampleCommand: ParsableCommand {
+ @Option(help: "The AWS Region to run AWS API calls in.")
+ var awsRegion = "us-east-1"
+
+ @Option(help: "The user's name.")
+ var username = "Johanna Doe"
+
+ @Option(help: "The name of the activity to find or create.")
+ var activityName = "scenario-example-activity"
+
+ @Option(help: "The name of the state machine to find or create.")
+ var stateMachineName = "scenario-example-state-machine"
+
+ @Option(help: "Path of the State Machine definition file.")
+ var definitionPath: String
+
+ static var configuration = CommandConfiguration(
+ commandName: "sfn-scenario",
+ abstract: """
+ Demonstrates a variety of AWS Step Function features.
+ """,
+ discussion: """
+ """
+ )
+
+ /// Called by ``main()`` to run the bulk of the example.
+ func runAsync() async throws {
+ let example = try await Example(region: awsRegion, username: username,
+ activityName: activityName,
+ stateMachineName: stateMachineName,
+ definitionPath: definitionPath)
+
+ await example.run()
+ }
+}
+
+/// The program's asynchronous entry point.
+@main
+struct Main {
+ static func main() async {
+ let args = Array(CommandLine.arguments.dropFirst())
+
+ do {
+ let command = try ExampleCommand.parse(args)
+ try await command.runAsync()
+ } catch {
+ ExampleCommand.exit(withError: error)
+ }
+ }
+}
+// snippet-end:[swift.sfn.scenario]