Hedronite · Cert Lesson · Cert-Prep / HashiCorp · Sun 2026-09-20

Terraform Associate: dynamic blocks — for_each, count, and splat

Meta-arguments choose how many. Expressions choose what shape. Splat projects a list.

Lesson Class: Cert (Terraform Associate 003 · HCL meta-arguments)
Vendor: HashiCorp
Paired Ops: AWS SG separate rule resources
Paired Dev: HCL dynamic + for_each ingress map
Grounding: Lab 19 · Lab 16 · Lab 18 referenced · Brikman referenced
count
Indexed instances. Shrink reshuffles.
for_each
Keyed instances. Stable under delete.
dynamic / splat
Nested expansion / list attribute projection.
Pick one meta-argument. Expand with intent. Project with the matching expression.

<!-- hal:authoritative:yaml -->

Meta-arguments choose how many. Expressions choose what shape. Splat projects a list.

§I — Frame: Associate objectives for tonight

09-17 covered ephemeral vs sensitive vs write-only. Leave secrets.

09-14 covered import and moved. Leave brownfield addressing.

09-11 covered remote backends and partial config. Leave state location.

Tonight the Associate stems ask how configuration expands: dynamic blocks, for_each, count, and splat expressions (.*.attr). Ops and Dev already show the AWS ingress map. Cert names the exam vocabulary.

§II — Four claims

Claim one. count creates indexed instances. resource "aws_instance" "web" { count = 3 } yields aws_instance.web[0] … [2]. Removing the first element renumbers the rest. Use count for simple N-of-the-same when order is stable and you accept index churn, or for a 0/1 conditional (count = var.enabled ? 1 : 0).

Claim two. for_each creates keyed instances. Maps and sets only (not free-form lists of objects without a keying projection). Addresses keep keys when other keys disappear. Prefer for_each for security group rules, IAM users, and subnet maps.

Claim three. dynamic expands nested blocks. When a resource schema expects repeated nested blocks (ingress, setting, rule), dynamic "ingress" { for_each = ... content { ... } } is the language tool. It is not a second resource. It does not create resource.addr["key"] addresses for those nested blocks.

Claim four. Splat projects attributes from a list of objects. aws_instance.web[*].id is the list of ids when count (or a list-typed value) is in play. For for_each maps, prefer a for expression: [for k, i in aws_instance.web : i.id], because splat is list-oriented.

§III — Exam traps

  1. 1. count and for_each together on one resource: illegal. Pick one.
  2. 2. dynamic vs for_each resource: dynamic is nested blocks; for_each on resource is sibling instances.
  3. 3. Splat on a map-for_each resource: often the wrong reflex; use for.
  4. 4. Treating NACL rule_no as an SG priority: wrong cloud shelf (Ops contrast). Associate still expects you to know SG rules are not numbered like NACLs in AWS.

§IV — Drill (Lab 19 primary)

  1. 1. Open Lab 19. Refactor a count resource to for_each with stable keys.
  2. 2. Add a dynamic block example on a throwaway SG inline shape (or read Dev lesson).
  3. 3. Write one splat and one for expression against the results; note which fits count vs for_each.
  4. 4. Answer three stems: when to pick for_each; what dynamic expands; what splat returns.

Success: Lab 19 validate path green; you can explain why deleting key "ssh" does not renumber "https".

§V — Close instruction

File three flash lines: count index churn; for_each key stability; dynamic nested-only. Maghrib owns quiz.html. Pair: Ops AWS SG separate rules; Dev HCL expansion grammar.