Terraform Dynamic Blocks: Generate Nested Blocks from Variables
Repeat nested blocks with a dynamic block #
Some resources have nested blocks that can be repeated, such as ingress in aws_security_group, setting in Elastic Beanstalk or statement in an IAM policy document. for_each and count work on the resource, not on its nested blocks. A dynamic block generates those blocks from a collection.
Without a dynamic block #
resource "aws_security_group" "web" {
name = "web"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}With a dynamic block #
variable "ingress_ports" {
type = list(number)
default = [80, 443]
}
resource "aws_security_group" "web" {
name = "web"
vpc_id = aws_vpc.main.id
dynamic "ingress" {
for_each = var.ingress_ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}- The label (
"ingress") is the name of the nested block to generate. for_eachis the collection. Each element creates one block.contentdefines the body of each generated block.- Inside,
ingress.valueandingress.keyrefer to the current element. The variable is named after the block label.
Rename the iterator #
Use iterator to give the current element a different name, which helps with nested dynamic blocks:
dynamic "ingress" {
for_each = var.rules
iterator = rule
content {
description = rule.value.description
from_port = rule.value.port
to_port = rule.value.port
protocol = rule.value.protocol
cidr_blocks = rule.value.cidrs
}
}with a variable of objects:
variable "rules" {
type = list(object({
description = string
port = number
protocol = string
cidrs = list(string)
}))
}Optional blocks #
An empty collection generates no block, so a dynamic block is also a way to make a nested block optional:
dynamic "versioning_configuration" {
for_each = var.enable_versioning ? [1] : []
content {
status = "Enabled"
}
}When not to use it #
Dynamic blocks make the code harder to read. Use them when the number of blocks really depends on input. If you always have the same two rules, write them explicitly.