skip to Main Content

I am trying to create 2 virtual machines under a Load balancer and I am using remote-exec provisioner to install nginx server to both VM. I cannot use azurerm_public_ip properly. It doesnt pass the IP address to the host connection block of my remote-exec provisioner.

Below is my code:

# Resource Group
resource "azurerm_resource_group" "test-rg-nginx" {
  name     = var.rgname
  location = var.rg_location
  #name     = "test-tf-test"
  #location = "East US"
}


# Virtual Network
resource "azurerm_virtual_network" "test-vnet-nginx" {
  name                = var.vnetname
  address_space       = ["10.66.0.0/16"]
  location            = azurerm_resource_group.test-rg-nginx.location
  resource_group_name = azurerm_resource_group.test-rg-nginx.name
  #name                = "test-tf-vnet"
}


# Subnet
resource "azurerm_subnet" "test-subnet-nginx" {
  name                 = var.subnetname
  resource_group_name  = azurerm_resource_group.test-rg-nginx.name
  virtual_network_name = azurerm_virtual_network.test-vnet-nginx.name
  address_prefixes     = ["10.66.1.0/24"]
}


# Public IPs
resource "azurerm_public_ip" "test-publicIP-VM" {
  count = var.vm_count
  name  = "${var.publicIP-VMname}${count.index}"


  location            = azurerm_resource_group.test-rg-nginx.location
  resource_group_name = azurerm_resource_group.test-rg-nginx.name
  allocation_method   = "Dynamic"
}


resource "azurerm_public_ip" "test-publicIP-LB" {
  name                = var.publicIP-LBname
  location            = azurerm_resource_group.test-rg-nginx.location
  resource_group_name = azurerm_resource_group.test-rg-nginx.name
  allocation_method   = "Static"
}




#Create Load Balancer
resource "azurerm_lb" "test-lb-nginx" {
  name                = var.lbname
  location            = azurerm_resource_group.test-rg-nginx.location
  resource_group_name = azurerm_resource_group.test-rg-nginx.name


  frontend_ip_configuration {
    name                 = "${var.publicIP-LBname}-frontend"
    public_ip_address_id = azurerm_public_ip.test-publicIP-LB.id
  }
}


resource "azurerm_lb_backend_address_pool" "lb_backendIPpool" {
  loadbalancer_id = azurerm_lb.test-lb-nginx.id
  name            = "BackEndAddressPool"
}


resource "azurerm_lb_probe" "http_probe" {
  name            = "http_probe"
  protocol        = "Tcp"
  port            = 80
  loadbalancer_id = azurerm_lb.test-lb-nginx.id
  #resource_group_name = azurerm_resource_group.test-rg-nginx.name
}


resource "azurerm_lb_rule" "http_rule" {
  name                           = "http-rule"
  protocol                       = "Tcp"
  frontend_port                  = 80
  backend_port                   = 80
  frontend_ip_configuration_name = "${var.publicIP-LBname}-frontend"
  #backend_address_pool_id = azurerm_lb_backend_address_pool.lb_backendIPpool.id
  probe_id        = azurerm_lb_probe.http_probe.id
  loadbalancer_id = azurerm_lb.test-lb-nginx.id
  #resource_group_name = azurerm_resource_group.test-rg-nginx.name
}


resource "azurerm_network_interface_backend_address_pool_association" "backendpoolAssoc" {
  count                   = var.vm_count
  network_interface_id    = azurerm_network_interface.test-nic[count.index].id
  ip_configuration_name   = "${var.nic-ip-configname}${count.index}"
  backend_address_pool_id = azurerm_lb_backend_address_pool.lb_backendIPpool.id
}


# Create network interface
resource "azurerm_network_interface" "test-nic" {
  count = var.vm_count
  #name = var.nicname
  name                = "${var.nicname}-${count.index}"
  location            = azurerm_resource_group.test-rg-nginx.location
  resource_group_name = azurerm_resource_group.test-rg-nginx.name


  ip_configuration {
    name                          = "${var.nic-ip-configname}${count.index}"
    subnet_id                     = azurerm_subnet.test-subnet-nginx.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.test-publicIP-VM[count.index].id
  }
}




# Network Security Group and Security rules
resource "azurerm_network_security_group" "test-nsg-nginx" {
  name                = var.nsgname
  location            = azurerm_resource_group.test-rg-nginx.location
  resource_group_name = azurerm_resource_group.test-rg-nginx.name


  security_rule {
    name                       = "HTTPS"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "443"
    source_address_prefixes    = var.address-list
    destination_address_prefix = "*"
  }
  security_rule {
    name                       = "HTTP"
    priority                   = 101
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefixes    = var.address-list
    destination_address_prefix = "*"
  }
  security_rule {
    name                       = "SSH-Inbound"
    priority                   = 102
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefixes    = var.address-list
    destination_address_prefix = "*"
  }
}


# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "test-sgConnect" {
  count                     = var.vm_count
  network_interface_id      = azurerm_network_interface.test-nic[count.index].id
  network_security_group_id = azurerm_network_security_group.test-nsg-nginx.id
}


resource "azurerm_availability_set" "avset" {
  name                         = "avset"
  location                     = azurerm_resource_group.test-rg-nginx.location
  resource_group_name          = azurerm_resource_group.test-rg-nginx.name
  platform_fault_domain_count  = 2
  platform_update_domain_count = 2
  managed                      = true
}


#Create VM
resource "azurerm_linux_virtual_machine" "test-linux" {
  count                 = var.vm_count
  name                  = "${var.vm-linux}-${count.index}"
  location              = azurerm_resource_group.test-rg-nginx.location
  resource_group_name   = azurerm_resource_group.test-rg-nginx.name
  availability_set_id   = azurerm_availability_set.avset.id
  network_interface_ids = [azurerm_network_interface.test-nic[count.index].id]
  size                  = var.vm-size




  os_disk {
    name                 = "myOsdisk-${count.index}"
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
  }


  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts-gen2"
    version   = "latest"
  }
  computer_name                   = var.admin-user
  admin_username                  = var.admin-user
  disable_password_authentication = true
  #wait_for_address = true


  admin_ssh_key {
    username   = var.admin-user
    public_key = file("${path.module}/connection/linux-pub0.pub")
  }


  depends_on = [
    azurerm_public_ip.test-publicIP-VM
  ]


 


data "azurerm_public_ip" "publicip" {
  count = var.vm_count
  name                = azurerm_public_ip.test-publicIP-VM[count.index].name
  resource_group_name   = azurerm_resource_group.test-rg-nginx.name
}


resource "null_resource" "default-web-server" {
  count = var.vm_count


  provisioner "remote-exec" {
      inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx",
      "sudo mkdir -p /var/www/html/",
      "sudo chown -R ${var.admin-user}:${var.admin-user} /var/www/html/",
      "sudo chmod 644 /var/www/html/index.nginx-debian.html"
    ]
    }
  Timeouts{
     read = “5m”
}
  connection {
      type        = "ssh"
      user        = var.admin-user
      private_key = file("${path.module}/connection/linux-priv0.pem")
      host = "${data.azurerm_public_ip.publicip[count.index].ip_address}"
      #host = data.azurerm_public_ip.publicip[count.index].fqdn
      #host        = azurerm_public_ip.test-publicIP-VM[count.index].ip_address
      timeout        = "2m"
    }




  provisioner "file" {
    #connection = azurerm_linux_virtual_machine.test-linux.connection
    source      = "${path.module}/WebContents/server-contents.html"
    destination = "/var/www/html/index.nginx-debian.html"
  }


   triggers = {
    timestamp = timestamp()
  }
  depends_on = [
    azurerm_linux_virtual_machine.test-linux,
    azurerm_network_interface.test-nic,
    azurerm_public_ip.test-publicIP-VM,
    data.azurerm_public_ip.publicip
  ]
}

I have tried to use data to pass the IP address but I still get and error. This is the link that I used: Error: host for provisioner cannot be empty for provisioner cannot be empty

The error that I am encountering is this:
Error: remote-exec provisioner error
host for provisioner cannot be empty

2

Answers


  1. Chosen as BEST ANSWER

    I was able to fix my issues by using the public_ip_address parameter of the azurerm_virtual machine:

    host = data.azurerm_virtual_machine.test-linux[count.index].public_ip_address

    data "azurerm_virtual_machine" "test-linux" { count = var.vm_count name = azurerm_linux_virtual_machine.test-linux[count.index].name resource_group_name = azurerm_resource_group.test-rg-nginx.name }


  2. To obtain the IP address of the network interface associated with each virtual machine, use the data azurerm_network_interface block.

    I made below changes to your code.

    data "azurerm_network_interface"  "test-nic" {
     count = var.vm_count 
     name = azurerm_network_interface.test-nic[count.index].name } 
    resource "null_resource"  "default-web-server" { 
    count = var.vm_count 
    provisioner "remote-exec" { 
    inline = [ 
    "sudo apt-get update", 
    "sudo apt-get install -y nginx", 
    "sudo mkdir -p /var/www/html/", 
    "sudo chown -R ${var.admin-user}:${var.admin-user} /var/www/html/", 
    "sudo chmod 644 /var/www/html/index.nginx-debian.html" 
    ] 
    } 
    connection { 
    type = "ssh" 
    user = var.admin-user 
    private_key = file("${path.module}/connection/linux-xxxx.pem") 
    host = data.azurerm_network_interface.test-nic[count.index].private_ip_address 
    timeout = "2m" 
    } 
    provisioner "file" { 
    source = "xxxx" 
    destination = "xxxx" 
    } 
    triggers = { 
    timestamp = timestamp() 
    } 
    depends_on = [ azurerm_linux_virtual_machine.test-linux, azurerm_network_interface.test-nic, azurerm_public_ip.test-publicIP-VM, data.azurerm_public_ip.publicip ] }
    

    After making these changes, I was able to successfully initialize terraform with a valid configuration.

    enter image description here

    If still the issue persists,

    Calling ssh from local-exec might help in fixing by allowing you to provide additional connection parameters to the output.

    Refer terraform hashicorp issues & Provisioners terraform for more relevant information.

    And this is an intermittent issue as per the github issues.

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