0
votes

I'm starting with terraform and I'm building a small project, just some aws instances which one with an ebs volume attached.

I believe I'll start to work with terraform more, so I want to do the work by defining modules that I can then reuse in other projects.

For that, I created 3 modules (one for instances, another to create ebs volumes and the last one to attach the volumes).

On other place, I have a "main.tf" in which I call those modules. The problem I'm having is that to create and attach volumes I need some data like the instanceID.

To get the InstanceID I defined an output variable on the "instance" module (which has to be a list in case the instance count is more than one):

output "instance_id" {
  value = ["${aws_instance.instance.*.id}"]
}

Then, on my main.tf file I call the variable on the module:

module "aws-instance" {
  source = "../../Terraform/aws-instance"
  instance_type = "t2.micro"
  instance_count = "2"
}

(some other code...)

module "aws-volume-attachment" {
  source = "../../Terraform/aws-volume-attachment"
  device_name = "/dev/sdf"
  instance_id = "${element("${module.aws-instance.instance_id}", count.index)}"
  volume_id = "${element("${module.aws-ebs-volume.volume_id}", count.index)}"
}

But I get an error:

Error: module "aws-volume-attachment": count variables are only valid within resources

My question is, how can I loop over the variable so that I can attach each volume to one instance ?

2

2 Answers

1
votes

"Count" is not supported when declaring Terraform modules. You have 2 options:

  1. Declare module for each instance and for each ebs volume. And pass variables into module without "count.index" part.

  2. Put Both EC2 and ESB in the same module, as they can't really work without each other. This a good practice for structuring terraform projects - to make modules for entire application stacks. Because when you have too many small modules - it becomes a bit messy.

1
votes

Count is not supported in modules, only in resources. In your instance you would want to pass the value of instance_count to the instance, volume and attachment modules. You would then use instance_count for the value of count within the modules (at the resource level).

If it is using count, your aws-instance module will output a "list" of instance_ids. The same would go for the volumes.

Pass these lists into the aws-volume-attachment module (instance_id and volume_id variables must be of type list) then iterate over these using count.index.

Excuse the resource name, I'm not familiar with AWS provider as I work with Azure, but hopefully this shows the principal.:

resource "aws-volume-attachment" {
  count = "${var.instance_count}"
  ...

  volume_id = "${var.volume_ids[count.index]}"
  instance_id = "${var.instance_ids[count.index])"
}