Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AWS SDK and Soto examples #396

Merged
merged 41 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
cb2cdde
fix typos on API GAteway example
sebsto Oct 8, 2024
bd07401
add aws sdk example
sebsto Oct 8, 2024
570b416
adjust for local CI
sebsto Oct 8, 2024
5e80824
add soto example
sebsto Oct 8, 2024
0398590
Merge branch 'main' into sebsto/awssdk_example
sebsto Oct 8, 2024
c75c999
update soto example readme
sebsto Oct 8, 2024
b545738
format
sebsto Oct 8, 2024
903c5d3
Merge branch 'main' into sebsto/awssdk_example
sebsto Oct 8, 2024
6bf8f0f
swift format
sebsto Oct 8, 2024
b41810e
Merge branch 'swift-server:main' into sebsto/awssdk_example
sebsto Oct 8, 2024
77b0c86
fix uppercase A
sebsto Oct 8, 2024
83446a8
remove unnecessary license header file
sebsto Oct 8, 2024
1030816
use trailing closure syntax + reuse S3 client
sebsto Oct 8, 2024
ba1f39d
remove unnecessary license header
sebsto Oct 8, 2024
33202cd
remove condition on Linux for platform
sebsto Oct 8, 2024
46e5337
swift format
sebsto Oct 8, 2024
683cd55
remove unnecessary license header
sebsto Oct 8, 2024
cc3f3c2
add soto client shutdown
sebsto Oct 8, 2024
20f7e51
Merge branch 'main' into sebsto/awssdk_example
sebsto Oct 9, 2024
5dc8371
Merge branch 'main' into sebsto/awssdk_example
sebsto Oct 9, 2024
0e4fa0c
revert platform dance to not break CI
sebsto Oct 9, 2024
39deb51
remove unnecessary init
sebsto Oct 9, 2024
bc3fe1a
rename directory to SotoS3
sebsto Oct 9, 2024
4748146
Merge branch 'main' into sebsto/awssdk_example
sebsto Oct 9, 2024
0e9b045
change directory name to focus on use case first, lib second
sebsto Oct 9, 2024
9c91745
fix typos in the readme
sebsto Oct 9, 2024
28ca63e
Merge branch 'main' into sebsto/awssdk_example
sebsto Oct 10, 2024
e54297b
Merge branch 'main' into sebsto/awssdk_example
sebsto Oct 10, 2024
a3b29c6
add new examples to CI
sebsto Oct 10, 2024
96efb9a
fix CI for examples
sebsto Oct 10, 2024
b47d1b8
use amazonlinux docker image instead of ubuntu
sebsto Oct 10, 2024
38ab48a
dynamically add runtime dependency based on env var
sebsto Oct 10, 2024
4e73292
remove import of Foundation.ProcessInfo
sebsto Oct 10, 2024
56b07b5
change log level and add comment in template.yaml
sebsto Oct 10, 2024
156c7e7
downgrade actions/checkout to v3 to workaround dependency on mazonLin…
sebsto Oct 10, 2024
b747e5d
Swift format
sebsto Oct 10, 2024
34ec3ed
workaround https://github.com/actions/checkout/issues/1487
sebsto Oct 10, 2024
d40d324
fix CI
sebsto Oct 10, 2024
6998a50
fix ci
sebsto Oct 10, 2024
c5039ea
fix ci
sebsto Oct 10, 2024
f5506f5
fix ci
sebsto Oct 10, 2024
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
4 changes: 2 additions & 2 deletions Examples/APIGateway/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let package = Package(
name: "swift-aws-lambda-runtime-example",
platforms: platforms,
products: [
.executable(name: "APIGAtewayLambda", targets: ["APIGAtewayLambda"])
.executable(name: "APIGatewayLambda", targets: ["APIGatewayLambda"])
],
dependencies: [
// dependency on swift-aws-lambda-runtime is added dynamically below
Expand All @@ -26,7 +26,7 @@ let package = Package(
],
targets: [
.executableTarget(
name: "APIGAtewayLambda",
name: "APIGatewayLambda",
dependencies: [
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
.product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events"),
Expand Down
10 changes: 5 additions & 5 deletions Examples/APIGateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ swift package archive --allow-network-access docker
```

If there is no error, there is a ZIP file ready to deploy.
The ZIP file is located at `.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip`
The ZIP file is located at `.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/APIGatewayLambda/APIGatewayLambda.zip`

## Deploy

Expand All @@ -40,9 +40,9 @@ To actually deploy your Lambda function and create the infrastructure, type the

```bash
sam deploy \
----resolve-s3 \
--resolve-s3 \
--template-file template.yaml \
--stack-name MyLambda \
--stack-name APIGatewayLambda \
--capabilities CAPABILITY_IAM
```

Expand All @@ -53,8 +53,8 @@ The output is similar to this one.
-----------------------------------------------------------------------------------------------------------------------------
Outputs
-----------------------------------------------------------------------------------------------------------------------------
Key APIGAtewayEndpoint
Description API Gateway endpoint UR"
Key APIGatewayEndpoint
Description API Gateway endpoint URL"
Value https://a5q74es3k2.execute-api.us-east-1.amazonaws.com
-----------------------------------------------------------------------------------------------------------------------------
```
Expand Down
6 changes: 3 additions & 3 deletions Examples/APIGateway/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ Description: SAM Template for QuoteService

Resources:
# Lambda function
APIGAtewayLambda:
APIGatewayLambda:
Type: AWS::Serverless::Function
Properties:
CodeUri: .build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/APIGAtewayLambda/APIGAtewayLambda.zip
CodeUri: .build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/APIGatewayLambda/APIGatewayLambda.zip
Timeout: 60
Handler: swift.bootstrap
Runtime: provided.al2
Expand All @@ -26,6 +26,6 @@ Resources:

Outputs:
# print API Gateway endpoint
APIGAtewayEndpoint:
APIGatewayEndpoint:
Description: API Gateway endpoint UR"
Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com"
12 changes: 12 additions & 0 deletions Examples/AWSSDK/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.DS_Store
.aws-sam/
.build
samtemplate.toml
*/build/*
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
55 changes: 55 additions & 0 deletions Examples/AWSSDK/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// swift-tools-version: 6.0

import PackageDescription

// needed for CI to test the local version of the library
import class Foundation.ProcessInfo
import struct Foundation.URL

#if os(macOS)
let platforms: [PackageDescription.SupportedPlatform]? = [.macOS(.v15)]
#else
let platforms: [PackageDescription.SupportedPlatform]? = nil
#endif
sebsto marked this conversation as resolved.
Show resolved Hide resolved

let package = Package(
name: "AWSSDKExample",
platforms: platforms,
products: [
.executable(name: "AWSSDKExample", targets: ["AWSSDKExample"])
],
dependencies: [
// dependency on swift-aws-lambda-runtime is added dynamically below
// .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", branch: "main")
.package(url: "https://github.com/swift-server/swift-aws-lambda-events", branch: "main"),
.package(url: "https://github.com/awslabs/aws-sdk-swift", from: "1.0.0"),
],
targets: [
.executableTarget(
name: "AWSSDKExample",
dependencies: [
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
.product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events"),
.product(name: "AWSS3", package: "aws-sdk-swift"),
]
)
]
)

if let localDepsPath = ProcessInfo.processInfo.environment["LAMBDA_USE_LOCAL_DEPS"],
localDepsPath != "",
let v = try? URL(fileURLWithPath: localDepsPath).resourceValues(forKeys: [.isDirectoryKey]),
let _ = v.isDirectory
{
print("[INFO] Compiling against swift-aws-lambda-runtime located at \(localDepsPath)")
package.dependencies += [
.package(name: "swift-aws-lambda-runtime", path: localDepsPath)
]

} else {
print("[INFO] LAMBDA_USE_LOCAL_DEPS is not pointing to your local swift-aws-lambda-runtime code")
print("[INFO] This project will compile against the main branch of the Lambda Runtime on GitHub")
package.dependencies += [
.package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", branch: "main")
]
}
88 changes: 88 additions & 0 deletions Examples/AWSSDK/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# API Gateway

This is a simple example of an AWS Lambda function that uses the [AWS SDK for Swift](https://github.com/awslabs/aws-sdk-swift) to read data from Amazon S3.

## Code

The Lambda function reads all bucket names from your AWS account and return them as a String.

The code creates a `LambdaRuntime` struct. In it's simplest form, the initializer takes a function as argument. The function is the handler that will be invoked when the API Gateway receives an HTTP request.

The handler is `(event: APIGatewayV2Request, context: LambdaContext) -> APIGatewayV2Response`. The function takes two arguments:
- the event argument is a `APIGatewayV2Request`. It is the parameter passed by the API Gateway. It contains all data passed in the HTTP request and some meta data.
- the context argument is a `Lambda Context`. It is a description of the runtime context.

The function must return a `APIGatewayV2Response`.

`APIGatewayV2Request` and `APIGatewayV2Response` are defined in the [Swift AWS Lambda Events](https://github.com/swift-server/swift-aws-lambda-events) library.

The handler creates an S3 client and `ListBucketsInput` object. It passes the input object to the client and receives an output response.
It then extract the list of bucket names from the output to create a `\n` separated list of names, as a `String`

## Build & Package

To build the package, type the following commands.

```bash
swift build
swift package archive --allow-network-access docker
```

If there is no error, there is a ZIP file ready to deploy.
The ZIP file is located at `.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/AWSSDKExample/AWSSDKExample.zip`

## Deploy

The deployment must include the Lambda function and an API Gateway. We use the [Serverless Application Model (SAM)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) to deploy the infrastructure.

**Prerequisites** : Install the [SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)

The example directory contains a file named `template.yaml` that describes the deployment.

To actually deploy your Lambda function and create the infrastructure, type the following `sam` command.

```bash
sam deploy \
--resolve-s3 \
--template-file template.yaml \
--stack-name AWSSDKExample \
--capabilities CAPABILITY_IAM
```

At the end of the deployment, the script lists the API Gateway endpoint.
The output is similar to this one.

```
-----------------------------------------------------------------------------------------------------------------------------
Outputs
-----------------------------------------------------------------------------------------------------------------------------
Key APIGatewayEndpoint
Description API Gateway endpoint URL"
Value https://a5q74es3k2.execute-api.us-east-1.amazonaws.com
-----------------------------------------------------------------------------------------------------------------------------
```

## Invoke your Lambda function

To invoke the Lambda function, use this `curl` command line.

```bash
curl https://a5q74es3k2.execute-api.us-east-1.amazonaws.com
```

Be sure to replace the URL with the API Gateway endpoint returned in the previous step.

This should print text similar to

```bash
my_bucket_1
my_bucket_2
```

## Undeploy

When done testing, you can delete the infrastructure with this command.

```bash
sam delete
```
38 changes: 38 additions & 0 deletions Examples/AWSSDK/Sources/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftAWSLambdaRuntime open source project
//
// Copyright (c) 2024 Apple Inc. and the SwiftAWSLambdaRuntime project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import AWSLambdaEvents
import AWSLambdaRuntime
@preconcurrency import AWSS3

let client = try await S3Client()

let runtime = LambdaRuntime.init {
sebsto marked this conversation as resolved.
Show resolved Hide resolved
(event: APIGatewayV2Request, context: LambdaContext) async throws -> APIGatewayV2Response in

var response: APIGatewayV2Response
do {
// read the list of buckets
context.logger.debug("Reading list of buckets")
let output = try await client.listBuckets(input: ListBucketsInput())
let bucketList = output.buckets?.compactMap { $0.name }
response = APIGatewayV2Response(statusCode: .ok, body: bucketList?.joined(separator: "\n"))
} catch {
context.logger.error("\(error)")
response = APIGatewayV2Response(statusCode: .internalServerError, body: "[ERROR] \(error)")
}
return response
}

try await runtime.run()
43 changes: 43 additions & 0 deletions Examples/AWSSDK/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for AWS SDK Example

Resources:
# Lambda function
AWSSDKExample:
Type: AWS::Serverless::Function
Properties:
CodeUri: .build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/AWSSDKExample/AWSSDKExample.zip
Timeout: 60
Handler: swift.bootstrap
Runtime: provided.al2
MemorySize: 512
Architectures:
- arm64
Environment:
Variables:
# by default, AWS Lambda runtime produces no log
# use `LOG_LEVEL: debug` for for lifecycle and event handling information
# use `LOG_LEVEL: trace` for detailed input event information
LOG_LEVEL: trace

# Handles all methods of the REST API
Events:
Api:
Type: HttpApi

# Add an IAM policy to this function.
# It grants the function permissions to read the list of buckets in your account.
Policies:
- Statement:
- Sid: ListAllS3BucketsInYourAccount
Effect: Allow
Action:
- s3:ListAllMyBuckets
Resource: '*'

# print API endpoint
Outputs:
SwiftAPIEndpoint:
Description: "API Gateway endpoint URL for your application"
Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com"
12 changes: 12 additions & 0 deletions Examples/Soto/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.DS_Store
.aws-sam/
.build
samtemplate.toml
*/build/*
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
56 changes: 56 additions & 0 deletions Examples/Soto/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// swift-tools-version: 6.0

import PackageDescription

// needed for CI to test the local version of the library
import class Foundation.ProcessInfo
import struct Foundation.URL

#if os(macOS)
let platforms: [PackageDescription.SupportedPlatform]? = [.macOS(.v15)]
#else
let platforms: [PackageDescription.SupportedPlatform]? = nil
#endif

let package = Package(
name: "SotoLambdaExample",
platforms: platforms,
products: [
.executable(name: "SotoLambdaExample", targets: ["SotoExample"])
],
dependencies: [
.package(url: "https://github.com/soto-project/soto.git", from: "7.0.0"),

// dependency on swift-aws-lambda-runtime is added dynamically below
// .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", branch: "main")
.package(url: "https://github.com/swift-server/swift-aws-lambda-events", branch: "main"),
],
targets: [
.executableTarget(
name: "SotoExample",
dependencies: [
.product(name: "SotoS3", package: "soto"),
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
.product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events"),
]
)
]
)

if let localDepsPath = ProcessInfo.processInfo.environment["LAMBDA_USE_LOCAL_DEPS"],
localDepsPath != "",
let v = try? URL(fileURLWithPath: localDepsPath).resourceValues(forKeys: [.isDirectoryKey]),
let _ = v.isDirectory
{
print("[INFO] Compiling against swift-aws-lambda-runtime located at \(localDepsPath)")
package.dependencies += [
.package(name: "swift-aws-lambda-runtime", path: localDepsPath)
]

} else {
print("[INFO] LAMBDA_USE_LOCAL_DEPS is not pointing to your local swift-aws-lambda-runtime code")
print("[INFO] This project will compile against the main branch of the Lambda Runtime on GitHub")
package.dependencies += [
.package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", branch: "main")
]
}
Loading
Loading