-
Notifications
You must be signed in to change notification settings - Fork 0
variable system
How config flows from Root Module to child modules.
-
Structured objects: Top-level variables are typed
object({})withoptional()attributes and defaults -
Null-disabling: Setting a component to
nulldisables it entirely - Extensive validation: Regex patterns, numeric ranges, cross-field checks, Fargate CPU/memory matrix
- Sensible defaults: Most attributes have defaults; only a few are truly required
| Variable | Type | Validation |
|---|---|---|
project_name |
string | 2-32 chars, lowercase alphanumeric + hyphens |
environment |
string | 2-16 chars, same pattern |
region |
string | AWS region format (e.g. us-east-1) |
| Variable | Default | Controls |
|---|---|---|
vpc |
{ create = true } |
VPC Module |
storage |
null (disabled; supply object to enable) |
Storage Module |
database |
Must provide min/max capacity | Database Module |
brms |
Must provide cpu, memory, domain, etc. | BRMS in ECS Module |
agent |
Must provide cpu, memory, etc. | Agent in ECS Module |
Leaving storage unset (its null default) disables storage creation, matching database, brms, and agent. When a non-null storage object is supplied, its inner attributes default to create_bucket = true and auth = "iam".
flowchart TD
subgraph VPC Flow
varVPC[var.vpc] --> modVPC["module.vpc[0]"]
modVPC -->|"outputs: vpc_id, subnet_ids"| localsVPC["locals.tf\nvpc_id, private_subnet_ids,\npublic_subnet_ids"]
localsVPC --> modDB["module.database[0]\nvpc_id, private_subnet_ids"]
localsVPC --> modECS1["module.ecs[0]\nvpc_id, all subnet_ids"]
end
subgraph Storage Flow
varStorage[var.storage] --> modStorage["module.storage[0]"]
modStorage -->|"outputs: bucket_name,\niam_policy_arns"| localsStorage["locals.tf\nbucket_name, bucket_arn"]
localsStorage --> modECS2["module.ecs[0]\nstorage config + IAM policies"]
end
subgraph Database Flow
varDB[var.database] --> modDB2["module.database[0]"]
modDB2 -->|"outputs: endpoint,\ncredentials_secret_arn"| rootMain["root main.tf"]
rootMain --> modECS3["module.ecs[0]\ndatabase config, BRMS only"]
end
subgraph Services
varBRMS[var.brms / var.agent] --> modECS4["module.ecs[0]\nfull config objects"]
end
The locals.tf file acts as a routing layer, resolving whether to use created or existing resources:
# VPC routing
local.vpc_id = local.create_vpc ? module.vpc[0].vpc_id : var.vpc.id
local.private_subnet_ids = local.create_vpc ? module.vpc[0].private_subnet_ids : var.vpc.private_subnet_ids
# Storage routing
local.bucket_name = local.create_bucket ? module.storage[0].bucket_name : var.storage.existing_bucket_name
# AZ selection
local.availability_zones = var.vpc != null && length(var.vpc.availability_zones) > 0 ? var.vpc.availability_zones : slice(data.aws_availability_zones.available.names, 0, 2)Two derived locals also drive provisioning decisions:
-
local.needs_public_subnetsis true when any enabled component hasalb_internal = false(the default). It controlscreate_public_subnetspassed to the VPC module and the public-subnet precondition invpc_validation. -
local.vpc_additional_endpointscomputes extra interface VPC endpoints to provision:kmswhenbrms.secrets_provider.type = "aws-kms",bedrock-runtimewhenbrms.ai.provider = "amazon-bedrock", plus anyvpc.additional_vpc_endpoints. It is passed to the VPC module asadditional_interface_endpoints.
validation {
condition = can(regex("^[a-z][a-z0-9-]*[a-z0-9]$", var.project_name))
error_message = "Must be lowercase alphanumeric with hyphens."
}Complex cross-field validation ensuring valid Fargate combinations. Memory must be one of the discrete values below (1024 MiB increments for the lower tiers, larger increments at the top), not any value in the range:
| CPU (units) | Valid Memory (MiB) | Increment |
|---|---|---|
| 256 | 512, 1024, 2048 | discrete |
| 512 | 1024, 2048, 3072, 4096 | 1024 |
| 1024 | 2048, 3072, 4096, 5120, 6144, 7168, 8192 | 1024 |
| 2048 | 4096 - 16384 | 1024 |
| 4096 | 8192 - 30720 | 1024 |
| 8192 | 16384 - 61440 | 4096 |
| 16384 | 32768 - 122880 | 8192 |
min_count <= max_count- Auto-pause requires
min_capacity = 0 - BRMS HTTPS:
route53_zone_idORcertificate_arn, unlessalb_http_only = true - Agent: when
domainis set,route53_zone_idORcertificate_arn, unlessalb_http_only = true -
alb_http_only = truerequiresalb_internal = true(brms and agent) -
alb_idle_timeoutmust be between 1 and 4000 seconds (brms and agent) - Azure OpenAI requires
azure_resource_name - AI API key required unless provider is
amazon-bedrock
name_prefix = "{project_name}-{environment}"
All resources follow: {project_name}-{environment}-{component}
Examples: gorules-prod-brms-alb, gorules-staging-aurora-sg
All resources get merged tags:
default_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
# The vpc, storage, and ecs modules add: Module = "<module_name>"
# (the database module does not add a Module tag)
# All modules merge with user-provided var.tags