迭代 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.