Bird
Raised Fist0
Terraformcloud~10 mins

Dynamic block syntax in Terraform - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - Dynamic block syntax
Start Terraform config
↓
Identify dynamic block
↓
Iterate over collection
↓
For each item: generate nested block
↓
Merge generated blocks into resource
↓
Apply Terraform plan
↓
Resource created with dynamic nested blocks
↓
End
Terraform reads the dynamic block, loops over the given collection, creates nested blocks for each item, and applies the configuration.
Execution Sample
Terraform
resource "aws_security_group" "example" {
  name = "example"

  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
    }
  }
}
This code dynamically creates multiple ingress rules inside an AWS security group based on the list variable 'ingress_rules'.
Process Table
StepActionInput/ConditionResultNotes
1Start processing resourceaws_security_group exampleReady to process blocksInitial resource parsing
2Identify dynamic blockdynamic "ingress"Prepare to iterate over var.ingress_rulesDynamic block found
3Evaluate for_eachvar.ingress_rules = [{from_port=80,...}, {from_port=443,...}]2 items to iterateTwo ingress rules
4Iterate item 1ingress.value = {from_port=80, to_port=80, protocol="tcp", cidr_blocks=["0.0.0.0/0"]}Generate ingress block #1First ingress rule created
5Iterate item 2ingress.value = {from_port=443, to_port=443, protocol="tcp", cidr_blocks=["0.0.0.0/0"]}Generate ingress block #2Second ingress rule created
6Merge blocksAll generated ingress blocksResource has 2 ingress blocksDynamic blocks merged
7Apply Terraform planResource with dynamic ingress blocksSecurity group created with 2 ingress rulesInfrastructure updated
8EndAll steps completeTerraform apply finishedExecution complete
💡 All items in var.ingress_rules processed, dynamic blocks generated and applied.
Status Tracker
VariableStartAfter 1After 2Final
var.ingress_rules[{from_port=80,...}, {from_port=443,...}]SameSameSame
ingress.valueN/A{from_port=80, to_port=80, protocol="tcp", cidr_blocks=["0.0.0.0/0"]}{from_port=443, to_port=443, protocol="tcp", cidr_blocks=["0.0.0.0/0"]}N/A
Key Moments - 3 Insights
Why does Terraform create multiple ingress blocks from one dynamic block?
Because the dynamic block uses for_each to loop over a list (var.ingress_rules). Each item creates one nested ingress block, as shown in execution_table rows 4 and 5.
What happens if var.ingress_rules is empty?
No ingress blocks are generated. The dynamic block produces zero nested blocks, so the resource has no ingress rules. This is implied by the iteration step in execution_table row 3.
Can the content block inside dynamic use the loop variable?
Yes, inside content, you access the current item with ingress.value, as shown in execution_table rows 4 and 5 where ingress.value fields are used.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 3. How many items does var.ingress_rules contain?
A2
B1
C3
D0
💡 Hint
Check the 'Input/Condition' column at step 3 showing the list length.
At which step does Terraform generate the second ingress block?
AStep 4
BStep 5
CStep 6
DStep 7
💡 Hint
Look at the 'Action' column describing iteration over items.
If var.ingress_rules was empty, what would happen to the resource?
ATerraform would error out
BIt would create one default ingress block
CIt would have no ingress blocks
DIt would create ingress blocks from previous runs
💡 Hint
Refer to key_moments about empty lists and dynamic block behavior.
Concept Snapshot
Dynamic block syntax in Terraform:
- Use dynamic "block_name" to create nested blocks dynamically.
- for_each loops over a collection to generate multiple blocks.
- content block defines the nested block structure using loop variable.
- Useful for variable-length nested configurations.
- If collection is empty, no nested blocks are created.
Full Transcript
This visual execution traces Terraform's dynamic block syntax. Terraform starts parsing the resource and finds a dynamic block named ingress. It evaluates the for_each expression, which is a list of ingress rules. For each item in the list, Terraform generates one nested ingress block using the content block, substituting values from the current item. After processing all items, Terraform merges the generated blocks into the resource and applies the plan, creating the security group with multiple ingress rules. Variables like var.ingress_rules remain constant, while ingress.value changes per iteration. Key points include how dynamic blocks loop over collections to create multiple nested blocks, and that empty collections produce no nested blocks. The execution table shows each step clearly, helping beginners understand the flow and state changes.

Practice

(1/5)
1. What is the main purpose of a dynamic block in Terraform?
easy
A. To generate multiple nested blocks from a list or map dynamically
B. To create a new Terraform provider
C. To define variables with default values
D. To execute shell commands during deployment

Solution

  1. Step 1: Understand the role of dynamic blocks

    Dynamic blocks allow repeating nested blocks based on a collection like a list or map.
  2. Step 2: Compare with other options

    Options A, B, and D describe unrelated Terraform features.
  3. Final Answer:

    To generate multiple nested blocks from a list or map dynamically -> Option A
  4. Quick Check:

    Dynamic block = repeated nested blocks [OK]
Hint: Dynamic blocks repeat nested blocks from lists/maps [OK]
Common Mistakes:
  • Confusing dynamic blocks with variable declarations
  • Thinking dynamic blocks create providers
  • Assuming dynamic blocks run commands
2. Which of the following is the correct syntax to start a dynamic block named ingress in Terraform?
easy
A. dynamic ingress { for_each = var.rules content { ... } }
B. dynamic(ingress) { for_each = var.rules content { ... } }
C. dynamic "ingress" { for_each = var.rules content { ... } }
D. dynamic { ingress for_each = var.rules content { ... } }

Solution

  1. Step 1: Recall dynamic block syntax

    The block must be declared as dynamic "block_name" { ... } with quotes around the block name.
  2. Step 2: Check each option

    dynamic "ingress" { for_each = var.rules content { ... } } uses correct syntax with quotes and proper structure; others miss quotes or have wrong syntax.
  3. Final Answer:

    dynamic "ingress" { for_each = var.rules content { ... } } -> Option C
  4. Quick Check:

    Dynamic block syntax requires quotes around block name [OK]
Hint: Use quotes around block name in dynamic block [OK]
Common Mistakes:
  • Omitting quotes around the block name
  • Using parentheses instead of braces
  • Placing block name outside dynamic keyword
3. Given this Terraform snippet:
dynamic "tag" {
  for_each = {"env" = "prod", "team" = "devops"}
  content {
    key   = tag.key
    value = tag.value
  }
}

What will be the result in the generated resource configuration?
medium
A. No tag blocks generated because map keys are strings
B. A single tag block with key and value set to the entire map
C. Syntax error due to incorrect for_each usage
D. Two tag blocks with keys "env" and "team" and their values

Solution

  1. Step 1: Understand for_each with map in dynamic block

    Using a map with for_each creates one nested block per key-value pair.
  2. Step 2: Analyze content block usage

    Inside content, tag.key and tag.value refer to each map entry's key and value, creating two blocks.
  3. Final Answer:

    Two tag blocks with keys "env" and "team" and their values -> Option D
  4. Quick Check:

    Map for_each creates one block per key-value pair [OK]
Hint: Map in for_each creates one block per key-value pair [OK]
Common Mistakes:
  • Thinking only one block is created for whole map
  • Confusing key and value references inside content
  • Assuming syntax error due to map usage
4. Identify the error in this Terraform dynamic block snippet:
dynamic "egress" {
  for_each = var.egress_rules
  content = {
    from_port = egress.value.from
    to_port   = egress.value.to
  }
}
medium
A. The content block should use braces, not an assignment
B. The variable egress is undefined inside the block
C. Missing quotes around "egress" in dynamic block declaration
D. for_each cannot be used with variables

Solution

  1. Step 1: Check dynamic block content syntax

    The content must be a block, not an assignment. It should be content { ... }, not content = { ... }.
  2. Step 2: Verify other parts

    Variable egress is valid as the iterator, quotes are present, and for_each can use variables.
  3. Final Answer:

    The content block should use braces, not an assignment -> Option A
  4. Quick Check:

    content must be a block, not an equals assignment [OK]
Hint: Use content { ... } block, not content = { ... } [OK]
Common Mistakes:
  • Writing content as an assignment instead of a block
  • Assuming iterator variable is undefined
  • Forgetting quotes around dynamic block name
5. You want to create multiple network_interface blocks dynamically in an AWS instance resource using a list of maps with keys device_index and subnet_id. Which dynamic block correctly achieves this?
hard
A. dynamic "network_interface" { for_each = var.interfaces content { device_index = network_interface.value.device_index subnet_id = network_interface.value.subnet_id } }
B. dynamic "network_interface" { for_each = var.interfaces content { device_index = each.value.device_index subnet_id = each.value.subnet_id } }
C. dynamic "network_interface" { for_each = var.interfaces content { device_index = network_interface.device_index subnet_id = network_interface.subnet_id } }
D. dynamic "network_interface" { for_each = var.interfaces content { device_index = network_interface.key.device_index subnet_id = network_interface.key.subnet_id } }

Solution

  1. Step 1: Identify the iterator variable in dynamic block

    Terraform uses each as the iterator inside dynamic blocks for for_each.
  2. Step 2: Check how to access map values

    Use each.value.key_name to access map elements inside content block.
  3. Step 3: Evaluate options

    dynamic "network_interface" { for_each = var.interfaces content { device_index = each.value.device_index subnet_id = each.value.subnet_id } } correctly uses each.value.device_index and each.value.subnet_id. Others incorrectly use network_interface or network_interface.key.
  4. Final Answer:

    dynamic "network_interface" { for_each = var.interfaces content { device_index = each.value.device_index subnet_id = each.value.subnet_id } } -> Option B
  5. Quick Check:

    Use each.value to access map in dynamic block [OK]
Hint: Use each.value inside dynamic content block [OK]
Common Mistakes:
  • Using block name as iterator variable
  • Using .key instead of .value for map access
  • Omitting the each keyword
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard