Terraform - 动态嵌套循环
Terraform - dynamic nested loops
我正在尝试创建一个嵌套循环以在 GCP 中创建防火墙规则。我有一个看起来像这样的 locals
变量:
local.firewall_definitions
{
"10.0.0.0/8" = [
{
"port" = "80"
"protocol" = "tcp"
},
{
"port" = "443"
"protocol" = "tcp"
},
{
"port" = "9000"
"protocol" = "udp"
},
]
"99.99.99.99/32" = [
{
"port" = "30000"
"protocol" = "tcp"
},
{
"port" = "1822"
"protocol" = "tcp"
},
{
"port" = "1823"
"protocol" = "udp"
},
]
}
我基本上想做的是以两种方式遍历这个变量:
- 为此列表中的每个不同的 CIDR 创建一个新的
google_compute_firewall
规则一次(有时可能是 1,有时可能是 10)
- 在每个 CIDR 中,遍历每个端口和协议的变量以创建每个
allow
规则
我的 main.tf
看起来像这样:
resource "google_compute_firewall" "firewalls" {
for_each = local.firewall_definitions
name = var.name
network = var.network
project = var.project
target_tags = var.targets
source_ranges = var.ranges
dynamic "allow" {
for_each = local.firewall_definitions[*]
content {
protocol = each.value[*].protocol
ports = each.value[*].port
}
}
}
问题是(我认为)我正在尝试使用 splat 进行循环,但我收到类似
的错误
each.value is tuple with 3 elements.
Inappropriate value for attribute "protocol": string required.
我认为这是因为 each.value[*].protocol
目前等于
"tcp",
"tcp",
"udp",
而 Terraform 只需要 string
形式的单个协议,而不是包含 3 个元素的 tuple
。
有没有人对实现嵌套循环的正确方法有任何想法?
这实际上不是嵌套循环,因为在 lambda 范围内的临时迭代器变量中忽略了键,因此结构可以完全展平。实现的第一个问题是动态块中的 for_each
在整个 local.firewall_definitions
上迭代。在资源范围内,对于 local.firewall_definitions
的每次迭代,key
将是未使用的 ip 地址,而 value
是分配给它的 list(object(string))
。我们可以更新动态块以迭代 list
值(动态块允许使用 for_each
元参数迭代 list
类型,与 resource
不同):
dynamic "allow" {
for_each = each.value
content {
protocol = each.value[*].protocol
ports = each.value[*].port
}
}
实现的第二个问题是分配给动态块中的 for_each
元参数的值在资源中被完全忽略。现在动态块正在 object
的 list
与 port
和 protocol
迭代特定 ip 地址 key
,我们需要访问协议迭代 list
:
中每个 object
的端口
dynamic "allow" {
for_each = each.value
content {
protocol = allow.value.protocol
ports = allow.value.port
}
}
达到了预期的效果。可以查看 for_each meta-argument and dynamic blocks 的文档以获取更多信息。
我正在尝试创建一个嵌套循环以在 GCP 中创建防火墙规则。我有一个看起来像这样的 locals
变量:
local.firewall_definitions
{
"10.0.0.0/8" = [
{
"port" = "80"
"protocol" = "tcp"
},
{
"port" = "443"
"protocol" = "tcp"
},
{
"port" = "9000"
"protocol" = "udp"
},
]
"99.99.99.99/32" = [
{
"port" = "30000"
"protocol" = "tcp"
},
{
"port" = "1822"
"protocol" = "tcp"
},
{
"port" = "1823"
"protocol" = "udp"
},
]
}
我基本上想做的是以两种方式遍历这个变量:
- 为此列表中的每个不同的 CIDR 创建一个新的
google_compute_firewall
规则一次(有时可能是 1,有时可能是 10) - 在每个 CIDR 中,遍历每个端口和协议的变量以创建每个
allow
规则
我的 main.tf
看起来像这样:
resource "google_compute_firewall" "firewalls" {
for_each = local.firewall_definitions
name = var.name
network = var.network
project = var.project
target_tags = var.targets
source_ranges = var.ranges
dynamic "allow" {
for_each = local.firewall_definitions[*]
content {
protocol = each.value[*].protocol
ports = each.value[*].port
}
}
}
问题是(我认为)我正在尝试使用 splat 进行循环,但我收到类似
的错误each.value is tuple with 3 elements. Inappropriate value for attribute "protocol": string required.
我认为这是因为 each.value[*].protocol
目前等于
"tcp",
"tcp",
"udp",
而 Terraform 只需要 string
形式的单个协议,而不是包含 3 个元素的 tuple
。
有没有人对实现嵌套循环的正确方法有任何想法?
这实际上不是嵌套循环,因为在 lambda 范围内的临时迭代器变量中忽略了键,因此结构可以完全展平。实现的第一个问题是动态块中的 for_each
在整个 local.firewall_definitions
上迭代。在资源范围内,对于 local.firewall_definitions
的每次迭代,key
将是未使用的 ip 地址,而 value
是分配给它的 list(object(string))
。我们可以更新动态块以迭代 list
值(动态块允许使用 for_each
元参数迭代 list
类型,与 resource
不同):
dynamic "allow" {
for_each = each.value
content {
protocol = each.value[*].protocol
ports = each.value[*].port
}
}
实现的第二个问题是分配给动态块中的 for_each
元参数的值在资源中被完全忽略。现在动态块正在 object
的 list
与 port
和 protocol
迭代特定 ip 地址 key
,我们需要访问协议迭代 list
:
object
的端口
dynamic "allow" {
for_each = each.value
content {
protocol = allow.value.protocol
ports = allow.value.port
}
}
达到了预期的效果。可以查看 for_each meta-argument and dynamic blocks 的文档以获取更多信息。