fix(terraform/platform): quote acdl: tags + fix Lambda + replace interpolation
acdl-ci / Lint (pull_request) Successful in 7s
acdl-ci / Test (pull_request) Successful in 4m5s
acdl-ci / Platform check-only (offline) (pull_request) Successful in 21s
acdl-modules-lifecycle / Platform VPC apply (pull_request) Failing after 42s
acdl-modules-lifecycle / L1 lifecycle (alb) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (cloudfront) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (ecr) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (ecs-cluster) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (ecs-service) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (iam-role) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (kms-key) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (rds) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (s3) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (uptime) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (vpc) (pull_request) Has been skipped
acdl-modules-lifecycle / L1 lifecycle (waf) (pull_request) Has been skipped
acdl-modules-lifecycle / Platform VPC destroy (pull_request) Successful in 48s

3 fixes in terraform/platform/main.tf that prevented terraform validate
from passing in CI:

1. All 40 acdl:owner/contract/environment/cost-center tag keys were
   unquoted (acdl:owner = ...). HCL requires quoting keys with colons.
   Fixed to "acdl:owner" = ...

2. filebase64sha256("contract_ingestor.zip") failed when the zip didn't
   exist (it's a build artifact). Wrapped with fileexists() guard.

3. ${account_id} and ${region} in the replace() call were interpreted
   as Terraform interpolation, not literal strings. Escaped as
   $${account_id} and $${region}.

Platform terraform now passes terraform validate.

---ci---
project: acdl
phase: P59
milestone: v1.11
status: execute
---/ci---
This commit is contained in:
Jon Chery
2026-07-28 16:42:17 +00:00
parent 315a86d396
commit 2f8c0203be
+57 -57
View File
@@ -31,8 +31,8 @@ provider "aws" {
# KMS customer-managed key for DynamoDB SSE + SSM Parameter Store encryption
resource "aws_kms_key" "acdl_platform" {
description = "ACDL platform KMS key (DynamoDB SSE + SSM + Secrets Manager)"
enable_key_rotation = true
description = "ACDL platform KMS key (DynamoDB SSE + SSM + Secrets Manager)"
enable_key_rotation = true
deletion_window_in_days = 30
}
@@ -43,7 +43,7 @@ resource "aws_kms_alias" "acdl_platform" {
# DynamoDB table for contract ingestion
resource "aws_dynamodb_table" "acdl_contracts" {
name = "acdl-contracts"
name = "acdl-contracts"
billing_mode = "PAY_PER_REQUEST"
hash_key = "consumerRepo"
range_key = "contractId#submittedAt"
@@ -68,10 +68,10 @@ resource "aws_dynamodb_table" "acdl_contracts" {
}
tags = {
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "prod"
acdl:cost-center = "acdl-default"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "prod"
"acdl:cost-center" = "acdl-default"
}
}
@@ -82,10 +82,10 @@ resource "aws_secretsmanager_secret" "github_token" {
kms_key_id = aws_kms_key.acdl_platform.arn
tags = {
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "prod"
acdl:cost-center = "acdl-default"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "prod"
"acdl:cost-center" = "acdl-default"
}
}
@@ -139,12 +139,12 @@ resource "aws_iam_role_policy" "lambda_permissions" {
# Lambda function
resource "aws_lambda_function" "contract_ingestor" {
function_name = "acdl-contract-ingestor"
handler = "contract_ingestor.lambda_handler"
runtime = "python3.12"
role = aws_iam_role.lambda_exec.arn
filename = "contract_ingestor.zip"
source_code_hash = filebase64sha256("contract_ingestor.zip")
function_name = "acdl-contract-ingestor"
handler = "contract_ingestor.lambda_handler"
runtime = "python3.12"
role = aws_iam_role.lambda_exec.arn
filename = "contract_ingestor.zip"
source_code_hash = fileexists("contract_ingestor.zip") ? filebase64sha256("contract_ingestor.zip") : "placeholder"
environment {
variables = {
@@ -155,17 +155,17 @@ resource "aws_lambda_function" "contract_ingestor" {
}
tags = {
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "prod"
acdl:cost-center = "acdl-default"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "prod"
"acdl:cost-center" = "acdl-default"
}
}
# Lambda Function URL (IAM auth — consumers invoke via SigV4)
resource "aws_lambda_function_url" "contract_ingestor" {
function_name = aws_lambda_function.contract_ingestor.function_name
authorization_type = "AWS_IAM"
authorization_type = "AWS_IAM"
}
# P1-6: Render the consumer invoke policy with the live AWS account ID.
@@ -179,8 +179,8 @@ data "aws_region" "current" {}
locals {
invoke_policy_template = file("${path.module}/consumer_invoke_policy.json")
rendered_invoke_policy = replace(
replace(local.invoke_policy_template, "${account_id}", data.aws_caller_identity.current.account_id),
"${region}", data.aws_region.current.name
replace(local.invoke_policy_template, "$${account_id}", data.aws_caller_identity.current.account_id),
"$${region}", data.aws_region.current.name
)
}
@@ -216,10 +216,10 @@ resource "aws_dynamodb_table" "acdl_change_requests" {
}
tags = {
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "prod"
acdl:cost-center = "acdl-default"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "prod"
"acdl:cost-center" = "acdl-default"
}
}
# REQ-107: SNS topic for separation-of-duties halt artifacts.
@@ -228,10 +228,10 @@ resource "aws_sns_topic" "acdl_sod_halt" {
name = "acdl-sod-halt"
kms_master_key_id = aws_kms_key.acdl_platform.id
tags = {
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "prod"
acdl:cost-center = "acdl-default"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "prod"
"acdl:cost-center" = "acdl-default"
}
}
@@ -247,11 +247,11 @@ output "acdl_sod_halt_topic_arn" {
resource "aws_vpc" "acdl_shared" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "acdl-shared"
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "shared"
acdl:cost-center = "acdl-default"
Name = "acdl-shared"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "shared"
"acdl:cost-center" = "acdl-default"
}
}
@@ -261,11 +261,11 @@ resource "aws_subnet" "acdl_shared" {
cidr_block = cidrsubnet(aws_vpc.acdl_shared.cidr_block, 8, count.index + 1)
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "acdl-shared-subnet-${count.index}"
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "shared"
acdl:cost-center = "acdl-default"
Name = "acdl-shared-subnet-${count.index}"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "shared"
"acdl:cost-center" = "acdl-default"
}
}
@@ -276,11 +276,11 @@ data "aws_availability_zones" "available" {
resource "aws_internet_gateway" "acdl_shared" {
vpc_id = aws_vpc.acdl_shared.id
tags = {
Name = "acdl-shared-igw"
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "shared"
acdl:cost-center = "acdl-default"
Name = "acdl-shared-igw"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "shared"
"acdl:cost-center" = "acdl-default"
}
}
@@ -291,11 +291,11 @@ resource "aws_route_table" "acdl_shared" {
gateway_id = aws_internet_gateway.acdl_shared.id
}
tags = {
Name = "acdl-shared-rt"
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "shared"
acdl:cost-center = "acdl-default"
Name = "acdl-shared-rt"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "shared"
"acdl:cost-center" = "acdl-default"
}
}
@@ -325,11 +325,11 @@ resource "aws_security_group" "ecs" {
}
tags = {
Name = "acdl-ecs-sg"
acdl:owner = "acdl"
acdl:contract = "platform"
acdl:environment = "shared"
acdl:cost-center = "acdl-default"
Name = "acdl-ecs-sg"
"acdl:owner" = "acdl"
"acdl:contract" = "platform"
"acdl:environment" = "shared"
"acdl:cost-center" = "acdl-default"
}
}