Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
stop-slop, taste-skill, terrashark had embedded .git dirs causing Woodpecker clone to fail on submodule update.
75 lines
3.3 KiB
Markdown
75 lines
3.3 KiB
Markdown
# Terraform Do and Don't Checklist
|
|
|
|
A fast reference checklist for safe Terraform and OpenTofu code generation. Use this for quick reviews.
|
|
|
|
## Identity and Iteration
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Use `for_each` with stable, business-meaningful keys | Use list index as long-lived identity |
|
|
| Keep identity keys separate from mutable attributes | Derive identity from a computed attribute |
|
|
| Add `moved` blocks when renaming resources or modules | Delete/rename addresses without an explicit migration plan |
|
|
|
|
## Secrets and Sensitive Data
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Mark secret outputs as `sensitive = true` | Put secrets in `default` values or `.tfvars` committed to VCS |
|
|
| Use secret managers and data sources for runtime injection | Echo secrets in provisioner commands |
|
|
| Avoid logging sensitive values in `locals` or `output` | Rely on `sensitive` alone to protect state contents |
|
|
|
|
## State Boundaries and Blast Radius
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Keep production in isolated state backends or workspaces | Mix unrelated systems in a single root state |
|
|
| Split large stacks by lifecycle and ownership | Apply directly to production from unreviewed branches |
|
|
| Use environment protection and approvals for apply | Use one monolithic stack for all environments |
|
|
|
|
## Module Contracts
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Expose typed inputs and explicit outputs | Accept untyped `map(any)` for core interfaces |
|
|
| Use `optional()` for evolution-friendly contracts | Expose entire provider objects as outputs |
|
|
| Validate invariants with `validation` and `precondition` | Push environment-specific policy into primitive modules |
|
|
|
|
## Providers and Versions
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Pin runtime and providers with bounded constraints | Float provider versions |
|
|
| Commit `.terraform.lock.hcl` intentionally | Rely on implicit provider inheritance in multi-region setups |
|
|
| Pass provider aliases explicitly to child modules | Mix upgrades with functional changes in the same PR |
|
|
|
|
## Data Sources and Dependencies
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Use data sources for read-only integration | Use `depends_on` to paper over missing interfaces |
|
|
| Model dependencies via input/output wiring | Use data sources for identity fields that can change |
|
|
| Keep `depends_on` for real ordering requirements only | Create hidden ordering between unrelated resources |
|
|
|
|
## CI/CD and Policy
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Separate plan and apply | Allow direct apply from arbitrary branches |
|
|
| Keep an auditable reviewed plan artifact | Skip policy checks for production changes |
|
|
| Run policy and cost checks on every plan | Delete plan artifacts before approval |
|
|
|
|
## Testing
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Run `terraform test` / `tofu test` for module-level checks | Rely on plan-only validation for runtime-only attributes |
|
|
| Use Terratest for workflow or integration validation | Run destructive tests without isolation and cleanup |
|
|
| Tier tests by risk and cost | Treat mocked provider tests as full integration coverage |
|
|
|
|
## Migration and Refactors
|
|
|
|
| Do | Don't |
|
|
|---|---|
|
|
| Include `moved` or `import` strategy in the same change | Rename resources without preserving state identity |
|
|
| Run a reviewed plan before any apply | Apply refactors without plan review |
|
|
| Document rollback steps for destructive changes | Remove resources without lifecycle transition |
|