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

[plugin] Add a deployer plugin + Swift-based DSL + SAM example #291

Closed
wants to merge 93 commits into from
Closed
Show file tree
Hide file tree
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 Dec 22, 2022
7c4babb
Remove unused example files
sebsto Dec 23, 2022
4f5cb9c
Simplify API for function developers
sebsto Dec 29, 2022
45733a6
fix comment
sebsto Dec 29, 2022
8fd7487
simplify data structures by removing unecessary enums
sebsto Dec 29, 2022
8ad22e6
simplify API
sebsto Dec 30, 2022
2f623be
add addResource API
sebsto Dec 31, 2022
c3d73a9
add support for passing SQS queue Arn
sebsto Dec 31, 2022
332fdb6
ad unit test
sebsto Dec 31, 2022
00029af
add test target to Package.swift
sebsto Dec 31, 2022
ae41897
simplify code and factorise functions
sebsto Jan 2, 2023
fef8bb2
simplify API : allow to pass Resource to SQSEventSource
sebsto Jan 3, 2023
b3ce4ca
add different type of env variable + refactor resource names
sebsto Jan 3, 2023
639d96d
add more example to create the deployment descriptor
sebsto Jan 3, 2023
fbd0b95
removed unused portion of code
sebsto Jan 3, 2023
11469a7
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto Jan 11, 2023
a2a1275
Merge branch 'master' into sebsto/deployerplugin
sebsto Jan 25, 2023
61d9c51
fix an issue that prevent to identify the correct path for Deploy exec
sebsto Jan 25, 2023
e0a94ef
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto Jan 30, 2023
e52d196
new version of the deployer plugin. Now it uses a declarative interfa…
sebsto Jan 30, 2023
09385fa
remove old Deployment swift code
sebsto Jan 30, 2023
607e877
add the PR README to the plugin source directory
sebsto Jan 30, 2023
fa6eddb
add linter to SAM validate
sebsto Jan 31, 2023
2d07b14
refactor unit test
sebsto Jan 31, 2023
8a816c5
Factor out common code between the two plugins
sebsto Jan 31, 2023
d09ecbe
remove dependency on URL
sebsto Jan 31, 2023
7180a4a
add help option to the deployer plugin
sebsto Jan 31, 2023
fac6719
refactor platform architecture for unit tests
sebsto Jan 31, 2023
c712083
refactor for better readability
sebsto Jan 31, 2023
f3f4021
function architecture is now a parameter that function developers can…
sebsto Jan 31, 2023
b8cb5b0
add sample architecture entry
sebsto Feb 1, 2023
464fd01
add example tests for the two Lambda functions
sebsto Feb 1, 2023
1d720a2
cleaner fix for --static-swift-stdlib issue on linux
sebsto Feb 1, 2023
ca4d1c2
update README to reflect latest changes
sebsto Feb 1, 2023
971af4f
minor refactor and reformat
sebsto Feb 1, 2023
9031b6a
minor refactor
sebsto Feb 1, 2023
6ed5f15
more code cleanup and documentation
sebsto Feb 1, 2023
a649d27
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto Feb 15, 2023
c2d8072
use sam list command to print endpoints and improve error handling w…
sebsto Feb 16, 2023
46b53ed
simplify example code
sebsto Feb 16, 2023
1f054b0
add extra sam commands
sebsto Feb 17, 2023
e4401a4
Update the README file
sebsto Feb 17, 2023
c39b82d
update git ignore
sebsto Feb 17, 2023
366fea3
Merge branch 'swift-server:main' into sebsto/deployerplugin
sebsto Feb 23, 2023
9e6e222
fix typos in comments
sebsto Feb 26, 2023
e5de04b
first version of DSL support to express the SAM Deployment Descriptor
sebsto Feb 26, 2023
160d4a4
add deployment descriptor unit tests
sebsto Feb 27, 2023
4fa3873
adjust copyright to 2023
sebsto Feb 27, 2023
4cc294a
add unit test for deployment descriptor builder
sebsto Feb 27, 2023
56a0d5f
do not overwrite SAM deployment descriptor, unless --force is passed …
sebsto Feb 27, 2023
b9a8826
change order of default values
sebsto Feb 27, 2023
483a9be
fix typos in help message
sebsto Feb 27, 2023
44d6f77
update readme
sebsto Feb 27, 2023
9d1a2d7
clarifies README
sebsto Feb 27, 2023
87e4f44
simplify dependencies management
sebsto Feb 28, 2023
29255ec
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto Feb 28, 2023
675a177
add support for SQS batchsize and enable properties
sebsto Feb 28, 2023
7f2fa69
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto Mar 14, 2023
965d978
fix an error I introduced earlier in packager plugin
sebsto Mar 14, 2023
40f02d1
fix path
sebsto Mar 14, 2023
560087c
fix to align to PR 292 https://github.com/swift-server/swift-aws-lamb…
sebsto Mar 14, 2023
4d55e53
refactor unit tests for deployment descriptor
sebsto Mar 14, 2023
f06ce00
remove makefile
sebsto Mar 14, 2023
a0d5499
remove dependency on Yams
sebsto Mar 20, 2023
a9e1736
batch of changes after review #2
sebsto Apr 1, 2023
04be9b8
modify archiver plugin to support local development
sebsto Apr 3, 2023
8604703
align default build configuration to archiver plugin's default
sebsto Apr 3, 2023
9765049
make sure the lib DeploymentDescriptor is built before the plugin run…
sebsto Apr 3, 2023
00dfdca
add check if AWS CLI is configured
sebsto Apr 5, 2023
e1177a6
update README to match latest code change
sebsto Apr 6, 2023
ab9999f
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto Apr 6, 2023
047d153
deployment descriptor description is optional as per SAM spec
sebsto Apr 6, 2023
8dfab34
add automatic camel case conversion for keys
sebsto Apr 13, 2023
d09b53a
add utility to compute a SH!256 digest on files
sebsto Apr 13, 2023
f558375
apply swift format
sebsto Apr 13, 2023
3178b8b
add support for a first set of additional Lambda function properties
sebsto Apr 13, 2023
638fd23
add example with URL invocation
sebsto Apr 13, 2023
81937df
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto Sep 4, 2023
4d77e36
remove unused key converter and respect key converter strategy for st…
sebsto Sep 11, 2023
69e37cf
Merge branch 'swift-server:main' into sebsto/deployerplugin_dsl
sebsto Sep 11, 2023
23364d0
Merge remote-tracking branch 'refs/remotes/origin/sebsto/deployerplug…
sebsto Sep 11, 2023
3e8b87f
add deployer plugin target to Swift 5.7 and Swift 5.8
sebsto Sep 12, 2023
60ce21f
Merge branch 'main' into sebsto/deployerplugin_dsl
sebsto Apr 14, 2024
edec15d
simplifiy the management of resource type
sebsto Apr 16, 2024
a2afbf1
add builder tests
sebsto Apr 16, 2024
4a162a1
further simplification for resultBuilder types
sebsto Apr 16, 2024
4432b02
add local directory to dependency
sebsto May 13, 2024
d65f050
removed unused code
sebsto May 13, 2024
ea66930
fix public access for some methods / struct
sebsto May 13, 2024
bddc2a1
support LAMBDA_USE_LOCAL_DEPS
sebsto May 15, 2024
8aa40ac
Merge branch 'main' into sebsto/deployerplugin_dsl
sebsto May 22, 2024
b26dccc
revert plugin execute to Utils
sebsto May 22, 2024
1f4aed6
Merge branch 'main' into sebsto/deployerplugin_dsl
sebsto May 22, 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
8 changes: 8 additions & 0 deletions Examples/SAM/.gitignore
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
112 changes: 112 additions & 0 deletions Examples/SAM/Deploy.swift
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&param2=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)
}
52 changes: 52 additions & 0 deletions Examples/SAM/HttpApiLambda/Lambda.swift
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)")

}
}
}
80 changes: 80 additions & 0 deletions Examples/SAM/Package.swift
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")
sebsto marked this conversation as resolved.
Show resolved Hide resolved
],
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")
]
}
40 changes: 40 additions & 0 deletions Examples/SAM/SQSLambda/Lambda.swift
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)")
}
}
}
46 changes: 46 additions & 0 deletions Examples/SAM/Tests/LambdaTests/HttpApiLambdaTest.swift
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)")
}
}
}
22 changes: 22 additions & 0 deletions Examples/SAM/Tests/LambdaTests/LambdaTest.swift
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
}
}
Loading