Getting blank azure public ip output from terraform

1.6k Views Asked by At

In my main terraform file I have:

resource "azurerm_resource_group" "rg" {
  name     = var.rg_name
  location = var.location
}

resource "azurerm_public_ip" "public_ip" {
  name                = "PublicIP"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  domain_name_label   = var.domain_name_label
  allocation_method   = "Dynamic"
}

And in my outputs file I have:

data "azurerm_public_ip" "public_ip" {
  name = "PublicIP"
  resource_group_name = azurerm_resource_group.rg.name
  depends_on = [azurerm_resource_group.rg, azurerm_public_ip.public_ip]
}

output "public_ip" {
  value = data.azurerm_public_ip.public_ip.ip_address
}

All the resources including IP get created, however the output is blank. How can I fix this?

3

There are 3 best solutions below

3
On

Make sure output.tf contains only output tags and main.tf contains resources tags

The following works just fine for me:

Main.tf

resource "azurerm_resource_group" "example" {
  name     = "resourceGroup1"
  location = "West US"
}

resource "azurerm_public_ip" "example" {
  name                = "acceptanceTestPublicIp1"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  allocation_method   = "Static"

  tags = {
    environment = "Production"
  }
}

Output.tf

output "azurerm_public_ip" {
  value = azurerm_public_ip.example.ip_address
}

enter image description here

In case you want to have a dependency between resources, use depends_on inside the resource tag.

For example:

depends_on = [azurerm_resource_group.example]

Steps to reproduce:

  • terraform init
  • terraform plan
  • terraform apply
  • terraform output

Update-

The reason you get blank public IP is since declaring allocation_method = "Dynamic"

From the docs:

Note Dynamic - Public IP Addresses aren't allocated until they're assigned to a resource (such as a Virtual Machine or a Load Balancer) by design within Azure.

Full working example with dynamic allocation.

1
On

I had the same issue. The actual problem seems to be the dynamic allocation. The IP address is not known until it is actually used by a VM.

In my case, I could solve the issue by adding the VM (azurerm_linux_virtual_machine.testvm) to the depends_on list in the data source:

data "azurerm_public_ip" "public_ip" {
  name = "PublicIP"
  resource_group_name = azurerm_resource_group.rg.name
  depends_on = [ azurerm_public_ip.public_ip, azurerm_linux_virtual_machine.testvm ]
}

Unfortunately, this seems not to be documented in https://www.terraform.io/docs/providers/azurerm/d/public_ip.html

0
On

Terraform seems to have updated it's documentation on that matter. I could make it work with the idea described in: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/public_ip.html

The dynamic pip will be empty until assigned to a nic. The trick here is to define data that depends on the pip and virtual machine at the same time. Then you can pipe that into an output and use it anywhere else.

#...

resource "azurerm_public_ip" "example" {
  name                    = "test-pip"
  location                = azurerm_resource_group.example.location
  resource_group_name     = azurerm_resource_group.example.name
  allocation_method       = "Dynamic"
  idle_timeout_in_minutes = 30
}

resource "azurerm_network_interface" "example" {
  name                = "test-nic"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.example.id
    private_ip_address_allocation = "Static"
    private_ip_address            = "10.0.2.5"
    public_ip_address_id          = azurerm_public_ip.example.id
  }
}

resource "azurerm_virtual_machine" "example" {
  name                  = "test-vm"
  location              = azurerm_resource_group.example.location
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.example.id]
  # ...
}

# Solution starts here

data "azurerm_public_ip" "example" {
  name                = azurerm_public_ip.example.name
  resource_group_name = azurerm_virtual_machine.example.resource_group_name
}

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