The symptom is that I get -/+ aws_instance.stage on each exec of plan and apply. Changing associate_public_ip_address from true to false did recreate the instance as expected, but subsequent plans and applies ALSO recreated the instance due to associate_public_ip_address: "true" => "false" (forces new resource). Naturally I inspected state and find that it correctly contains "associate_public_ip_address": "false".
Perhaps a more pertinent detail is that I converted from 0.6.16 to 0.7.8 on this run, after which it began acting as described. I'm not sure if the conversion is related but since this same code does not behave this way in an existing 0.7.7 env, I'm going to start off looking at changes in the latest version.
0.7.8 & 0.8.1
associate_public_ip_address = false
The tf code has not changed, and in fact the same symlinked file performs as expected in 0.7.7
Please provider a link to a GitHub Gist containing the complete debug output: https://gist.githubusercontent.com/Gary-Armstrong/abee399a98d8f297ad149b72d77eac3b/raw/f131e32dff6f13f4bd139a41a929fa32b88001f9/TF%25200.7.8%2520Adventure%2520in%2520Plan+Apply%2520Unexpectations
I expected after the initial recreation of the instance that it would not happen again.
TF will plan and apply a -/+ action on the instance, citing the same change reason.
terraform applyMoved from 0.6.16 to 0.7.8, while other envs in this repo use 0.7.7 instead.
Same problem here since upgrading from 0.7.7 to 0.7.8.
Terraforms wants to associate a public ip address to my instances configured with public_ip_address = false.
And even for a stopped instance with public_ip_address = true, the plan execution want to change the flag from false to true. If I start it, the plan execution have no changes to apply.
Something is wrong with 0.7.8 at this point.
@Gary-Armstrong maybe you have an EIP association on your instances ? I had this problem so it explains probably this behavior. For the second case where the instance is stopped it is definitely a bug of TF as the instance has already a public IP and it's not an elastic IP.
I do have an EIP association on all of my instances, and this has not changed for quite some time. TF 0.7.7 is able to handle this config with an EIP, while 0.7.8 seems to have some trouble. Is it related to the EIP association? I do not know.
The return from AWS appears identical in both cases (unsurprisingly) on a casual inspection. I don't know how TF normally would determine if there is an EIP which is providing the public IP (have not gone looking inside TF), but I also don't know why it would rely on that describe instances data to determine if the associate_public_ip field has changed. I didn't see any indicator in the return data if it is a EIP or just a public IP.
I also have this issue with hosts that have associate_public_ip_address = false as well as an EIP.
Looks like it detects an EIP as if it was an public_ip_address on the machine itself ?
Using git-bisect seems related to this change: e79ebfc11331e0173967eca497532c0de3a02ce0
commit e79ebfc11331e0173967eca497532c0de3a02ce0
Date: Wed Oct 19 16:16:04 2016 +0100
Infer aws_instance.associate_public_ip_address from the presence of a network interface association.
diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go
index c50cb80..a5dfa4b 100644
--- a/builtin/providers/aws/resource_aws_instance.go
+++ b/builtin/providers/aws/resource_aws_instance.go
@@ -498,6 +498,7 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
if *ni.Attachment.DeviceIndex == 0 {
d.Set("subnet_id", ni.SubnetId)
d.Set("network_interface_id", ni.NetworkInterfaceId)
+ d.Set("associate_public_ip_address", ni.Association != nil)
}
}
} else {
A workaround is to add:
lifecycle {
ignore_changes = [
"associate_public_ip_address",
]
}
Although this does seem like a major regression in v0.7.8 and hopefully can be fixed as such.
Even if this means reverting e79ebfc until a more proper fix for it can be found.
Just to add a few more informations, I backed down to the 0.6.16 state file and then converted successfully to 0.7.7 with no sign of the symptom in this issue. In fact, since I had already done edits to move to 0.7.X, I didn't have to change any TF code.
The bulk of the work was due to SG rules being out of sync, which is a chronic problem in any fail case involving SG changes (unfortunately I had some CIDR changes as part of the 0.7.8 apply). The set of rules were therefore in AWS but not in my rolled-back state file.
I know it's not directly related, but terraform import didn't do anything to solve this, basically being unable to import a SG rule resource alone. Importing the entire SG ran afoul of the fact that the (incorrect) rule resources were indeed already in state. I resorted to the old "Shellaform" process whereby I added some identical rules to a SG (via TF) designed for this purpose, added that to the instances (via TF), then manually deleted the AWS-but-not-TF rules from the AWS web console.
Same problem here, with the following configuration:
resource "aws_instance" "ssh-bastion" {
...
associate_public_ip_address = false
}
resource "aws_eip_association" "ip-bastion" {
instance_id = "${aws_instance.ssh-bastion.id}"
allocation_id = "${aws_eip.ssh-bastion.id}"
}
resource "aws_eip" "ssh-bastion" {
vpc = true
}
i'm currently using this configuration to prototype a new deployment so I destroyed and re-created this a lot of time. Starting from an empty AWS configuration and running an initial apply works OK, but without touching the Terraform configuration, running plan just after produces the symptom posted by OP in the very first paragraph.
I got the problem after upgrading from Terraform 0.7.6 to 0.7.8
Surprised that not more people have this issue since this seems to effect any aws_instance with aws_eip and associate_public_ip_address = false.
Terraform 0.7.10 still has this issue:
-/+ module.bastion_host_1.aws_instance.bastion
ami: "ami-2ef48339" => "ami-2ef48339"
associate_public_ip_address: "true" => "false" (forces new resource)
...
This https://github.com/hashicorp/terraform/pull/9453 pull request seems to have introduced this bug in order to try and solve https://github.com/hashicorp/terraform/issues/8187.
IMO the cure at this point is worse then the illness. Better to either fix #8187 correctly or at least revert so that infrastructure does not break. (If we want to revert https://github.com/hashicorp/terraform/pull/9453 this PR also seems related https://github.com/hashicorp/terraform/pull/9560)
I wonder that more people are not seeing this, or maybe they are just being quiet.
I made several new instances today with TF 0.7.7 and before I start working on something else, I tried a plan using TF 0.7.13. I wasn't VERY surprised to see this was still a problem.
Fresh instances started off with:
associate_public_ip_address = false
Everything works great in TF 0.7.7 but 0.7.13 plan does:
-/+ aws_instance.viewer
ami: "ami-648ce573" => "ami-648ce573"
associate_public_ip_address: "true" => "false" (forces new resource)
availability_zone: "us-east-1b" => "us-east-1b"
for each instance in the entire state, old and new.
@Gary-Armstrong we are seeing this as well.
This occurs in TF v0.8.0 exactly as in v0.7.8
Also TF v0.8.1
I had this in 0.7.8, just tested and its in 8.0.1 as well.
Plan wants to change two instances that already have associate_public_ip_address = true to true again: associate_public_ip_address: "false" => "true" (forces new resource)
Also in TF 0.8.2
machines with associate_public_ip_address 'true' but are currently stopped are seen as 'false'.
This triggers destruction of the machine and starting of an entirely new machine, while it should not do anything.
To be clear, this fails for me even without the usage of any EIP.
I accidentally discovered some more information about this issue.
I am currently refactoring some instances into a separate state file and using data.terraform_remote_state which so far works just fine. I am also using state mv to move things into the new state, but I am mostly reusing the same HCL but minus the data source changes required to read from the master state.
Just to be clear, unchanged code in the instance definition:
associate_public_ip_address = false
lifecycle {
ignore_changes = [
"user_data",
"ephemeral_block_device",
"associate_public_ip_address"
]
}
Having not changed either the associate_public_ip_address nor the ignore_changes list in the lifecycle block, I was surprised to see my old enemy:
associate_public_ip_address: "true" => "false" (forces new resource)
availability_zone: "us-east-1b" => "us-east-1" (forces new resource)
I pasted in the availability_zone line for a reason. The AZ variable was previously reading from a local tfvars in the original dir, but not in the new code, and I forgot to convert the string interpolation to use data.terraform_remote_state so we see the b is missing.
There are three instances to fix in the new sub-state and so I fixed the availability_zone interpolation in one of them. I then ran a plan because I have been using TF for over a year. Interestingly:
~ aws_instance.compute_200
Most importantly, the -/+ is gone. The change here is because I still need to fix region interpolation in tags.Name. Simply due to realigning the availability_zone value in HCL to match state. The -/+ is still present in the other 2 instance plans.
Does this help anyone?
same here with terraform v0.8.4
Still exists with terraform v0.8.5
Issue present in TF 0.9.0
I'm wondering, what's your default setting for the subnet? I'm going to take a wild guess and say that your subnet defaults to true for map_public_ip_on_launch. There was discussion (though now searching fails me) whereby I've raised this or it has been raised before about the tri-state nature of the aws_subnet resource.
IMO - what the user specifies should win no matter what the harvested results from aws_subnet return. If this is also now making an evaluation between map_public_ip_on_launch and the instance attribute public_ip, that's another additional problem.
Present in 0.9.2
My subnets are defined with map_public_ip_on_launch = false in all cases. Naturally this is because I only want to connect to internets when I assign a EIP.
I did validate in the AWS console that "Auto-assign Public IP: no" is present for one of the affected subnets.
Present in 0.9.5 :(
And 0.9.6, still not working correctly.
Terraform v0.11.7
+ provider.aws v1.20.0
Still an issue.
Okay so the problem was that my default subnet was set to create public IP addresses automatically.
In order to solve this:
Not sure if there is a programmatic way to do this on all default subnets.
Okay so the problem was that my default
subnetwas set to create public IP addresses automatically.In order to solve this:
- Go to your subnet > Actions
- Modify auto-assign IP settings
- Uncheck: Auto-assign IPv4
Not sure if there is a programmatic way to do this on all default subnets.
This didn't work for me, using Terraform v0.11.8 and provider.aws v1.39.0.
None of my subnets auto-assign IPv4, yet Terraform still wants to change associate_public_ip_address from true to false regardless of my map_public_ip_on_launch setting, or the auto-assign IPv4 setting.
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.
Most helpful comment
Also in TF 0.8.2
machines with associate_public_ip_address 'true' but are currently stopped are seen as 'false'.
This triggers destruction of the machine and starting of an entirely new machine, while it should not do anything.
To be clear, this fails for me even without the usage of any EIP.