14/07/2023 - AWS, GO, TERRAFORM
You can use this Terraform code to build your environment so that your AWS Lambda function is regularly called by AWS EventBridge's Scheduler feature.
├── cmd
│ └── greeter
│ └── main.go
├── .gitignore
├── go.mod
├── go.sum
└── terraform
└── development
└── main.tf
package main
import (
"context"
"os"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"golang.org/x/exp/slog"
)
func main() {
lambda.Start(handler)
}
func handler(ctx context.Context, event events.CloudWatchEvent) {
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("scheduler is calling", slog.Any("event", event))
}
terraform {
required_version = "~> 1.4.4"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.41.0"
}
archive = {
source = "hashicorp/archive"
version = "~> 2.3.0"
}
null = {
source = "hashicorp/null"
version = "~> 3.2.1"
}
}
}
provider "aws" {
profile = "development"
region = "eu-west-1"
}
# -- VARS ----------------------------------------------------------------------
locals {
lambda_function_name = "greeter"
go_source_path = "${path.module}/../../cmd/${local.lambda_function_name}/..."
go_binary_path = "${path.module}/../../bin/${local.lambda_function_name}"
go_zip_path = "${path.module}/../../tmp/${local.lambda_function_name}.zip"
}
# -- LAMBDA --------------------------------------------------------------------
resource "null_resource" "lambda_go_binary" {
provisioner "local-exec" {
command = "GOOS=linux GOARCH=amd64 CGO_ENABLED=0 GOFLAGS=-trimpath go build -mod=readonly -ldflags='-s -w' -o ${local.go_binary_path} ${local.go_source_path}"
}
}
data "archive_file" "lambda_go_zip" {
type = "zip"
source_file = local.go_binary_path
output_path = local.go_zip_path
depends_on = [
null_resource.lambda_go_binary,
]
}
resource "aws_lambda_function" "greeter" {
function_name = local.lambda_function_name
handler = local.lambda_function_name
filename = local.go_zip_path
package_type = "Zip"
runtime = "go1.x"
timeout = 30
memory_size = 128
role = aws_iam_role.lambda_executor.arn
source_code_hash = data.archive_file.lambda_go_zip.output_base64sha256
depends_on = [
aws_cloudwatch_log_group.lambda_log_group,
]
}
resource "aws_iam_role" "lambda_executor" {
name = "greeter-lambda-executor"
managed_policy_arns = [aws_iam_policy.lambda_log.arn]
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
},
]
})
}
resource "aws_iam_policy" "lambda_log" {
name = "greeter-lambda-log"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
]
Effect = "Allow"
Resource = [
"arn:aws:logs:*:*:*",
]
},
]
})
}
resource "aws_cloudwatch_log_group" "lambda_log_group" {
name = "/aws/lambda/${local.lambda_function_name}"
retention_in_days = 5
}
# -- CLOUDWATCH ----------------------------------------------------------------
resource "aws_scheduler_schedule" "schedule" {
name = "greeter-lambda-schedule"
flexible_time_window {
mode = "OFF"
}
schedule_expression = "rate(1 minutes)"
target {
arn = aws_lambda_function.greeter.arn
role_arn = aws_iam_role.schedule_executor.arn
}
}
resource "aws_iam_role" "schedule_executor" {
name = "greeter-lambda-schedule-executor"
managed_policy_arns = [aws_iam_policy.schedule_invoker.arn]
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "scheduler.amazonaws.com"
}
},
]
})
}
resource "aws_iam_policy" "schedule_invoker" {
name = "greeter-lambda-schedule-invoker"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "lambda:InvokeFunction"
Effect = "Allow"
Resource = aws_lambda_function.greeter.arn
},
]
})
}
.terraform/
terraform.tfstate*
tmp/
bin/
me:~/aws/terraform/development$ terraform apply \
-replace="null_resource.lambda_go_binary" \
-replace="archive_file.lambda_go_zip" \
-replace="aws_lambda_function.greeter"
fields @message
| parse @message '"level":"*"' as level
| filter level in ["INFO", "WARN", "ERROR"]
| display level, @message
| sort @timestamp desc
| limit 20
level, @message
INFO, "{""time"":""2023-07-11T19:54:42.096957233Z"",""level"":""INFO"",""msg"":""scheduler is calling"",""event"":{""...""}}"
INFO, "{""time"":""2023-07-11T19:53:42.122494263Z"",""level"":""INFO"",""msg"":""scheduler is calling"",""event"":{""...""}}"