Мне интересно, можно ли выполнить итерацию по структуре, подобной этой, используя комбинацию 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"
Я уверен, что мне не хватает чего-то крошечного, потому что это выглядит выполнимо. Любые указатели действительно помогут