Model/deployment/terraform/lambda/fast-api/main.tf
Khalim Conn-Kowlessar b6746cc24a Terraform + CI for bulk_document_download: exports bucket, 10GB /tmp, SES SMTP, wiring 🟩
New lambda_with_sqs consumer (timeout 900, memory 3008, ephemeral_storage 10240
for multi-GB ZIPs); dedicated retrofit-document-exports bucket (no lifecycle on
DATA_BUCKET); IAM to read source buckets + write/presign-read the exports
bucket; SES SMTP creds baked from Secrets Manager (no ses:* on the role). Adds
ephemeral_storage_size knob to the shared lambda modules (default 512, backward
compatible). Wires the queue url+arn into fast-api and orders the CI jobs
(ADR-0055).

NOTE: terraform is drafted, not validated (no AWS/terraform in the dev env).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 10:03:50 +00:00

195 lines
7.3 KiB
HCL

############################################
# Load Terraform State
############################################
data "terraform_remote_state" "shared" {
backend = "s3"
config = {
bucket = "assessment-model-terraform-state"
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "engine" {
backend = "s3"
config = {
bucket = "ara-engine-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "categorisation" {
backend = "s3"
config = {
bucket = "categorisation-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "postcode_splitter" {
backend = "s3"
config = {
bucket = "postcode-splitter-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "bulk_address2uprn_combiner" {
backend = "s3"
config = {
bucket = "bulk-address2uprn-combiner-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "bulk_upload_finaliser" {
backend = "s3"
config = {
bucket = "bulk-upload-finaliser-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "landlord_description_overrides" {
backend = "s3"
config = {
bucket = "landlord-description-overrides-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "modelling_e2e" {
backend = "s3"
config = {
bucket = "modelling-e2e-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
data "terraform_remote_state" "bulk_document_download" {
backend = "s3"
config = {
bucket = "bulk-document-download-terraform-state",
key = "env:/${var.stage}/terraform.tfstate"
region = "eu-west-2"
}
}
############################################
# Load Credentials
############################################
data "aws_secretsmanager_secret_version" "db_credentials" {
secret_id = "${var.stage}/assessment_model/db_credentials"
}
locals {
db_credentials = jsondecode(data.aws_secretsmanager_secret_version.db_credentials.secret_string)
}
############################################
# FastAPI Lambda + API Gateway
############################################
module "fastapi" {
source = "../../modules/lambda_with_api_gateway"
name = "fastapi"
stage = var.stage
source_dir = "${path.root}/../../../../"
handler = "backend.app.main.handler"
runtime = "python3.11"
timeout = 600
memory_size = 512
artifact_bucket = data.terraform_remote_state.shared.outputs.ara_fast_api_state_bucket
requirements_file = "${path.root}/../../../../backend/app/requirements/requirements.txt"
domain_name = "api.${var.domain_name}"
environment = {
ENVIRONMENT = var.stage
GITHUB_SHA = var.github_sha
API_KEY = var.api_key
SECRET_KEY = var.secret_key
# DOMAIN_NAME = var.domain_name
EPC_AUTH_TOKEN = var.epc_auth_token
GOOGLE_SOLAR_API_KEY = var.google_solar_api_key
DB_HOST = var.db_host
DB_NAME = var.db_name
DB_PORT = var.db_port
DB_USERNAME = local.db_credentials.db_assessment_model_username
DB_PASSWORD = local.db_credentials.db_assessment_model_password
PLAN_TRIGGER_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_plan_trigger_bucket_name
DATA_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_sap_data_bucket_name
SAP_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_sap_predictions_bucket_name
CARBON_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_carbon_predictions_bucket_name
HEAT_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_heat_predictions_bucket_name
HEATING_KWH_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_heating_kwh_predictions_bucket_name
HOTWATER_KWH_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_hotwater_kwh_predictions_bucket_name
ENERGY_ASSESSMENTS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_energy_assessments_bucket_name
SAP_BASELINE_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_sap_baseline_predictions_bucket_name
CARBON_BASELINE_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_carbon_baseline_predictions_bucket_name
HEAT_BASELINE_PREDICTIONS_BUCKET = data.terraform_remote_state.shared.outputs.retrofit_heat_baseline_predictions_bucket_name
ENGINE_SQS_URL = data.terraform_remote_state.engine.outputs.ara_engine_queue_url
CATEGORISATION_SQS_URL = data.terraform_remote_state.categorisation.outputs.categorisation_queue_url
POSTCODE_SPLITTER_SQS_URL = data.terraform_remote_state.postcode_splitter.outputs.postcode_splitter_queue_url
COMBINER_SQS_URL = data.terraform_remote_state.bulk_address2uprn_combiner.outputs.bulk_address2uprn_combiner_queue_url
FINALISER_SQS_URL = data.terraform_remote_state.bulk_upload_finaliser.outputs.bulk_upload_finaliser_queue_url
LANDLORD_OVERRIDES_SQS_URL = data.terraform_remote_state.landlord_description_overrides.outputs.landlord_description_overrides_queue_url
MODELLING_E2E_SQS_URL = data.terraform_remote_state.modelling_e2e.outputs.modelling_e2e_queue_url
BULK_DOCUMENT_DOWNLOAD_SQS_URL = data.terraform_remote_state.bulk_document_download.outputs.bulk_document_download_queue_url
}
}
############################################
# IAM policy attachments
############################################
# SQS
module "fastapi_sqs_policy" {
source = "../../modules/general_iam_policy"
policy_name = "fastapi-sqs-send-${var.stage}"
policy_description = "Allow FastAPI to send messages to engine & categorisation queues"
actions = [
"sqs:SendMessage"
]
resources = [
data.terraform_remote_state.engine.outputs.ara_engine_queue_arn,
data.terraform_remote_state.categorisation.outputs.categorisation_queue_arn,
data.terraform_remote_state.postcode_splitter.outputs.postcode_splitter_queue_arn,
data.terraform_remote_state.bulk_address2uprn_combiner.outputs.bulk_address2uprn_combiner_queue_arn,
data.terraform_remote_state.bulk_upload_finaliser.outputs.bulk_upload_finaliser_queue_arn,
data.terraform_remote_state.landlord_description_overrides.outputs.landlord_description_overrides_queue_arn,
data.terraform_remote_state.modelling_e2e.outputs.modelling_e2e_queue_arn,
data.terraform_remote_state.bulk_document_download.outputs.bulk_document_download_queue_arn
]
conditions = null
tags = {
Service = "fastapi"
Stage = var.stage
}
}
resource "aws_iam_role_policy_attachment" "fastapi_sqs_send" {
role = module.fastapi.role_name
policy_arn = module.fastapi_sqs_policy.policy_arn
}
# S3
resource "aws_iam_role_policy_attachment" "fastapi_s3_read_and_write" {
role = module.fastapi.role_name
policy_arn = data.terraform_remote_state.shared.outputs.fast_api_s3_read_and_write_arn
}