# terraform/aws/byoc/seed

Child Terraform module for the **seed (control plane) AWS account** in a BYOC region. Provisions an EKS cluster, VPC, IAM roles, RDS databases, and all in-cluster services. Invoked by the parent `../` root module — **not applied directly**.

See [../AGENTS.md](../AGENTS.md) for workflow, backend config, provider aliases, and cross-module dependencies.

## Cluster naming

`{env}-seed-{logical_region_name}` — e.g. `dev-seed-us-west-2`.

Kubeconfig written to `/tmp/{cluster_name}-kubeconfig` during apply.

## In-cluster service pattern

Every service in this module follows the same pattern via `../../../modules/app`:

```hcl
module "foo" {
  source          = "../../../modules/app"
  kubeconfig_path = module.kubeconfig.path
  workflow        = "deploy-new-region-next-gen-foo.yaml"   # ArgoCD workflow name
  parameters      = { env, logicalRegionName, cluster, region, cloud, additionalArgs }
  services        = [{ name, namespace, wait_for }]
}
```

`services` entries block apply until readiness conditions pass (e.g. `jsonpath='{.status.availableReplicas}'=REPLICAS`).

## Additional remote state dependencies

Beyond what the parent documents, `seed` also reads:

| Key | Used for |
|---|---|
| `aws/devops/{env}.json` (`staging.json` for `dev`) | `bastion_ips` passed to dataplane-manager |
| `aws/region/{env}-{aws_region}.json` | RDS endpoint, password secret ARN, proxy info |

## Required environment variable at apply

`config-center-regional.tf` runs a `local-exec` provisioner that POSTs to `inner-central.{env}.tidbcloud.com`. Requires:

```sh
export GLOBAL_AUTH_KEY=<base64-encoded-credentials>
```

Apply will fail at the `null_resource.config-center-registration` step without this.

## Deployment ordering (Kong → DNS → registration)

The following dependency chain is enforced and takes ~5 minutes due to a DNS propagation sleep:

```
cert-manager → gateway-crds → kong-gateway
  → aws_route53_record.regional_api
  → time_sleep.wait_for_dns_regional_api (5 min)
  → module.region_registration + module.dataplane-manager
```

Do not expect fast applies — the DNS wait is intentional.

## ECR image registry is always us-west-2

All in-cluster services use `{seed_account}.dkr.ecr.us-west-2.amazonaws.com` as the image registry, even when deploying to other AWS regions. This is hardcoded in every `additionalArgs.imageRegistry`. The customer-facing BYOC ECR (`var.byoc_ecr`) is separate and configurable.

## EKS admin roles

These IAM roles are granted `AmazonEKSClusterAdminPolicy` at cluster creation:

- `cicd-role`
- `argocd-oidc-role`
- `dbaas-central-role-{env}`
- Jumpserver role: `dbaas-prod-devops` (prod) or `dbaas-dev` (non-prod)

## ECR PrivateLink validation

When `var.enable_ecr_privatelink = true`, `var.byoc_ecr` must be a valid ECR registry hostname (e.g. `123456789012.dkr.ecr.eu-west-1.amazonaws.com`). A `precondition` enforces this with a clear error message.

## Crossplane / Upbound providers

`upbound-aws-provider.tf` installs Crossplane and the Upbound AWS family providers (ec2, eks, iam, route53, s3). These use `check_before_destroy = false` — destroy does not wait for provider health.

## Related Documentation

- [../AGENTS.md](../AGENTS.md) — parent module: workflow, backend, provider aliases, cross-module wiring
