Last active
November 27, 2022 23:14
-
-
Save elvisciotti/a30ab0cd46e2eb16546e74c2199d966b to your computer and use it in GitHub Desktop.
AWS node function deployed with Terraform - complete example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
function shuffle(array) { | |
let currentIndex = array.length, temporaryValue, randomIndex; | |
// While there remain elements to shuffle... | |
while (0 !== currentIndex) { | |
// Pick a remaining element... | |
randomIndex = Math.floor(Math.random() * currentIndex); | |
currentIndex -= 1; | |
// And swap it with the current element. | |
temporaryValue = array[currentIndex]; | |
array[currentIndex] = array[randomIndex]; | |
array[randomIndex] = temporaryValue; | |
} | |
return array; | |
} | |
const QUOTE_ENTRIES = [ | |
'If you are not ashamed of what you were 1 year ago, then you have not improved much', | |
'Success is determined by how well you manage failures', | |
'The egg has a perfect shape, even if it\'s laid from the ass', | |
'Those who know everything learn nothing' | |
]; | |
function http200Response(event, data) { | |
return { | |
statusCode: 200, | |
body: JSON.stringify({ | |
data: data, | |
event: event.queryStringParameters | |
}, | |
null, | |
2 | |
) | |
}; | |
} | |
module.exports.handler = async (event) => { | |
const action = event.queryStringParameters.action; | |
const limit = event.queryStringParameters.limit ? parseInt(event.queryStringParameters.limit) : 10; | |
switch (action) { | |
case 'random-quote': | |
const gratitudeItems = shuffle(QUOTE_ENTRIES); | |
return http200Response( | |
event, | |
gratitudeItems.slice(0, limit) | |
); | |
case 'today-date': | |
return http200Response( | |
event, | |
new Date() | |
); | |
} | |
return { | |
statusCode: 404, | |
body: "action not implemented" | |
}; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://learn.hashicorp.com/tutorials/terraform/lambda-api-gateway | |
terraform { | |
required_providers { | |
aws = { | |
source = "hashicorp/aws" | |
version = "~> 4.0.0" | |
} | |
random = { | |
source = "hashicorp/random" | |
version = "~> 3.1.0" | |
} | |
archive = { | |
source = "hashicorp/archive" | |
version = "~> 2.2.0" | |
} | |
} | |
required_version = "~> 1.0" | |
} | |
provider "aws" { | |
region = "us-east-1" | |
shared_credentials_files = [ | |
"/Users/elvisciotti/.aws/credentials" | |
] | |
profile = "elvis" | |
} | |
resource "random_pet" "lambda_bucket_name" { | |
prefix = "ec-notes" | |
length = 4 | |
} | |
resource "aws_s3_bucket" "lambda_bucket" { | |
bucket = random_pet.lambda_bucket_name.id | |
# bucket = "EcNotesLambdaProd" | |
# acl = "private" | |
force_destroy = true | |
} | |
######################################### | |
# zip upload into bucket | |
######################################### | |
data "archive_file" "lambda_notes" { | |
type = "zip" | |
source_dir = "${path.module}" | |
output_path = "/tmp/ec-notes.zip" | |
excludes = [ | |
".git", | |
".gitattributes", | |
".gitignore", | |
".idea", | |
".jshintrc", | |
".terraform", | |
".terraform.lock.hcl" | |
] | |
} | |
resource "aws_s3_object" "lambda_ec_notes" { | |
bucket = aws_s3_bucket.lambda_bucket.id | |
key = "ec-notes.zip" | |
source = data.archive_file.lambda_notes.output_path | |
etag = filemd5(data.archive_file.lambda_notes.output_path) | |
} | |
######################################### | |
# define your Lambda function and related resources. | |
######################################### | |
resource "aws_lambda_function" "ec_notes_random_notes" { | |
function_name = "EcNotesRandomNotes" | |
s3_bucket = aws_s3_bucket.lambda_bucket.id | |
s3_key = aws_s3_object.lambda_ec_notes.key | |
runtime = "nodejs12.x" | |
handler = "handler.handler" | |
source_code_hash = data.archive_file.lambda_notes.output_base64sha256 | |
role = aws_iam_role.lambda_exec.arn | |
} | |
# log group to store log messages from your Lambda function for 2 days | |
resource "aws_cloudwatch_log_group" "ec_random_notes" { | |
name = "/aws/lambda/${aws_lambda_function.ec_notes_random_notes.function_name}" | |
retention_in_days = 1 | |
} | |
# IAM role that allows Lambda to access resources in your AWS account. | |
resource "aws_iam_role" "lambda_exec" { | |
name = "serverless_lambda" | |
assume_role_policy = jsonencode({ | |
Version = "2012-10-17" | |
Statement = [{ | |
Action = "sts:AssumeRole" | |
Effect = "Allow" | |
Sid = "" | |
Principal = { | |
Service = "lambda.amazonaws.com" | |
} | |
} | |
] | |
}) | |
} | |
# attaches a policy the IAM role | |
resource "aws_iam_role_policy_attachment" "lambda_policy" { | |
role = aws_iam_role.lambda_exec.name | |
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" | |
} | |
######################################### | |
# gateway | |
######################################### | |
# defines a name for the API Gateway and sets its protocol to HTTP. | |
resource "aws_apigatewayv2_api" "lambda" { | |
name = "serverless_lambda_gw" | |
protocol_type = "HTTP" | |
} | |
# application single stage (test/prod...) for the API Gateway | |
resource "aws_apigatewayv2_stage" "lambda" { | |
api_id = aws_apigatewayv2_api.lambda.id | |
name = "prod" | |
auto_deploy = true | |
access_log_settings { | |
destination_arn = aws_cloudwatch_log_group.api_gw.arn | |
format = jsonencode({ | |
requestId = "$context.requestId" | |
sourceIp = "$context.identity.sourceIp" | |
requestTime = "$context.requestTime" | |
protocol = "$context.protocol" | |
httpMethod = "$context.httpMethod" | |
resourcePath = "$context.resourcePath" | |
routeKey = "$context.routeKey" | |
status = "$context.status" | |
responseLength = "$context.responseLength" | |
integrationErrorMessage = "$context.integrationErrorMessage" | |
} | |
) | |
} | |
} | |
# configures the API Gateway to use your Lambda function. | |
resource "aws_apigatewayv2_integration" "ec_random_notes" { | |
api_id = aws_apigatewayv2_api.lambda.id | |
integration_uri = aws_lambda_function.ec_notes_random_notes.invoke_arn | |
integration_type = "AWS_PROXY" | |
integration_method = "POST" | |
} | |
# maps an HTTP request to a target, in | |
resource "aws_apigatewayv2_route" "ec_random_notes" { | |
api_id = aws_apigatewayv2_api.lambda.id | |
route_key = "GET /notes" | |
target = "integrations/${aws_apigatewayv2_integration.ec_random_notes.id}" | |
} | |
# log group to store access logs f | |
resource "aws_cloudwatch_log_group" "api_gw" { | |
name = "/aws/api_gw/${aws_apigatewayv2_api.lambda.name}" | |
retention_in_days = 1 | |
} | |
# API Gateway permission to invoke your Lambda function. | |
resource "aws_lambda_permission" "api_gw_random_notes" { | |
statement_id = "AllowExecutionFromAPIGateway" | |
action = "lambda:InvokeFunction" | |
function_name = aws_lambda_function.ec_notes_random_notes.function_name | |
principal = "apigateway.amazonaws.com" | |
source_arn = "${aws_apigatewayv2_api.lambda.execution_arn}/*/*" | |
} | |
# Output value definitions | |
output "lambda_bucket_name" { | |
description = "Name of the S3 bucket used to store function code." | |
value = aws_s3_bucket.lambda_bucket.id | |
} | |
output "function_name" { | |
description = "Name of the EC notes random Lambda function." | |
value = aws_lambda_function.ec_notes_random_notes.function_name | |
} | |
output "base_url_random_quote" { | |
description = "random quote" | |
value = "curl ${aws_apigatewayv2_stage.lambda.invoke_url}/notes?action=random-quote" | |
} | |
output "base_url_today_date" { | |
description = "today-date" | |
value = "curl ${aws_apigatewayv2_stage.lambda.invoke_url}/notes?action=today-date" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# init (just once) | |
terraform init | |
# preview | |
terraform plan | |
# deploy with confirmation | |
terraform apply | |
# deploy without confirmation | |
# terraform apply -auto-approve |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment