Skip to content

Commit

Permalink
Update package and deplioy
Browse files Browse the repository at this point in the history
Using archive command plugin and AWS SAM
  • Loading branch information
adam-fowler committed Jan 28, 2024
1 parent a68ee6a commit 957ae50
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 83 deletions.
2 changes: 1 addition & 1 deletion todos-lambda/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.0.0-alpha.1"),
.package(url: "https://github.com/hummingbird-project/hummingbird-lambda.git", branch: "2.x.x"),
.package(url: "https://github.com/hummingbird-project/hummingbird-lambda.git", branch: "2.x.x-request-headers"),
.package(url: "https://github.com/soto-project/soto.git", from: "7.0.0-alpha"),
],
targets: [
Expand Down
6 changes: 3 additions & 3 deletions todos-lambda/Sources/App/Controllers/TodoController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ struct TodoController {
typealias Context = HBBasicLambdaRequestContext<APIGatewayRequest>

let dynamoDB: DynamoDB
let tableName = "hummingbird-todos"
let tableName: String

func addRoutes(to group: HBRouterGroup<Context>) {
group
.get(use: self.list)
.post(use: self.create)
.delete(use: self.deleteAll)
.get("{id}", use: self.get)
.get(use: self.list)
.patch("{id}", use: self.updateId)
.delete("{id}", use: self.deleteId)
.delete(use: self.deleteAll)
}

@Sendable func list(_ request: HBRequest, context: Context) async throws -> [Todo] {
Expand Down
29 changes: 23 additions & 6 deletions todos-lambda/Sources/App/lambda.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,32 @@
import AWSLambdaEvents
import AWSLambdaRuntime
import HummingbirdLambda
import Logging
import SotoDynamoDB

@main
struct AppLambda: HBAPIGatewayLambda {
let awsClient: AWSClient
let logger: Logger

init(context: LambdaInitializationContext) {
self.awsClient = AWSClient(httpClientProvider: .createNewWithEventLoopGroup(context.eventLoop))
self.logger = context.logger
}

func buildResponder() -> some HBResponder<Context> {
let tableName = HBEnvironment.shared.get("TODOS_TABLE_NAME") ?? "hummingbird-todos"
self.logger.info("Using table \(tableName)")
let dynamoDB = DynamoDB(client: awsClient, region: .euwest1)

let router = HBRouter(context: Context.self)
// middleware
router.middlewares.add(ErrorMiddleware())
router.middlewares.add(HBLogRequestsMiddleware(.debug))
router.middlewares.add(HBCORSMiddleware(
allowOrigin: .originBased,
allowHeaders: [.contentType],
allowMethods: [.get, .options, .post, .delete, .patch]
))
router.get("/") { _, _ in
return "Hello"
}
TodoController(dynamoDB: dynamoDB).addRoutes(to: router.group("todos"))
TodoController(dynamoDB: dynamoDB, tableName: tableName).addRoutes(to: router.group("todos"))

return router.buildResponder()
}
Expand All @@ -48,3 +49,19 @@ struct AppLambda: HBAPIGatewayLambda {
try await self.awsClient.shutdown()
}
}

struct ErrorMiddleware<Context: HBBaseRequestContext>: HBMiddlewareProtocol {
func handle(
_ input: HBRequest,
context: Context,
next: (HBRequest, Context) async throws -> HBResponse
) async throws -> HBResponse {
do {
return try await next(input, context)
} catch let error as HBHTTPError {
throw error
} catch {
throw HBHTTPError(.internalServerError, message: "Error: \(error)")
}
}
}
19 changes: 3 additions & 16 deletions todos-lambda/scripts/build-and-package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,7 @@
##
##===----------------------------------------------------------------------===##

set -eu
here=$(dirname "$0")

base=$(pwd)
executable=HummingbirdTodosLambda
swift_docker=swift:5.3-amazonlinux2

echo "-------------------------------------------------------------------------"
echo "building \"$executable\" lambda"
echo "-------------------------------------------------------------------------"
docker run --rm -v "$base":/src -w /src/ $swift_docker bash -cl "swift package update"
docker run --rm -v "$base":/src -w /src/ $swift_docker bash -cl "swift build --product $executable -c release -Xswiftc -static-stdlib"
echo "done"

echo "-------------------------------------------------------------------------"
echo "packaging \"$executable\" lambda"
echo "-------------------------------------------------------------------------"
./scripts/package.sh $executable
cd "$here"/..
swift package --disable-sandbox archive
38 changes: 7 additions & 31 deletions todos-lambda/scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,13 @@
##
##===----------------------------------------------------------------------===##

set -eu
here=$(dirname "$0")

export AWS_PROFILE=opticalaberration-admin_dev

here=$(dirname $0)
# Lambda Function name
function_name=TodosBackend
executable_name=HummingbirdTodosLambda
policy_name="${function_name}-lamba-policy"
role_name="${function_name}-lamba-role"

# does function already exist
if [ -n "$(aws lambda list-functions --output json --query 'Functions[*].FunctionName' | grep -w "$function_name")" ]; then
# function exists so just need to update it
echo "-------------------------------------------------------------------------"
echo "updating lambda \"$function_name\""
echo "-------------------------------------------------------------------------"
aws lambda update-function-code --function "$function_name" --zip-file fileb://.build/lambda/"$executable_name"/lambda.zip

else
# function does not exist need to create role to run it
echo "-------------------------------------------------------------------------"
echo "creating role \"$role_name\""
echo "-------------------------------------------------------------------------"
assume_role_policy='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["sts:AssumeRole"],"Principal":{"Service":["lambda.amazonaws.com"]}}]}'
iam_role_arn=$(aws iam create-role --role-name "$role_name" --assume-role-policy-document "$assume_role_policy" --output text --query "Role.Arn")
aws iam put-role-policy --role-name "$role_name" --policy-name "$policy_name" --policy-document file://$here/policy.json
# create lambda
echo "-------------------------------------------------------------------------"
echo "creating lambda \"$function_name\""
echo "-------------------------------------------------------------------------"
aws lambda create-function --function "$function_name" --role "$iam_role_arn" --runtime provided --memory-size 192 --timeout 20 --handler "$function_name" --zip-file fileb://.build/lambda/"$executable_name"/lambda.zip
if [ ! $(which sam) ]; then
echo "The deploy script requires AWS SAM."
echo "More information about AWS SAM and installation instructions can be found at https://aws.amazon.com/serverless/sam/"
exit -1
fi

cd "$here"/..
sam deploy --stack-name hb-todos-lambda --resolve-s3 --template scripts/sam.yml $@
26 changes: 0 additions & 26 deletions todos-lambda/scripts/package.sh

This file was deleted.

99 changes: 99 additions & 0 deletions todos-lambda/scripts/sam.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: A sample SAM template for deploying Hummingbird Lambda Todos function.

Globals:
Function:
Timeout: 3
MemorySize: 256

Resources:
# Todos Function
hbTodosFunction:
Type: AWS::Serverless::Function
Properties:
Handler: Provided
Runtime: provided.al2
Architectures:
- arm64
CodeUri: ../.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/App/App.zip
# Instructs new versions to be published to an alias named "live".
AutoPublishAlias: live
Events:
Hello:
Type: Api
Properties:
Path: /
Method: get
Create:
Type: Api
Properties:
Path: /todos
Method: post
Get:
Type: Api
Properties:
Path: /todos/{id}
Method: get
List:
Type: Api
Properties:
Path: /todos/
Method: get
Patch:
Type: Api
Properties:
Path: /todos/{id}
Method: path
Delete:
Type: Api
Properties:
Path: /todos/{id}
Method: delete
DeleteAll:
Type: Api
Properties:
Path: /todos
Method: delete
Environment:
Variables:
TODOS_TABLE_NAME: !Ref TodosTable
Policies:
- DynamoDBCrudPolicy: # More info about SAM policy templates: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-templates.html
TableName: !Ref TodosTable

TodosTable:
Type: AWS::Serverless::SimpleTable # More info about SimpleTable Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-simpletable.html
Properties:
PrimaryKey:
Name: id
Type: String

Outputs:
HelloFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for Hello function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
CreateFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for Create function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/todos/"
GetFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for Get function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/todos/{id}"
ListFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for List function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/todos/"
PatchFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for Patch function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/todos/{id}"
DeleteFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for Delete function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/todos/{id}"
DeleteAllFunctionApi:
Description: "API Gateway endpoint URL for Prod stage for DeleteAll function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/todos/"
TodosFunction:
Description: "Todos function name"
Value: !GetAtt hbTodosFunction.Arn
TodosTable:
Description: "Hummingbird Todos Lambda Table"
Value: !GetAtt TodosTable.Arn
31 changes: 31 additions & 0 deletions todos-lambda/scripts/samconfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# More information about the configuration file can be found here:
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
version = 0.1

[default]
[default.global.parameters]
stack_name = "hb-todos-lambda"

[default.build.parameters]
cached = true
parallel = true

[default.validate.parameters]
lint = true

[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true

[default.package.parameters]
resolve_s3 = true

[default.sync.parameters]
watch = true

[default.local_start_api.parameters]
warm_containers = "EAGER"

[default.local_start_lambda.parameters]
warm_containers = "EAGER"

0 comments on commit 957ae50

Please sign in to comment.