Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
180 changes: 70 additions & 110 deletions swift/example_code/lambda/using-lambda-runtime/Sources/lambda.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// snippet-start:[lambda.swift.function.imports]
import Foundation
import AWSLambdaRuntime
import AWSS3
@preconcurrency import AWSS3

import protocol AWSClientRuntime.AWSServiceError
import enum Smithy.ByteStream
Expand Down Expand Up @@ -38,125 +38,85 @@ enum S3ExampleLambdaErrors: Error {
/// A required environment variable is missing. The missing variable is
/// specified.
case noEnvironmentVariable(String)
/// The Amazon Simple Storage Service (S3) client couldn't be created.
case noS3Client
}
// snippet-end:[lambda.swift.function.errors]
// snippet-end:[lambda.swift.function.types]

// snippet-start:[lambda.swift.function.handler]
/// A Swift AWS Lambda Runtime `LambdaHandler` lets you both perform needed
/// initialization and handle AWS Lambda requests. There are other handler
/// protocols available for other use cases.
@main
struct S3ExampleLambda: LambdaHandler {
let s3Client: S3Client?

// snippet-start:[lambda.swift.function.handler.init]
/// Initialize the AWS Lambda runtime.
///
/// ^ The logger is a standard Swift logger. You can control the verbosity
/// by setting the `LOG_LEVEL` environment variable.
init(context: LambdaInitializationContext) async throws {
// Display the `LOG_LEVEL` configuration for this process.
context.logger.info(
"Log Level env var : \(ProcessInfo.processInfo.environment["LOG_LEVEL"] ?? "info" )"
)

// Initialize the Amazon S3 client. This single client is used for every
// request.
let currentRegion = ProcessInfo.processInfo.environment["AWS_REGION"] ?? "us-east-1"
self.s3Client = try? S3Client(region: currentRegion)
}
// snippet-end:[lambda.swift.function.handler.init]

// snippet-start:[lambda.swift.function.handler.putobject]
/// Write the specified text into a given Amazon S3 bucket. The object's
/// name is based on the current time.
///
/// - Parameters:
/// - s3Client: The `S3Client` to use when sending the object to the
/// bucket.
/// - bucketName: The name of the Amazon S3 bucket to put the object
/// into.
/// - body: The string to write into the new object.
///
/// - Returns: A string indicating the name of the file created in the AWS
/// S3 bucket.
private func putObject(client: S3Client,
bucketName: String,
body: String) async throws -> String {
// Generate an almost certainly unique object name based on the current
// timestamp.
let objectName = "\(Int(Date().timeIntervalSince1970*1_000_000)).txt"

// Create a Smithy `ByteStream` that represents the string to write into
// the bucket.
let inputStream = Smithy.ByteStream.data(body.data(using: .utf8))

// Store the text into an object in the Amazon S3 bucket.
let putObjectRequest = PutObjectInput(
let currentRegion = ProcessInfo.processInfo.environment["AWS_REGION"] ?? "us-east-1"
let s3Client = try S3Client(region: currentRegion)

// snippet-start:[lambda.swift.function.putobject]
/// Create a new object on Amazon S3 whose name is based on the current
/// timestamp, containing the text specified.
///
/// - Parameters:
/// - body: The text to store in the new S3 object.
/// - bucketName: The name of the Amazon S3 bucket to put the new object
/// into.
///
/// - Throws: Errors from `PutObject`.
///
/// - Returns: The name of the new Amazon S3 object that contains the
/// specified body text.
func putObject(body: String, bucketName: String) async throws -> String {
// Generate an almost certainly unique object name based on the current
// timestamp.

let objectName = "\(Int(Date().timeIntervalSince1970*1_000_000)).txt"

// Create a Smithy `ByteStream` that represents the string to write into
// the bucket.

let inputStream = Smithy.ByteStream.data(body.data(using: .utf8))

// Store the text into an object in the Amazon S3 bucket.

_ = try await s3Client.putObject(
input: PutObjectInput(
body: inputStream,
bucket: bucketName,
key: objectName
)
let _ = try await client.putObject(input: putObjectRequest)
)

// Return the name of the file

return objectName
}
// snippet-end:[lambda.swift.function.putobject]

// snippet-start:[lambda.swift.function.runtime]
let runtime = LambdaRuntime {
(event: Request, context: LambdaContext) async throws -> Response in

// Return the name of the file.
return objectName
var responseMessage: String

// Get the name of the bucket to write the new object into from the
// environment variable `BUCKET_NAME`.
guard let bucketName = ProcessInfo.processInfo.environment["BUCKET_NAME"] else {
context.logger.error("Set the environment variable BUCKET_NAME to the name of the S3 bucket to write files to.")
throw S3ExampleLambdaErrors.noEnvironmentVariable("BUCKET_NAME")
}
// snippet-end:[lambda.swift.function.handler.putobject]

// snippet-start:[lambda.swift.function.handler.handle]
/// The Lambda function's entry point. Called by the Lambda runtime.
///
/// - Parameters:
/// - event: The `Request` describing the request made by the
/// client.
/// - context: A `LambdaContext` describing the context in
/// which the lambda function is running.
///
/// - Returns: A `Response` object that will be encoded to JSON and sent
/// to the client by the Lambda runtime.
func handle(_ event: Request, context: LambdaContext) async throws -> Response {
// Get the bucket name from the environment.
guard let bucketName = ProcessInfo.processInfo.environment["BUCKET_NAME"] else {
throw S3ExampleLambdaErrors.noEnvironmentVariable("BUCKET_NAME")
}

// Make sure the `S3Client` is valid.
guard let s3Client else {
throw S3ExampleLambdaErrors.noS3Client
}

// Call the `putObject` function to store the object on Amazon S3.
var responseMessage: String
do {
let filename = try await putObject(
client: s3Client,
bucketName: bucketName,
body: event.body)

// Generate the response text.
responseMessage = "The Lambda function has successfully stored your data in S3 with name \(filename)'"

// Send the success notification to the logger.
context.logger.info("Data successfully stored in S3.")
} catch let error as AWSServiceError {
// Generate the error message.
responseMessage = "The Lambda function encountered an error and your data was not saved. Root cause: \(error.errorCode ?? "") - \(error.message ?? "")"

// Send the error message to the logger.
context.logger.error("Failed to upload data to Amazon S3.")
}

// Return the response message. The AWS Lambda runtime will send it to the
// client.
return Response(
req_id: context.requestID,
body: responseMessage)

do {
let filename = try await putObject(body: event.body, bucketName: bucketName)

// Generate the response text and update the log.
responseMessage = "The Lambda function has successfully stored your data in S3 with name '\(filename)'"
context.logger.info("Data successfully stored in S3.")
} catch let error as AWSServiceError {
// Generate the error message and update the log.
responseMessage = "The Lambda function encountered an error and your data was not saved. Root cause: \(error.errorCode ?? "") - \(error.message ?? "")"
context.logger.error("Failed to upload data to Amazon S3.")
}
// snippet-end:[lambda.swift.function.handler.handle]

return Response(req_id: context.requestID, body: responseMessage)
}
// snippet-end:[lambda.swift.function.handler]
// snippet-end:[lambda.swift.function.runtime]

// Start up the runtime.

// snippet-start:[lambda.swift.function.start]
try await runtime.run()
// snippet-end:[lambda.swift.function.start]
// snippet-end:[lambda.swift.function.complete]
122 changes: 122 additions & 0 deletions swift/example_code/sfn/README.md
Original file line number Diff line number Diff line change
@@ -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.

<!--custom.overview.start-->
<!--custom.overview.end-->

_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).

<!--custom.important.start-->
<!--custom.important.end-->

## Code examples

### Prerequisites

For prerequisites, see the [README](../../README.md#Prerequisites) in the `swift` folder.


<!--custom.prerequisites.start-->
<!--custom.prerequisites.end-->

### 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)


<!--custom.examples.start-->
<!--custom.examples.end-->

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

<!--custom.instructions.start-->
<!--custom.instructions.end-->


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

<!--custom.basic_prereqs.sfn_Scenario_GetStartedStateMachines.start-->
<!--custom.basic_prereqs.sfn_Scenario_GetStartedStateMachines.end-->


<!--custom.basics.sfn_Scenario_GetStartedStateMachines.start-->
<!--custom.basics.sfn_Scenario_GetStartedStateMachines.end-->


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



<!--custom.tests.start-->
<!--custom.tests.end-->

## 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)

<!--custom.resources.start-->
<!--custom.resources.end-->

---

Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
47 changes: 47 additions & 0 deletions swift/example_code/sfn/hello/Package.swift
Original file line number Diff line number Diff line change
@@ -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]
Loading
Loading