Terraform: for_each and count meta-arguments

By default, a terraform resource block adds one infrastructure resource when we apply the code, however, many times we may need to create several similar infrastructure resources with same configuration.

terraform flow

we can use count and for_each meta-arguments to achieve this.

Count

count meta-argument accepts a whole number and creates that many instances of the resource. Each instance is separate from other instances when creating, updating, deleting. We can use count meta-argument with every resource type.

Below example code uses count to create two instances of “null_resource

resource "null_resource" "bar" {
  count = 2
  provisioner "local-exec" {
    command = "echo ${count.index}"
  }
}

below is the plan for above code.

Terraform will perform the following actions:

  # null_resource.bar[0] will be created
  + resource "null_resource" "bar" {
      + id = (known after apply)
    }

  # null_resource.bar[1] will be created
  + resource "null_resource" "bar" {
      + id = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

below is the plan result. it prints 2 messages on screen for each instance.

Plan: 2 to add, 0 to change, 0 to destroy.
null_resource.bar[1]: Creating...
null_resource.bar[0]: Creating...
null_resource.bar[1]: Provisioning with 'local-exec'...
null_resource.bar[0]: Provisioning with 'local-exec'...
null_resource.bar[1] (local-exec): Executing: ["/bin/sh" "-c" "echo 1"]
null_resource.bar[0] (local-exec): Executing: ["/bin/sh" "-c" "echo 0"]
null_resource.bar[0] (local-exec): 0
null_resource.bar[1] (local-exec): 1
null_resource.bar[0]: Creation complete after 0s [id=7336107683621128284]
null_resource.bar[1]: Creation complete after 1s [id=1645344777701497525]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

it is also possible to use if condition to supply whole number to count.

following code creates one “null_resource” when env=”prod”, if not it will not create anything.

variable "env" {
 default = "prod"
}
resource "null_resource" "bar" {
  count = var.env == "prod" ? 1 : 0
  provisioner "local-exec" {
    command = "echo ${count.index}"
  }
}

for_each

We supply a map or list to for_each meta-argument to create instances for each item in that list or map. Each instance is separate from other instances when creating, updating, deleting. We can use for_each meta-argument with every resource type.

Below example code uses for_each to create two instances of “null_resource” for “prod” and “dev” times in environments list.

locals {
  environments = ["prod", "dev"]
}

resource "null_resource" "foo" {
  for_each = { for k in local.environments : k => k }
  provisioner "local-exec" {
    command = "echo ${each.key}"
  }
}

below is the plan for above code.

Terraform will perform the following actions:

  # null_resource.foo["dev"] will be created
  + resource "null_resource" "foo" {
      + id = (known after apply)
    }

  # null_resource.foo["prod"] will be created
  + resource "null_resource" "foo" {
      + id = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Below code uses a map called user_list to create multiple resources with for_each.

locals {
  user_list = {user="John", group="admin"}
}

resource "null_resource" "foo" {
  for_each = { for k,v in local.environments : k => v }
  provisioner "local-exec" {
    command = "echo ${each.key} is ${each.value}"
  }
}

Note: A given resource or module block cannot use both count and for_each

we can use if condition with for_each, in the following example, only when env=”prod” then for_each will create resource instances for users_list map.

locals {
  users_list = {user="John", group="admin"}
  env = "prod"
}

resource "null_resource" "foo" {
  for_each = { for k,v in local.users_list : k => v if local.env == "prod" }
  provisioner "local-exec" {
    command = "echo ${each.key} is ${each.value}"
  }
}

Conclusion

In this quick start demo we have tested terraform for_each and count meta-arguments with different examples. You can find information in Terraform official documentation.

More on Terraform:

Terratest: Writing Automated Tests for Terraform Code

Leave a Reply

%d