'Adding service endpoints as part of subnet variables in network module in terraform

I have created a network module. Below is the code for it

variables.tf

variable "resource_group_name" {
  description = "Name of the resource group to be imported."
  type        = string
}

variable "location" {
  description = "The location of the vnet to create. Defaults to the location of the resource group."
  type        = string
  default     = null
}

variable "vnets" {
  type = map(object({
    address_space = string
    subnets = list(object({
      subnet_name    = string
      subnet_address = string
      service_endpoints = list(string)
    }))
  }))

  default = {
    "bupavnet1" = {
      address_space = "192.168.0.0/16",
      subnets       = []
    },
    "bupavnet2" = {
      address_space = "10.0.0.0/16",
      subnets = [
        {
          subnet_name    = "subnet1_bupavnet1"
          subnet_address = "10.0.2.0/24"
          service_endpoints = []
        },
        {
          subnet_name    = "subnet2_bupavnet1"
          subnet_address = "10.0.0.0/24"
          service_endpoints = ["Microsoft.AzureCosmosDB","Microsoft.ContainerRegistry"]
          
        }
      ]
    },

    "bupavnet3" = {
      address_space = "10.80.0.0/16"
      subnets = [
        {
          subnet_name    = "subnet1_bupavnet3"
          subnet_address = "10.80.2.0/24"
          service_endpoints = ["Microsoft.AzureCosmosDB","Microsoft.ContainerRegistry"]
        },

        {
          subnet_name    = "subnet2_bupavnet3"
          subnet_address = "10.80.1.0/24"
          service_endpoints = ["Microsoft.AzureCosmosDB","Microsoft.ContainerRegistry"]
        },

        {
          subnet_name    = "subnet3_bupavnet3"
          subnet_address = "10.80.0.0/24"
          service_endpoints = ["Microsoft.AzureCosmosDB","Microsoft.ContainerRegistry"]
        },
      ]
    }
  }
}

output.tf

output "vnet_names" {
  description = "The name of the virtual networks"
  value       = tomap({for k, v in azurerm_virtual_network.vnets: k => v.name})
} 

output "vnet_addresses" {
  description = "The name of the virtual networks"
  value       = tomap({for k, v in azurerm_virtual_network.vnets: k => v.address_space})
} 

output "subnet_names" {
  description = "The name of the subnets"
  value       = tomap({for k, v in azurerm_subnet.subnets: k => v.name})
} 

output "subnet_addresses" {
  description = "The name of the subnet addresses"
  value       = {for k, v in azurerm_subnet.subnets: k => v.address_prefixes}
} 

output "subnet_ids" {
  description = "The name of the subnet addresses"
  value       = tomap({for k, v in azurerm_subnet.subnets: k => v.id})
} 

main.tf

data "azurerm_resource_group" "network" {
  name = var.resource_group_name
}



resource "azurerm_virtual_network" "vnets" {
  for_each            = var.vnets
  name                = each.key
  resource_group_name = data.azurerm_resource_group.network.name
  location            = data.azurerm_resource_group.network.location
  address_space       = [each.value.address_space]
}

resource "azurerm_subnet" "subnets" {
  for_each             = local.subnets
  name                 = each.value.subnet_name
  resource_group_name  = data.azurerm_resource_group.network.name
  virtual_network_name = azurerm_virtual_network.vnets[each.value.vnet_name].name
  address_prefixes     = [each.value.subnet_address]
  service_endpoints = [each.value.service_endpoints]
}

locals.tf

locals {
  subnets_flatlist = flatten([for key, val in var.vnets : [
    for subnet in val.subnets : {
      vnet_name      = key
      subnet_name    = subnet.subnet_name
      subnet_address = subnet.subnet_address
      service_endpoints = subnet.service_endpoints
    }
    ]
  ])
  subnets = { for subnet in local.subnets_flatlist : subnet.subnet_name => subnet }
}

main.tf

resource "azurerm_resource_group" "rg2" {
  name     = "rg2"
  location = "Australia East"
}

module "network" {
  source = "./network_resources"
  resource_group_name = azurerm_resource_group.rg2.name
  location = azurerm_resource_group.rg2.location
}

I am getting the below error when I am doing terraform plan

│ Error: Incorrect attribute value type │ │ on network_resources\main.tf line 21, in resource "azurerm_subnet" "subnets": │ 21: service_endpoints = [each.value.service_endpoints] │ ├──────────────── │ │ each.value.service_endpoints is list of string with 2 elements │ │ Inappropriate value for attribute "service_endpoints": element 0: string required.

Please can you let me know how service_endpoints can be added as part of variable vnets so that the module will start working fine



Solution 1:[1]

The reason you get this error is that your service_endpoints is already a list, but you are wrapping it in [] which is creating a list of lists. Remove the [] from service_endpoints:

resource "azurerm_subnet" "subnets" {
  for_each             = local.subnets
  name                 = each.value.subnet_name
  resource_group_name  = data.azurerm_resource_group.network.name
  virtual_network_name = azurerm_virtual_network.vnets[each.value.vnet_name].name
  address_prefixes     = [each.value.subnet_address]
  service_endpoints    = each.value.service_endpoints
} 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1