Using `for_each` in Terraform's `dynamic` blocks

The for_each instruction in Terraform allows you to loop a resource or module over a set to create multiple instances. For instance, if you were to do:

variable "vm_instances" {
type = map(object({
location = string
default = {
instance1 = {
location = "East US"
instance2 = {
location = "West US"

resource "azurerm_virtual_machine" "vm_instances" {
for_each = var.vm_instances

name = each.key
location = each.value.location

You would create 2 VMs, one in East US, the other in West US.

However, it is also possible to use the for_each function to loop dynamic blocks within a resource.

As an example of this, I need to create 5 restriction blocks in the PagerDuty Schedule resource type:

resource "pagerduty_schedule" "in_hours_schedule" {
name = "In Hours"

layer {
dynamic "restriction" {
for_each = toset(range(1, 6))

content {
type = "weekly_restriction"
start_day_of_week = restriction.value

There are a couple of things to call out here:

  • for_each = toset(range(1, 6)) - This iterates from 1 to 5 creating an array of number type
  • restriction.value - When for_each is used in a resource, we would generally refer to the iterator with each.value (or each.key). However, within a dynamic block, the syntax changes and we have to use the name of the dynamic block. Hence in this case restriction.value refers to the number that the iterator is currently selecting (in this case the numbers 1 to 5).