How to understand the execution order of provisioner in Terraform script?

3,181 views
Skip to first unread message

Sean Bigdatafun

unread,
May 25, 2016, 5:35:46 PM5/25/16
to Terraform
(the example is from Terraform document page https://www.terraform.io/intro/getting-started/provision.html)

In the following script, I understand resource "ip" depends on "example". My understanding is that Terraform reach out AWS API and create EC2 instance first, and then create EIP resource secondly using AWS API.


Because of the above order, I think "aws_instance.example.public_ip" variable has not been computed at the time of "local-exec" provisioner is executed. However, it turns out this script is working. 

Can someone help me to understand how that worked out?

provider "aws" {

  access_key = "ACCESS_KEY_HERE"

  secret_key = "SECRET_KEY_HERE"

  region     = "us-east-1"

}



resource "aws_instance" "example" {

  ami           = "ami-0d729a60"

  instance_type = "t2.micro"

  provisioner "local-exec" {

    command = "echo ${aws_instance.example.public_ip} > file.txt"

  }

}


resource "aws_eip" "ip" {

    instance = "${aws_instance.example.id}"

    depends_on = ["aws_instance.example"]

}

David Maze

unread,
May 25, 2016, 6:45:37 PM5/25/16
to Terraform
On Wednesday, May 25, 2016 at 5:35:46 PM UTC-4, Sean Bigdatafun wrote:
Because of the above order, I think "aws_instance.example.public_ip" variable has not been computed at the time of "local-exec" provisioner is executed. However, it turns out this script is working. 

If you log into the AWS console, is the EIP public address actually the same as the public IP address you're logging?  Or, add

output "eip_address" { value = "${aws_eip.eip.public_ip}" }

and re-run "terraform apply"; does the address match?
 
Can someone help me to understand how that worked out?

I'm going to guess that you're deploying on to a public subnet, and so you are getting a public IP address even without having the EIP defined.  Since you're using an output of aws_instance.example you don't need to explicitly depends_on it, this happens automatically.

I think the piece you're missing is a null_resource provisioner, that you can run after the EIP exists.  (I just started using null_resource this week.  It's surprisingly awesome, especially if your provisioner is something vaguely expensive that you'd like to be able to re-run without destroying your instance.)  So I think you need:

provider "aws" {}
resource "aws_instance" "example" { ... } # with no provisioners
resource "aws_eip" "eip" {
  instance = "${aws_instance.example.id}"
resource "null_resource" "example" {
  triggers {
    eip = "${aws_eip.eip.allocation_id}"
  }
  connection {
    host = "${aws_instance.example.private_ip}"
  }
  provisioner "local-exec" {

    command = "echo ${aws_eip.eip.public_ip} > file.txt"

  }

}

Sean Bigdatafun

unread,
May 25, 2016, 7:37:18 PM5/25/16
to Terraform
Thanks -- your answer gave me the hint.

Let me self-clarify my own question, i.e., why I asked. I missed EIP with the (automatically assigned) Public IP.  The follow script did not ask for EIP information, instead, it asks the (automatically assigned) Public IP from that instance. 

  provisioner "local-exec" {

    command = "echo ${aws_instance.example.public_ip} > file.txt"

  }


I originally thought there exists a mutual dependency (there would be a mutual dependency if the provisioner execute the following command though, I think)
Reply all
Reply to author
Forward
0 new messages