Refreshing aws_instance's public_dns

442 views
Skip to first unread message

Kent Shultz

unread,
Nov 30, 2015, 1:58:30 PM11/30/15
to Terraform
Hello all,

I'm running into trouble using an aws_route53_record in the following terraform plan:

resource "aws_instance" "app" {
  associate_public_ip_address
= false

  tags
{
   
Name = "${var.my_instance_name}”
  }
}

resource "
aws_eip" "app" {
  instance = "
${aws_instance.app.id}"
  vpc = true
}

resource "
aws_route53_record" "cluster_base" {
  zone_id = "
${var.my_r53_zone}"
  type = "
CNAME"
  name = "
${var.my_instance_name}.${var.my_r53_domain}."

  records = [
    "
${aws_instance.app.public_dns}"
  ]

  depends_on = [
    "
aws_eip.app"
  ]
}

I've left out some (most) arguments above for brevity.

As you can see, I'm creating an EC2 instance, attaching an EIP to it, and then trying to create a CNAME record pointing to the public_dns of the instance. The problem is that the instance's public_dns attribute is empty when the aws_route53_record resource provisions (because I'm using associate_public_ip_address = false), and the resource is not allowed to have an empty value for its records argument.

I get the following error on a terraform apply:

Error applying plan:

1 error(s) occurred:

* aws_route53_record.cluster_base: InvalidChangeBatch: Invalid Resource Record: FATAL problem: DomainNameEmpty encountered at
    status code
: 400, request id: 4c86cc78-9792-11e5-88cf-b3d969a424ae

I came up with a workaround here -- basically having the EIP resource poll for the instance's public_dns until it's not empty, and adding that as a public_dns attribute to the EIP -- but I'm sure this isn't the right away to go about this.

Is there a simpler way to have the aws_instance refresh it's attributes *after* the aws_eip attaches to it, so that the route53 record gets the most up-to-date value of the instance's public_dns?

Thanks in advance!
Kent

Kent Shultz

unread,
Nov 30, 2015, 2:19:03 PM11/30/15
to Terraform
For reference, here's the plan updated to use the hacky gist:

resource "aws_instance" "app" {
  associate_public_ip_address
= false

  tags
{
   
Name = "${var.my_instance_name}”
  }
}

resource "
aws_eip" "app" {
  instance = "
${aws_instance.app.id}
"
  vpc = true
  wait_for_instance_dns = true
}

resource "
aws_route53_record" "cluster_base" {
  zone_id = "
${var.my_r53_zone}"
  type = "
CNAME"
  name = "
${var.my_instance_name}.${var.my_r53_domain}."

  records = [
    "
${aws_eip.app.public_dns}"
  ]
}

Paul Hinze

unread,
Dec 3, 2015, 7:38:13 PM12/3/15
to terrafo...@googlegroups.com
Hi Kent,

Interesting scenario!

First, it's each resource's responsibility to poll until it is "ready for service". I believe aws_eip might be failing to perform the proper polling that should guarantee it's ready to go. Looking at the code it does seem like it just calls AssociateAddress and moves on. That's probably worth filing as a bug.

The refresh of the instance's public_dns is trickier. It's actually a similar problem to the one being discussed over in this ML thread. Theoretically what we should be able to express is something like this:

resource "aws_instance" "app" {
  associate_public_ip_address = false

  # !!! Proposed config, does not work today.
  refresh_on = ["aws_eip.app"]
}

resource "aws_eip" "app" {
  instance = "${aws_instance.app.id}"
}

resource "aws_route53_record" "cluster_base" {
  records = ["${aws_instance.app.public_dns}"]

  depends_on = [
    "aws_eip.app"
  ]
}

That would cause the order of operations to be:

 * Create instance
 * Create and associate EIP
 * Refresh instance
 * Create record

Today, we don't have functionality like that. Could I make the naive workaround suggestion of switching to an A record that references the EIP directly? :)

Paul


--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-too...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/5ac41e82-d43b-4793-b044-a0fdc036f020%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Kent Shultz

unread,
Dec 3, 2015, 9:07:51 PM12/3/15
to Terraform
Hey Paul,

Thanks for the reply!
 
Could I make the naive workaround suggestion of switching to an A record that references the EIP directly? :)

In fact that's what I'm doing for now :) It's preferable to actually deploying my aws_eip hack from the gist. However, I'd like to get the CNAME -> instance.public_dns working eventually.


First, it's each resource's responsibility to poll until it is "ready for service". I believe aws_eip might be failing to perform the proper polling that should guarantee it's ready to go. Looking at the code it does seem like it just calls AssociateAddress and moves on. That's probably worth filing as a bug.

How exactly is it a bug? Assuming the AssociateAddress call returns successfully (and it is, in my testing), isn't the EIP actually good to go? What else should it be checking before returning?

Interesting idea with
refresh_on! Nearly all single-server-oriented configuration management tools (Chef, SaltStack, etc) provide ways for resources to "watch" one another for refreshes, and then refresh themselves. It would be a nice addition to Terraform!

If I can understand how aws_eip may be buggy now, I'm happy to file a bug or issue. Otherwise, I'll use my A record for now and look forward to
refresh_on.

Cheers,
Kent


Paul Hinze

unread,
Dec 4, 2015, 9:37:18 AM12/4/15
to terrafo...@googlegroups.com
How exactly is it a bug? Assuming the AssociateAddress call returns successfully (and it is, in my testing), isn't the EIP actually good to go? What else should it be checking before returning?

In many places in the AWS API, a successful response merely indicates that the action has been started, not that it has taken effect. In these cases we add code to Terraform to poll until the resource reaches the correct state. RunInstances is a good example - aws_instance polls while the instances goes through all the various "pending" states until it is "running".

If your experience with attaching EIPs is that a successful response from the initial API call is sufficient to move forward, then we are AOK!



Kent Shultz

unread,
Dec 4, 2015, 3:51:01 PM12/4/15
to Terraform
Aha, I see. Another example is the aws_route53_record resource, which invokes the GetChange operation repeatedly until it returns 'INSYNC'.

AFAIK there's not any property of an EIP that reflects the status of a call to AssociateAddress. I haven't noticed any problems in the state of an aws_eip resource when terraform is finished applying it.

Thanks for the explanation!

Kent
Reply all
Reply to author
Forward
0 new messages