In a previous article (Terraform Count vs. For Each: Which One Do You Use?), you learned how to create multiple resources using both the for_each and count arguments. While these argument made duplicates of entire resources, sometimes you need to repeat blocks within a resource. Enter Terraform dynamic blocks!

In this article, you will learn what are Terraform dynamic blocks and how to add them to your resource definitions. After that, follow a tutorial on how to create multiple subnets in an Azure virtual network.

What are Terraform Dynamic Blocks?

Terraform dynamic blocks are used to create repeatable nested blocks inside an argument. These dynamic blocks represent separate objects that are related or embedded with the containing object. Dynamic blocks are a lot like the for expression except dynamic blocks iterate over complex values.

For example, let’s say a resource has a setting block that defines multiple components of a resource. Within the resource definition, use the dynamic keyword followed by the property name (setting).

Within the block, use the for_each argument to provide a complex value for the dynamic block to iterate over. The value in for_each must be a collection with one element per nested block. Finally, use a nested content block to define the body of each generated block.

Here is a basic outline of a dynamic block syntax within a resource:

resource "resource_type" "name" {
  // Other resource settings
  dynamic "setting" {
    for_each = var.settings
    content {
      property1 = setting.value.<property>
      // etc.
    }
  }
}

Creating Multiple Subnets in an Azure Virtual Network

Let’s take a look at an example where you create multiple subnets within an Azure virtual network definition. First, create a local variable of list type that contains multiple objects. Each object represents a subnet’s name and address prefix.

locals {
  subnets = [
    {
      name           = "snet01"
      address_prefix = "192.168.1.0/24"
    },
    {
      name           = "snet02"
      address_prefix = "192.168.2.0/24"
    }
  ]
}

Within the virtual network definition, create a dynamic block for the subnet property that iterates over local.subnets and accesses the objects in the list using their key name (name and address_prefix).

Note that the resource group (azurerm_resource_group.rg) is defined earlier in the configuration and is not listed in the code below.

resource "azurerm_virtual_network" "vnet" {
  name                = "vnet-westus2"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  address_space       = ["192.168.0.0/16"]
  dynamic "subnet" {
    for_each = local.subnets
    content {
      name           = subnet.value.name
      address_prefix = subnet.value.address_prefix
    }
  }
}

Performing a terraform plan shows that each subnet is now dynamically generated within the virtual network definition.

terraform dynamic block example
Using Terraform dynamic blocks on subnet definitions

Closing

Terraform dynamic blocks are a great way to duplicate properties within a resource. This method saves you from copying and pasting multiple lines of code in your configuration file.

Enjoyed this article? Check out more of my Terraform content here!