Search code examples
for-loopterraformdevopsterraform-template-filelibreswan

Terraform - foreach list of maps within a list of maps


I am currently struggling to wrap my head around how to foreach a list of maps within a list of maps.

locals {

  vpn_configurations = [

    {
      customer_name      = "test125231"
      custom_path        = "test123123"
      shared_by          = []
      nat                = false
      nat_source_ip      = ""
      nat_destination_ip = ""
      nat_route          = ""
      tunnels = [
        {
          tunnel_name   = "test-tunnel"
          left          = "%defaultroute"
          leftid        = ""
          leftsubnet    = ""
          leftsourceip  = ""
          rightid       = ""
          right         = ""
          rightsubnet   = ""
          rightsourceip = ""
          ike           = "aes256-sha256-modp2048"
          keyexchange   = "ike"
          ikev2         = "no"
          esp           = "aes256-sha256-modp2048"
          salifetime    = 3600
          ikelifetime   = 3600
          authby        = "secret"
          # use auto=start when done testing the tunnel
          auto = "ondemand"
        },
        {
          tunnel_name   = "test-tunnel2"
          left          = "%defaultroute"
          leftid        = ""
          leftsubnet    = ""
          leftsourceip  = ""
          rightid       = ""
          right         = ""
          rightsubnet   = ""
          rightsourceip = ""
          ike           = "aes256-sha256-modp2048"
          keyexchange   = "ike"
          ikev2         = "no"
          esp           = "aes256-sha256-modp2048"
          salifetime    = 3600
          ikelifetime   = 3600
          authby        = "secret"
          # use auto=start when done testing the tunnel
          auto = "ondemand"
        }
      ]
    },
    {
      customer_name      = "sdfsdfsd"
      custom_path        = "sdfsdfsdf"
      shared_by          = []
      nat                = false
      nat_source_ip      = ""
      nat_destination_ip = ""
      nat_route          = ""
      tunnels = [
        {
          tunnel_name   = "test-tunnel3"
          left          = "%defaultroute"
          leftid        = ""
          leftsubnet    = ""
          leftsourceip  = ""
          rightid       = ""
          right         = ""
          rightsubnet   = ""
          rightsourceip = ""
          ike           = "aes256-sha256-modp2048"
          keyexchange   = "ike"
          ikev2         = "no"
          esp           = "aes256-sha256-modp2048"
          salifetime    = 3600
          ikelifetime   = 3600
          authby        = "secret"
          # use auto=start when done testing the tunnel
          auto = "ondemand"
        },
        {
          tunnel_name   = "test-tunnel4"
          left          = "%defaultroute"
          leftid        = ""
          leftsubnet    = ""
          leftsourceip  = ""
          rightid       = ""
          right         = ""
          rightsubnet   = ""
          rightsourceip = ""
          ike           = "aes256-sha256-modp2048"
          keyexchange   = "ike"
          ikev2         = "no"
          esp           = "aes256-sha256-modp2048"
          salifetime    = 3600
          ikelifetime   = 3600
          authby        = "secret"
          # use auto=start when done testing the tunnel
          auto = "ondemand"
        }
      ]
    }

  ]

}

I am trying to pass each of the tunnels for each vpn configuration into a terraform template generator in order to create individual configuration files for each tunnel associated with a customer.

data "template_file" "networking_configs" {
  for_each = local.vpn_configurations
  template = file("${path.module}/template-files/networking-templates/tunnel-configuration.tpl")
  vars = {

    tunnel_name   = each.value.tunnels["tunnel_name"]
    left          = each.value.tunnels["left"]
    leftid        = module.ipsec.public_ip
    leftsubnet    = each.value.tunnels["leftsubnet"]
    leftsourceip  = data.aws_network_interface.eni_ip.private_ip
    rightid       = each.value.tunnels["rightid"]
    right         = each.value.tunnels["right"]
    rightsubnet   = each.value.tunnels["rightsubnet"]
    rightsourceip = each.value.tunnels["rightsourceip"]
    ike           = each.value.tunnels["ike"]
    keyexchange   = each.value.tunnels["keyexchange"]
    ikev2         = each.value.tunnels["ikev2"]
    esp           = each.value.tunnels["esp"]
    salifetime    = each.value.tunnels["salifetime"]
    ikelifetime   = each.value.tunnels["ikelifetime"]
    authby        = each.value.tunnels["authby"]
    auto          = each.value.tunnels["auto"]

  }
}

Appreciate any help available.


Solution

  • You have to flatten your double for loop into one. For example (only some variables listed):

    locals {
      flat_vpn_configurations = merge([
             for vpn_config in local.vpn_configurations :
             {
                 for tunnel in vpn_config["tunnels"]:
                 "${vpn_config["customer_name"]}-${tunnel["tunnel_name"]}" =>
                  {
                      customer_name = vpn_config["customer_name"]
                      custom_path = vpn_config["custom_path"]
                      tunnel_name = tunnel["tunnel_name"]
                      left = tunnel["left"]
                  }
             }
          ]...)
    }
    

    which will give you local.flat_vpn_configurations as (only part shown):

    {
      "sdfsdfsd-test-tunnel3" = {
        "custom_path" = "sdfsdfsdf"
        "customer_name" = "sdfsdfsd"
        "left" = "%defaultroute"
        "tunnel_name" = "test-tunnel3"
      }
      "sdfsdfsd-test-tunnel4" = {
        "custom_path" = "sdfsdfsdf"
        "customer_name" = "sdfsdfsd"
        "left" = "%defaultroute"
        "tunnel_name" = "test-tunnel4"
      }
      "test125231-test-tunnel" = {
        "custom_path" = "test123123"
        "customer_name" = "test125231"
        "left" = "%defaultroute"
        "tunnel_name" = "test-tunnel"
      }
      "test125231-test-tunnel2" = {
        "custom_path" = "test123123"
        "customer_name" = "test125231"
        "left" = "%defaultroute"
        "tunnel_name" = "test-tunnel2"
      }
    }
    

    Then you can very easly iterate over flat_vpn_configurations with for_each.