WIP : init plugin

This commit is contained in:
Sébastien Stormacq
2024-11-07 10:00:05 +01:00
parent 4992ba5bd8
commit 2b5405a87d
6 changed files with 236 additions and 3 deletions
+1
View File
@@ -0,0 +1 @@
Plugins/AWSLambdaInitializer/Template.swift
+39
View File
@@ -0,0 +1,39 @@
#!/bin/sh
# check if docker is installed
which docker > /dev/null
if [[ $? != 0 ]]; then
echo "Docker is not installed. Please install Docker and try again."
exit 1
fi
# check if user has an access key and secret access key
echo "This script creates and deploys a Lambda function on your AWS Account.
You must have an AWS account and know an AWS access key, secret access key, and an optional session token. These values are read from '~/.aws/credentials' or asked interactively.
"
read -p "Are you ready to create your first Lambda function in Swift? [y/n] " continue
if [[ continue != ^[Yy]$ ]]; then
echo "OK, try again later when you feel ready"
exit 1
fi
echo "⚡️ Create your Swift command line project"
swift package init --type executable --name MyLambda
echo "📦 Add the AWS Lambda Swift runtime to your project"
swift package add-dependency https://github.com/swift-server/swift-aws-lambda-runtime.git --branch main
swift package add-dependency https://github.com/swift-server/swift-aws-lambda-events.git --branch main
swift package add-target-dependency AWSLambdaRuntime MyLambda --package swift-aws-lambda-runtime
swift package add-target-dependency AWSLambdaEvents MyLambda --package swift-aws-lambda-events
echo "📝 Write the Swift code"
swift package lambda-init --allow-writing-to-package-directory
echo "📦 Compile and package the function for deployment"
swift package archive --allow-network-connections docker
echo "🚀 Deploy to AWS Lambda"
+47
View File
@@ -16,15 +16,21 @@ let package = Package(
.library(name: "AWSLambdaRuntime", targets: ["AWSLambdaRuntime"]),
// this has all the main functionality for lambda and it does not link Foundation
.library(name: "AWSLambdaRuntimeCore", targets: ["AWSLambdaRuntimeCore"]),
// plugin to create a new Lambda function, based on a template
.plugin(name: "AWSLambdaInitializer", targets: ["AWSLambdaInitializer"]),
// plugin to package the lambda, creating an archive that can be uploaded to AWS
// requires Linux or at least macOS v15
.plugin(name: "AWSLambdaPackager", targets: ["AWSLambdaPackager"]),
// plugin to deploy a Lambda function
.plugin(name: "AWSLambdadeployer", targets: ["AWSLambdaDeployer"]),
.executable(name: "AWSLambdaDeployerHelper", targets: ["AWSLambdaDeployerHelper"]),
// for testing only
.library(name: "AWSLambdaTesting", targets: ["AWSLambdaTesting"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.72.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.4"),
.package(url: "https://github.com/apple/swift-crypto.git", from: "3.9.1"),
],
targets: [
.target(
@@ -45,6 +51,19 @@ let package = Package(
],
swiftSettings: [.swiftLanguageMode(.v5)]
),
.plugin(
name: "AWSLambdaInitializer",
capability: .command(
intent: .custom(
verb: "lambda-init",
description:
"Create a new Lambda function in the current project directory."
),
permissions: [
.writeToPackageDirectory(reason: "Create a file with an HelloWorld Lambda function.")
]
)
),
.plugin(
name: "AWSLambdaPackager",
capability: .command(
@@ -61,6 +80,34 @@ let package = Package(
]
)
),
.plugin(
name: "AWSLambdaDeployer",
capability: .command(
intent: .custom(
verb: "deploy",
description:
"Deploy the Lambda function. You must have an AWS account and know an access key and secret access key."
),
permissions: [
.allowNetworkConnections(
scope: .all(ports: [443]),
reason: "This plugin uses the AWS Lambda API to deploy the function."
)
]
),
dependencies: [
.target(name: "AWSLambdaDeployerHelper")
]
),
.executableTarget(
name: "AWSLambdaDeployerHelper",
dependencies: [
.product(name: "NIOHTTP1", package: "swift-nio"),
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "Crypto", package: "swift-crypto"),
],
swiftSettings: [.swiftLanguageMode(.v6)]
),
.testTarget(
name: "AWSLambdaRuntimeCoreTests",
dependencies: [
+91
View File
@@ -0,0 +1,91 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftAWSLambdaRuntime open source project
//
// Copyright (c) 2022 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 Foundation
import PackagePlugin
@main
@available(macOS 15.0, *)
struct AWSLambdaPackager: CommandPlugin {
let destFileName = "Sources/main.swift"
func performCommand(context: PackagePlugin.PluginContext, arguments: [String]) async throws {
let configuration = try Configuration(context: context, arguments: arguments)
if configuration.help {
self.displayHelpMessage()
return
}
let destFileURL = context.package.directoryURL.appendingPathComponent(destFileName)
do {
try functionWithUrlTemplate.write(to: destFileURL, atomically: true, encoding: .utf8)
if configuration.verboseLogging {
Diagnostics.progress("✅ Lambda function written to \(destFileName)")
Diagnostics.progress("📦 You can now package with: 'swift package archive'")
}
} catch {
Diagnostics.error("🛑Failed to create the Lambda function file: \(error)")
}
}
private func displayHelpMessage() {
print(
"""
OVERVIEW: A SwiftPM plugin to scaffold a HelloWorld Lambda function.
USAGE: swift package lambda-init
[--help] [--verbose]
[--allow-writing-to-package-directory]
OPTIONS:
--allow-writing-to-package-directory Don't ask for permissions to write files.
--verbose Produce verbose output for debugging.
--help Show help information.
"""
)
}
}
private struct Configuration: CustomStringConvertible {
public let help: Bool
public let verboseLogging: Bool
public init(
context: PluginContext,
arguments: [String]
) throws {
var argumentExtractor = ArgumentExtractor(arguments)
let verboseArgument = argumentExtractor.extractFlag(named: "verbose") > 0
let helpArgument = argumentExtractor.extractFlag(named: "help") > 0
// help required ?
self.help = helpArgument
// verbose logging required ?
self.verboseLogging = verboseArgument
}
var description: String {
"""
{
verboseLogging: \(self.verboseLogging)
}
"""
}
}
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftAWSLambdaRuntime open source project
//
// Copyright (c) 2022 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 Foundation
let functionWithUrlTemplate = #"""
import AWSLambdaRuntime
import AWSLambdaEvents
// in this example we receive a FunctionURLRequest and we return a FunctionURLResponse
// https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads
let runtime = LambdaRuntime {
(event: FunctionURLRequest, context: LambdaContext) -> FunctionURLResponse in
guard let name = event.queryStringParameters?["name"] else {
return FunctionURLResponse(statusCode: .badRequest)
}
return FunctionURLResponse(statusCode: .ok, body: #"{ "message" : "Hello \#\#(name)" } "#)
}
try await runtime.run()
"""#
+23 -3
View File
@@ -18,6 +18,17 @@
## TL;DR
The `Examples/_MyFirstFunction` contains a script that goes through the steps described in this section.
If you are really impatient, just type:
```bash
cd Examples/_MyFirstFunction
./create_and_deploy_function.sh
```
Otherwise, continue reading.
1. Create a new Swift executable project
```bash
@@ -64,7 +75,15 @@ swift package init --type executable
)
```
3. Edit `Sources/main.swift` file and replace the content with this code
3. Scaffold a minimal Lambda function
The runtime comes with a plugin to generate the code of a simple AWS Lambda function:
```bash
swift package lambda-init --allow-writing-to-package-directory
```
Your `Sources/main.swift` file must look like this.
```swift
import AWSLambdaRuntime
@@ -81,12 +100,13 @@ try await runtime.run()
4. Build & archive the package
The runtime comes with a plugin to compile on Amazon Linux and create a ZIP archive:
```bash
swift build
swift package archive --allow-network-connections docker
```
If there is no error, there is a ZIP file ready to deploy.
If there is no error, the ZIP archive is ready to deploy.
The ZIP file is located at `.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip`
5. Deploy to AWS