# terraform/alicloud

Root of all Terraform for Alibaba Cloud infrastructure. Contains independent root modules (each has its own `backend "s3"` config and must be `init`-ed separately) and shared module libraries.

## Directory map

| Path | Type | Purpose |
|---|---|---|
| `account/seed/` | root module | Provisions seed (controlplane) Alibaba Cloud account metadata; outputs `seed_account` + `base_account` |
| `account/shoot/` | root module | Provisions shoot (dataplane) account metadata; outputs `shoot_account`, `seed_account`, `plan` |
| `account/o11y/` | root module | Provisions observability account metadata; outputs `regional_account` + `global_account` |
| `region/` | root module | Provisions per-region VPC + RDS MySQL for the seed/shoot accounts (non-o11y) |
| `o11y-region-shared/` | root module | Provisions shared o11y region infra: VPC, KMS, RDS, secrets |
| `o11y-region/` | root module | Provisions a full o11y ACK cluster + in-cluster services for a region |
| `premium/` | root module | Provisions a Premium (`DEPLOY_TYPE_NEXTGEN`) seed ACK cluster + all services |
| `alicloud_modules/` | reusable modules | Shared Terraform modules (RAM roles, AWS OIDC provider, Crossplane, shared-bandwidth) |

## Shared backend and state conventions

- **All root modules** use S3 backend: bucket `autonomous-deployment-terraform-state`, region `us-west-2`, native S3 locking (`use_lockfile = true`).
- The state key is **never hardcoded** in `terraform.tf`; it must be provided at init time:
  ```sh
  terraform init -backend-config="key=alicloud/<module>/<env>/<name>.json"
  ```
- All modules read remote state from the same S3 bucket via an `aws.tf_state` provider alias (profile `default`, region `us-west-2`).

## Typical workflow (per root module)

```sh
terraform init -backend-config="key=alicloud/<module-path>/<env>.json"
terraform plan  -var-file=test.tfvars   # or a real vars file
terraform apply -var-file=test.tfvars
```

Each module ships a `test.tfvars` with a working example (usually targeting `prod` or `staging`).

## Account resolution pattern

Every root module resolves account IDs at plan time by reading upstream S3 state objects — never via hardcoded values:

- `account/seed` → read by `region/`, `premium/`, `account/shoot/`
- `account/shoot` → read by `region/` (via prefix scan for all shoot states under an env)
- `account/o11y` → read by `o11y-region/`, `o11y-region-shared/`

## Module-specific constraints

- **`region/`**: `ap-southeast-1` is explicitly blocked (`check` assertion in `vars.tf`) — that region is managed separately.
- **`region/`**: RDS instance type is auto-selected from AliCloud data source; `myduck`-prefixed instance classes are explicitly filtered out (separate product requiring subscription).
- **`o11y-region/`**: Requires exactly 3 `zone_ids`. ACR provider alias is always `ap-southeast-1` regardless of `cloud_region`.
- **`premium/`**: See [premium/AGENTS.md](premium/AGENTS.md) for the full constraint list, including the 3-dataplane-account maximum, Argo Workflows deploy pattern, and pre-existing RAM role requirements.

## Kubeconfig handling (o11y-region, premium)

Kubeconfig is written to `/tmp/<cluster_name>-kubeconfig` during apply by the `kubeconfig` module. All `helm`, `kubernetes`, and `kubectl` providers in the same run consume it via `config_path`. It is not persisted.

## `alicloud_modules/` structure

Reusable modules consumed by the root modules above (not standalone):

- `ram/` — RAM role sub-modules: `cert-manager/`, `dataplane-manager/`, `external-secrets-operator/`
- `aws/` — AWS-side modules: `oidc-provider/`, `crossplane-aws-provider/`, `aws_modules/`
- `service-quota/` — AliCloud service quota management (has local state; not remote-backed)
- `shared-bandwidth/` — Shared bandwidth package module (consumed by `premium/`)

## Related Documentation

- [premium/AGENTS.md](premium/AGENTS.md)
- [../../.github/AGENTS.md](../../.github/AGENTS.md)
