Resources in Terraform are deployed as top-level resources. A server or App Service plan for example. These top-level resources include inline, or sub-resources; blocks of code that configure the top-level resource. In this blog post and video, we use a Network Security Group (NSG) as a Dynamic block example by creating multiple security rules as inline or sub-resources.
Typically, inline recourse requires multiple configuration settings. We could create multiple copies of the inline resource when more than one is needed. We’ll stick with the Network Security Group (NSG) for this example. An NSG will likely contain more than one security rule, and creating a copy of each rule will limit the code’s portability and use in a module.
We may want three rules for one deployment and 10 for the other. So how do we make an inline, or sub-resource dynamic? That is what Dynamic blocks are for. A Dynamic block uses a for_each loop to create multiple copies of a sub-resource nested inside a resource block. It makes repeatable, nested blocks in the parent resource argument.
Dynamic blocks can be used for Resource, Data, Provider, and Provisioner blocks. They can also be nested inside other dynamic blocks but use nesting sparingly. Nesting multiple levels makes the code difficult to read.
The example below creates a Network Security Group with multiple security rules using the dynamic block. The code used for this example can be found here https://github.com/tsrob50/TerraformExamples/tree/main/DynamicNSG
Create the Dynamic Block
Below is the default configuration for an NSG and a single security rule. This is the example from the AzureRM resource at https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_security_group
Let’s turn the Security Rule section into a dynamic block. Start by adding dynamic in front of security_rule, then add double quotes around security_rule.
One item to note, security_rule is an inline resource that the NSG expects to see at the time of deployment. It is not an arbitrary local name, it has to be called security_rule.
Next, we need to add a for_each loop in the dynamic block. For_each provides the looping functionality for the block. Add ‘for_each =’ in the dynamic block. Shown below are the changes so far.
Variable Type List
The use of a for_each loop implies a list of items to loop through. Let’s move over to the variable.tf file and create a list of variables. The example below uses the variable type list to create a collection object with all the expected variables. Each item in the list represents one security rule. With a list, we can add one, five, or ten rules to the list and each one will be added with the Dynamic block.
IMAGE Variable List Object
It is possible to use the type of list without the object. Using an object with a list of values allows for input validation and makes the code easier to read.
Now that we have the variable let’s move on to providing values for the deployment. The section of the terraform.tfvars file below shows the value supplied for the nsg_rules variable. The square brackets  indicate a list of items. Each item in the list provides the value for a security rule. Deploying this example will create an NSG with three rules.
Create the Dynamic Block Continued
Now that we have the variables in place, let’s get back to creating the dynamic block. We set the for_each loop in the dynamic block, let’s set it to equal the nsg_rules variable.
When we deploy a resource with a dynamic block, it creates multiple inline resource blocks, one for each item supplied by the list of variables. We need to specify the content that makes up each item next. We do that by putting the arguments in a content block. Add content on the line under the for_each and wrap the arguments in squiggly brackets as shown below. Don’t forget the closing bracket.
At this point, the dynamic block will loop through each item in the list of variables and use the values to create the security rules. Currently, the example uses hardcoded values. We specify to use the value from the variable by changing the arguments to security_rule.value, then specifying the value by putting the value name in double quotes and square brackets
name = security_rule.value[“name”]
Once finished, the dynamic block will look similar to below.
Save the files and run terraform init and terraform plan. The output from the plan shows three rules are added to the NSG.
That is how to use dynamic blocks in Terraform with Azure.