I spent some time working through this problem and found the other answers helpful, but incomplete.
For those people trying to reallocate an AWS elastic IP using Terraform, we can do so using a combination of terraform_remote_state and the aws_eip_association. Let me explain.
We should use two separate root modules, themselves within a parent folder:
parent_folder
├--elasticip
| └main.tf
└--server
└main.tf
In elasticip/main.tf you can use the following code which will create an elastic IP, and store the state in a local backend so that you can access its output from the server module. The output variable name cannot be 'id', as this will clash with the remote state variable id and it will not work. Just use a different name, such as eip_id.
terraform {
backend "local" {
path = "../terraform-eip.tfstate"
}
}
resource "aws_eip" "main" {
vpc = true
lifecycle {
prevent_destroy = true
}
}
output "eip_id" {
value = "${aws_eip.main.id}"
}
Then in server/main.tf the following code will create a server and associate the elastic IP with it.
data "terraform_remote_state" "eip" {
backend = "local"
config = {
path = "../terraform-eip.tfstate"
}
}
resource "aws_eip_association" "eip_assoc" {
instance_id = "${aws_instance.web.id}"
allocation_id = "${data.terraform_remote_state.eip.eip_id}"
#For >= 0.12
#allocation_id = "${data.terraform_remote_state.eip.outputs.eip_id}"
}
resource "aws_instance" "web" {
ami = "insert-your-AMI-ref"
}
With that all set up, you can go into the elasticip folder, run terraform init, and terraform apply to get your elastic IP. Then go into the server folder, and run the same two commands to get your server with its associated elastic IP. From within the server folder you can run terraform destroy and terraform apply and the new server will get the same elastic IP.