Understanding terraform count, for_each and for loop?
When you are working with collection variables
inside Terrafrom then you must understand the concept of loops with count
, loops with for each
and `for loop, otherwise, it will be really hard to iterate over collections such list, map and set.
This article is particularly focused on understanding how the loops work. We will see the example of each concept in more details -
Table of Content
1. Loops with count
As the name suggests we need to use count
but to use the count
first we need to declare collections inside our terraform file.
Let's create a collection variable of type list(string)
-
1variable "user_names" {
2 description = "IAM usernames"
3 type = list(string)
4 default = ["user1", "user2", "user3"]
5}
Here is the pictorial representation of the above list variable
-
In the above collection, we have created a list
of type string
which contains usernames and these usernames we are going to use for creating aws_iam_user
.
The code snippet shows how we are going to iterate over the list(string)
-
1resource "aws_iam_user" "example" {
2 count = length(var.user_names)
3 name = var.user_names[count.index]
4}
Here is the complete terraform
file -
1provider "aws" {
2 region = "eu-central-1"
3 access_key = "AKIATQ37NXB2OBQHAALW"
4 secret_key = "ilKygurap8zSErv7jySTDi2796WGqMkEtN6txxxx"
5}
6resource "aws_instance" "ec2_example" {
7
8 ami = "ami-0767046d1677be5a0"
9 instance_type = "t2.micro"
10 count = 1
11
12 tags = {
13 Name = "Terraform EC2"
14 }
15
16}
17
18resource "aws_iam_user" "example" {
19 count = length(var.user_names)
20 name = var.user_names[count.index]
21}
22
23variable "user_names" {
24 description = "IAM usernames"
25 type = list(string)
26 default = ["user1", "user2", "user3"]
27}
Once you apply this terraform configuration using the terraform apply
command, it will do the following on aws
-
- Create one
ec2
instance - Create three
IAM
users -user1
,user2
,user3
2. Loops with for_each
The for_each
is a little special in terraforming and you can not use it on any collection variable.
Note : - It can only be used on set(string)
or map(string)
.
The reason why for_each
does not work on list(string)
is because a list can contain duplicate values but if you are using set(string)
or map(string)
then it does not support duplicate values.
Let's first create a set(string)
variable -
1variable "user_names" {
2 description = "IAM usernames"
3 type = set(string)
4 default = ["user1", "user2", "user3s"]
5}
Now let's iterate over the variable user_names
.
1resource "aws_iam_user" "example" {
2 for_each = var.user_names
3 name = each.value
4}
Here is the complete terraform file with implementation of for_each
1provider "aws" {
2 region = "eu-central-1"
3 access_key = "AKIATQ37NXB2NN3D4ARS"
4 secret_key = "3v9mlwZQvmccL3ou1dxiDeEf1bWaG3kccpVlXXXX"
5}
6resource "aws_instance" "ec2_example" {
7
8 ami = "ami-0767046d1677be5a0"
9 instance_type = "t2.micro"
10 count = 1
11
12 tags = {
13 Name = "Terraform EC2"
14 }
15
16}
17
18resource "aws_iam_user" "example" {
19 for_each = var.user_names
20 name = each.value
21}
22
23variable "user_names" {
24 description = "IAM usernames"
25 type = set(string)
26 default = ["user1", "user2", "user3"]
27}
You can apply the above terraform configuration by running the command terraform apply
.
Here is the output which you will notice after running the command -
1# aws_iam_user.example["user1"] will be created
2 + resource "aws_iam_user" "example" {
3 + arn = (known after apply)
4 + force_destroy = false
5 + id = (known after apply)
6 + name = "user1"
7 + path = "/"
8 + tags_all = (known after apply)
9 + unique_id = (known after apply)
10 }
11
12 # aws_iam_user.example["user2"] will be created
13 + resource "aws_iam_user" "example" {
14 + arn = (known after apply)
15 + force_destroy = false
16 + id = (known after apply)
17 + name = "user2"
18 + path = "/"
19 + tags_all = (known after apply)
20 + unique_id = (known after apply)
21 }
22
23 # aws_iam_user.example["user3s"] will be created
24 + resource "aws_iam_user" "example" {
25 + arn = (known after apply)
26 + force_destroy = false
27 + id = (known after apply)
28 + name = "user3s"
29 + path = "/"
30 + tags_all = (known after apply)
31 + unique_id = (known after apply)
32 }
3. for loop
The for
loop is pretty simple and if you have used any programming language before then I guess you will be pretty much familiar with the for
loop.
Only the difference you will notice over here is the syntax in Terraform.
I am going to take the same example by declaring a list(string)
and adding three users to it - user1
, user2
, user3
1variable "user_names" {
2 description = "IAM usernames"
3 type = list(string)
4 default = ["user1", "user2", "user3"]
5}
You can use the above-declared variable inside your terraform file in a very simple way -
1output "print_the_names" {
2 value = [for name in var.user_names : name]
3}
You apply the above terraform configuration by running the command terraform apply
. And if you see the logs where it will show how many users it is going to create -
1# aws_iam_user.example["user1"] will be created
2 + resource "aws_iam_user" "example" {
3 + arn = (known after apply)
4 + force_destroy = false
5 + id = (known after apply)
6 + name = "user1"
7 + path = "/"
8 + tags_all = (known after apply)
9 + unique_id = (known after apply)
10 }
11
12 # aws_iam_user.example["user2"] will be created
13 + resource "aws_iam_user" "example" {
14 + arn = (known after apply)
15 + force_destroy = false
16 + id = (known after apply)
17 + name = "user2"
18 + path = "/"
19 + tags_all = (known after apply)
20 + unique_id = (known after apply)
21 }
22
23 # aws_iam_user.example["user3s"] will be created
24 + resource "aws_iam_user" "example" {
25 + arn = (known after apply)
26 + force_destroy = false
27 + id = (known after apply)
28 + name = "user3s"
29 + path = "/"
30 + tags_all = (known after apply)
31 + unique_id = (known after apply)
32 }
How to iterate over MAP?
We can use a similar approach to iterate over the map
also. But always keep in mind you need to specify the type of the map
like string
or number
.
Here is the same example which I have taken but modified a bit for map
-
1variable "iam_users" {
2 description = "map"
3 type = map(string)
4 default = {
5 user1 = "normal user"
6 user2 = "admin user"
7 user3 = "root user"
8 }
9}
Now let's iterate over the map
1output "user_with_roles" {
2 value = [for name, role in var.iam_users : "${name} is the ${role}"]
3}
Here is the difference between list and map syntax
For list -
1{for <ITEM> in <LIST> : <OUTPUT_KEY> => <OUTPUT_VALUE>}
For Map -
1{for <KEY>, <VALUE> in <MAP> : <OUTPUT_KEY> => <OUTPUT_VALUE>}
Read More - Terragrunt -
Posts in this Series
- Managing strings in Terraform: A comprehensive guide
- How to use terraform depends_on meta argument?
- What is user_data in Terraform?
- Why you should not store terraform state file(.tfstate) inside Git Repository?
- How to import existing resource using terraform import comand?
- Terraform - A detailed guide on setting up ALB(Application Load Balancer) and SSL?
- Testing Infrastructure as Code with Terraform?
- How to remove a resource from Terraform state?
- What is Terraform null Resource?
- In terraform how to skip creation of resource if the resource already exist?
- How to setup Virtual machine on Google Cloud Platform
- How to use Terraform locals?
- Terraform Guide - Docker Containers & AWS ECR(elastic container registry)?
- How to generate SSH key in Terraform using tls_private_key?
- How to fix-Terraform Error acquiring the state lock ConditionalCheckFiledException?
- Terraform Template - A complete guide?
- How to use Terragrunt?
- Terraform and AWS Multi account Setup?
- Terraform and AWS credentials handling?
- How to fix-error configuring S3 Backend no valid credential sources for S3 Backend found?
- Terraform state locking using DynamoDB (aws_dynamodb_table)?
- Managing Terraform states?
- Securing AWS secrets using HashiCorp Vault with Terraform?
- How to use Workspaces in Terraform?
- How to run specific terraform resource, module, target?
- How Terraform modules works?
- Terraform how to do SSH in AWS EC2 instance?
- What is terraform provisioner?
- Is terraform destroy needed before terraform apply?
- How to fix terraform error Your query returned no results. Please change your search criteria and try again?
- How to use Terraform Data sources?
- How to use Terraform resource meta arguments?
- How to use Terraform Dynamic blocks?
- Terraform - How to nuke AWS resources and save additional AWS infrastructure cost?
- Understanding terraform count, for_each and for loop?
- How to use Terraform output values?
- How to fix error configuring Terraform AWS Provider error validating provider credentials error calling sts GetCallerIdentity SignatureDoesNotMatch?
- How to fix Invalid function argument on line in provider credentials file google Invalid value for path parameter no file exists
- How to fix error value for undeclared variable a variable named was assigned on the command line?
- What is variable.tf and terraform.tfvars?
- How to use Terraform Variables - Locals,Input,Output
- Terraform create EC2 Instance on AWS
- How to fix Error creating service account googleapi Error 403 Identity and Access Management (IAM) API has not been used in project before or it is disabled
- Install terraform on Ubuntu 20.04, CentOS 8, MacOS, Windows 10, Fedora 33, Red hat 8 and Solaris 11