Terraform Lambda Layers
There are number of Terraform Lambda tutorials which say you need an S3 bucket (for the Layer).
You don’t.
I recently implemented a POC, which had one job. To implement a Lambda Layer for some simple Node code, and wrap in Terraform.
Terraform and node code (github)
Create and zip source and dependencies:
cd layers/date-fns/nodejs
npm init -y
npm install date-fns@2.24.0
zip -r9 date-fns-layer.zip .
Zip the Lambda code:
zip -r9 lambda.zip index.js
Terraform:
terraform plan
terraform apply
terraform destroy
Terraform
The Layer:
resource "aws_lambda_layer_version" "simple_node_lambda-layer" {
filename = "layers/date-fns/date-fns-layer.zip"
layer_name = "simple_node_lambda-layer"
source_code_hash = "${filebase64sha256("layers/date-fns/date-fns-layer.zip")}"
compatible_runtimes = ["nodejs14.x"]
}
The Lambda references the Layer:
resource "aws_lambda_function" "simple_node_lambda_function" {
filename = "lambda.zip"
function_name = "SimpleNodeLambdaFunction"
role = aws_iam_role.simple-node-lambda_role.arn
handler = "index.handler"
source_code_hash = filebase64sha256("lambda.zip")
runtime = "nodejs14.x"
layers = [aws_lambda_layer_version.simple_node_lambda-layer.arn]
}
I found a useful terraform module, aws_lambda_invocation:
resource "aws_lambda_invocation" "lambda_invocation" {
function_name = "SimpleNodeLambdaFunction"
input = jsonencode({
hello = "world"
})
triggers = {
redeployment = timestamp()
}
depends_on = [
aws_lambda_function.simple_node_lambda_function
]
}
I created an output, which outputs the Lambda invocation:
output "lambda_invoke" {
description = "Result of Lambda invocation"
value = aws_lambda_invocation.lambda_invocation.result
}
The Terraform apply, showing the invocation, and output:
aws_iam_role.simple-node-lambda_role: Creating...
aws_cloudwatch_log_group.main: Creating...
aws_lambda_layer_version.simple_node_lambda-layer: Creating...
aws_cloudwatch_log_group.main: Creation complete after 0s [id=SimpleNodeLambdaFunction]
aws_iam_role.simple-node-lambda_role: Creation complete after 1s [id=simple-node_role]
aws_iam_role_policy.lambda_basic_policy: Creating...
aws_iam_role_policy.lambda_basic_policy: Creation complete after 0s [id=simple-node_role:lambda_simple_node_basic_policy]
aws_lambda_layer_version.simple_node_lambda-layer: Still creating... [10s elapsed]
aws_lambda_layer_version.simple_node_lambda-layer: Creation complete after 15s [id=arn:aws:lambda:eu-west-1:457954557100:layer:simple_node_lambda-layer:7]
aws_lambda_function.simple_node_lambda_function: Creating...
aws_lambda_function.simple_node_lambda_function: Creation complete after 9s [id=SimpleNodeLambdaFunction]
aws_lambda_invocation.lambda_invocation: Creating...
aws_lambda_invocation.lambda_invocation: Creation complete after 1s [id=SimpleNodeLambdaFunction_$LATEST_fbc24bcc7a1794758fc1327fcfebdaf6]
Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
Outputs:
lambda_invoke = "{\"statusCode\":200,\"body\":\"{\\\"today\\\":\\\"👉️ Today is a Sunday\\\"}\"}"
Terraform (continued):
IAM role:
resource "aws_iam_role" "simple-node-lambda_role" {
name = "simple-node_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
IAM Role Policy (for cloudwatch logs:)
resource "aws_iam_role_policy" "lambda_basic_policy" {
name = "lambda_simple_node_basic_policy"
role = aws_iam_role.simple-node-lambda_role.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
}
]
}
EOF
}
resource "aws_cloudwatch_log_group" "main" {
name = "SimpleNodeLambdaFunction"
retention_in_days = 1
}