Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provisionning multiple resources depending on one another #2677

Closed
ghost opened this issue Jul 10, 2015 · 9 comments
Closed

Provisionning multiple resources depending on one another #2677

ghost opened this issue Jul 10, 2015 · 9 comments
Assignees
Labels

Comments

@ghost
Copy link

ghost commented Jul 10, 2015

I am trying to create 3 EC2 instances for a Mesos cluster. I would then like to save the private_ip of all 3 instances in each of them:

resource "aws_instance" "mesos-master" {
    count = 3
    ami = "ami-cf35f3a4"
    instance_type = "t2.micro"

    provisioner "remote-exec" {
        inline = [
          "echo ${count.index+1} > /tmp/myid",
          "echo ${aws_instance.mesos-master.self.private_ip} > /tmp/myip",
          "echo ${element(aws_instance.mesos-master.*.private_ip, count.index)} > /tmp/masterips"
        ]
    }
}

Which gives me the following error when I run terraform plan:

connection info cannot contain splat variable referencing itself

I also tried this:

resource "aws_instance" "mesos-master" {
    count = 3
    ami = "ami-cf35f3a4"
    instance_type = "t2.micro"

    provisioner "remote-exec" {
        inline = [
          "echo ${count.index+1} > /tmp/myid",
          "echo ${aws_instance.mesos-master.self.private_ip} > /tmp/myip",
          "echo ${aws_instance.mesos-master.0.private_ip} > /tmp/masterip-1",
          "echo ${aws_instance.mesos-master.1.private_ip} > /tmp/masterip-2",
          "echo ${aws_instance.mesos-master.2.private_ip} > /tmp/masterip-3",
        ]
    }
}

Which does nothing and just hangs. Probably because it's stuck in a dependency cycle.
Is there a way to work around this and somehow wait for all instances to be created before provisioning all of them?

@phinze
Copy link
Contributor

phinze commented Jul 10, 2015

Good question! Pretty sure there's a way to accomplish this. I'll circle back when I get the chance to fiddle around with some examples and post my findings.

@phinze phinze self-assigned this Jul 10, 2015
@nrcxcia
Copy link

nrcxcia commented Jul 10, 2015

Set the private_ip's to static values with variable lookups.

variable "instance_ips" {
  default = {
    "0" = "10.11.12.100"
    "1" = "10.11.12.101"
    "2" = "10.11.12.102"
  }
}

I think maybe provisioner should exist outside of resource.

@phinze
Copy link
Contributor

phinze commented Jul 10, 2015

Managed to accomplish this behavior with a "null_resource" - moving the provisioners to that allowed them to properly depend on the whole collection of EC2 instances booting first.

module "ami" {
  source = "github.com/terraform-community-modules/tf_aws_ubuntu_ami/ebs"
  region = "us-west-2"
  distribution = "trusty"
  instance_type = "t2.micro"
}

resource "aws_instance" "mesos-master" {
  count         = 3
  ami           = "${module.ami.ami_id}"
  instance_type = "t2.micro"
  key_name      = "tftest"
}

resource "null_resource" "configure-mesos-ips" {
  count = 3

  connection {
    user = "ubuntu"
    host = "${element(aws_instance.mesos-master.*.public_ip, count.index)}"
  }

  provisioner "remote-exec" {
    inline = [
      "echo '${element(aws_instance.mesos-master.*.private_ip, count.index)}' > /tmp/myip",
      "echo '${join(",", aws_instance.mesos-master.*.private_ip)}' > /tmp/masterips",
    ]
  }
}

This results in each machine having /tmp/myip with its private IP and /tmp/masterips with a comma separated list of master ips.

Let me know if this meets your needs, @mickael1787!

@ghost
Copy link
Author

ghost commented Jul 11, 2015

Thanks @phinze ! Didn't know about the "null_resource".

@kaelumania
Copy link

@phinze this does not work when one of the aws_instances is down and you reapply, then the provisioner for this instance is not being reexecuted. You can use the trigger option, but this results in executing the provisioner for ALL aws_instances not only for the one recreated.

@phinze
Copy link
Contributor

phinze commented Feb 5, 2016

Hi @kaelumania - once #3449 is fixed, that trigger strategy should work properly for you. 👍

carlosonunez pushed a commit to carlosonunez/code-for-demos that referenced this issue Jul 19, 2017
…lf-referencing splat error that preventing me from using the same approach taht I did with the (single-node) managers. using a null resource with triggers proports to solve this. See: hashicorp/terraform#2677
@dhrsharma
Copy link

You can also use instance metadata endpoints in your user data, like LOCAL_IP=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)

@birdypme
Copy link

birdypme commented Feb 5, 2019

Hello, you can also use the 'self' variable inside provisioners: terraform doc: interpolation "attributes of your own resource"

In your case, this fixes accessing the ip for the current resource, but you still need a null_resource to build the full list of ips:

resource "aws_instance" "mesos-master" {
    count = 3
    ami = "ami-cf35f3a4"
    instance_type = "t2.micro"

    provisioner "remote-exec" {
        inline = [
          "echo ${count.index+1} > /tmp/myid",
          "echo ${self.private_ip} > /tmp/myip",
        ]
    }
}

@github-actions
Copy link

github-actions bot commented Jun 2, 2021

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants