Home > Enterprise >  Use Terraform Locals for list object {type = list(object({}))}
Use Terraform Locals for list object {type = list(object({}))}

Time:09-27

Please how do I simplify this configuration using locals, the code works fine as is but gets complex passing the variables manually each time.

VARIABLES:

variable "vm_all" {
    type = list(object({}))
    default = [
      {
        name        = "vm1"
        rg  = "rg1"
        sn  = "sn1"
        sn_prefix = ["10.0.1.0/24"]
          },
      {
        name        = "vm2"
        rg  = "rg2"
        sn  = "sn2"
        sn_prefix = ["10.0.2.0/24"]
          },
      {
        name        = "vm3"
        rg  = "rg3"
        sn  = "sn3"
        sn_prefix = ["10.0.3.0/24"]
          }
    ]
    }

CURRENT ITERATION USING LOCALS:(requires manually mapping the variables as shown above)

resource "example_resource" "resource1" {
    for_each     = {for vm_all in var.vm_all:  vm_all.name => vm_all }
    name         = each.value.name
    rg           = each.value.rg
    sn           = each.value.sn
    sn_prefix    = each.value.sn_prefix
}

DESIRED METHOD OF PASSING VARIABLES:

 variable "name" {
    default = [
    "vm1",
    "vm2",
    "vm3"
]
 }

 variable "rg_names" {
    default = [
    "rg1",
    "rg2",
    "rg3"
]
 }

variable "subnets" {
    default = [
    "sn1",
    "sn2",
    "sn3"
]
 }

variable "subnet_prefixes" {
    default = [
    "sn_prefix1",
    "sn_prefix2",
    "sn_prefix3"
]
 }

QUESTION: How can I use locals in a more effective way to allow passing the variables as lists shown above and avoid the need to map manually?

CodePudding user response:

You can combine them as follows:

locals {
  vm_all = {for idx, name in var.name: 
            name => {
              "name" = name
              rg  = var.rg_names[idx]
              sn  = var.subnets[idx]
              sn_prefix = [var.subnet_prefixes[idx]]
            }
           }
}

then

resource "example_resource" "resource1" {
    for_each     = local.vm_all
    name         = each.value.name
    rg           = each.value.rg
    sn           = each.value.sn
    sn_prefix    = each.value.sn_prefix
}

CodePudding user response:

Thank you @Marcin, really helpful but I'm not yet there, I feel so close though, I get the following error when I try to created nics using ids from the created subnets:

(The given key does not identify an element in this collection value.)

 Error: Invalid index
│
│   on main.tf line 165, in resource "azurerm_network_interface" "nic":
│  165:     subnet_id                     = azurerm_subnet.subnet[each.value.sn].id
│     ├────────────────
│     │ azurerm_subnet.subnet is object with 10 attributes
│     │ each.value.sn is "subnet7"
│
│ The given key does not identify an element in this collection value.

see the main.tf below:

resource "azurerm_subnet" "subnet" {
  for_each             = local.vm_all
  name                 = each.value.sn
  resource_group_name  = each.value.rg
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = each.value.sn_prefix
}
    
resource "azurerm_network_interface" "nic" {
      for_each            = local.vm_all
      name                = each.value.name
      location            = var.location
      resource_group_name = each.value.rg
    
      ip_configuration {
        name                          = "internal"
        subnet_id                     = azurerm_subnet.subnet[each.value.sn].id
        private_ip_address_allocation = "Dynamic"
      }
    }
  • Related