How do I work with "count" and connection.host using Terraform?

September 11, 2019 93 views
Terraform DigitalOcean

Using this setup

me@mybox:~terraform -v
Terraform v0.12.8
+ provider.digitalocean v1.7.0

I try to create two droplets serving Nginx using this Terraform file

resource "digitalocean_droplet" "web" {

    count = 2
    name  = "web-${count.index}"

    image = "ubuntu-14-04-x64"
    region = "fra1"
    size = "512mb"
    private_networking = true
    ssh_keys = [
      "${var.ssh_fingerprint}"
    ]

  connection {
    user = "root"
    type = "ssh"
    host = digitalocean_droplet.web[count.index].ipv4_address
    private_key = "${file(var.pvt_key)}"
    timeout = "2m"
  }

  provisioner "remote-exec" {
    inline = [
      "export PATH=$PATH:/usr/bin",
      # install nginx
      "sudo apt-get update",
      "sudo apt-get -y install nginx",
      "curl -sSL https://repos.insights.digitalocean.com/install.sh | sudo bash"
    ]
  }
}

but get this error when running terraform plan

Error: Cycle: digitalocean_droplet.web[1], digitalocean_droplet.web[0]

If I change the specification of connection.host to foo terraform runs without errors. Of course, it becomes hard to run any commands on the host afterwards, so my question is this:

How do I specify the host address when using count variables?

Thanks in advance and have a nice day,
Morten

2 Answers
asb MOD September 11, 2019
Accepted Answer

Rather than using the count, you can simplify this a bit by referencing self.ipv4_address and Terraform will do the right thing. self allows you to access attributes of the resource it is called from.

Putting this all together, you get:

resource "digitalocean_droplet" "web" {

    count = 2
    name  = "web-${count.index}"

    image = "ubuntu-14-04-x64"
    region = "fra1"
    size = "512mb"
    private_networking = true
    monitoring = true
    ssh_keys = [
      "${var.ssh_fingerprint}"
    ]

  connection {
    user = "root"
    type = "ssh"
    host = self.ipv4_address
    private_key = "${file(var.pvt_key)}"
    timeout = "2m"
  }

  provisioner "remote-exec" {
    inline = [
      "export PATH=$PATH:/usr/bin",
      # install nginx
      "sudo apt-get update",
      "sudo apt-get -y install nginx",
      "curl -sSL https://repos.insights.digitalocean.com/install.sh | sudo bash"
    ]
  }
}

Thank you a metric ton, asb! That did the trick.

As you might have guessed, I have just started my journey into Terraform and your help on this matter has been invaluable. Should your life bring you through Denmark, make sure to drop in for a serving of your favourite beverage!

Have another answer? Share your knowledge.