Model/deployment/terraform/lambda/fast-api/main.tf
Jun-te Kim adb1bf4b56 Log GITHUB_SHA on /health; move zip-size gate to its own PR workflow
/health already returned GITHUB_SHA in its response but never logged
it, and the fastapi lambda's Terraform environment never actually set
GITHUB_SHA — so every health check response contained "unknown" in
production. Wire var.github_sha through the fastapi lambda module
(default "unknown" for local/other invocations) via a new
TF_VAR_github_sha env var set from `github.sha` in
_deploy_lambda.yml's Terraform Plan step, and log it on every /health
call so a request in CloudWatch can be tied back to the deploy that
served it.

Also fix the zip-size gate added for PR #1469: putting it in
tests/test_lambda_zip_size.py (run via the Docker-based ddd_tests.yml
suite) broke CI, because Dockerfile.test's build context excludes
deployment/* (.dockerignore), so check_lambda_zip_size.py couldn't
find variables.tf to read zip_excludes from inside that container.
Move the check to its own lightweight workflow,
check_lambda_zip_size.yml, triggered on pull_request into main — a
plain checkout (no Docker build) has the full repo, so the check
works, runs fast, and still gates merges to main before a regression
can roll into the dev deploy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 13:43:36 +00:00

161 lines
6 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"
}
}
############################################
# 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
}
}
############################################
# 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
]
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
}