foreach - Terraform for_each 用于地图内的地图
问题描述
我想知道是否可以使用 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
}
----------------------更新-1-------------- --------------------
根据到目前为止的发现,flatten 函数应该提供这种机制,如此处所述
但是,我无法使该示例也正常工作:
主文件
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 是这个用例的正确功能,我已经在车道上移动得更远了,但最后一个阶段仍然没有工作。我现在拥有的:
值.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
}
]
]
])
}
主文件
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)]
}
但我不断收到此错误:
错误:属性值类型不正确
在 ../../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"
我确信我错过了一些微小的东西,因为它看起来是可行的。任何指针都会有帮助
解决方案
推荐阅读
- php - 无法在 PHP 中回显 json 数据
- excel - Splitbook,但可以选择使用自定义名称保存 nw 文件工作表
- apache-kafka-connect - 通过 Kafka Connect 转换插入时间戳
- mongodb - 用于在 Macos Mojave 中使用 mongodb-community 版本的 mongod 命令给出错误
- c# - Travis 上的 dotnet 恢复
- azure - 尝试更改 Kubernetes 集群中的最大节点数会返回错误
- android - 面临滑行的 Registry$NoModelLoaderAvailableException 无法从 Firebase 存储中加载图像
- c# - 如何将实体 ID 从 c sharp API 返回到 angular 9?
- java - 直接使用 github 存储库位置的复合构建
- ansible - ansible 模块 postgresql_schema 不支持从数据库中对单个模式进行备份和恢复