# terraform/aws/region

Root Terraform module that provisions an **Aurora RDS cluster** inside a dedicated VPC for a single AWS region. Supports three connectivity modes (public, RDS Proxy via NLB/VPC Endpoint Service, VPC Lattice Resource Gateway) selected automatically or explicitly.

## Purpose and wiring

- `account.tf` — reads `seed_account` and `shoot_accounts` from S3 state (`aws/account/seed/${var.env}.json` and `aws/account/shoot/${var.env}-*`). The `seed_account` value becomes the AWS CLI profile used for all target-region resources.
- `rds.tf` — VPC (terraform-aws-modules/vpc ~6.0), RDS cluster (two variants: `managed_password` / `self_managed_password`), PrivateLink infrastructure.
- `secret.tf` — for non-`us-west-2` deployments, copies two secrets (`clinic-auto-deploy-token`, `${env}-proxy-auth0-client`) from `us-west-2` via `aws.source` provider.
- `migration/` — submodule that calculates AZ exclusion lists and sg ingress CIDRs; holds migration state for regions already transitioned (currently `eu-central-1` bypasses AZ exclusion).
- `lambda_rds_proxy_updater.py` — zipped at apply time by `archive_file`; resolves RDS Proxy DNS and syncs IPs to NLB target group every 5 minutes via EventBridge.

## PrivateLink selection logic

| `publicly_accessible` | `privatelink_type` | Result |
|---|---|---|
| `true` | any | Direct public RDS endpoint |
| `false` | `auto` | VPC Lattice Resource Gateway if region is in `vpc_lattice_region_unsupported_azs` keys, else RDS Proxy |
| `false` | `resource-gateway` | Forces Resource Gateway; fails if region unsupported |
| `false` | `rds-proxy` | Forces RDS Proxy NLB + VPC Endpoint Service path |

## Required variables (no defaults)

- `name` — name suffix for all resources
- `vpc` — object; `cidr` defaults to `192.168.0.0/16`, but the object itself must be provided
- `db` — object; all fields optional with defaults (`db.t3.micro`, `aurora-mysql 8.0`, 1 instance, port 3306)

## Key non-obvious constraints

- **Deletion protection is ON** for both RDS cluster variants. `terraform destroy` requires manually setting `deletion_protection = false` first (or `-target` to remove it).
- **`cluster_members` is ignored** on both clusters — instances are managed by `aws_rds_cluster_instance` separately.
- **`terraform.tf` calls `git rev-parse HEAD`** via `data.local_command`; must run from inside a git repo or this data source errors.
- **`lambda_rds_proxy_updater.zip`** is generated in-place at apply time — never commit it.
- **Subnets**: `/16` VPC CIDR split into `/19` subnets (3-bit offset); public subnets at cidrsubnets offsets 0–2, private at 4–6.
- **Secret replication skipped for `us-west-2`** — `secret_set` is empty when `var.region == "us-west-2"`.

## State backend

- Bucket: `autonomous-deployment-terraform-state` (us-west-2)
- State key: set by the caller (workspace or `-backend-config`)
- Lock: native S3 lockfile (`use_lockfile = true`)

## Example var file

See [`test.tfvars`](test.tfvars) for a real region deployment example (Aurora MySQL 8.0, `ap-south-1`, publicly accessible, with cluster params).

## Providers required

Three provider configurations are used:

| Alias | Profile | Region | Purpose |
|---|---|---|---|
| `tf_state` | `default` | `us-west-2` | Read state bucket and source secrets |
| _(default)_ | `local.seed_account` | `var.region` | All target-region resources |
| `source` | `local.seed_account` | `us-west-2` | Read secrets to replicate |

`local.seed_account` is resolved at plan time from S3 — the `default` AWS profile must have read access to the state bucket before `terraform plan`.

## resolve-ip.sh

Standalone DNS-poll utility. Reads `{"dns_name":"..."}` from stdin, retries up to 30× (10 s sleep), prints `{"ip":"<resolved>"}` on success. Not called by Terraform directly; used externally.

## Related Documentation

- [migration/main.tf](migration/main.tf) — AZ exclusion and ingress CIDR migration logic (source of truth, no separate doc)
