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
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 }
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.
After making these changes, I was able to successfully initialize terraform with a valid configuration.
If still the issue persists,
Calling
ssh
fromlocal-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.