skip to Main Content

I’m new to Azure Terraform and is having issues setting public_ip_address_id correctly on this part of azurerm_network_interface resource. Can I request for advice. Thanks!

I’m creating 8 interface and trying to bind public ip on the first 3 interfaces. tried using try function to return and set public_ip_id on the first 3 interfaces and set null on the rest of the interfaces

resource "azurerm_network_interface" "virtual_network_interfaces" {
  
  for_each = var.interfaces

   location            = var.location
   resource_group_name = var.resource_group_name 

   name = "${var.device_name}_${var.instance_type}_${var.site_name}_${each.value.name}_Interface"    
   enable_ip_forwarding = true
   enable_accelerated_networking = true
   
   ip_configuration {
      name                          = "${var.device_name}_${var.instance_type}_${var.site_name}_${each.value.name}_IP_Config"
      private_ip_address            = each.value.address_prefixes[0]
      private_ip_address_allocation = "Static"  

      # set Management interface as primary vNIC
      primary = each.value.name == "Management" ? true : false

      subnet_id = try(
         lookup(
            { for k, v in var.subnets : v.name => v.id },
               each.value.name, null
         ), null
       )

       public_ip_address_id = try(
         {
            for k1, v1 in var.public_ips :
              k1 => can(regex("${each.value.name}", v1.name)) ? v1.id : null
          },
           null)
     }
}

2

Answers


  1. Chosen as BEST ANSWER

    Trying to understand more I created public_ip_address (3 object) and interface (8 object) name exact match. With 3 public IPs works.

    public_ip_address_id = try(
        lookup(
            { for k1, v1 in var.public_ips : v1.name => v1.id },
            each.value.name, null
        ), 
    

    null)

    But with this code failed, both cases will match 1st 3 interface bind public IP rest returns null

    public_ip_address_id = try({
             for k1, v1 in var.public_ips :
             k1 => can(regex("${each.value.name}", v1.name)) ? v1.id : null
         },
     null)
    

    Any idea, advise. thanks!


  2. I tried to set values on azurerm_network_interface public_ip_address_id and I was able to provision the requirement successfully.

    The current logic you’re using to set public_ip_address_id is to iterate over var.public_ips and, for each public IP, check if the current NIC’s name (from var.interfaces) matches the name of the public IP. If it does, set the public_ip_address_id to the ID of that public IP, otherwise set it to null.

    The issue with this approach is that the logic will always return the ID of the last matched public IP (or null if no match was found). This isn’t ideal because, if multiple public IPs match the NIC’s name, only the last one will be set.

    Moreover, the use of the can(regex()) function here is not ideal. If you’re trying to bind the first 3 interfaces to public IPs, a more deterministic approach is recommended.

    I tried to achieve your requirement using my won configuration module changes which were mentioned as follows.

    My terraform configuration:

    main.tf:

    provider "azurerm" {
        features {}
    }
    
    
    resource "azurerm_resource_group" "example" {
      name     = var.resource_group_name
      location = var.location
    }
    
    resource "azurerm_virtual_network" "example" {
      name                = "vksbl-vnet"
      resource_group_name = azurerm_resource_group.example.name
      location            = azurerm_resource_group.example.location
      address_space       = ["10.0.0.0/16"]
    }
    
    resource "azurerm_subnet" "example" {
      name                 = "vksbl-subnet"
      resource_group_name  = azurerm_resource_group.example.name
      virtual_network_name = azurerm_virtual_network.example.name
      address_prefixes     = ["10.0.1.0/24"]
    }
    
    resource "azurerm_public_ip" "example" {
      count               = 3
      name                = "vksbl-public-ip-${count.index}"
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      allocation_method   = "Dynamic"
    }
    
    resource "azurerm_network_interface" "virtual_network_interfaces" {
      count = length(var.interfaces)
    
      location            = var.location
      resource_group_name = azurerm_resource_group.example.name
      
      name                = "${var.device_name}_${var.instance_type}_${var.site_name}_${var.interfaces[count.index].name}_Interface"
      enable_ip_forwarding          = true
      enable_accelerated_networking = true
       
      ip_configuration {
        name                          = "${var.device_name}_${var.instance_type}_${var.site_name}_${var.interfaces[count.index].name}_IP_Config"
        private_ip_address            = var.interfaces[count.index].address_prefixes[0]
        private_ip_address_allocation = "Static"
        primary                       = var.interfaces[count.index].name == "Management" ? true : false
    
        subnet_id = azurerm_subnet.example.id
    
        # Bind the first 3 interfaces to public IPs
        public_ip_address_id = count.index < 3 ? azurerm_public_ip.example[count.index].id : null
      }
    }
    

    variable.tf:

    variable "interfaces" {
      description = "List of interfaces"
      type        = list(object({
        name            = string
        address_prefixes = list(string)
      }))
      default = [
        {
          name            = "Interface1"
          address_prefixes = ["10.0.1.4"]
        },
        {
          name            = "Interface2"
          address_prefixes = ["10.0.1.5"]
        },
        {
          name            = "Interface3"
          address_prefixes = ["10.0.1.6"]
        },
        {
          name            = "Interface4"
          address_prefixes = ["10.0.1.7"]
        },
        {
          name            = "Interface5"
          address_prefixes = ["10.0.1.8"]
        },
        {
          name            = "Interface6"
          address_prefixes = ["10.0.1.9"]
        },
        {
          name            = "Interface7"
          address_prefixes = ["10.0.1.10"]
        },
        {
          name            = "Interface8"
          address_prefixes = ["10.0.1.11"]
        }
      ]
    }
    
    variable "location" {
      description = "Azure region/location"
      default     = "East US"
    }
    
    variable "resource_group_name" {
      description = "Name of the resource group"
      default     = "demorgvk"
    }
    
    variable "device_name" {
      description = "Device name"
      default     = "my-device"
    }
    
    variable "instance_type" {
      description = "Instance type"
      default     = "t2.micro"
    }
    
    variable "site_name" {
      description = "Site name"
      default     = "my-site"
    }
    

    Output:

    enter image description here

    enter image description here

    enter image description here

    This configuration creates a virtual network, a subnet, 3 public IPs, and 8 network interfaces. The first 3 of those interfaces will be bound to the public IPs, while the rest will not have public IPs.

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