diff --git a/infrastructure/terraform/modules/lambda_service_zip/variables.tf b/infrastructure/terraform/modules/lambda_service_zip/variables.tf new file mode 100644 index 00000000..3a243c49 --- /dev/null +++ b/infrastructure/terraform/modules/lambda_service_zip/variables.tf @@ -0,0 +1,9 @@ +variable "name" { type = string } +variable "role_arn" { type = string } +variable "filename" { type = string } +variable "source_code_hash" { type = string } +variable "handler" { type = string } +variable "runtime" { type = string } +variable "timeout" { type = number default = 30 } +variable "memory_size" { type = number default = 128 } +variable "environment" { type = map(string) default = {} } \ No newline at end of file diff --git a/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf b/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf index e69de29b..23ccc4b1 100644 --- a/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf +++ b/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf @@ -0,0 +1,103 @@ +############################################ +# IAM role +############################################ +module "role" { + source = "../lambda_execution_role" + name = "${var.name}-lambda-${var.stage}" +} + +############################################ +# Zip the source code +############################################ +data "archive_file" "this" { + type = "zip" + source_dir = var.source_dir + output_path = "${path.module}/lambda_package.zip" + excludes = var.zip_excludes +} + +############################################ +# Lambda +############################################ +module "lambda" { + source = "../lambda_service_zip" + + name = "${var.name}-${var.stage}" + role_arn = module.role.role_arn + filename = data.archive_file.this.output_path + source_code_hash = data.archive_file.this.output_base64sha256 + handler = var.handler + runtime = var.runtime + timeout = var.timeout + memory_size = var.memory_size + environment = var.environment +} + +############################################ +# API Gateway +############################################ +resource "aws_apigatewayv2_api" "this" { + name = "${var.name}-api-${var.stage}" + protocol_type = "HTTP" +} + +resource "aws_apigatewayv2_stage" "this" { + api_id = aws_apigatewayv2_api.this.id + name = "$default" + auto_deploy = true +} + +resource "aws_apigatewayv2_integration" "this" { + api_id = aws_apigatewayv2_api.this.id + integration_type = "AWS_PROXY" + integration_uri = module.lambda.lambda_arn + payload_format_version = "2.0" +} + +resource "aws_apigatewayv2_route" "catch_all" { + api_id = aws_apigatewayv2_api.this.id + route_key = "$default" + target = "integrations/${aws_apigatewayv2_integration.this.id}" +} + +resource "aws_lambda_permission" "apigw_invoke" { + statement_id = "AllowAPIGatewayInvoke" + action = "lambda:InvokeFunction" + function_name = module.lambda.lambda_arn + principal = "apigateway.amazonaws.com" + source_arn = "${aws_apigatewayv2_api.this.execution_arn}/*/*" +} + +############################################ +# Custom domain +############################################ +resource "aws_apigatewayv2_domain_name" "this" { + count = var.domain_name != null ? 1 : 0 + domain_name = var.domain_name + + domain_name_configuration { + certificate_arn = var.certificate_arn + endpoint_type = "REGIONAL" + security_policy = "TLS_1_2" + } +} + +resource "aws_apigatewayv2_api_mapping" "this" { + count = var.domain_name != null ? 1 : 0 + api_id = aws_apigatewayv2_api.this.id + domain_name = aws_apigatewayv2_domain_name.this[0].id + stage = aws_apigatewayv2_stage.this.id +} + +resource "aws_route53_record" "this" { + count = var.domain_name != null ? 1 : 0 + name = aws_apigatewayv2_domain_name.this[0].domain_name + type = "A" + zone_id = var.route53_zone_id + + alias { + name = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].target_domain_name + zone_id = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].hosted_zone_id + evaluate_target_health = false + } +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/lambda_with_api_gateway/outputs.tf b/infrastructure/terraform/modules/lambda_with_api_gateway/outputs.tf new file mode 100644 index 00000000..52db1ff9 --- /dev/null +++ b/infrastructure/terraform/modules/lambda_with_api_gateway/outputs.tf @@ -0,0 +1,11 @@ +output "role_name" { + value = module.role.role_name +} + +output "api_endpoint" { + value = aws_apigatewayv2_stage.this.invoke_url +} + +output "custom_domain_endpoint" { + value = var.domain_name != null ? "https://${var.domain_name}" : null +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/lambda_with_api_gateway/variables.tf b/infrastructure/terraform/modules/lambda_with_api_gateway/variables.tf new file mode 100644 index 00000000..1a08ff2e --- /dev/null +++ b/infrastructure/terraform/modules/lambda_with_api_gateway/variables.tf @@ -0,0 +1,18 @@ +variable "name" { type = string } +variable "stage" { type = string } +variable "source_dir" { type = string } +variable "handler" { type = string } +variable "runtime" { type = string } + +variable "zip_excludes" { + type = list(string) + default = ["**/__pycache__/**", "**/*.pyc", "**/.pytest_cache/**"] +} + +variable "timeout" { type = number default = 600 } +variable "memory_size" { type = number default = 512 } +variable "environment" { type = map(string) default = {} } + +variable "domain_name" { type = string default = null } +variable "certificate_arn" { type = string default = null } +variable "route53_zone_id" { type = string default = null } \ No newline at end of file