diff --git a/Examples/_MyFirstFunction/.gitignore b/Examples/_MyFirstFunction/.gitignore new file mode 100644 index 00000000..0023a534 --- /dev/null +++ b/Examples/_MyFirstFunction/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Examples/_MyFirstFunction/clean.sh b/Examples/_MyFirstFunction/clean.sh new file mode 100755 index 00000000..457e1c8a --- /dev/null +++ b/Examples/_MyFirstFunction/clean.sh @@ -0,0 +1,36 @@ +#!/bin/bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the SwiftAWSLambdaRuntime open source project +## +## Copyright (c) 2017-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 +## +##===----------------------------------------------------------------------===## + +echo "This script deletes the Lambda function and the IAM role created in the previous step and deletes the project files." +read -r -p "Are you you sure you want to delete everything that was created? [y/n] " continue +if [[ ! $continue =~ ^[Yy]$ ]]; then + echo "OK, try again later when you feel ready" + exit 1 +fi + +echo "πŸš€ Deleting the Lambda function and the role" +aws lambda delete-function --function-name MyLambda +aws iam detach-role-policy \ + --role-name lambda_basic_execution \ + --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole +aws iam delete-role --role-name lambda_basic_execution + +echo "πŸš€ Deleting the project files" +rm -rf .build +rm -rf ./Sources +rm trust-policy.json +rm Package.swift Package.resolved + +echo "πŸŽ‰ Done! Your project is cleaned up and ready for a fresh start." \ No newline at end of file diff --git a/Examples/_MyFirstFunction/create_and_deploy_function.sh b/Examples/_MyFirstFunction/create_and_deploy_function.sh new file mode 100755 index 00000000..eb8f6d4f --- /dev/null +++ b/Examples/_MyFirstFunction/create_and_deploy_function.sh @@ -0,0 +1,194 @@ +#!/bin/bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the SwiftAWSLambdaRuntime open source project +## +## Copyright (c) 2017-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 +## +##===----------------------------------------------------------------------===## + +# Stop the script execution if an error occurs +set -e -o pipefail + +check_prerequisites() { + # check if docker is installed + which docker > /dev/null || (echo "Docker is not installed. Please install Docker and try again." && exit 1) + + # check if aws cli is installed + which aws > /dev/null || (echo "AWS CLI is not installed. Please install AWS CLI and try again." && exit 1) + + # 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'. + " + + read -r -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 +} + +create_lambda_execution_role() { + role_name=$1 + + # Allow the Lambda service to assume the IAM role + cat < trust-policy.json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} +EOF + + # Create the IAM role + echo "πŸ” Create the IAM role for the Lambda function" + aws iam create-role \ + --role-name "${role_name}" \ + --assume-role-policy-document file://trust-policy.json > /dev/null 2>&1 + + # Attach basic permissions to the role + # The AWSLambdaBasicExecutionRole policy grants permissions to write logs to CloudWatch Logs + echo "πŸ”’ Attach basic permissions to the role" + aws iam attach-role-policy \ + --role-name "${role_name}" \ + --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole > /dev/null 2>&1 + + echo "⏰ Waiting 10 secs for IAM role to propagate..." + sleep 10 +} + +create_swift_project() { + echo "⚑️ Create your Swift Lambda project" + swift package init --type executable --name MyLambda > /dev/null + + echo "πŸ“¦ Add the AWS Lambda Swift runtime to your project" + # The following commands are commented out until the `lambad-init` plugin will be release + # 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 + cat < Package.swift +// swift-tools-version:6.0 + +import PackageDescription + +let package = Package( + name: "swift-aws-lambda-runtime-example", + platforms: [.macOS(.v15)], + products: [ + .executable(name: "MyLambda", targets: ["MyLambda"]) + ], + dependencies: [ + .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", branch: "main") + ], + targets: [ + .executableTarget( + name: "MyLambda", + dependencies: [ + .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime") + ], + path: "." + ) + ] +) +EOF + + echo "πŸ“ Write the Swift code" + # The following command is commented out until the `lambad-init` plugin will be release + # swift package lambda-init --allow-writing-to-package-directory + cat < Sources/main.swift +import AWSLambdaRuntime + +let runtime = LambdaRuntime { + (event: String, context: LambdaContext) in + "Hello \(event)" +} + +try await runtime.run() +EOF + + echo "πŸ“¦ Compile and package the function for deployment (this might take a while)" + swift package archive --allow-network-connections docker > /dev/null 2>&1 +} + +deploy_lambda_function() { + echo "πŸš€ Deploy to AWS Lambda" + + # retrieve your AWS Account ID + echo "πŸ”‘ Retrieve your AWS Account ID" + AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) + export AWS_ACCOUNT_ID + + # Check if the role already exists + echo "πŸ” Check if a Lambda execution IAM role already exists" + aws iam get-role --role-name lambda_basic_execution > /dev/null 2>&1 || create_lambda_execution_role lambda_basic_execution + + # Create the Lambda function + echo "πŸš€ Create the Lambda function" + aws lambda create-function \ + --function-name MyLambda \ + --zip-file fileb://.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip \ + --runtime provided.al2 \ + --handler provided \ + --architectures "$(uname -m)" \ + --role arn:aws:iam::"${AWS_ACCOUNT_ID}":role/lambda_basic_execution > /dev/null 2>&1 + + echo "⏰ Waiting 10 secs for the Lambda function to be ready..." + sleep 10 +} + +invoke_lambda_function() { + # Invoke the Lambda function + echo "πŸ”— Invoke the Lambda function" + aws lambda invoke \ + --function-name MyLambda \ + --cli-binary-format raw-in-base64-out \ + --payload '"Lambda Swift"' \ + output.txt > /dev/null 2>&1 + + echo "πŸ‘€ Your Lambda function returned:" + cat output.txt && rm output.txt +} + +main() { + # + # Check prerequisites + # + check_prerequisites + + # + # Create the Swift project + # + create_swift_project + + # + # Now the function is ready to be deployed to AWS Lambda + # + deploy_lambda_function + + # + # Invoke the Lambda function + # + invoke_lambda_function + + echo "" + echo "πŸŽ‰ Done! Your first Lambda function in Swift is now deployed on AWS Lambda. πŸš€" +} + +main "$@" \ No newline at end of file diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/Deployment.md b/Sources/AWSLambdaRuntimeCore/Documentation.docc/Deployment.md new file mode 100644 index 00000000..b44db1dc --- /dev/null +++ b/Sources/AWSLambdaRuntimeCore/Documentation.docc/Deployment.md @@ -0,0 +1,624 @@ +# Deploying your Swift Lambda functions + +Learn how to deploy your Swift Lambda functions to AWS. + +There are multiple ways to deploy your Swift code to AWS Lambda. The very first time, you'll probably use the AWS Console to create a new Lambda function and upload your code as a zip file. However, as you iterate on your code, you'll want to automate the deployment process. + +To take full advantage of the cloud, we recommend using Infrastructure as Code (IaC) tools like the [AWS Serverless Application Model (SAM)](https://aws.amazon.com/serverless/sam/) or [AWS Cloud Development Kit (CDK)](https://aws.amazon.com/cdk/). These tools allow you to define your infrastructure and deployment process as code, which can be version-controlled and automated. + +In this section, we show you how to deploy your Swift Lambda functions using different AWS Tools. Alternatively, you might also consider using popular third-party tools like [Serverless Framework](https://www.serverless.com/), [Terraform](https://www.terraform.io/), or [Pulumi](https://www.pulumi.com/) to deploy Lambda functions and create and manage AWS infrastructure. + +Here is the content of this guide: + + * [Prerequisites](#prerequisites) + * [Choosing the AWS Region where to deploy](#choosing-the-aws-region-where-to-deploy) + * [The Lambda execution IAM role](#the-lambda-execution-iam-role) + * [Deploy your Lambda function with the AWS Console](#deploy-your-lambda-function-with-the-aws-console) + * [Deploy your Lambda function with the AWS Command Line Interface (CLI)](#deploy-your-lambda-function-with-the-aws-command-line-interface-cli) + * [Deploy your Lambda function with AWS Serverless Application Model (SAM)](#deploy-your-lambda-function-with-aws-serverless-application-model-sam) + * [Deploy your Lambda function with AWS Cloud Development Kit (CDK)](#deploy-your-lambda-function-with-aws-cloud-development-kit-cdk) + * [Third-party tools](#third-party-tools) + +## Prerequisites + +1. Your AWS Account + + To deploy a Lambda function on AWS, you need an AWS account. If you don't have one yet, you can create a new account at [aws.amazon.com](https://signin.aws.amazon.com/signup?request_type=register). It takes a few minutes to register. A credit card is required. + + We do not recommend using the root credentials you entered at account creation time for day-to-day work. Instead, create an [Identity and Access Manager (IAM) user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) with the necessary permissions and use its credentials. + + Follow the steps in [Create an IAM User in your AWS account](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html). + + We suggest to attach the `AdministratorAccess` policy to the user for the initial setup. For production workloads, you should follow the principle of least privilege and grant only the permissions required for your users. The ['AdministratorAccess' gives the user permission](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) to manage all resources on the AWS account. + +2. AWS Security Credentials + + [AWS Security Credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html) are required to access the AWS console, AWS APIs, or to let tools access your AWS account. + + AWS Security Credentials can be **long-term credentials** (for example, an Access Key ID and a Secret Access Key attached to your IAM user) or **temporary credentials** obtained via other AWS API, such as when accessing AWS through single sign-on (SSO) or when assuming an IAM role. + + To follow the steps in this guide, you need to know your AWS Access Key ID and Secret Access Key. If you don't have them, you can create them in the AWS Management Console. Follow the steps in [Creating access keys for an IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey). + + When you use SSO with your enterprise identity tools (such as Microsoft entra ID –formerly Active Directory–, Okta, and others) or when you write scripts or code assuming an IAM role, you receive temporary credentials. These credentials are valid for a limited time, have a limited scope, and are rotated automatically. You can use them in the same way as long-term credentials. In addition to an AWS Access Key and Secret Access Key, temporary credentials include a session token. + + Here is a typical set of temporary credentials (redacted for security). + + ```json + { + "Credentials": { + "AccessKeyId": "ASIA...FFSD", + "SecretAccessKey": "Xn...NL", + "SessionToken": "IQ...pV", + "Expiration": "2024-11-23T11:32:30+00:00" + } + } + ``` + +3. A Swift Lambda function to deploy. + + You need a Swift Lambda function to deploy. If you don't have one yet, you can use one of the examples in the [Examples](https://github.com/swift-server/swift-aws-lambda-runtime/tree/main/Examples) directory. + + Compile and package the function using the following command + + ```sh + swift package archive --allow-network-connections docker + ``` + + This command creates a ZIP file with the compiled Swift code. The ZIP file is located in the `.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip` folder. + + The name of the ZIP file depends on the target name you entered in the `Package.swift` file. + +## Choosing the AWS Region where to deploy + +[AWS Global infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/) spans over 34 geographic Regions (and continuously expanding). When you create a resource on AWS, such as a Lambda function, you have to select a geographic region where the resource will be created. The two main factors to consider to select a Region are the physical proximity with your users and geographical compliance. + +Physical proximity helps you reduce the network latency between the Lambda function and your customers. For example, when the majority of your users are located in South-East Asia, you might consider deploying in the Singapore, the Malaysia, or Jakarta Region. + +Geographical compliance, also known as data residency compliance, involves following location-specific regulations about how and where data can be stored and processed. + +## The Lambda execution IAM role + +A Lambda execution role is an AWS Identity and Access Management (IAM) role that grants your Lambda function the necessary permissions to interact with other AWS services and resources. Think of it as a security passport that determines what your function is allowed to do within AWS. For example, if your Lambda function needs to read files from Amazon S3, write logs to Amazon CloudWatch, or access an Amazon DynamoDB table, the execution role must include the appropriate permissions for these actions. + +When you create a Lambda function, you must specify an execution role. This role contains two main components: a trust policy that allows the Lambda service itself to assume the role, and permission policies that determine what AWS resources the function can access. By default, Lambda functions get basic permissions to write logs to CloudWatch Logs, but any additional permissions (like accessing S3 buckets or sending messages to SQS queues) must be explicitly added to the role's policies. Following the principle of least privilege, it's recommended to grant only the minimum permissions necessary for your function to operate, helping maintain the security of your serverless applications. + +## Deploy your Lambda function with the AWS Console + +In this section, we deploy the HelloWorld example function using the AWS Console. The HelloWorld function is a simple function that takes a `String` as input and returns a `String`. + +Authenticate on the AWS console using your IAM username and password. On the top right side, select the AWS Region where you want to deploy, then navigate to the Lambda section. + +![Console - Select AWS Region](console-10-regions) + +### Create the function + +Select **Create a function** to create a function. + +![Console - Lambda dashboard when there is no function](console-20-dashboard) + +Select **Author function from scratch**. Enter a **Function name** (`HelloWorld`) and select `Amazon Linux 2` as **Runtime**. +Select the architecture. When you compile your Swift code on a x84_64 machine, such as an Intel Mac, select `x86_64`. When you compile your Swift code on an Arm machine, such as the Apple Silicon M1 or more recent, select `arm64`. + +Select **Create function** + +![Console - create function](console-30-create-function) + +On the right side, select **Upload from** and select **.zip file**. + +![Console - select zip file](console-40-select-zip-file) + +Select the zip file created with the `swift package archive --allow-network-connections docker` command as described in the [Prerequisites](#prerequisites) section. + +Select **Save** + +![Console - select zip file](console-50-upload-zip) + +You're now ready to test your function. + +### Invoke the function + +Select the **Test** tab in the console and prepare a payload to send to your Lambda function. In this example, you've deployed the [HelloWorld](Exmaples.HelloWorld/README.md) example function. As explained, the function takes a `String` as input and returns a `String`. we will therefore create a test event with a JSON payload that contains a `String`. + +Select **Create new event**. Enter an **Event name**. Enter `"Swift on Lambda"` as **Event JSON**. Note that the payload must be a valid JSON document, hence we use surrounding double quotes (`"`). + +Select **Test** on the upper right side of the screen. + +![Console - prepare test event](console-60-prepare-test-event) + +The response of the invocation and additional meta data appear in the green section of the page. + +You can see the response from the Swift code: `Hello Swift on Lambda`. + +The function consumed 109.60ms of execution time, out of this 83.72ms where spent to initialize this new runtime. This initialization time is known as Lambda cold start time. + +> Lambda cold start time refers to the initial delay that occurs when a Lambda function is invoked for the first time or after being idle for a while. Cold starts happen because AWS needs to provision and initialize a new container, load your code, and start your runtime environment (in this case, the Swift runtime). This delay is particularly noticeable for the first invocation, but subsequent invocations (known as "warm starts") are typically much faster because the container and runtime are already initialized and ready to process requests. Cold starts are an important consideration when architecting serverless applications, especially for latency-sensitive workloads. Usually, compiled languages, such as Swift, Go, and Rust, have shorter cold start times compared to interpreted languages, such as Python, Java, Ruby, and Node.js. + +```text + +![Console - view invocation result](console-70-view-invocation-response) + +Select **Test** to invoke the function again with the same payload. + +Observe the results. No initialization time is reported because the Lambda execution environment was ready after the first invocation. The runtime duration of the second invocation is 1.12ms. + +```text +REPORT RequestId: f789fbb6-10d9-4ba3-8a84-27aa283369a2 Duration: 1.12 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 26 MB +``` + +AWS lambda charges usage per number of invocations and the CPU time, rounded to the next millisecond. AWS Lambda offers a generous free-tier of 1 million invocation each month and 400,000 GB-seconds of compute time per month. See [Lambda pricing](https://aws.amazon.com/lambda/pricing/) for the details. + +### Delete the function + +When you're finished with testing, you can delete the Lambda function and the IAM execution role that the console created automatically. + +While you are on the `HelloWorld` function page in the AWS console, select **Actions**, then **Delete function** in the menu on the top-right part of the page. + +![Console - delete function](console-80-delete-function) + +Then, navigate to the IAM section of the AWS console. Select **Roles** on the right-side menu and search for `HelloWorld`. The console appended some random characters to role name. The name you see on your console is different that the one on the screenshot. + +Select the `HelloWorld-role-xxxx` role and select **Delete**. Confirm the deletion by entering the role name again, and select **Delete** on the confirmation box. + +![Console - delete IAM role](console-80-delete-role) + +## Deploy your Lambda function with the AWS Command Line Interface (CLI) + +You can deploy your Lambda function using the AWS Command Line Interface (CLI). The CLI is a unified tool to manage your AWS services from the command line and automate your operations through scripts. The CLI is available for Windows, macOS, and Linux. Follow the [installation](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and [configuration](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) instructions in the AWS CLI User Guide. + +In this example, we're building the HelloWorld example from the [Examples](https://github.com/swift-server/swift-aws-lambda-runtime/tree/main/Examples) directory. + +### Create the function + +To create a function, you must first create the function execution role and define the permission. Then, you create the function with the `create-function` command. + +The command assumes you've already created the ZIP file with the `swift package archive --allow-network-connections docker` command, as described in the [Prerequisites](#prerequisites) section. + +```sh +# enter your AWS Account ID +export AWS_ACCOUNT_ID=123456789012 + +# Allow the Lambda service to assume the execution role +cat < assume-role-policy.json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} +EOF + +# Create the execution role +aws iam create-role \ +--role-name lambda_basic_execution \ +--assume-role-policy-document file://assume-role-policy.json + +# create permissions to associate with the role +cat < permissions.json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": "arn:aws:logs:*:*:*" + } + ] +} +EOF + +# Attach the permissions to the role +aws iam put-role-policy \ +--role-name lambda_basic_execution \ +--policy-name lambda_basic_execution_policy \ +--policy-document file://permissions.json + +# Create the Lambda function +aws lambda create-function \ +--function-name MyLambda \ +--zip-file fileb://.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip \ +--runtime provided.al2 \ +--handler provided \ +--architectures arm64 \ +--role arn:aws:iam::${AWS_ACCOUNT_ID}:role/lambda_basic_execution +``` + +The `--architectures` flag is only required when you build the binary on an Apple Silicon machine (Apple M1 or more recent). It defaults to `x64`. + +To update the function, use the `update-function-code` command after you've recompiled and archived your code again with the `swift package archive` command. + +```sh +aws lambda update-function-code \ +--function-name MyLambda \ +--zip-file fileb://.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip +``` + +### Invoke the function + +Use the `invoke-function` command to invoke the function. You can pass a well-formed JSON payload as input to the function. The payload must be encoded in base64. The CLI returns the status code and stores the response in a file. + +```sh +# invoke the function +aws lambda invoke \ +--function-name MyLambda \ +--payload $(echo \"Swift Lambda function\" | base64) \ +out.txt + +# show the response +cat out.txt + +# delete the response file +rm out.txt +``` + +### Delete the function + +To cleanup, first delete the Lambda funtion, then delete the IAM role. + +```sh +# delete the Lambda function +aws lambda delete-function --function-name MyLambda + +# delete the IAM policy attached to the role +aws iam delete-role-policy --role-name lambda_basic_execution --policy-name lambda_basic_execution_policy + +# delete the IAM role +aws iam delete-role --role-name lambda_basic_execution +``` + +## Deploy your Lambda function with AWS Serverless Application Model (SAM) + +AWS Serverless Application Model (SAM) is an open-source framework for building serverless applications. It provides a simplified way to define the Amazon API Gateway APIs, AWS Lambda functions, and Amazon DynamoDB tables needed by your serverless application. You can define your serverless application in a single file, and SAM will use it to deploy your function and all its dependencies. + +To use SAM, you need to [install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) on your machine. The SAM CLI provides a set of commands to package, deploy, and manage your serverless applications. + +Use SAM when you want to deploy more than a Lambda function. SAM helps you to create additional resources like an API Gateway, an S3 bucket, or a DynamoDB table, and manage the permissions between them. + +### Create the function + +We assume your Swift function is compiled and packaged, as described in the [Prerequisites](#prerequisites) section. + +When using SAM, you describe the infrastructure you want to deploy in a YAML file. The file contains the definition of the Lambda function, the IAM role, and the permissions needed by the function. The SAM CLI uses this file to package and deploy your function. + +You can create a SAM template to define a REST API implemented by AWS API Gateway and a Lambda function with the following command + +```sh +cat < template.yaml +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: SAM Template for APIGateway Lambda Example + +Resources: + # Lambda function + APIGatewayLambda: + Type: AWS::Serverless::Function + Properties: + # the directory name and ZIP file names depends on the Swift executable target name + CodeUri: .build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/APIGatewayLambda/APIGatewayLambda.zip + Timeout: 60 + Handler: swift.bootstrap # ignored by the Swift runtime + Runtime: provided.al2 + MemorySize: 512 + Architectures: + - arm64 + # The events that will trigger this function + Events: + HttpApiEvent: + Type: HttpApi # AWS API Gateway v2 + +Outputs: + # display API Gateway endpoint + APIGatewayEndpoint: + Description: "API Gateway endpoint URI" + Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com" +EOF +``` + +In this example, the Lambda function must accept an APIGateway v2 JSON payload as input parameter and return a valid APIGAteway v2 JSON response. See the example code in the [APIGateway example README file](https://github.com/swift-server/swift-aws-lambda-runtime/blob/main/Examples/APIGateway/README.md). + +To deploy the function with SAM, use the `sam deploy` command. The very first time you deploy a function, you should use the `--guided` flag to configure the deployment. The command will ask you a series of questions to configure the deployment. + +Here is the command to deploy the function with SAM: + +```sh +# start the first deployment +sam deploy --guided + +Configuring SAM deploy +====================== + + Looking for config file [samconfig.toml] : Not found + + Setting default arguments for 'sam deploy' + ========================================= + Stack Name [sam-app]: APIGatewayLambda + AWS Region [us-east-1]: + #Shows you resources changes to be deployed and require a 'Y' to initiate deploy + Confirm changes before deploy [y/N]: n + #SAM needs permission to be able to create roles to connect to the resources in your template + Allow SAM CLI IAM role creation [Y/n]: y + #Preserves the state of previously provisioned resources when an operation fails + Disable rollback [y/N]: n + APIGatewayLambda has no authentication. Is this okay? [y/N]: y + Save arguments to configuration file [Y/n]: y + SAM configuration file [samconfig.toml]: + SAM configuration environment [default]: + + Looking for resources needed for deployment: + +(redacted for brevity) + +CloudFormation outputs from deployed stack +-------------------------------------------------------------------------------- +Outputs +-------------------------------------------------------------------------------- +Key APIGatewayEndpoint +Description API Gateway endpoint URI" +Value https://59i4uwbuj2.execute-api.us-east-1.amazonaws.com +-------------------------------------------------------------------------------- + + +Successfully created/updated stack - APIGAtewayLambda in us-east-1 +``` + +To update your function or any other AWS service defined in your YAML file, you can use the `sam deploy` command without the `--guided` flag. + +### Invoke the function + +SAM allows you to invoke the function locally and remotely. + +Local invocations allows you to test your code before uploading it. It requires docker to run. + +```sh +# First, generate a sample event +sam local generate-event apigateway http-api-proxy > event.json + +# Next, invoke the function locally +sam local invoke -e ./event.json + +START RequestId: 3f5096c6-0fd3-4605-b03e-d46658e6b141 Version: $LATEST +END RequestId: 3134f067-9396-4f4f-bebb-3c63ef745803 +REPORT RequestId: 3134f067-9396-4f4f-bebb-3c63ef745803 Init Duration: 0.04 ms Duration: 38.38 msBilled Duration: 39 ms Memory Size: 512 MB Max Memory Used: 512 MB +{"body": "{\"version\":\"2.0\",\"routeKey\":\"$default\",\"rawPath\":\"\\/path\\/to\\/resource\",... REDACTED FOR BREVITY ...., "statusCode": 200, "headers": {"content-type": "application/json"}} +``` + +> If you've previously authenticated to Amazon ECR Public and your auth token has expired, you may receive an authentication error when attempting to do unauthenticated docker pulls from Amazon ECR Public. To resolve this issue, it may be necessary to run `docker logout public.ecr.aws` to avoid the error. This will result in an unauthenticated pull. For more information, see [Authentication issues](https://docs.aws.amazon.com/AmazonECR/latest/public/public-troubleshooting.html#public-troubleshooting-authentication). + +Remote invocations are done with the `sam remote invoke` command. + +```sh +sam remote invoke \ + --stack-name APIGatewayLambda \ + --event-file ./event.json + +Invoking Lambda Function APIGatewayLambda +START RequestId: ec8082c5-933b-4176-9c63-4c8fb41ca259 Version: $LATEST +END RequestId: ec8082c5-933b-4176-9c63-4c8fb41ca259 +REPORT RequestId: ec8082c5-933b-4176-9c63-4c8fb41ca259 Duration: 6.01 ms Billed Duration: 7 ms Memory Size: 512 MB Max Memory Used: 35 MB +{"body":"{\"stageVariables\":{\"stageVariable1\":\"value1\",\"stageVariable2\":\"value2\"},\"rawPath\":\"\\\/path\\\/to\\\/resource\",\"routeKey\":\"$default\",\"cookies\":[\"cookie1\",\"cookie2\"] ... REDACTED FOR BREVITY ... \"statusCode\":200,"headers":{"content-type":"application/json"}} +``` + +SAM allows you to access the function logs from Amazon Cloudwatch. + +```sh +sam logs --stack-name APIGatewayLambda + +Access logging is disabled for HTTP API ID (g9m53sn7xa) +2024/12/19/[$LATEST]4dd42d66282145a2964ff13dfcd5dc65 2024-12-19T10:16:25.593000 INIT_START Runtime Version: provided:al2.v75 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:4f3438ed7de2250cc00ea1260c3dc3cd430fad27835d935a02573b6cf07ceed8 +2024/12/19/[$LATEST]4dd42d66282145a2964ff13dfcd5dc65 2024-12-19T10:16:25.715000 START RequestId: d8afa647-8361-4bce-a817-c57b92a060af Version: $LATEST +2024/12/19/[$LATEST]4dd42d66282145a2964ff13dfcd5dc65 2024-12-19T10:16:25.758000 END RequestId: d8afa647-8361-4bce-a817-c57b92a060af +2024/12/19/[$LATEST]4dd42d66282145a2964ff13dfcd5dc65 2024-12-19T10:16:25.758000 REPORT RequestId: d8afa647-8361-4bce-a817-c57b92a060af Duration: 40.74 ms Billed Duration: 162 ms Memory Size: 512 MB Max Memory Used: 34 MB Init Duration: 120.64 ms +2024/12/19/[$LATEST]4dd42d66282145a2964ff13dfcd5dc65 2024-12-19T10:17:10.343000 START RequestId: ec8082c5-933b-4176-9c63-4c8fb41ca259 Version: $LATEST +2024/12/19/[$LATEST]4dd42d66282145a2964ff13dfcd5dc65 2024-12-19T10:17:10.350000 END RequestId: ec8082c5-933b-4176-9c63-4c8fb41ca259 +2024/12/19/[$LATEST]4dd42d66282145a2964ff13dfcd5dc65 2024-12-19T10:17:10.350000 REPORT RequestId: ec8082c5-933b-4176-9c63-4c8fb41ca259 Duration: 6.01 ms Billed Duration: 7 ms Memory Size: 512 MB Max Memory Used: 35 MB +``` + +You can also tail the logs with the `-t, --tail` flag. + +### Delete the function + +SAM allows you to delete your function and all infrastructure that is defined in the YAML template with just one command. + +```sh +sam delete + +Are you sure you want to delete the stack APIGatewayLambda in the region us-east-1 ? [y/N]: y +Are you sure you want to delete the folder APIGatewayLambda in S3 which contains the artifacts? [y/N]: y +- Deleting S3 object with key APIGatewayLambda/1b5a27c048549382462bd8ea589f7cfe +- Deleting S3 object with key APIGatewayLambda/396d2c434ecc24aaddb670bd5cca5fe8.template +- Deleting Cloudformation stack APIGatewayLambda + +Deleted successfully +``` + +## Deploy your Lambda function with the AWS Cloud Development Kit (CDK) + +The AWS Cloud Development Kit is an open-source software development framework to define cloud infrastructure in code and provision it through AWS CloudFormation. The CDK provides high-level constructs that preconfigure AWS resources with best practices, and you can use familiar programming languages like TypeScript, Javascript, Python, Java, C#, and Go to define your infrastructure. + +To use the CDK, you need to [install the CDK CLI](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) on your machine. The CDK CLI provides a set of commands to manage your CDK projects. + +Use the CDK when you want to define your infrastructure in code and manage the deployment of your Lambda function and other AWS services. + +This example deploys the [APIGateway]((https://github.com/swift-server/swift-aws-lambda-runtime/blob/main/Examples/APIGateway/) example code. It comprises a Lambda function that implements a REST API and an API Gateway to expose the function over HTTPS. + +### Create a CDK project + +To create a new CDK project, use the `cdk init` command. The command creates a new directory with the project structure and the necessary files to define your infrastructure. + +```sh +# In your Swift Lambda project folder +mkdir infra && cd infra +cdk init app --language typescript +``` + +In this example, the code to create a Swift Lambda function with the CDK is written in TypeScript. The following code creates a new Lambda function with the `swift` runtime. + +It requires the `@aws-cdk/aws-lambda` package to define the Lambda function. You can install the dependency with the following command: + +```sh +npm install aws-cdk-lib constructs +``` + +Then, in the lib folder, create a new file named `swift-lambda-stack.ts` with the following content: + +```typescript +import * as cdk from 'aws-cdk-lib'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; + +export class LambdaApiStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + // Create the Lambda function + const lambdaFunction = new lambda.Function(this, 'SwiftLambdaFunction', { + runtime: lambda.Runtime.PROVIDED_AL2, + architecture: lambda.Architecture.ARM_64, + handler: 'bootstrap', + code: lambda.Code.fromAsset('../.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/APIGatewayLambda/APIGatewayLambda.zip'), + memorySize: 512, + timeout: cdk.Duration.seconds(30), + environment: { + LOG_LEVEL: 'debug', + }, + }); + } +} +``` +The code assumes you already built and packaged the APIGateway Lambda function with the `swift package archive --allow-network-connections docker` command, as described in the [Prerequisites](#prerequisites) section. + +You can write code to add an API Gateway to invoke your Lambda function. The following code creates an HTTP API Gateway that triggers the Lambda function. + +```typescript +// in the import section at the top +import * as apigateway from 'aws-cdk-lib/aws-apigatewayv2'; +import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations'; + +// in the constructor, after having created the Lambda function +// ... + + // Create the API Gateway + const httpApi = new apigateway.HttpApi(this, 'HttpApi', { + defaultIntegration: new HttpLambdaIntegration({ + handler: lambdaFunction, + }), + }); + + // Output the API Gateway endpoint + new cdk.CfnOutput(this, 'APIGatewayEndpoint', { + value: httpApi.url!, + }); + +// ... +``` + +### Deploy the infrastructure + +To deploy the infrastructure, type the following commands. + +```sh +# Change to the infra directory +cd infra + +# Install the dependencies (only before the first deployment) +npm install + +# Deploy the infrastructure +cdk deploy + +✨ Synthesis time: 2.88s +... redacted for brevity ... +Do you wish to deploy these changes (y/n)? y +... redacted for brevity ... + βœ… LambdaApiStack + +✨ Deployment time: 42.96s + +Outputs: +LambdaApiStack.ApiUrl = https://tyqnjcawh0.execute-api.eu-central-1.amazonaws.com/ +Stack ARN: +arn:aws:cloudformation:eu-central-1:012345678901:stack/LambdaApiStack/e0054390-be05-11ef-9504-065628de4b89 + +✨ Total time: 45.84s +``` + +### Invoke your Lambda function + +To invoke the Lambda function, use this `curl` command line. + +```bash +curl https://tyqnjcawh0.execute-api.eu-central-1.amazonaws.com +``` + +Be sure to replace the URL with the API Gateway endpoint returned in the previous step. + +This should print a JSON similar to + +```bash +{"version":"2.0","rawPath":"\/","isBase64Encoded":false,"rawQueryString":"","headers":{"user-agent":"curl\/8.7.1","accept":"*\/*","host":"a5q74es3k2.execute-api.us-east-1.amazonaws.com","content-length":"0","x-amzn-trace-id":"Root=1-66fb0388-691f744d4bd3c99c7436a78d","x-forwarded-port":"443","x-forwarded-for":"81.0.0.43","x-forwarded-proto":"https"},"requestContext":{"requestId":"e719cgNpoAMEcwA=","http":{"sourceIp":"81.0.0.43","path":"\/","protocol":"HTTP\/1.1","userAgent":"curl\/8.7.1","method":"GET"},"stage":"$default","apiId":"a5q74es3k2","time":"30\/Sep\/2024:20:01:12 +0000","timeEpoch":1727726472922,"domainPrefix":"a5q74es3k2","domainName":"a5q74es3k2.execute-api.us-east-1.amazonaws.com","accountId":"012345678901"} +``` + +If you have `jq` installed, you can use it to pretty print the output. + +```bash +curl -s https://tyqnjcawh0.execute-api.eu-central-1.amazonaws.com | jq +{ + "version": "2.0", + "rawPath": "/", + "requestContext": { + "domainPrefix": "a5q74es3k2", + "stage": "$default", + "timeEpoch": 1727726558220, + "http": { + "protocol": "HTTP/1.1", + "method": "GET", + "userAgent": "curl/8.7.1", + "path": "/", + "sourceIp": "81.0.0.43" + }, + "apiId": "a5q74es3k2", + "accountId": "012345678901", + "requestId": "e72KxgsRoAMEMSA=", + "domainName": "a5q74es3k2.execute-api.us-east-1.amazonaws.com", + "time": "30/Sep/2024:20:02:38 +0000" + }, + "rawQueryString": "", + "routeKey": "$default", + "headers": { + "x-forwarded-for": "81.0.0.43", + "user-agent": "curl/8.7.1", + "host": "a5q74es3k2.execute-api.us-east-1.amazonaws.com", + "accept": "*/*", + "x-amzn-trace-id": "Root=1-66fb03de-07533930192eaf5f540db0cb", + "content-length": "0", + "x-forwarded-proto": "https", + "x-forwarded-port": "443" + }, + "isBase64Encoded": false +} +``` + +### Delete the infrastructure + +When done testing, you can delete the infrastructure with this command. + +```bash +cdk destroy + +Are you sure you want to delete: LambdaApiStack (y/n)? y +LambdaApiStack: destroying... [1/1] +... redacted for brevity ... + βœ… LambdaApiStack: destroyed +``` + +## Third-party tools + +We welcome contributions to this section. If you have experience deploying Swift Lambda functions with third-party tools like Serverless Framework, Terraform, or Pulumi, please share your knowledge with the community. \ No newline at end of file diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/Documentation.md b/Sources/AWSLambdaRuntimeCore/Documentation.docc/Documentation.md index 68088df8..4016bcbd 100644 --- a/Sources/AWSLambdaRuntimeCore/Documentation.docc/Documentation.md +++ b/Sources/AWSLambdaRuntimeCore/Documentation.docc/Documentation.md @@ -18,7 +18,6 @@ Swift AWS Lambda Runtime was designed to make building Lambda functions in Swift ### Essentials -- - - - ``LambdaHandler`` - +- +- diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-10-regions.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-10-regions.png new file mode 100644 index 00000000..afe97b53 Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-10-regions.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-20-dashboard.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-20-dashboard.png new file mode 100644 index 00000000..b48ea591 Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-20-dashboard.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-30-create-function.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-30-create-function.png new file mode 100644 index 00000000..e3bd131f Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-30-create-function.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-40-select-zip-file.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-40-select-zip-file.png new file mode 100644 index 00000000..da4ff924 Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-40-select-zip-file.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-50-upload-zip.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-50-upload-zip.png new file mode 100644 index 00000000..89eedab9 Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-50-upload-zip.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-60-prepare-test-event.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-60-prepare-test-event.png new file mode 100644 index 00000000..2f7b15ed Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-60-prepare-test-event.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-70-view-invocation-response.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-70-view-invocation-response.png new file mode 100644 index 00000000..f4f712bc Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-70-view-invocation-response.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-80-delete-function.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-80-delete-function.png new file mode 100644 index 00000000..f205f47b Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-80-delete-function.png differ diff --git a/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-80-delete-role.png b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-80-delete-role.png new file mode 100644 index 00000000..2a335d5d Binary files /dev/null and b/Sources/AWSLambdaRuntimeCore/Documentation.docc/img/deployment/console-80-delete-role.png differ diff --git a/readme.md b/readme.md index 0717c3e3..ff88d772 100644 --- a/readme.md +++ b/readme.md @@ -1,9 +1,19 @@ -> [!IMPORTANT] +> [!IMPORTANT] > The documentation included here refers to the Swift AWS Lambda Runtime v2 (code from the main branch). If you're developing for the runtime v1.x, check this [readme](https://github.com/swift-server/swift-aws-lambda-runtime/blob/v1/readme.md) instead. > [!WARNING] > The Swift AWS Runtime v2 is work in progress. We will add more documentation and code examples over time. +This guide contains the follwoing sections: + +- [The Swift AWS Lambda Runtime](#the-swift-aws-lambda-runtime) +- [Pre-requisites](#pre-requisites) +- [Getting started](#getting-started) +- [Developing your Swift Lambda functions](#developing-your-swift-lambda-functions) +- [Testing Locally](#testing-locally) +- [Deploying your Swift Lambda functions](#deploying-your-swift-lambda-functions) +- [Swift AWS Lambda Runtime - Design Principles](#swift-aws-lambda-runtime---design-principles)% + ## The Swift AWS Lambda Runtime Many modern systems have client components like iOS, macOS or watchOS applications as well as server components that those clients interact with. Serverless functions are often the easiest and most efficient way for client application developers to extend their applications into the cloud. @@ -34,6 +44,17 @@ To get started, read [the Swift AWS Lambda runtime v1 tutorial](https://swiftpac Or, if you're impatient to start with runtime v2, try these six steps: +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 @@ -80,7 +101,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 @@ -95,14 +124,15 @@ let runtime = LambdaRuntime { try await runtime.run() ``` -4. Build & archive the package +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 @@ -125,6 +155,13 @@ The `--architectures` flag is only required when you build the binary on an Appl Be sure to replace with your actual AWS account ID (for example: 012345678901). +> [!IMPORTANT] +> Before starting, you need the `lambda_basic_execution` IAM role in your AWS account. +> +> You can create this role in two ways: +> 1. Using AWS Console +> 2. Running the commands in the `create_lambda_execution_role()` function in `Examples/_MyFirstFunction/create_iam_role.sh` + 6. Invoke your Lambda function ```bash @@ -134,7 +171,7 @@ aws lambda invoke \ out.txt && cat out.txt && rm out.txt ``` -This should print +This should print ``` { @@ -144,7 +181,7 @@ This should print "dlroW olleH" ``` -## Developing your Swift Lambda functions +## Developing your Swift Lambda functions ### Receive and respond with JSON objects @@ -221,7 +258,7 @@ You can learn how to deploy and invoke this function in [the streaming example R ### Integration with AWS Services Most Lambda functions are triggered by events originating in other AWS services such as `Amazon SNS`, `Amazon SQS` or `AWS APIGateway`. - + The [Swift AWS Lambda Events](http://github.com/swift-server/swift-aws-lambda-events) package includes an `AWSLambdaEvents` module that provides implementations for most common AWS event types further simplifying writing Lambda functions. Here is an example Lambda function invoked when the AWS APIGateway receives an HTTP request. @@ -241,11 +278,11 @@ try await runtime.run() You can learn how to deploy and invoke this function in [the API Gateway example README file](Examples/APIGateway/README.md). -### Integration with Swift Service LifeCycle +### Integration with Swift Service LifeCycle tbd + link to docc -### Use Lambda Background Tasks +### Use Lambda Background Tasks Background tasks allow code to execute asynchronously after the main response has been returned, enabling additional processing without affecting response latency. This approach is ideal for scenarios like logging, data updates, or notifications that can be deferred. The code leverages Lambda's "Response Streaming" feature, which is effective for balancing real-time user responsiveness with the ability to perform extended tasks post-response. For more information about Lambda background tasks, see [this AWS blog post](https://aws.amazon.com/blogs/compute/running-code-after-returning-a-response-from-an-aws-lambda-function/). @@ -322,10 +359,10 @@ curl -v --header "Content-Type:\ application/json" --data @events/create-session > Accept: */* > Content-Type:\ application/json > Content-Length: 1160 -> +> < HTTP/1.1 200 OK < content-length: 247 -< +< * Connection #0 to host 127.0.0.1 left intact {"statusCode":200,"isBase64Encoded":false,"body":"...","headers":{"Access-Control-Allow-Origin":"*","Content-Type":"application\/json; charset=utf-8","Access-Control-Allow-Headers":"*"}} ``` @@ -343,9 +380,48 @@ LOCAL_LAMBDA_SERVER_INVOCATION_ENDPOINT=/2015-03-31/functions/function/invocatio ## Deploying your Swift Lambda functions +There is a full deployment guide available in [the documentation](https://swiftpackageindex.com/swift-server/swift-aws-lambda-runtime/main/documentation/awslambdaruntime). + +> [!NOTE] +> We will add the deep link to the correct page once published on the [Swift Package Index](https://swiftpackageindex.com/swift-server/swift-aws-lambda-runtime). + +There are multiple ways to deploy your Swift code to AWS Lambda. The very first time, you'll probably use the AWS Console to create a new Lambda function and upload your code as a zip file. However, as you iterate on your code, you'll want to automate the deployment process. + +To take full advantage of the cloud, we recommend using Infrastructure as Code (IaC) tools like the [AWS Serverless Application Model (SAM)](https://aws.amazon.com/serverless/sam/) or [AWS Cloud Development Kit (CDK)](https://aws.amazon.com/cdk/). These tools allow you to define your infrastructure and deployment process as code, which can be version-controlled and automated. + +Alternatively, you might also consider using popular third-party tools like [Serverless Framework](https://www.serverless.com/), [Terraform](https://www.terraform.io/), or [Pulumi](https://www.pulumi.com/) to deploy Lambda functions and create and manage AWS infrastructure. + +Here is a short example that shows how to deploy using SAM. + +**Prerequisites** : Install the [SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) -TODO +When using SAM, you describe your deployment in a YAML text file. +The [API Gateway example directory](Examples/APIGateway/template.yaml) contains a file named `template.yaml` that you can use as a starting point. + +To deploy your Lambda function and create the infrastructure, type the following `sam` command. + +```bash +sam deploy \ +--resolve-s3 \ +--template-file template.yaml \ +--stack-name APIGatewayLambda \ +--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 +----------------------------------------------------------------------------------------------------------------------------- +``` +Please refer to the full deployment guide available in [the documentation](https://swiftpackageindex.com/swift-server/swift-aws-lambda-runtime/main/documentation/awslambdaruntime) for more details. ## Swift AWS Lambda Runtime - Design Principles @@ -367,8 +443,8 @@ The v2 API prioritizes the following principles: The v2 API introduces two new features: -[Response Streaming](https://aws.amazon.com/blogs/compute/introducing-aws-lambda-response-streaming/]): This functionality is ideal for handling large responses that need to be sent incrementally. Β  +[Response Streaming](https://aws.amazon.com/blogs/compute/introducing-aws-lambda-response-streaming/]): This functionality is ideal for handling large responses that need to be sent incrementally. Β  [Background Work](https://aws.amazon.com/blogs/compute/running-code-after-returning-a-response-from-an-aws-lambda-function/): Schedule tasks to run after returning a response to the AWS Lambda control plane. -These new capabilities provide greater flexibility and control when building serverless functions in Swift with the swift-aws-lambda-runtime library. \ No newline at end of file +These new capabilities provide greater flexibility and control when building serverless functions in Swift with the swift-aws-lambda-runtime library.