Terraform – Resolving Cycle Error with AWS EC2 Instance, Volume, and Template File

terraform

Could you please help to explain and work around this error?

I have the following TF program for an instance with an EBS volume and template file using that volume id:

resource "aws_instance" "edge1" {

  instance_type = "t3a.micro" 

  ami = data.aws_ami.ubuntu.id
  key_name = "ozonm"

  £ root block device 
  root_block_device {
    volume_size = 10
  }

  user_data = data.template_file.user_data_edge1.rendered

}
£ End of resource "aws_instance" "edge1" 

£
£ EBS for homes
£
resource "aws_ebs_volume" "homes" {
  availability_zone = aws_instance.edge1.availability_zone
  size = 1
}

resource "aws_volume_attachment" "homes-volume-attachment" {
  device_name = "/dev/xvdf"
  instance_id = aws_instance.edge1.id
  volume_id   = aws_ebs_volume.homes.id
}

data "template_file" "user_data_edge1" {  
  template = file("metadata-edge1.yml", { vol_id = aws_ebs_volume.homes.id })
}

So this gives me a cycle error:

 Error: Cycle: data.template_file.user_data_edge1, aws_instance.edge1, aws_ebs_volume.homes

while I think it should not. I know what circular dependence is, when first objects refers to the second, while the second refers to the first. But I think it's totally fine in this case with the following order:

  • volume is created
  • template file is rendered using the volume id
  • instance is created with the template file for user_data
  • volume is attached to the instance

But the TF graph shows that the instance depends on the volume:

TF graph

So, why is this happening, and how can I use a volume id in the template file for the instance?

Thanks in advance!

Best Answer

Ok, so after some experiments, I found that the solution is to use depends_on meta-argument.

resource "aws_instance" "edge1" {

 depends_on [
    aws_ebs_volume.homes
 ]

In this case also availability_zone in aws_ebs_volume.homes must not refer back to the instance.

Also, use of data for making a template is not necessary, one can place template right into the body of aws_instance resource definition:

user_data = templatefile(...)