diff --git a/serverless-lambda-layers/Makefile b/lambda-layers/serverless-framework/Makefile similarity index 100% rename from serverless-lambda-layers/Makefile rename to lambda-layers/serverless-framework/Makefile diff --git a/serverless-lambda-layers/README.md b/lambda-layers/serverless-framework/README.md similarity index 96% rename from serverless-lambda-layers/README.md rename to lambda-layers/serverless-framework/README.md index ae91102..b227baf 100644 --- a/serverless-lambda-layers/README.md +++ b/lambda-layers/serverless-framework/README.md @@ -1,4 +1,4 @@ -# LocalStack Demo: Lambda Layers +# Lambda Layers with Serverless Framework Simple demo application illustrating Lambda layers using LocalStack, deployed via the Serverless framework. diff --git a/serverless-lambda-layers/handler.js b/lambda-layers/serverless-framework/handler.js similarity index 100% rename from serverless-lambda-layers/handler.js rename to lambda-layers/serverless-framework/handler.js diff --git a/serverless-lambda-layers/layer/nodejs/lib.js b/lambda-layers/serverless-framework/layer/nodejs/lib.js similarity index 100% rename from serverless-lambda-layers/layer/nodejs/lib.js rename to lambda-layers/serverless-framework/layer/nodejs/lib.js diff --git a/serverless-lambda-layers/package-lock.json b/lambda-layers/serverless-framework/package-lock.json similarity index 100% rename from serverless-lambda-layers/package-lock.json rename to lambda-layers/serverless-framework/package-lock.json diff --git a/serverless-lambda-layers/package.json b/lambda-layers/serverless-framework/package.json similarity index 100% rename from serverless-lambda-layers/package.json rename to lambda-layers/serverless-framework/package.json diff --git a/serverless-lambda-layers/serverless.yml b/lambda-layers/serverless-framework/serverless.yml similarity index 100% rename from serverless-lambda-layers/serverless.yml rename to lambda-layers/serverless-framework/serverless.yml diff --git a/lambda-layers/terraform/.gitignore b/lambda-layers/terraform/.gitignore new file mode 100644 index 0000000..c1f7eee --- /dev/null +++ b/lambda-layers/terraform/.gitignore @@ -0,0 +1,6 @@ +.terraform +.venv +build +.terraform.lock.hcl +output.json +terraform.* diff --git a/lambda-layers/terraform/Makefile b/lambda-layers/terraform/Makefile new file mode 100644 index 0000000..7494a8f --- /dev/null +++ b/lambda-layers/terraform/Makefile @@ -0,0 +1,52 @@ +export AWS_ACCESS_KEY_ID ?= test +export AWS_SECRET_ACCESS_KEY ?= test +export AWS_DEFAULT_REGION = us-east-1 +SHELL := /bin/bash +PYTHON_BIN ?= $(shell which python3 || which python) + +usage: ## Show this help + @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//' + +start: + localstack start -d + +install: ## Install dependencies + @which localstack || pip install localstack + @which awslocal || pip install awscli-local + @which terraform || (\ + echo 'Terraform was not found, installing locally' && \ + wget https://releases.hashicorp.com/terraform/1.0.8/terraform_1.0.8_linux_amd64.zip && \ + unzip terraform_*.zip && \ + rm terraform_*.zip) + @test -e .venv || ($(PYTHON_BIN) -m venv .venv; source .venv/bin/activate; pip3 install terraform-local;) + +package: + source .venv/bin/activate; pip install \ + --platform manylinux2014_x86_64 \ + --target=package \ + --implementation cp \ + --only-binary=:all: \ + --upgrade \ + --requirement requirements.txt \ + --target build/my-lambda-layer/python + +init: + tflocal init + +deploy: + tflocal apply --auto-approve + +invoke: + awslocal lambda invoke \ + --function-name my-lambda-function \ + output.json + cat output.json + +run: start install package init deploy invoke + +clean: + rm -rf build + rm -rf .terraform + rf -f output.json + +.PHONY: start install init deploy invoke clean diff --git a/lambda-layers/terraform/README.md b/lambda-layers/terraform/README.md new file mode 100644 index 0000000..c22c621 --- /dev/null +++ b/lambda-layers/terraform/README.md @@ -0,0 +1,49 @@ +# Lambda Layers with Terraform + +Simple demo application illustrating Lambda layers using LocalStack, deployed via Terraform. + +## Prerequisites + +* LocalStack +* Docker +* Terraform & `tflocal` +* Python & `pip` +* `make` + +## Installing + +To install the dependencies: +``` +make install +``` + +## Running + +Make sure that LocalStack is started: + +``` +LOCALSTACK_AUTH_TOKEN=... DEBUG=1 localstack start +``` + +Deploy the app locally and run a Lambda test invocation: + +``` +make run +``` + +You should see a success output in the terminal: +``` +{"status": "success"} +``` + +... and your LocalStack container should contain output similar to this: + +``` +2024-05-17T15:46:22.870 DEBUG --- [et.reactor-1] l.s.l.i.version_manager : [my-lambda-function-52785b61-d14d-4871-8074-d5ab5fc49bb1] REPORT RequestId: 52785b61-d14d-4871-8074-d5ab5fc49bb1 Duration: 20.65 ms Billed Duration: 21 ms Memory Size: 128 MBMax Memory Used: 128 MB +2024-05-17T15:46:22.872 DEBUG --- [et.reactor-1] l.s.lambda_.provider : Lambda invocation duration: 2230.03ms +2024-05-17T15:46:22.874 INFO --- [et.reactor-1] localstack.request.aws : AWS lambda.Invoke => 200 +``` + +## License + +This code is available under the Apache 2.0 license. diff --git a/lambda-layers/terraform/main.tf b/lambda-layers/terraform/main.tf new file mode 100644 index 0000000..b53c280 --- /dev/null +++ b/lambda-layers/terraform/main.tf @@ -0,0 +1,100 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = "us-east-1" # Replace with your preferred region +} + +# Lambda Layer +data "archive_file" "lambda_layer_zip" { + type = "zip" + source_dir = "${path.module}/build/my-lambda-layer" # Path to your Python dependencies directory + output_path = "${path.module}/build/lambda_layer.zip" +} + +# Layer bucket +resource "aws_s3_bucket" "lambda_layer_bucket" { + bucket = "my-lambda-layer-bucket" +} + +# Layer ZIP upload +resource "aws_s3_object" "lambda_layer" { + bucket = aws_s3_bucket.lambda_layer_bucket.id + key = "lambda_layer.zip" + source = data.archive_file.lambda_layer_zip.output_path + depends_on = [data.archive_file.lambda_layer_zip] # Triggered only if the zip file is created +} + +# Lambda Layer from S3 +resource "aws_lambda_layer_version" "dependencies" { + s3_bucket = aws_s3_bucket.lambda_layer_bucket.id + s3_key = aws_s3_object.lambda_layer.key + layer_name = "my-lambda-layer" + compatible_runtimes = ["python3.12"] + depends_on = [aws_s3_object.lambda_layer] # Triggered only if the zip file is uploaded to the bucket +} + +# Lambda Function +data "archive_file" "lambda_function" { + type = "zip" + source_file = "${path.module}/src/lambda_function.py" + output_path = "${path.module}/build/lambda_function.zip" +} + +resource "aws_lambda_function" "my_lambda" { + filename = data.archive_file.lambda_function.output_path + function_name = "my-lambda-function" + role = aws_iam_role.lambda_role.arn # See IAM Role below + handler = "lambda_function.handler" + runtime = "python3.12" + + layers = [aws_lambda_layer_version.dependencies.arn] +} + +# IAM Role for Lambda +resource "aws_iam_role" "lambda_role" { + name = "lambda_basic_execution" + + assume_role_policy = <