Explaining Count Loop in Terraform
2 min readNov 27, 2023
The aim of this pageđź“ť is to explain count
looping constructs in Terraform. Being new to HCL and its declarative nature, this looping construct/meta-argument is initially weird (there is also for_each
and dynamic blocks). So, you iterate, but you also assign a value (use =
) simultaneously. In addition, your loop is a part of the resource definition, not the other way around.
the count
loop is used to create multiple almost identical resources
- the
count
takes a positive integer or a0
- why
0
? because settingcount
to0
is a way to condition the creation of a resource - the definition syntax is very simple — use the keyword
count
right after theresource
declaration - it is possible and often useful to create a dedicated variable that is referred to in the
count
meta-argument instead of hardcoding the count with a number so that you control the same value used many times from a single place (classical DRY principle)
# DEFINITION
## SYNTAX
resource "<resource_type>" "<name_label>" {
count = <int>
...
}
## EXAMPLE #1
resource "aws_instance" "web_server" {
count = 3
tags = {
Name = "mrp-web-${count.index}:
}
}
## EXAMPLE #2
resource "aws_lb" "alb" {
count = var.instance_count
...
}
# THE VARIABLE USED THROUGOUHT THE CONFIG
variable "instance count" {
type = number
description = "Number of instances to create"
default = 2
}
there are 3 ways of referring with count
: <name>[count.index]
— <name>[<int>]
— <name>[*]
count
creates alist
of resources- the created
list
is referred by classical indexing syntax using square brackets - as terraform loops through items via
count
, it also creates and iterates overcount.index
count.index
value starts with0
- you explicitly use
count.index
for referring to resources if you are harmonizingcount
across resources
resource "aws_instance" "nginx" {
count = var.instance_count # <-- DRY
ami = nonsensitive(data.aws_ssm_parameter.amzn2_linux.value)
instance_type = "t2.micro"
}
# aws_lb_target_group_attachment
resource "aws_lb_target_group_attachment" "nginx" {
count = var.instance_count # <-- DRY
target_group_arn = aws_lb_target_group.nginx.arn
target_id = aws_instance.nginx[count.index].id # <--- `count.index` refering to the first resource within larger iteration
port = 80
}
- what is in the language is the possibility to refer to all instances at once by using a wildcard
*
- …this is a special character returning
list
of referred values for each instance - using
*
is known as splat syntax
# REFERENCE/INDEXING
## SYNTAX
<!-- <attribute> is optional -->
<resource_type>.<name_label>[element_index].<attribute>
<resource_type>.<name_label>[*].<attribute>
# REFERENCE EXAMPLE #1
aws_instance.web_server[count.index].name
aws_instance.web_server[0].name
aws_instance.web_server[*].name
# REFERENCE EXAMPLE #2
output "alb_id" {
value = "${var.deploy ? join("", aws_lb.alb.*.id) : ""}"
}