Terraform for_each для карт внутри карты - PullRequest
0 голосов
/ 28 января 2020

Мне интересно, можно ли выполнить итерацию по структуре, подобной этой, используя комбинацию for_each / for

module "network" {
  source    = "../../"
  role                = "test"
  resource_group_name = xyz
  location            = "centralus"
  environment         = "test-1"
  tags = {
    role = "unit-test"
  }
  subnets = {
    subnet-1 = {
      name              = "subnet-a"
      cidr              = "10.0.1.0/24",
      nsg = {
        httpallowinbound = {
          name = "junk"
        }
      }
    }
  }
}

Я могу сделать for_each для внешней структуры, чтобы получить значения и присвоить их соответствующие поля, но не могут сделать для вложенной структуры выше. Ценю любую обратную связь до сих пор. Что у меня пока так:

resource "azurerm_subnet" "this" {
  for_each             = var.subnets
  name                 = lookup(each.value, "name")
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.this.name
  address_prefix       = lookup(each.value, "cidr"
}

Нет идей для этого куска

resource "azurerm_network_security_group" "this" {
   Map NSGs to Subnets 
}

-------------------- --update-1 ---------------------------------------------

Основываясь на обнаружении, предполагается, что функция сглаживания должна обеспечивать этот механизм, как описано здесь

Однако я не могу заставить работать пример:

Main.tf

variable "networks" {
  type = map(object({
    cidr_block = string
    subnets = map(object({
      cidr_block = string
    })) # this is missing in the document
  })) # this is missing in the document
}

locals {
  # flatten ensures that this local value is a flat list of objects, rather
  # than a list of lists of objects.
  network_subnets = flatten([
    for network_key, network in var.networks : [
      for subnet_key, subnet in network.subnets : {
        network_key = network_key
        subnet_key  = subnet_key
        #network_id  = aws_vpc.example[network_key].id
        cidr_block  = subnet.cidr_block
      }
    ]
  ])
}

resource "null_resource" "dynamic_self" {
  for_each = {
    for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
  }

  provisioner "local-exec" {
    command = "echo ${local.network_subnets}"
  }
}

*. Tfvars

networks = {
    network-1 = {
      cidr_block = "10.0.0.0/16"
      subnets = {
        subnet-1 = {
          cidr_block = "10.0.0.0/24"
        }
      }
    }
}

Сбой с ошибкой: Ошибка: недопустимое значение интерполяции шаблона: невозможно включить указанное значение в шаблон строки: требуется строка.

-------------------- Обновление-2 ----------- ------------------------------

Похоже, что flatten - правильная функция для этого варианта использования, и у меня есть переместился довольно далеко вниз по дорожке, но последний этап все еще не работает. Что у меня сейчас:

Values.tfvars

  subnets = {
    inbound-subnet = {
      name              = "subnet-a"
      cidr              = "10.0.1.0/24",
      nsgs = {
        nsg1 = {
            httpallowinbound = {
              name                       = "httpallow"
              priority                   = 100
              direction                  = "Inbound"
              access                     = "Allow"
              protocol                   = "Tcp"
              source_port_range          = "*"
              destination_port_range     = "*"
              source_address_prefix      = "*"
              destination_address_prefix = "*"
            },
            httpdenyinbound = {
              name                       = "httpdeny"
              priority                   = 101
              direction                  = "Inbound"
              access                     = "Deny"
              protocol                   = "Tcp"
              source_port_range          = "*"
              destination_port_range     = "*"
              source_address_prefix      = "*"
              destination_address_prefix = "*"
           },
        },
      }
    }
  }
}

местных жителей

nsgs = flatten([
    for subnets_name, subnets_values in var.subnets : [
      for nsg_name, nsg_values in subnets_values.nsgs : [
        for rule_name, rule_values in nsg_values: {
          nsg_name                   = nsg_name
          rule                       = rule_name
          name                       = rule_values.name
          priority                   = rule_values.priority
          direction                  = rule_values.direction
          access                     = rule_values.access
          protocol                   = rule_values.protocol
          source_port_range          = rule_values.source_port_range
          destination_port_range     = rule_values.destination_port_range
          source_address_prefix      = rule_values.source_address_prefix
          destination_address_prefix = rule_values.destination_address_prefix
       }
      ]
    ]
  ])
}

main. tf

resource "azurerm_subnet" "this" {
  for_each             = var.subnets
  name                 = lookup(each.value, "name")
  resource_group_name  = var.resource_group_name
  virtual_network_name = azurerm_virtual_network.this.name
  address_prefix       = lookup(each.value, "cidr")
}


resource "azurerm_network_security_group" "this" {
  for_each = {
      for sg in local.nsg_name:
        "${sg.nsg_name}" => sg
  }
  name                 = each.value.nsg_name
  location             = var.location
  resource_group_name  = var.resource_group_name
}


resource "azurerm_network_security_rule" "this" {
  for_each = {
      for sg in local.nsgs:
        //"${sg.rule}.${sg.name}" => sg
        sg.nsg_name => sg...
  }
  name                        = each.value.name
  priority                    = each.value.priority
  direction                   = each.value.direction
  access                      = each.value.access
  protocol                    = each.value.protocol
  source_port_range           = each.value.source_port_range
  destination_port_range      = each.value.destination_port_range
  source_address_prefix       = each.value.source_address_prefix
  destination_address_prefix  = each.value.destination_address_prefix
  resource_group_name         = var.resource_group_name
  network_security_group_name = azurerm_network_security_group.this[tostring(each.key)]
}

Но я продолжаю получать эту ошибку:

Ошибка: неверный тип значения атрибута

on ../../vnet.tf строка 55, в ресурсе "azurerm_network_security_rule" "this": 55: network_security_group_name = azurerm_network_security_group.this [tostring (each.value.nsg_name)]] | ----------------

| azurerm_network_security_group.this is object with 1 attribute "nsg1"
| each.value.nsg_name is "nsg1"

Недопустимое значение для атрибута "network_security_group_name": обязательная строка.

Error: Incorrect attribute value type

  on ../../vnet.tf line 55, in resource "azurerm_network_security_rule" "this":
  55:   network_security_group_name = azurerm_network_security_group.this[tostring(each.value.nsg_name)]
    |----------------
    | azurerm_network_security_group.this is object with 1 attribute "nsg1"
    | each.value.nsg_name is "nsg1"

Я уверен, что мне не хватает чего-то крошечного, потому что это выглядит выполнимо. Любые указатели действительно помогут

...