📖 Scenario: You are setting up a cloud infrastructure using Terraform. You need to create a resource that has nested blocks which are generated dynamically based on input variables. This is common when configuring complex cloud resources like load balancers or security groups.
🎯 Goal: Build a Terraform configuration that uses nested dynamic blocks to create multiple nested blocks inside a resource. You will first define the data structure, then create the dynamic blocks for the inner and outer levels.
📋 What You'll Learn
Create a variable listeners with a list of maps, each map containing port and protocol keys
Create a variable rules with a list of maps, each map containing host and paths keys, where paths is a list of strings
Use a dynamic block named listener to iterate over listeners
Inside each listener block, use a nested dynamic block named rule to iterate over rules
Inside each rule block, use a nested dynamic block named path to iterate over the paths list
💡 Why This Matters
🌍 Real World
Cloud engineers often need to configure resources with multiple nested settings that vary by environment or input. Nested dynamic blocks let them write flexible, reusable Terraform code.
💼 Career
Understanding nested dynamic blocks is essential for Terraform users working in cloud infrastructure roles, enabling them to automate complex resource setups efficiently.
Progress0 / 4 steps
1
Define the listeners variable
Create a Terraform variable called listeners of type list with two maps. The first map should have port = 80 and protocol = "HTTP". The second map should have port = 443 and protocol = "HTTPS".
Terraform
Hint
Use variable "listeners" with type = list(object({ port = number, protocol = string })) and set the default to the two maps.
2
Define the rules variable with nested paths
Create a Terraform variable called rules of type list with two maps. The first map should have host = "example.com" and paths = ["/", "/app"]. The second map should have host = "test.com" and paths = ["/test"].
Terraform
Hint
Use variable "rules" with type = list(object({ host = string, paths = list(string) })) and set the default to the two maps.
3
Create the outer dynamic "listener" block
Inside a resource aws_lb named example, add a dynamic "listener" block that iterates over var.listeners. For each listener, set port and protocol attributes using listener.value.port and listener.value.protocol.
Terraform
Hint
Use dynamic "listener" with for_each = var.listeners and set port and protocol inside content.
4
Add nested dynamic "rule" and dynamic "path" blocks inside listener
Inside the content block of the dynamic "listener", add a nested dynamic "rule" block that iterates over var.rules. Inside each rule block, set host to rule.value.host. Then add a nested dynamic "path" block inside rule that iterates over rule.value.paths. Inside path, set value to path.value.
Terraform
Hint
Inside listener content, add dynamic "rule" with for_each = var.rules. Inside rule content, set host = rule.value.host and add dynamic "path" with for_each = rule.value.paths. Inside path content, set value = path.value.
Practice
(1/5)
1.
What is the main purpose of using nested dynamic blocks in Terraform?
easy
A. To write static configuration without loops
B. To create repeated blocks inside other repeated blocks dynamically
C. To define provider settings only
D. To manage Terraform state files
Solution
Step 1: Understand dynamic blocks
Dynamic blocks allow repeating a block multiple times based on a list or map.
Step 2: Understand nested dynamic blocks
Nested dynamic blocks repeat blocks inside other repeated blocks, useful for complex nested lists.
Final Answer:
To create repeated blocks inside other repeated blocks dynamically -> Option B
C. Using var.subnets instead of network.value.subnets for nested for_each
D. network.value.name is invalid syntax
Solution
Step 1: Check nested for_each source
The nested dynamic block should iterate over subnets related to the current network, not the entire var.subnets list.
Step 2: Confirm correct variable usage
Using var.subnets ignores the current network context; it should be network.value.subnets to nest properly.
Final Answer:
Using var.subnets instead of network.value.subnets for nested for_each -> Option C
Quick Check:
Nested for_each must use parent block's value [OK]
Hint: Nested loops must use parent block's current item [OK]
Common Mistakes:
Using global variables instead of nested context
Forgetting quotes around dynamic block names
Misplacing content blocks
5.
You have a variable var.services which is a list of maps. Each map has a name and a list of ports. You want to create an aws_security_group resource with nested dynamic blocks to create ingress rules for each port of each service. Which Terraform code snippet correctly implements this?
hard
A.
resource "aws_security_group" "example" {
for_each = { for s in var.services : s.name => s }
name = each.key
dynamic "ingress" {
for_each = each.value.ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}