Skip to content

Commit f6c8fc0

Browse files
committed
First commit
1 parent 1c9996c commit f6c8fc0

File tree

11 files changed

+282
-2
lines changed

11 files changed

+282
-2
lines changed

.github/workflows/ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "master" ]
6+
pull_request:
7+
branches: [ "master" ]
8+
workflow_dispatch: # enable manual execution
9+
10+
env:
11+
TERRAFORM_VERSION: 1.3.6
12+
13+
concurrency:
14+
group: ${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
verify:
19+
name: Verify
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 5
22+
steps:
23+
24+
- uses: actions/checkout@v3
25+
26+
- name: Setup Terraform
27+
uses: hashicorp/setup-terraform@v2
28+
with:
29+
terraform_version: ${{ env.TERRAFORM_VERSION }}
30+
31+
- name: Format check
32+
run: terraform fmt -check -recursive .
33+
34+
- name: Validate
35+
run: terraform validate

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ override.tf.json
2626
# !example_override.tf
2727

2828
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
29-
# example: *tfplan*
29+
*tfplan*

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2022 Nicola
3+
Copyright (c) 2022 horothesun
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

api_gateway.tf

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
resource "aws_apigatewayv2_api" "api_gw" {
2+
name = aws_lambda_function.lambda.function_name
3+
protocol_type = "HTTP"
4+
description = "HTTP API for ${aws_lambda_function.lambda.function_name}"
5+
6+
cors_configuration {
7+
allow_credentials = false
8+
allow_headers = []
9+
allow_methods = [var.http_method]
10+
allow_origins = ["*"]
11+
expose_headers = []
12+
max_age = 0
13+
}
14+
}
15+
16+
resource "aws_apigatewayv2_stage" "default" {
17+
api_id = aws_apigatewayv2_api.api_gw.id
18+
19+
name = "$default"
20+
auto_deploy = true
21+
22+
access_log_settings {
23+
destination_arn = aws_cloudwatch_log_group.api_gw.arn
24+
25+
format = jsonencode({
26+
request_id = "$context.requestId"
27+
source_ip = "$context.identity.sourceIp"
28+
request_time = "$context.requestTime"
29+
protocol = "$context.protocol"
30+
http_method = "$context.httpMethod"
31+
resource_path = "$context.resourcePath"
32+
route_key = "$context.routeKey"
33+
status = "$context.status"
34+
response_length = "$context.responseLength"
35+
integration_error_message = "$context.integrationErrorMessage"
36+
})
37+
}
38+
39+
default_route_settings {
40+
throttling_burst_limit = var.burst_limit_rps
41+
throttling_rate_limit = var.rate_limit_rps
42+
}
43+
}
44+
45+
resource "aws_apigatewayv2_integration" "lambda" {
46+
api_id = aws_apigatewayv2_api.api_gw.id
47+
48+
integration_uri = aws_lambda_function.lambda.invoke_arn
49+
integration_type = "AWS_PROXY"
50+
payload_format_version = "2.0"
51+
timeout_milliseconds = 1000 * local.http_timeout_in_seconds
52+
}
53+
54+
resource "aws_apigatewayv2_route" "lambda" {
55+
api_id = aws_apigatewayv2_api.api_gw.id
56+
route_key = "${var.http_method} ${var.http_route}"
57+
target = "integrations/${aws_apigatewayv2_integration.lambda.id}"
58+
}
59+
60+
resource "aws_lambda_permission" "api_gw" {
61+
statement_id = "AllowExecutionFromAPIGateway"
62+
action = "lambda:InvokeFunction"
63+
function_name = aws_lambda_function.lambda.function_name
64+
principal = "apigateway.amazonaws.com"
65+
source_arn = "${aws_apigatewayv2_api.api_gw.execution_arn}/*/*"
66+
}

cloudwatch.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
resource "aws_cloudwatch_log_group" "lambda" {
2+
name = "/aws/lambda/${aws_lambda_function.lambda.function_name}"
3+
retention_in_days = var.lambda_logs_retention_days
4+
lifecycle {
5+
prevent_destroy = false
6+
}
7+
}
8+
9+
resource "aws_cloudwatch_log_group" "api_gw" {
10+
name = "/aws/api_gw/${aws_apigatewayv2_api.api_gw.name}"
11+
retention_in_days = var.apigw_logs_retention_days
12+
lifecycle {
13+
prevent_destroy = false
14+
}
15+
}

ecr.tf

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
resource "aws_ecr_repository" "ecr_repo" {
2+
name = var.lambda_name
3+
image_tag_mutability = "MUTABLE"
4+
5+
image_scanning_configuration {
6+
scan_on_push = false # additional cost
7+
}
8+
}
9+
10+
resource "aws_ecr_lifecycle_policy" "ecr_repo_lifecycle_policy" {
11+
repository = aws_ecr_repository.ecr_repo.name
12+
13+
policy = jsonencode({
14+
"rules" : [
15+
{
16+
"rulePriority" : 1,
17+
"description" : "Keep last untagged image",
18+
"selection" : {
19+
"tagStatus" : "untagged",
20+
"countType" : "imageCountMoreThan",
21+
"countNumber" : 1
22+
},
23+
"action" : {
24+
"type" : "expire"
25+
}
26+
}
27+
]
28+
})
29+
}
30+
31+
resource "aws_ecr_repository_policy" "ecr_repo_policy" {
32+
repository = aws_ecr_repository.ecr_repo.name
33+
34+
policy = jsonencode({
35+
"Version" : "2008-10-17",
36+
"Statement" : [
37+
{
38+
"Sid" : "LambdaECRImageRetrievalPolicy",
39+
"Effect" : "Allow",
40+
"Principal" : {
41+
"Service" : "lambda.amazonaws.com"
42+
},
43+
"Action" : [
44+
"ecr:BatchGetImage",
45+
"ecr:GetDownloadUrlForLayer"
46+
]
47+
}
48+
]
49+
})
50+
}
51+
52+
data "aws_ecr_image" "ecr_image" {
53+
repository_name = aws_ecr_repository.ecr_repo.name
54+
image_tag = "latest"
55+
}

iam.tf

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
resource "aws_iam_role" "lambda" {
2+
name = "${var.lambda_name}-lambda-role"
3+
assume_role_policy = jsonencode({
4+
"Version" : "2012-10-17",
5+
"Statement" : [
6+
{
7+
"Effect" : "Allow",
8+
"Action" : "sts:AssumeRole",
9+
"Principal" : { "Service" : "lambda.amazonaws.com" }
10+
}
11+
]
12+
})
13+
}
14+
15+
resource "aws_iam_role_policy_attachment" "lambda" {
16+
role = aws_iam_role.lambda.id
17+
policy_arn = aws_iam_policy.lambda_cloudwatch.arn
18+
}
19+
20+
resource "aws_iam_policy" "lambda_cloudwatch" {
21+
name = "${var.lambda_name}-cloudwatch"
22+
policy = data.aws_iam_policy_document.lambda_cloudwatch.json
23+
}
24+
25+
data "aws_iam_policy_document" "lambda_cloudwatch" {
26+
statement {
27+
sid = "CreateCloudWatchLogs"
28+
effect = "Allow"
29+
actions = [
30+
"logs:CreateLogStream",
31+
"logs:PutLogEvents"
32+
]
33+
resources = ["arn:aws:logs:*:*:*"]
34+
}
35+
}

lambda.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "aws_lambda_function" "lambda" {
2+
function_name = var.lambda_name
3+
role = aws_iam_role.lambda.arn
4+
timeout = local.http_timeout_in_seconds - 1
5+
memory_size = var.lambda_memory_MB
6+
architectures = ["x86_64"]
7+
image_uri = "${aws_ecr_repository.ecr_repo.repository_url}@${data.aws_ecr_image.ecr_image.id}"
8+
package_type = "Image"
9+
}

locals.tf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
locals {
2+
http_timeout_in_seconds = 30
3+
}

outputs.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
output "ecr_repo_arn" {
2+
value = aws_ecr_repository.ecr_repo.arn
3+
}
4+
5+
output "lambda_function_arn" {
6+
value = aws_lambda_function.lambda.arn
7+
}

0 commit comments

Comments
 (0)