迭代 Terraform 动态块内的单个地图
Iterate over single map inside Terraform dynamic block
我在资源块中有以下代码片段,
...
condition {
dynamic "http_header" {
for_each = var.http_headers
content {
http_header_name = http_header.value.header_name[0]
values = [http_header.value.values[0]]
}
}
}
...
变量当前设置为:
variable "http_headers" {
type = map
default = {}
}
我想提供一张地图并让 Terraform 在内容块中为它们设置值,例如
http_headers = {
header_name = "foo"
values = "bar"
}
根据我目前所做的阅读,我认为这会奏效,但我收到了类似于以下内容的错误。
Error: Unsupported attribute
on .terraform/main.tf line 138, in resource "aws_alb_listener_rule" "listener_rule":
138: values = [http_header.value.values[0]]
|----------------
| http_header.value is "foo"
This value does not have any attributes.
FWIW 如果我将 http_headers
变量包装在列表中并对其进行迭代,我已经能够使它工作,但我想简化配置以仅使用单个映射。这可能吗?
看起来你混合了地图和列表,如果你想遍历某些东西,它应该是一个列表...
我更喜欢具有明确定义的对象的列表,这样可以验证输入:
type = list(object({
num = number
protoc = string
values = string
}))
但你也可以选择更简单的
type = list(any)
这是一个例子:
variable "http_headers" {
type = list(object({
num = number
values = string
}))
default = []
}
data "aws_vpc" "default" {
default = true
}
resource "aws_network_acl" "network_acl" {
vpc_id = data.aws_vpc.default.id
dynamic "ingress" {
for_each = var.http_headers
content {
rule_no = ingress.value.num
protocol = ingress.value.protoc
action = "allow"
cidr_block = ingress.value.values
from_port = 22
to_port = 22
}
}
}
然后我们在 json 文件中输入 (input.tfvars.json
):
[
{
"num": 1,
"protoc": "tcp",
"values": "10.0.0.1/32"
},
{
"num": 2,
"protoc": "tcp",
"values": "10.0.0.2/32"
}
]
最后我们可以运行一个计划:
terraform plan -var-file="input.tfvars.json"
Terraform will perform the following actions:
# aws_network_acl.network_acl will be created
+ resource "aws_network_acl" "network_acl" {
+ arn = (known after apply)
+ egress = (known after apply)
+ id = (known after apply)
+ ingress = [
+ {
+ action = "allow"
+ cidr_block = "10.0.0.1/32"
+ from_port = 22
...
+ rule_no = 1
+ to_port = 22
},
+ {
+ action = "allow"
+ cidr_block = "10.0.0.2/32"
+ from_port = 22
...
+ rule_no = 2
+ to_port = 22
},
]
+ owner_id = (known after apply)
+ subnet_ids = (known after apply)
+ vpc_id = "vpc-f99999999"
}
Plan: 1 to add, 0 to change, 0 to destroy.
我在资源块中有以下代码片段,
...
condition {
dynamic "http_header" {
for_each = var.http_headers
content {
http_header_name = http_header.value.header_name[0]
values = [http_header.value.values[0]]
}
}
}
...
变量当前设置为:
variable "http_headers" {
type = map
default = {}
}
我想提供一张地图并让 Terraform 在内容块中为它们设置值,例如
http_headers = {
header_name = "foo"
values = "bar"
}
根据我目前所做的阅读,我认为这会奏效,但我收到了类似于以下内容的错误。
Error: Unsupported attribute
on .terraform/main.tf line 138, in resource "aws_alb_listener_rule" "listener_rule":
138: values = [http_header.value.values[0]]
|----------------
| http_header.value is "foo"
This value does not have any attributes.
FWIW 如果我将 http_headers
变量包装在列表中并对其进行迭代,我已经能够使它工作,但我想简化配置以仅使用单个映射。这可能吗?
看起来你混合了地图和列表,如果你想遍历某些东西,它应该是一个列表...
我更喜欢具有明确定义的对象的列表,这样可以验证输入:
type = list(object({
num = number
protoc = string
values = string
}))
但你也可以选择更简单的
type = list(any)
这是一个例子:
variable "http_headers" {
type = list(object({
num = number
values = string
}))
default = []
}
data "aws_vpc" "default" {
default = true
}
resource "aws_network_acl" "network_acl" {
vpc_id = data.aws_vpc.default.id
dynamic "ingress" {
for_each = var.http_headers
content {
rule_no = ingress.value.num
protocol = ingress.value.protoc
action = "allow"
cidr_block = ingress.value.values
from_port = 22
to_port = 22
}
}
}
然后我们在 json 文件中输入 (input.tfvars.json
):
[
{
"num": 1,
"protoc": "tcp",
"values": "10.0.0.1/32"
},
{
"num": 2,
"protoc": "tcp",
"values": "10.0.0.2/32"
}
]
最后我们可以运行一个计划:
terraform plan -var-file="input.tfvars.json"
Terraform will perform the following actions:
# aws_network_acl.network_acl will be created
+ resource "aws_network_acl" "network_acl" {
+ arn = (known after apply)
+ egress = (known after apply)
+ id = (known after apply)
+ ingress = [
+ {
+ action = "allow"
+ cidr_block = "10.0.0.1/32"
+ from_port = 22
...
+ rule_no = 1
+ to_port = 22
},
+ {
+ action = "allow"
+ cidr_block = "10.0.0.2/32"
+ from_port = 22
...
+ rule_no = 2
+ to_port = 22
},
]
+ owner_id = (known after apply)
+ subnet_ids = (known after apply)
+ vpc_id = "vpc-f99999999"
}
Plan: 1 to add, 0 to change, 0 to destroy.