How to Use Dynamic Block in Terraform: Syntax and Example
Use the
dynamic block in Terraform to create repeated nested blocks dynamically based on a list or map. It requires specifying a for_each expression and a content block that defines the nested block structure.Syntax
The dynamic block lets you generate multiple nested blocks dynamically. It has three main parts:
- for_each: A list or map to loop over.
- content: Defines the nested block structure to repeat.
- each: Represents the current item in the loop inside
content.
terraform
dynamic "block_name" { for_each = var.items content { attribute = each.value } }
Example
This example shows how to create multiple ingress rules in an AWS security group using a dynamic block. The for_each loops over a list of rules, and each rule creates an ingress block with the specified attributes.
terraform
variable "ingress_rules" { type = list(object({ from_port = number to_port = number protocol = string cidr_blocks = list(string) })) 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 } } }
Output
Terraform will create an AWS security group with two ingress rules: one for port 80 and one for port 443, both allowing TCP traffic from any IP.
Common Pitfalls
Common mistakes when using dynamic blocks include:
- Using
each.valueinsidecontentbut forgetting to match the label used indynamic "label"(e.g., useingress.valueif the label isingress). - Trying to use
dynamicblocks for simple repeated attributes instead of nested blocks. - Not providing a proper iterable for
for_each, causing errors.
Wrong example:
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = each.value.from_port # Incorrect: should be ingress.value.from_port
}
}Right example:
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
}
}Quick Reference
Tips for using dynamic blocks:
- Use
dynamiconly for nested blocks, not simple attributes. - Inside
content, use the label name (e.g.,ingress.value) to access the current item. for_eachmust be a list or map.- Combine with variables to create flexible, reusable configurations.
Key Takeaways
Use dynamic blocks to create repeated nested blocks based on a list or map.
Inside the content block, access the current item with the dynamic block label and .value.
for_each must be a valid iterable like a list or map.
Avoid using dynamic blocks for simple repeated attributes; use them only for nested blocks.
Dynamic blocks help make Terraform configurations flexible and reusable.