skip to Main Content

I have a Terraform file called azure.tf which is supposed to deploy a Virtual machine to Azure and afterwards SSH to said machine to run an Ansible playbook. The problem is that everytime i run terraform apply, the old public IP-address of the previous vm gets used.

I’ve got a file called outputs.tf which outputs this IP-address

output "public_ip_address" {
  value = data.azurerm_public_ip.my_terraform_public_ip.ip_address
}

This Outputs IP address but it seems to be the old IP-adress of the already destroyed resource

# Create public IPs
resource "azurerm_public_ip" "my_terraform_public_ip" {
  name                = "testpublicIP"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
}

data "azurerm_public_ip" "my_terraform_public_ip" {
  name = azurerm_public_ip.my_terraform_public_ip.name
  resource_group_name = azurerm_public_ip.my_terraform_public_ip.resource_group_name
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "my_terraform_nsg" {
  name                = "myNetworkSecurityGroup"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "SSH"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

# Create network interface
resource "azurerm_network_interface" "my_terraform_nic" {
  name                = "myNIC"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "my_nic_configuration"
    subnet_id                     = azurerm_subnet.my_terraform_subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.my_terraform_public_ip.id
  }
}

# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "example" {
  network_interface_id      = azurerm_network_interface.my_terraform_nic.id
  network_security_group_id = azurerm_network_security_group.my_terraform_nsg.id
}

resource "azurerm_virtual_machine" "my_terraform_vm" {
  name = "myVM"  #abstract away
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.my_terraform_nic.id]
  vm_size = "Standard_DS1_v2" #abstract away


  delete_data_disks_on_termination = true

  delete_os_disk_on_termination = true

  storage_image_reference {
    publisher = "canonical"         #abstract away
    offer     = "0001-com-ubuntu-server-focal"    #abstract away
    sku       = "20_04-lts"       #abstract away
    version   = "latest"          #abstract away

  }
    storage_os_disk {
    name              = "vm1-osdisk"   #abstract away
    caching           = "ReadWrite"   #abstract away
    create_option     = "FromImage"   #abstract away
    managed_disk_type = "Standard_LRS"#abstract away
  }
  os_profile {
    computer_name  = "hostname"       #abstract away
    admin_username = "testadmin"      #abstract away
  }
  os_profile_linux_config {
    disable_password_authentication = false
  }
   provisioner "remote-exec" {
    inline = ["echo 'Wait until SSH is ready'"]

    connection {
      type        = "ssh"
      user        = "ubuntu"
      private_key =  file(local.private_key_path_Azure)
      host        = data.azurerm_public_ip.my_terraform_public_ip.ip_address
    }
  }
  provisioner "local-exec" {
    command = "ansible-playbook  -i ${data.azurerm_public_ip.my_terraform_public_ip.ip_address}, --private-key ${local.private_key_path_Azure} docker.yaml"
  }
}

I’ve looked at the NIC, public IP, and vm in the portal and they all get assigned the new public IP-adress. So why does the remote-exec use the old one?

Any help would be greatly appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    allocation_method = "Dynamic" should have been "static"


  2. A Terraform configuration should typically not contain both a resource block and a data block referring to the same object, because when you do that it can be hard to explain to Terraform the correct order of operations so that all of the resources end up having the correct data at the end of the run.

    Inside your connection block (and anywhere else you refer to data.azurerm_public_ip.my_terraform_public_ip), you should refer directly to azurerm_public_ip.my_terraform_public_ip (the resource block) instead. For example:

        connection {
          type        = "ssh"
          user        = "ubuntu"
          private_key = file(local.private_key_path_Azure)
          host        = azurerm_public_ip.my_terraform_public_ip.ip_address
        }
    

    You can then remove the data "azurerm_public_ip" "my_terraform_public_ip" altogether, because it isn’t necessary here. A data block is for telling Terraform that your configuration depends on an object managed elsewhere, but this object is managed directly inside this configuration and so this data block is misleading.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search