AWS EIP Not being created nor associated

Hi there,

I’m having an issue creating an instance and associating an Elastic IP to it.
My code creates an AIP, an EIP Association and the Instance, but when running apply, it tries to connect to the instance (ssh) using the wrong public IP (the one initially assigned to the instance) instead of the EIP.

Checking on AWS I also don’t see the EIP being created, nor being associated with the instance.

EIP:

resource "aws_eip" "toolbox" {
  vpc = true

  tags = {
    "Name" = "${var.environment}-toolbox"
  }
}

EIP Association:

resource "aws_eip_association" "eip_assoc_toolbox" {
  instance_id      = aws_instance.toolbox.id
  allocation_id    = aws_eip.toolbox.id
}

Instance:

resource "aws_instance" "toolbox" {
  ami                               = var.ami
  instance_type                     = var.size
  subnet_id                         = var.subnet_id
  associate_public_ip_address       = true
  vpc_security_group_ids            = [var.sec_group]
  disable_api_termination           = var.instance_static_protection
  iam_instance_profile              = aws_iam_instance_profile.toolbox.id
  key_name                          = var.key_name

  root_block_device {
    volume_type = "gp2"
    volume_size = 8
    encrypted   = true
    kms_key_id  = var.kms_key_arn
  }

  tags = {
    #Name               = "${var.environment}-toolbox-${count.index + 1}",
    Name                = "${var.environment}-toolbox",
    Environment         = "${var.environment}"
    OS                  = "Linux"
    Group               = "Toolbox"
    Access              = "PublicIP"
  }

  # Stop Terraform replacing static instances when an AMI is changed
  lifecycle {
    ignore_changes = [
      ami,
    ]
  }

  # INLINE Script - Setup Hostname 

  provisioner "remote-exec" {
    inline = [
      # Set Hostname
      "echo '127.0.0.1 ${self.tags.Name}' | sudo tee -a /etc/hosts",
      "sudo hostnamectl set-hostname ${self.tags.Name}",
      "echo '##########################################'",
      "echo '${self.tags.Name} sleeping for 60 seconds'",
      "echo '##########################################'",
      "sleep 60",
      # https://docs.aws.amazon.com/efs/latest/ug/installing-other-distro.html
      # Clone Amazon EFS Utils toolbox
      "git clone https://github.com/aws/efs-utils",
      "sudo apt update && sudo apt upgrade -y",
      "cd efs-utils && ./build-deb.sh",
      "sudo apt-get -y install ./build/amazon-efs-utils*deb",
      # https://docs.aws.amazon.com/efs/latest/ug/mounting-fs-mount-helper.html
      # create a directory to mount our efs volume to
      "sudo mkdir -p /mnt/efs",
      # Mount EFS filesystem
      "sudo mount -t efs '${var.efs_id}':/ /mnt/efs",
      # Add entry to FSTAB
      "sudo su -c \"echo '${var.efs_id}:/ /mnt/efs nfs4 defaults,vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 0 0' >> /etc/fstab\"",
      # Uncomment AllowAgentForwarding in the SSHD Config
      "sudo sed -i '/AllowAgentForwarding/s/^#//g' /etc/ssh/sshd_config",
      # Create host folder on EFS
      "sudo mkdir /mnt/efs/${self.tags.Name}",
      "sudo touch /mnt/efs/${self.tags.Name}/terraform-file-can-be-deleted.txt",
      "sudo mkdir /mnt/efs/scripts",
      "sudo mkdir /mnt/efs/share"
    ]
    connection {
      host        = self.public_ip
      type        = "ssh"
      agent       = false
      private_key ="${file("key.pem")}"
      user        = "ubuntu"
    }
  }
}

I’ve also tried removing the EIP Association and using (as used in https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip):

resource "aws_eip" "toolbox" {
 instance = aws_instance.toolbox.id
  vpc     = true

  tags = {
    "Name" = "${var.environment}-toolbox"
  }
}

But this doesn’t seem to work either.

I am not able to figure out what is wrong or failing. Any suggestions?

Thanks!

What’s happening here at the first run is:

  1. Instance creation
  2. Provisionning with remote-exec
  3. EIP creation
  4. EIP attachment

The annoying thing with this approach is idempotency with EIP (public_ip is the eip after attachment) so I’d recommend a different approach.

Options in order of complexity:

Note that for the last option, you can Terraform all SSM resources as well (see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_association).

Thank you for the response @ohmer !

I used a null_resource as your first suggestion and that worked!

Thanks!