In this Terraform article I have two examples for loop and count loop. I have one map of object. Where I will use both the loops on map to show how to use them in different way. You can check my earlier articles for different loops examples - Terraform for_each loop on map example and Terraform one module deploy null or multiple resources based on input (nested for loop).
Download this Terraform for_each and count configuration here or it is also available on github.com.
In the below example I have terraform configuration provider.tf for azurerm and variables.tf file which has information of map of objects and mentioned default configuration.
provider.tf terraform { required_version = ">=1.0" required_providers { azurerm = { source = "hashicorp/azurerm" version = ">=3.0" } } } provider "azurerm" { features {} } variables.tf variable "foreach_records" { type = map(object({ name = string location = string })) default = { "rg01" = { name = "rg01" location = "EastUS" } "rg02" = { name = "rg02" location = "EastUS" } } } variable "count_records" { type = map(object({ name = string location = string })) default = { "rg01" = { name = "rg03" location = "EastUS" } "rg02" = { name = "rg04" location = "EastUS" } } }
In the first example, to use first variable foreach_records, I am using for_each and for loop on the map. Then I am using each.value of object properties to create resources on azure.
for_each_example.tf resource "azurerm_resource_group" "rg_foreach" { for_each = { for r in var.foreach_records : r.name => r } name = each.value.name location = each.value.location }
In my second example, Incase if I want to use count loop, first I am manipulating count_records variable and creating locals variable to create custom list of objects. Next using the local variable with count loop using function length() of newly created local variable. Next to determine the correct values from list I am using count.index of local variable as in the given example below.
count_example.tf locals { count_records_list = [ for key, value in var.count_records : { name = value.name location = value.location } ] } resource "azurerm_resource_group" "rg_count" { count = length(local.count_records_list) name = local.count_records_list[count.index].name location = local.count_records_list[count.index].location }
This is the screenshot of terraform apply of the configuration code.
This is the output of applied and destroyed terraform configuration on Microsoft Azure.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
PS D:\Projects\Terraform\Testings\Terraform_Count_Vs_Foreach> terraform apply --auto-approve Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.rg_count[0] will be created + resource "azurerm_resource_group" "rg_count" { + id = (known after apply) + location = "eastus" + name = "rg03" } # azurerm_resource_group.rg_count[1] will be created + resource "azurerm_resource_group" "rg_count" { + id = (known after apply) + location = "eastus" + name = "rg04" } # azurerm_resource_group.rg_foreach["rg01"] will be created + resource "azurerm_resource_group" "rg_foreach" { + id = (known after apply) + location = "eastus" + name = "rg01" } # azurerm_resource_group.rg_foreach["rg02"] will be created + resource "azurerm_resource_group" "rg_foreach" { + id = (known after apply) + location = "eastus" + name = "rg02" } Plan: 4 to add, 0 to change, 0 to destroy. azurerm_resource_group.rg_foreach["rg01"]: Creating... azurerm_resource_group.rg_count[1]: Creating... azurerm_resource_group.rg_foreach["rg02"]: Creating... azurerm_resource_group.rg_count[0]: Creating... azurerm_resource_group.rg_count[0]: Creation complete after 4s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03] azurerm_resource_group.rg_foreach["rg01"]: Creation complete after 4s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01] azurerm_resource_group.rg_count[1]: Creation complete after 4s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04] azurerm_resource_group.rg_foreach["rg02"]: Creation complete after 4s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02] Apply complete! Resources: 4 added, 0 changed, 0 destroyed. PS D:\Projects\Terraform\Testings\Terraform_Count_Vs_Foreach> PS D:\Projects\Terraform\Testings\Terraform_Count_Vs_Foreach> terraform destroy --auto-approve azurerm_resource_group.rg_count[0]: Refreshing state... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03] azurerm_resource_group.rg_foreach["rg02"]: Refreshing state... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02] azurerm_resource_group.rg_foreach["rg01"]: Refreshing state... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01] azurerm_resource_group.rg_count[1]: Refreshing state... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azurerm_resource_group.rg_count[0] will be destroyed - resource "azurerm_resource_group" "rg_count" { - id = "/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03" -> null - location = "eastus" -> null - name = "rg03" -> null - tags = {} -> null } # azurerm_resource_group.rg_count[1] will be destroyed - resource "azurerm_resource_group" "rg_count" { - id = "/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04" -> null - location = "eastus" -> null - name = "rg04" -> null - tags = {} -> null } # azurerm_resource_group.rg_foreach["rg01"] will be destroyed - resource "azurerm_resource_group" "rg_foreach" { - id = "/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01" -> null - location = "eastus" -> null - name = "rg01" -> null - tags = {} -> null } # azurerm_resource_group.rg_foreach["rg02"] will be destroyed - resource "azurerm_resource_group" "rg_foreach" { - id = "/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02" -> null - location = "eastus" -> null - name = "rg02" -> null - tags = {} -> null } Plan: 0 to add, 0 to change, 4 to destroy. azurerm_resource_group.rg_foreach["rg02"]: Destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02] azurerm_resource_group.rg_foreach["rg01"]: Destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01] azurerm_resource_group.rg_count[0]: Destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03] azurerm_resource_group.rg_count[1]: Destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 10s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 10s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 10s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 10s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 20s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 20s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 20s elapsed] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 20s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 30s elapsed] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 30s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 30s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 30s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 40s elapsed] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 40s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 40s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 40s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 50s elapsed] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 50s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 50s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 50s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 1m0s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 1m0s elapsed] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 1m0s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 1m0s elapsed] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 1m10s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 1m10s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 1m10s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 1m10s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg01, 1m20s elapsed] azurerm_resource_group.rg_count[1]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg04, 1m20s elapsed] azurerm_resource_group.rg_count[0]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg03, 1m20s elapsed] azurerm_resource_group.rg_foreach["rg02"]: Still destroying... [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/rg02, 1m20s elapsed] azurerm_resource_group.rg_foreach["rg01"]: Destruction complete after 1m24s azurerm_resource_group.rg_count[1]: Destruction complete after 1m24s azurerm_resource_group.rg_foreach["rg02"]: Destruction complete after 1m25s azurerm_resource_group.rg_count[0]: Destruction complete after 1m25s Destroy complete! Resources: 4 destroyed. PS D:\Projects\Terraform\Testings\Terraform_Count_Vs_Foreach> |
Useful Articles
Terraform remote-exec provisioner with ssh connection in null_resource
Terraform fore_each for loop filter with if condition example
Terraform testing local variables and output csv file without resource Part 1
Terraform testing variable map object values without resource configuration part 2
Terraform foreach module output to show only required results
Hashicorp Terraform map and object inside module and variable example
Terraform one module deploy null or multiple resources based on input
Terraform A reference to a resource type must be followed by at least one attribute access, specifying the resource name
Create an Azure virtual machine scale set and load balancer using Terraform
Azure Terraform fixed Availibility Zones on Virtual Machine Scale Set
Writing and Using Terraform modules
Terraform Using one module variable in another module
Hashicorp Terraform dynamic block with example
Terraform for_each loop on map example