mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Add ara_export Lambda + SQS terraform module 🟩
Self-contained root module mirroring bulk_document_download (4GB memory per ADR-0065, exports-bucket-only IAM). Cross-module wiring (shared ECR/state, fast-api remote_state + ARA_EXPORT_SQS_URL env, CI image build) still needs a terraform plan review — unverifiable in this environment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8bd9c564dc
commit
30c7133b9a
4 changed files with 174 additions and 0 deletions
84
deployment/terraform/lambda/ara_export/main.tf
Normal file
84
deployment/terraform/lambda/ara_export/main.tf
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
############################################
|
||||
# ara_export Lambda (ADR-0065) — builds one branded sheet-per-scenario .xlsx
|
||||
# from persisted modelling data, uploads it to the exports bucket, and emails a
|
||||
# presigned link. Reads only the DB (no source-bucket reads, unlike
|
||||
# bulk_document_download), so the role needs only exports-bucket write/presign.
|
||||
############################################
|
||||
data "aws_secretsmanager_secret_version" "db_credentials" {
|
||||
secret_id = "${var.stage}/assessment_model/db_credentials"
|
||||
}
|
||||
|
||||
data "aws_secretsmanager_secret_version" "ses_smtp" {
|
||||
secret_id = "${var.stage}/ses/smtp_credentials"
|
||||
}
|
||||
|
||||
locals {
|
||||
db_credentials = jsondecode(data.aws_secretsmanager_secret_version.db_credentials.secret_string)
|
||||
ses_smtp = jsondecode(data.aws_secretsmanager_secret_version.ses_smtp.secret_string)
|
||||
|
||||
document_exports_bucket = "retrofit-document-exports-${var.stage}"
|
||||
}
|
||||
|
||||
############################################
|
||||
# Lambda + SQS queue + trigger
|
||||
############################################
|
||||
module "lambda" {
|
||||
source = "../../modules/lambda_with_sqs"
|
||||
|
||||
name = var.lambda_name
|
||||
stage = var.stage
|
||||
|
||||
image_uri = local.image_uri
|
||||
|
||||
reserved_concurrent_executions = var.reserved_concurrent_executions
|
||||
|
||||
batch_size = var.batch_size
|
||||
maximum_concurrency = var.maximum_concurrency
|
||||
|
||||
timeout = 900
|
||||
# Normal-mode openpyxl holds the workbook in memory (ADR-0065); 4 GB covers the
|
||||
# 100k-property ceiling. Raise here (then switch to write_only) if it OOMs.
|
||||
memory_size = 4096
|
||||
|
||||
environment = {
|
||||
STAGE = var.stage
|
||||
LOG_LEVEL = "info"
|
||||
|
||||
POSTGRES_USERNAME = local.db_credentials.db_assessment_model_username
|
||||
POSTGRES_PASSWORD = local.db_credentials.db_assessment_model_password
|
||||
POSTGRES_HOST = var.db_host
|
||||
POSTGRES_DATABASE = var.db_name
|
||||
POSTGRES_PORT = var.db_port
|
||||
|
||||
DOCUMENT_EXPORTS_BUCKET = local.document_exports_bucket
|
||||
|
||||
# SES SMTP — IAM-user credentials sourced from Secrets Manager (modules/ses).
|
||||
SES_SMTP_HOST = "email-smtp.eu-west-2.amazonaws.com"
|
||||
SES_SMTP_PORT = "587"
|
||||
SES_SMTP_USERNAME = local.ses_smtp.username
|
||||
SES_SMTP_PASSWORD = local.ses_smtp.password
|
||||
SES_SMTP_FROM_ADDRESS = var.ses_from_address
|
||||
}
|
||||
}
|
||||
|
||||
############################################
|
||||
# IAM: write + presign-read the workbook on the dedicated exports bucket.
|
||||
# GetObject is required so the Lambda-signed presigned GET URL resolves.
|
||||
############################################
|
||||
module "s3_exports" {
|
||||
source = "../../modules/s3_iam_policy"
|
||||
|
||||
policy_name = "AraExportS3Exports-${var.stage}"
|
||||
policy_description = "Allow ara_export Lambda to write and presign-read Scenario Exports on the exports bucket"
|
||||
bucket_arns = ["arn:aws:s3:::${local.document_exports_bucket}"]
|
||||
actions = ["s3:PutObject", "s3:GetObject"]
|
||||
resource_paths = ["/*"]
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "s3_exports" {
|
||||
role = module.lambda.role_name
|
||||
policy_arn = module.s3_exports.policy_arn
|
||||
}
|
||||
|
||||
# NOTE: no ses:* on the role — the handler sends over SMTP with the SES IAM-user
|
||||
# credentials injected above.
|
||||
9
deployment/terraform/lambda/ara_export/outputs.tf
Normal file
9
deployment/terraform/lambda/ara_export/outputs.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
output "ara_export_queue_url" {
|
||||
value = module.lambda.queue_url
|
||||
description = "URL of the ara-export SQS queue (FastAPI enqueues jobs here)"
|
||||
}
|
||||
|
||||
output "ara_export_queue_arn" {
|
||||
value = module.lambda.queue_arn
|
||||
description = "ARN of the ara-export SQS queue"
|
||||
}
|
||||
20
deployment/terraform/lambda/ara_export/provider.tf
Normal file
20
deployment/terraform/lambda/ara_export/provider.tf
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = ">= 5.0"
|
||||
}
|
||||
}
|
||||
|
||||
backend "s3" {
|
||||
bucket = "ara-export-terraform-state"
|
||||
key = "terraform.tfstate"
|
||||
region = "eu-west-2"
|
||||
}
|
||||
|
||||
required_version = ">= 1.2.0"
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = "eu-west-2"
|
||||
}
|
||||
61
deployment/terraform/lambda/ara_export/variables.tf
Normal file
61
deployment/terraform/lambda/ara_export/variables.tf
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
variable "lambda_name" {
|
||||
type = string
|
||||
description = "Logical name of the lambda"
|
||||
}
|
||||
|
||||
variable "stage" {
|
||||
description = "Deployment stage (e.g. dev, prod)"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ecr_repo_url" {
|
||||
type = string
|
||||
description = "ECR repository URL (no tag, no digest)"
|
||||
}
|
||||
|
||||
variable "image_digest" {
|
||||
type = string
|
||||
description = "Image digest (sha256:...)"
|
||||
}
|
||||
|
||||
variable "reserved_concurrent_executions" {
|
||||
type = number
|
||||
default = -1
|
||||
description = "Reserved concurrency for the Lambda. -1 = unreserved."
|
||||
}
|
||||
|
||||
variable "maximum_concurrency" {
|
||||
type = number
|
||||
default = 5
|
||||
description = "Maximum concurrent Lambda invocations from the SQS trigger."
|
||||
}
|
||||
|
||||
variable "batch_size" {
|
||||
type = number
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "db_host" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "db_name" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "db_port" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "ses_from_address" {
|
||||
type = string
|
||||
description = "Verified SES sender for Scenario Export notifications (ADR-0059)."
|
||||
default = "noreply@domna.homes"
|
||||
}
|
||||
|
||||
locals {
|
||||
image_uri = "${var.ecr_repo_url}@${var.image_digest}"
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue