How to retrieve map of objects and list for azure loadbalancer using terraform

164 Views Asked by At

I am trying to create Azure load balancers using the Terraform module with the below json as a input input. I am not sure am I using the write of using the for , foreach, dynamic forloop in the terraform code. Could someone throw someone light on the syntax.

locals {
  tiers = {
    lbs = {
      app-lb = {
        lb_name         = "app-lb"
        fip_name        = "app-fip"
        subnet_id       = "*****"
        private_ip_type = "Dynamic"

        address_pool_name = "app-address-pool"

        lb_probes = {
          ssh_probe = {"Tcp", "22"}
        }
        lb_rules = {
          ssh_rule = {"22", "Tcp", "22", "22", true}
        }
      },
      db-lb = {
        lb_name         = "db-lb"
        fip_name        = "db-fip"
        subnet_id       = "*****"
        private_ip_type = "Dynamic"

        address_pool_name = "db-address-pool"

        lb_probes = {
          ssh_probe = {"Tcp", "22"}

        }
        lb_rules = {
          ssh_rule = {"22", "Tcp", "22", "22", false}
        }
      }

    }
  }
}

Below is the terraform code create loadbalancer, backendaddress pool, probes, lb rules.

data "azurerm_resource_group" "rg" {
  name = "test-rg"
}

data "azurerm_virtual_network" "example" {
  name                = "test-vnet"
  resource_group_name = "test-rg"
}

data "azurerm_subnet" "example" {
  name                 = "app"
  virtual_network_name = data.azurerm_virtual_network.example.name
  resource_group_name  = data.azurerm_resource_group.rg.name
}

resource "azurerm_lb" "lb" {

  for_each            = local.tiers.lbs
  name                = each.value.lb_name
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name

  dynamic "frontend_ip_configuration" {
    for_each = local.tiers.lbs
    content {
      name                          = each.value.fip_name
      subnet_id                     = each.value.subnet_id
      private_ip_address_allocation = each.value.private_ip_type
    }
  }
}

resource "azurerm_lb_probe" "probe" {
  for_each   = local.tiers.lbs.lb_probes
  loadbalancer_id = [for lb_id in azurerm_lb.lb : lb_id.id]
  name            = each.value.key
  port            = each.value.[1]

}

resource "azurerm_lb_backend_address_pool" "bepool" {
  loadbalancer_id = [for lb_id in azurerm_lb.lb : lb_id.id]
  name            = each.value.address_pool_name
}

resource "azurerm_lb_rule" "rule" {
  for_each                       = local.tiers.lbs
  loadbalancer_id                = [for lb_id in azurerm_lb.lb : lb_id.id]
  name                           = each.value.key
  protocol                       = each.value[0]
  frontend_port                  = each.value[1]
  backend_port                   = each.value[2]
  frontend_ip_configuration_name = each.value.fip_name
  probe_id                       = [for probe_id in azurerm_lb_probe.probe : probe_id.id]
  backend_address_pool_ids       = [azurerm_lb_backend_address_pool.bepool.id]
  enable_floating_ip             = each.value[5]
}

Error :

╷
│ Error: Incorrect attribute value type
│
│   on lb.tf line 89, in resource "azurerm_lb_backend_address_pool" "bepool":
│   89:   loadbalancer_id = [for lb_id in azurerm_lb.lb : lb_id.id]
│     ├────────────────
│     │ azurerm_lb.lb is object with 2 attributes
│
│ Inappropriate value for attribute "loadbalancer_id": string required.
1

There are 1 best solutions below

1
Vinay B On BEST ANSWER

I tried to retrieve map of objects and list for azure loadbalancer using terraform and I was able to provision the requirement successfully.

Thanks MatthewSchuchard & Harambo on your valuble inputs.

Yes, The error you're encountering is related to the way you're trying to assign the loadbalancer_id in the azurerm_lb_backend_address_pool resource. The error message indicates that a string is required, but you're providing a list. This is where modification need to be takes place.

My terraform configuration:

provider "azurerm" {
    features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "demorg-vk"
  location = "East US"
}

resource "azurerm_virtual_network" "example" {
  name                = "test-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "example" {
  name                 = "app"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.1.0/24"]
}

locals {
  tiers = {
    lbs = {
      app-lb = {
        lb_name            = "app-lb"
        fip_name           = "app-fip"
        subnet_id          = azurerm_subnet.example.id  
        private_ip_type    = "Dynamic"
        address_pool_name  = "app-address-pool"

        lb_probes = {
          ssh_probe = {
            protocol = "Tcp"
            port     = "22"
          }
        }

        lb_rules = {
          ssh_rule = {
            frontend_port           = "22"
            protocol                = "Tcp"
            backend_port            = "22"
            enable_floating_ip      = true
            frontend_ip_config_name = "app-fip" 
          }
        }
      },

      db-lb = {
        lb_name            = "db-lb"
        fip_name           = "db-fip"
        subnet_id          = azurerm_subnet.example.id  
        private_ip_type    = "Dynamic"
        address_pool_name  = "db-address-pool"

        lb_probes = {
          ssh_probe = {
            protocol = "Tcp"
            port     = "22"
          }
        }

        lb_rules = {
          ssh_rule = {
            frontend_port           = "22"
            protocol                = "Tcp"
            backend_port            = "22"
            enable_floating_ip      = false
            frontend_ip_config_name = "db-fip" 
          }
        }
      }
    }
  }
}


resource "azurerm_lb" "lb" {
  for_each            = local.tiers.lbs
  name                = each.value.lb_name
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku                 = "Standard"

  frontend_ip_configuration {
  name                          = each.value.fip_name
  subnet_id                     = each.value.subnet_id
  private_ip_address_allocation = each.value.private_ip_type
  }
}

resource "azurerm_lb_backend_address_pool" "bepool" {
  for_each        = local.tiers.lbs
  loadbalancer_id = azurerm_lb.lb[each.key].id
  name            = each.value.address_pool_name
}


resource "azurerm_lb_probe" "probe" {
  for_each = { for lb, details in local.tiers.lbs : lb => details.lb_probes }

  loadbalancer_id = azurerm_lb.lb[each.key].id
  name            = "ssh-probe"  
  protocol        = each.value["ssh_probe"].protocol
  port            = each.value["ssh_probe"].port
}


resource "azurerm_lb_rule" "rule" {
  for_each = { for lb, details in local.tiers.lbs : lb => details.lb_rules }

  loadbalancer_id                = azurerm_lb.lb[each.key].id
  name                           = "ssh-rule"  
  protocol                       = each.value["ssh_rule"].protocol
  frontend_port                  = each.value["ssh_rule"].frontend_port
  backend_port                   = each.value["ssh_rule"].backend_port
  frontend_ip_configuration_name = azurerm_lb.lb[each.key].frontend_ip_configuration[0].name
  enable_floating_ip             = each.value["ssh_rule"].enable_floating_ip
}

Output:

enter image description here

enter image description here

enter image description here

enter image description here