count (int) - The number of identical resources to create. This doesn’t apply to all resources. For details on using variables in conjunction with count, see Using Variables with count below.
TL;DR: only use the count
attribute to enable resources.
Basic example
The count
attribute can be used to instantiate multiple resources with a single resource declaration. Here we instanciate 10 EC2 instances:
Eg:
resource "aws_instance" "web" {
count = 10
ami = "ami-0cdba8e998f076547"
instance_type = "t2.micro"
}
On the surface it looks useful but it suffers from a number of limitations that make it almost useless.
Pattern: enable
attribute
This is pretty much the only viable use-case for the count
attribute. Use count = 0
to disable a resource and count = 1
to enable it.
Even then, evaluation might fail if the resource is disabled and another resource depends on it’s outputs.
Eg:
variable "enable_elb" {
default = 1
}
resource "aws_elb" "bar" {
count = "${var.enable_elb}"
name = "foobar-terraform-elb"
availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"]
listener {
instance_port = 8000
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
instances = ["${aws_instance.web.id}"]
cross_zone_load_balancing = true
idle_timeout = 400
connection_draining = true
connection_draining_timeout = 400
}
Anti-pattern: avoid repetition
Forget DRY with Terraform. Copy-and-paste is your friend :slight_smile:
This is a natural usage of count
. Don’t do this:
variable "users" {
type = "list"
}
resource "aws_iam_user" "my-users" {
count = "${length(var.users)}"
name = "${element(var.users, count.index)}"
path = "/"
}
Let’s say I instantiace that module with:
module "my-users" {
source = "../tf_my_users"
users = [
"bob",
"alice",
"jannet",
]
}
This will work great on the first invocation. The problem is that each aws_iam_user
is actually a different resource.
Let’s say that later that bob
leaves the company.
aws_iam_user.my-users.0 "bob" => "alice"
aws_iam_user.my-users.1 "alice" => "jannet"
aws_iam_user.my-users.2 "jannet" => ""
All the users get re-created, invalidating their AWS credentials. With bad luck your current AWS account might be in that list.
So in conclusion, Terraform deals with individual resources. Having them tied to a specific ordering is quite a bad idea as it makes the application of those resource inflexible.
For that use-case it’s better to copy-and-paste the IAM user. Or write a script that generates the terraform code from the list of users.