Skip to content

Stage 2 — Basics (local, no cloud)

Thirteen topics that prove every core Terraform mechanic without touching a cloud API. Nothing here authenticates, costs money, or can be broken in a way that matters. The local, random, null and archive providers write files to /tmp — but the lifecycle, the state file, the dependency graph and the plan/apply loop are the real thing, identical to what runs against GCP in Stage 3.

The code lives in 01-basics/, seven numbered folders holding eight self-contained Terraform roots — 4-dependencies/ isn't a root itself, its explicit/ and implicit/ subdirectories are. This section is the only prose: the folders hold .tf files, plus one checked-in graph.svg where the graph is the point.

Prerequisites

terraform version      # anything 1.x

That's it. No gcloud, no credentials, no billing account. Graphviz is optional and only needed for terraform graph:

brew install graphviz

The sequence

Ordered by difficulty, not by folder number. Six topics have no folder yet — the code is in the page, ready to paste into a scratch root.

# Topic Folder Writes
1 Resources and state 1-create-local-file/ /tmp/hello.txt
2 Variables 2-variable-use/ /tmp/helloFruits.txt
3 Locals /tmp/tf-practice/greeting-*.txt
4 References and dependencies 3-resource-attribute-reference/, 4-dependencies/ /tmp/hello_resourceAttribute.txt, /tmp/hello_{im,ex}plicit_dependencies.txt
5 Outputs 4-dependencies/explicit/ nothing
6 Data sources 6-data-sources/ /tmp/hello.txt
7 count and for_each /tmp/pet-*.txt
8 Conditionals /tmp/backup.txt
9 Lifecycle 5-lifecycle/ /tmp/hello.txt
10 Validation and sensitive values /tmp/app-config.txt
11 Provider versions 7-version-constraints/ ./hello.txt
12 State surgery nothing new
13 Provisioners and archive_file /tmp/greeting-*.txt, /tmp/tf-practice-bundle.zip

Folder numbers and topic numbers deliberately don't line up. The folders were numbered in the order they were written; the topics are numbered in the order that makes them easiest to learn.

Running any of them

cd 01-basics/1-create-local-file
terraform init
terraform plan
terraform apply
terraform state list          # what Terraform now thinks it owns
terraform destroy

Each folder is an independent root with its own state. terraform destroy between topics is optional here — nothing costs money and nothing needs cleanup approval — but several folders write to the same /tmp/hello.txt, so destroying as you go avoids confusion about which root owns the file.

Deliberate defects

Three folders contain bugs on purpose. Fixing them teaches more than reading a working example, so don't "clean them up" without reading the relevant page first.

Folder Defect Page
5-lifecycle/ ignore_changes = [tags]local_file has no tags attribute, so this errors Lifecycle
7-version-constraints/ Writes hello.txt to the current directory while the comment says /tmp Provider versions
3- vs 4-dependencies/implicit/ Byte-identical main.tf, which looks like duplication and isn't References and dependencies

Not yet implemented

Six topics are documented here but have no folder under 01-basics/. The code on each page is complete and runnable — paste it into an empty directory and terraform init.

Roughly in the order worth building them:

Topic Why it's worth building
State surgery Highest value. State surgery is far cheaper to practise on a local_file than on a GCP resource, and it's the same muscle needed for GCP Lab 6 and Lab 11.
Conditionals The count = 0 error and guard propagation are the cheapest possible rehearsal of the bug that cost a whole session in the sandbox (Session 2). Reading it is not the same as hitting it.
count and for_each The destructive test — remove a middle element and diff terraform state list — has to be run to land. It's the entire argument for for_each and it takes two applies.
Locals The timestamp() perpetual-diff experiment needs a real second plan to be convincing; a config that can never converge is a strange thing to take on trust.
Validation and sensitive values grepping your own "secret" out of terraform.tfstate in plaintext is the moment sensitive = true stops sounding like encryption. Worth doing once, locally, where the secret is fake.
Provisioners and archive_file Lowest priority — the triggers re-run behaviour is the only part that needs observing, and provisioners are a pattern to recognise rather than adopt.

Conventions

  • One directory per concept, numbered in the order they were written — except 4-dependencies/, where one concept needs two roots side by side to contrast against each other.
  • main.tf for resources, variables.tf for inputs — the same layout as 02-gcp-terraform/ and every root in the sandbox, so moving between them costs nothing.
  • .terraform/, terraform.tfstate and lock files are gitignored. Only the HCL is committed.

Start with Resources and state.