-
Notifications
You must be signed in to change notification settings - Fork 113
[plugin] Add a deployer plugin + Swift-based DSL + SAM example #291
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
Closed
Closed
Changes from all commits
Commits
Show all changes
93 commits
Select commit
Hold shift + click to select a range
3af979a
initial commit for deployer plugin + SAM example
sebsto 7c4babb
Remove unused example files
sebsto 4f5cb9c
Simplify API for function developers
sebsto 45733a6
fix comment
sebsto 8fd7487
simplify data structures by removing unecessary enums
sebsto 8ad22e6
simplify API
sebsto 2f623be
add addResource API
sebsto c3d73a9
add support for passing SQS queue Arn
sebsto 332fdb6
ad unit test
sebsto 00029af
add test target to Package.swift
sebsto ae41897
simplify code and factorise functions
sebsto fef8bb2
simplify API : allow to pass Resource to SQSEventSource
sebsto b3ce4ca
add different type of env variable + refactor resource names
sebsto 639d96d
add more example to create the deployment descriptor
sebsto fbd0b95
removed unused portion of code
sebsto 11469a7
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto a2a1275
Merge branch 'master' into sebsto/deployerplugin
sebsto 61d9c51
fix an issue that prevent to identify the correct path for Deploy exec
sebsto e0a94ef
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto e52d196
new version of the deployer plugin. Now it uses a declarative interfa…
sebsto 09385fa
remove old Deployment swift code
sebsto 607e877
add the PR README to the plugin source directory
sebsto fa6eddb
add linter to SAM validate
sebsto 2d07b14
refactor unit test
sebsto 8a816c5
Factor out common code between the two plugins
sebsto d09ecbe
remove dependency on URL
sebsto 7180a4a
add help option to the deployer plugin
sebsto fac6719
refactor platform architecture for unit tests
sebsto c712083
refactor for better readability
sebsto f3f4021
function architecture is now a parameter that function developers can…
sebsto b8cb5b0
add sample architecture entry
sebsto 464fd01
add example tests for the two Lambda functions
sebsto 1d720a2
cleaner fix for --static-swift-stdlib issue on linux
sebsto ca4d1c2
update README to reflect latest changes
sebsto 971af4f
minor refactor and reformat
sebsto 9031b6a
minor refactor
sebsto 6ed5f15
more code cleanup and documentation
sebsto a649d27
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto c2d8072
use sam list command to print endpoints and improve error handling w…
sebsto 46b53ed
simplify example code
sebsto 1f054b0
add extra sam commands
sebsto e4401a4
Update the README file
sebsto c39b82d
update git ignore
sebsto 366fea3
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto 9e6e222
fix typos in comments
sebsto e5de04b
first version of DSL support to express the SAM Deployment Descriptor
sebsto 160d4a4
add deployment descriptor unit tests
sebsto 4fa3873
adjust copyright to 2023
sebsto 4cc294a
add unit test for deployment descriptor builder
sebsto 56a0d5f
do not overwrite SAM deployment descriptor, unless --force is passed …
sebsto b9a8826
change order of default values
sebsto 483a9be
fix typos in help message
sebsto 44d6f77
update readme
sebsto 9d1a2d7
clarifies README
sebsto 87e4f44
simplify dependencies management
sebsto 29255ec
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto 675a177
add support for SQS batchsize and enable properties
sebsto 7f2fa69
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto 965d978
fix an error I introduced earlier in packager plugin
sebsto 40f02d1
fix path
sebsto 560087c
fix to align to PR 292 https://github.com/swift-server/swift-aws-lamb…
sebsto 4d55e53
refactor unit tests for deployment descriptor
sebsto f06ce00
remove makefile
sebsto a0d5499
remove dependency on Yams
sebsto a9e1736
batch of changes after review #2
sebsto 04be9b8
modify archiver plugin to support local development
sebsto 8604703
align default build configuration to archiver plugin's default
sebsto 9765049
make sure the lib DeploymentDescriptor is built before the plugin run…
sebsto 00dfdca
add check if AWS CLI is configured
sebsto e1177a6
update README to match latest code change
sebsto ab9999f
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto 047d153
deployment descriptor description is optional as per SAM spec
sebsto 8dfab34
add automatic camel case conversion for keys
sebsto d09b53a
add utility to compute a SH!256 digest on files
sebsto f558375
apply swift format
sebsto 3178b8b
add support for a first set of additional Lambda function properties
sebsto 638fd23
add example with URL invocation
sebsto 81937df
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto 4d77e36
remove unused key converter and respect key converter strategy for st…
sebsto 69e37cf
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto 23364d0
Merge remote-tracking branch 'refs/remotes/origin/sebsto/deployerplug…
sebsto 3e8b87f
add deployer plugin target to Swift 5.7 and Swift 5.8
sebsto 60ce21f
Merge branch 'main' into sebsto/deployerplugin_dsl
sebsto edec15d
simplifiy the management of resource type
sebsto a2afbf1
add builder tests
sebsto 4a162a1
further simplification for resultBuilder types
sebsto 4432b02
add local directory to dependency
sebsto d65f050
removed unused code
sebsto ea66930
fix public access for some methods / struct
sebsto bddc2a1
support LAMBDA_USE_LOCAL_DEPS
sebsto 8aa40ac
Merge branch 'main' into sebsto/deployerplugin_dsl
sebsto b26dccc
revert plugin execute to Utils
sebsto 1f4aed6
Merge branch 'main' into sebsto/deployerplugin_dsl
sebsto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,8 @@ | ||
Makefile | ||
TODO | ||
notes.md | ||
sam.yaml | ||
sam.json | ||
template.yaml | ||
template.json | ||
samconfig.toml |
This file contains hidden or 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,112 @@ | ||
import AWSLambdaDeploymentDescriptor | ||
|
||
// example of a shared resource | ||
let sharedQueue = Queue( | ||
logicalName: "SharedQueue", | ||
physicalName: "swift-lambda-shared-queue") | ||
|
||
// example of common environment variables | ||
let sharedEnvironmentVariables = ["LOG_LEVEL": "debug"] | ||
|
||
let validEfsArn = | ||
"arn:aws:elasticfilesystem:eu-central-1:012345678901:access-point/fsap-abcdef01234567890" | ||
|
||
// the deployment descriptor | ||
DeploymentDescriptor { | ||
|
||
// an optional description | ||
"Description of this deployment descriptor" | ||
|
||
// Create a lambda function exposed through a REST API | ||
Function(name: "HttpApiLambda") { | ||
|
||
// an optional description | ||
"Description of this function" | ||
|
||
EventSources { | ||
|
||
// example of a catch all api | ||
HttpApi() | ||
|
||
// example of an API for a specific HTTP verb and path | ||
// HttpApi(method: .GET, path: "/test") | ||
|
||
} | ||
|
||
EnvironmentVariables { | ||
[ | ||
"NAME1": "VALUE1", | ||
"NAME2": "VALUE2", | ||
] | ||
|
||
// shared environment variables declared upfront | ||
sharedEnvironmentVariables | ||
} | ||
} | ||
|
||
// Example Function modifiers: | ||
|
||
// .autoPublishAlias() | ||
// .ephemeralStorage(2048) | ||
// .eventInvoke(onSuccess: "arn:aws:sqs:eu-central-1:012345678901:lambda-test", | ||
// onFailure: "arn:aws:lambda:eu-central-1:012345678901:lambda-test", | ||
// maximumEventAgeInSeconds: 600, | ||
// maximumRetryAttempts: 3) | ||
// .fileSystem(validEfsArn, mountPoint: "/mnt/path1") | ||
// .fileSystem(validEfsArn, mountPoint: "/mnt/path2") | ||
|
||
// Create a Lambda function exposed through an URL | ||
// you can invoke it with a signed request, for example | ||
// curl --aws-sigv4 "aws:amz:eu-central-1:lambda" \ | ||
// --user $AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY \ | ||
// -H 'content-type: application/json' \ | ||
// -d '{ "example": "test" }' \ | ||
// "$FUNCTION_URL?param1=value1¶m2=value2" | ||
Function(name: "UrlLambda") { | ||
"A Lambda function that is directly exposed as an URL, with IAM authentication" | ||
} | ||
.urlConfig(authType: .iam) | ||
|
||
// Create a Lambda function triggered by messages on SQS | ||
Function(name: "SQSLambda", architecture: .arm64) { | ||
|
||
EventSources { | ||
|
||
// this will reference an existing queue by its Arn | ||
// Sqs("arn:aws:sqs:eu-central-1:012345678901:swift-lambda-shared-queue") | ||
|
||
// // this will create a new queue resource | ||
Sqs("swift-lambda-queue-name") | ||
|
||
// // this will create a new queue resource, with control over physical queue name | ||
// Sqs() | ||
// .queue(logicalName: "LambdaQueueResource", physicalName: "swift-lambda-queue-resource") | ||
|
||
// // this references a shared queue resource created at the top of this deployment descriptor | ||
// // the queue resource will be created automatically, you do not need to add `sharedQueue` as a resource | ||
// Sqs(sharedQueue) | ||
} | ||
|
||
EnvironmentVariables { | ||
sharedEnvironmentVariables | ||
} | ||
} | ||
|
||
// | ||
// Additional resources | ||
// | ||
// Create a SQS queue | ||
Queue( | ||
logicalName: "TopLevelQueueResource", | ||
physicalName: "swift-lambda-top-level-queue") | ||
|
||
// Create a DynamoDB table | ||
Table( | ||
logicalName: "SwiftLambdaTable", | ||
physicalName: "swift-lambda-table", | ||
primaryKeyName: "id", | ||
primaryKeyType: "String") | ||
|
||
// example modifiers | ||
// .provisionedThroughput(readCapacityUnits: 10, writeCapacityUnits: 99) | ||
} |
This file contains hidden or 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,52 @@ | ||
// ===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the SwiftAWSLambdaRuntime open source project | ||
// | ||
// Copyright (c) 2021 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 | ||
import Foundation | ||
|
||
@main | ||
struct HttpApiLambda: LambdaHandler { | ||
init() {} | ||
init(context: LambdaInitializationContext) async throws { | ||
context.logger.info( | ||
"Log Level env var : \(ProcessInfo.processInfo.environment["LOG_LEVEL"] ?? "info" )") | ||
} | ||
|
||
// the return value must be either APIGatewayV2Response or any Encodable struct | ||
func handle(_ event: APIGatewayV2Request, context: AWSLambdaRuntimeCore.LambdaContext) async throws -> APIGatewayV2Response { | ||
|
||
var header = HTTPHeaders() | ||
do { | ||
context.logger.debug("HTTP API Message received") | ||
|
||
header["content-type"] = "application/json" | ||
|
||
// echo the request in the response | ||
let data = try JSONEncoder().encode(event) | ||
let response = String(data: data, encoding: .utf8) | ||
|
||
// if you want control on the status code and headers, return an APIGatewayV2Response | ||
// otherwise, just return any Encodable struct, the runtime will wrap it for you | ||
return APIGatewayV2Response(statusCode: .ok, headers: header, body: response) | ||
|
||
} catch { | ||
// should never happen as the decoding was made by the runtime | ||
// when the input event is malformed, this function is not even called | ||
header["content-type"] = "text/plain" | ||
return APIGatewayV2Response(statusCode: .badRequest, headers: header, body: "\(error.localizedDescription)") | ||
|
||
} | ||
} | ||
} |
This file contains hidden or 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,80 @@ | ||
// swift-tools-version:5.7 | ||
|
||
// ===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the SwiftAWSLambdaRuntime open source project | ||
// | ||
// Copyright (c) 2021 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 class Foundation.ProcessInfo // needed for CI to test the local version of the library | ||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "swift-aws-lambda-runtime-example", | ||
platforms: [ | ||
.macOS(.v12) | ||
], | ||
products: [ | ||
.executable(name: "HttpApiLambda", targets: ["HttpApiLambda"]), | ||
.executable(name: "SQSLambda", targets: ["SQSLambda"]), | ||
.executable(name: "UrlLambda", targets: ["UrlLambda"]) | ||
], | ||
dependencies: [ | ||
.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.git", branch: "main") | ||
], | ||
targets: [ | ||
.executableTarget( | ||
name: "HttpApiLambda", | ||
dependencies: [ | ||
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"), | ||
.product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events") | ||
], | ||
path: "./HttpApiLambda" | ||
), | ||
.executableTarget( | ||
name: "UrlLambda", | ||
dependencies: [ | ||
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"), | ||
.product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events") | ||
], | ||
path: "./UrlLambda" | ||
), | ||
.executableTarget( | ||
name: "SQSLambda", | ||
dependencies: [ | ||
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"), | ||
.product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events") | ||
], | ||
path: "./SQSLambda" | ||
), | ||
.testTarget( | ||
name: "LambdaTests", | ||
dependencies: [ | ||
"HttpApiLambda", "SQSLambda", | ||
.product(name: "AWSLambdaTesting", package: "swift-aws-lambda-runtime"), | ||
], | ||
// testing data | ||
resources: [ | ||
.process("data/apiv2.json"), | ||
.process("data/sqs.json") | ||
] | ||
) | ||
] | ||
) | ||
|
||
// for CI to test the local version of the library | ||
if ProcessInfo.processInfo.environment["LAMBDA_USE_LOCAL_DEPS"] != nil { | ||
package.dependencies = [ | ||
.package(name: "swift-aws-lambda-runtime", path: "../.."), | ||
.package(url: "https://github.com/swift-server/swift-aws-lambda-events.git", branch: "main") | ||
] | ||
} |
This file contains hidden or 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,40 @@ | ||
// ===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the SwiftAWSLambdaRuntime open source project | ||
// | ||
// Copyright (c) 2021 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 | ||
import Foundation | ||
|
||
@main | ||
struct SQSLambda: LambdaHandler { | ||
typealias Event = SQSEvent | ||
typealias Output = Void | ||
|
||
init() {} | ||
init(context: LambdaInitializationContext) async throws { | ||
context.logger.info( | ||
"Log Level env var : \(ProcessInfo.processInfo.environment["LOG_LEVEL"] ?? "info" )") | ||
} | ||
|
||
func handle(_ event: Event, context: AWSLambdaRuntimeCore.LambdaContext) async throws -> Output { | ||
|
||
context.logger.info("Log Level env var : \(ProcessInfo.processInfo.environment["LOG_LEVEL"] ?? "not defined" )" ) | ||
context.logger.debug("SQS Message received, with \(event.records.count) record") | ||
|
||
for msg in event.records { | ||
context.logger.debug("Message ID : \(msg.messageId)") | ||
context.logger.debug("Message body : \(msg.body)") | ||
} | ||
} | ||
} |
This file contains hidden or 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,46 @@ | ||
// ===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the SwiftAWSLambdaRuntime open source project | ||
// | ||
// Copyright (c) 2021 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 | ||
import AWSLambdaTesting | ||
import XCTest | ||
@testable import HttpApiLambda | ||
|
||
class HttpApiLambdaTests: LambdaTest { | ||
|
||
func testHttpAPiLambda() async throws { | ||
|
||
// given | ||
let eventData = try self.loadTestData(file: .apiGatewayV2) | ||
let event = try JSONDecoder().decode(APIGatewayV2Request.self, from: eventData) | ||
|
||
do { | ||
// when | ||
let result = try await Lambda.test(HttpApiLambda.self, with: event) | ||
|
||
// then | ||
XCTAssertEqual(result.statusCode.code, 200) | ||
XCTAssertNotNil(result.headers) | ||
if let headers = result.headers { | ||
XCTAssertNotNil(headers["content-type"]) | ||
if let contentType = headers["content-type"] { | ||
XCTAssertTrue(contentType == "application/json") | ||
} | ||
} | ||
} catch { | ||
XCTFail("Lambda invocation should not throw error : \(error)") | ||
} | ||
} | ||
} |
This file contains hidden or 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,22 @@ | ||
import Foundation | ||
import XCTest | ||
|
||
enum TestData: String { | ||
case apiGatewayV2 = "apiv2" | ||
case sqs = "sqs" | ||
} | ||
|
||
class LambdaTest: XCTestCase { | ||
// return the URL of a test file | ||
// files are copied to the bundle during build by the `resources` directive in `Package.swift` | ||
private func urlForTestData(file: TestData) throws -> URL { | ||
let filePath = Bundle.module.path(forResource: file.rawValue, ofType: "json")! | ||
return URL(fileURLWithPath: filePath) | ||
} | ||
|
||
// load a test file added as a resource to the executable bundle | ||
func loadTestData(file: TestData) throws -> Data { | ||
// load list from file | ||
return try Data(contentsOf: urlForTestData(file: file)) | ||
sebsto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.