Bird
Raised Fist0
Terraformcloud~10 mins

Dynamic blocks in ingress rules in Terraform - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - Dynamic blocks in ingress rules
Start Terraform config
↓
Define ingress rules list
↓
Enter resource block
↓
Use dynamic block to loop over ingress rules
↓
For each rule: create ingress block
↓
Terraform applies config
↓
Ingress rules created dynamically
↓
End
Terraform reads a list of ingress rules, then uses a dynamic block inside a resource to create multiple ingress entries automatically.
Execution Sample
Terraform
variable "ingress_rules" {
  default = [
    { 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"] }
  ]
}

resource "aws_security_group" "example" {
  name = "example-sg"

  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 Terraform code dynamically creates two ingress rules in a security group using a dynamic block looping over a list.
Process Table
StepActionDynamic Block IterationIngress Rule CreatedResource State
1Start Terraform applyN/ANoSecurity group resource initialized, no ingress rules yet
2Evaluate dynamic blockIteration 1Ingress rule with from_port=80, to_port=80, protocol=tcp, cidr_blocks=["0.0.0.0/0"]Ingress block 1 added to security group
3Evaluate dynamic blockIteration 2Ingress rule with from_port=443, to_port=443, protocol=tcp, cidr_blocks=["0.0.0.0/0"]Ingress block 2 added to security group
4Finish applyN/AAll ingress rules createdSecurity group with 2 ingress rules ready
💡 All ingress rules from the list processed, dynamic block iterations complete
Status Tracker
VariableStartAfter Iteration 1After Iteration 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
aws_security_group.example.ingressEmpty1 ingress rule added2 ingress rules added2 ingress rules total
Key Moments - 3 Insights
Why does Terraform create multiple ingress blocks from one dynamic block?
Because the dynamic block loops over each item in var.ingress_rules, creating one ingress block per item as shown in execution_table rows 2 and 3.
What happens if var.ingress_rules is empty?
The dynamic block has no items to loop over, so no ingress blocks are created. This is implied by the loop behavior in execution_table where iterations correspond to list items.
How does Terraform know which values to assign inside each ingress block?
Inside the dynamic block, ingress.value refers to the current item in the list, so its properties (from_port, to_port, etc.) are assigned to the block fields as shown in the code and execution_table.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the from_port value in iteration 2 of the dynamic block?
A443
B22
C80
D0
💡 Hint
Check execution_table row 3 under 'Ingress Rule Created' for iteration 2 details.
At which step does Terraform finish creating all ingress rules?
AStep 2
BStep 3
CStep 4
DStep 1
💡 Hint
Look at execution_table row 4 describing the finish apply step.
If var.ingress_rules had 3 items instead of 2, how would the execution_table change?
AOnly 2 iterations would run regardless
BThere would be 3 iterations with 3 ingress rules created
CTerraform would error out
DIngress rules would be merged into 2 blocks
💡 Hint
Dynamic blocks loop over all items in the list as shown in variable_tracker and execution_table.
Concept Snapshot
Terraform dynamic blocks let you create multiple nested blocks from a list.
Use dynamic "block_name" { for_each = list ... } to loop.
Inside content { ... }, use block_name.value to access each item.
This avoids repeating similar blocks manually.
Useful for ingress rules where many similar entries exist.
Full Transcript
This visual execution shows how Terraform uses dynamic blocks to create multiple ingress rules in a security group. It starts by defining a list of ingress rules. Then, inside the aws_security_group resource, a dynamic block loops over this list. For each item, Terraform creates one ingress block with the specified ports, protocol, and CIDR blocks. The execution table traces each iteration, showing how ingress rules are added step-by-step. Variables track the list and current item values. Key moments clarify why multiple blocks are created and how values are assigned. The quiz tests understanding of iteration details and dynamic block behavior. This helps beginners see how dynamic blocks automate repetitive resource definitions in Terraform.

Practice

(1/5)
1. What is the main purpose of using dynamic blocks in Terraform ingress rules?
easy
A. To define a single static ingress rule
B. To encrypt ingress rule data
C. To delete existing ingress rules automatically
D. To create multiple similar ingress rules without repeating code

Solution

  1. Step 1: Understand what dynamic blocks do

    Dynamic blocks allow repeating a block multiple times based on a list or map, avoiding code repetition.
  2. Step 2: Apply this to ingress rules

    Ingress rules often need multiple similar blocks; dynamic blocks generate these efficiently.
  3. Final Answer:

    To create multiple similar ingress rules without repeating code -> Option D
  4. Quick Check:

    Dynamic blocks = multiple similar blocks [OK]
Hint: Dynamic blocks repeat blocks from lists or maps [OK]
Common Mistakes:
  • Thinking dynamic blocks delete rules
  • Confusing dynamic with static blocks
  • Assuming dynamic blocks encrypt data
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

    Dynamic blocks require the block type as a quoted string, e.g., dynamic "ingress".
  2. Step 2: Check for correct placement of for_each and content

    for_each is assigned outside braces, and content block is inside the dynamic block.
  3. Final Answer:

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

    Dynamic block syntax uses quotes and for_each outside braces [OK]
Hint: Use quotes around block type and place for_each before content [OK]
Common Mistakes:
  • Omitting quotes around block type
  • Placing for_each inside braces incorrectly
  • Using braces incorrectly around for_each
3. Given the Terraform snippet:
variable "rules" {
  default = [
    { from_port = 80, to_port = 80, protocol = "tcp" },
    { from_port = 443, to_port = 443, protocol = "tcp" }
  ]
}

resource "aws_security_group" "example" {
  name = "example"

  dynamic "ingress" {
    for_each = var.rules
    content {
      from_port   = each.value.from_port
      to_port     = each.value.to_port
      protocol    = each.value.protocol
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}

How many ingress rules will be created?
medium
A. 2
B. 0
C. 1
D. 3

Solution

  1. Step 1: Count elements in var.rules

    var.rules contains 2 map elements, each with from_port, to_port, protocol.
  2. Step 2: Understand dynamic block behavior

    Dynamic block creates one ingress block per element in var.rules, so 2 ingress blocks.
  3. Final Answer:

    2 -> Option A
  4. Quick Check:

    List length = 2 ingress rules created [OK]
Hint: Count list items in for_each to find block count [OK]
Common Mistakes:
  • Counting only one rule
  • Assuming dynamic block creates zero rules
  • Miscounting list elements
4. Identify the error in this Terraform dynamic block snippet for ingress rules:
dynamic "ingress" {
  for_each = var.rules
  content = {
    from_port   = each.value.from_port
    to_port     = each.value.to_port
    protocol    = each.value.protocol
    cidr_blocks = ["0.0.0.0/0"]
  }
}
medium
A. Incorrect use of '=' after content instead of block
B. Missing quotes around "ingress"
C. for_each should be inside content block
D. cidr_blocks must be a string, not a list

Solution

  1. Step 1: Check dynamic block syntax for content

    The content block should be a block, not assigned with '='. Using '=' causes syntax error.
  2. Step 2: Verify other parts

    Quotes around "ingress" are present; for_each is correctly outside content; cidr_blocks accepts list.
  3. Final Answer:

    Incorrect use of '=' after content instead of block -> Option A
  4. Quick Check:

    content is a block, not an assignment [OK]
Hint: Use block syntax for content, not '=' assignment [OK]
Common Mistakes:
  • Using '=' after content instead of block braces
  • Placing for_each inside content
  • Omitting quotes around block type
5. You want to create ingress rules dynamically but only for rules where from_port is greater than 1000. Which Terraform expression correctly filters var.rules for use in a dynamic block's for_each?
hard
A. for_each = [for r in var.rules : r if r.from_port > 1000]
B. for_each = { for idx, r in var.rules : idx => r if r.from_port > 1000 }
C. for_each = filter(var.rules, r => r.from_port > 1000)
D. for_each = { for r in var.rules : r.from_port => r if r.from_port > 1000 }

Solution

  1. Step 1: Understand for_each type requirements

    for_each expects a map or set of strings; using a map with keys is preferred for dynamic blocks.
  2. Step 2: Analyze each option

    A returns a list, which is invalid for for_each in dynamic blocks. B uses r.from_port as key, which may duplicate keys. C uses filter function which is invalid syntax in Terraform. D creates a map with index keys filtered by condition, valid and safe.
  3. Final Answer:

    for_each = { for idx, r in var.rules : idx => r if r.from_port > 1000 } -> Option B
  4. Quick Check:

    for_each needs map with unique keys filtered by condition [OK]
Hint: Use map comprehension with index keys and condition [OK]
Common Mistakes:
  • Using list instead of map for for_each
  • Using non-unique keys causing errors
  • Trying unsupported filter() function
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