【问题标题】:Iterate over single map inside Terraform dynamic block迭代 Terraform 动态块内的单个地图
【发布时间】:2021-06-03 06:16:03
【问题描述】:

我在资源块中有以下 sn-p,

...
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 变量包装在一个列表中并对其进行迭代,我已经能够使其工作,但我想简化配置以仅使用单个映射。这可能吗?

【问题讨论】:

    标签: terraform terraform-provider-aws terraform0.12+


    【解决方案1】:

    看起来你混合了地图和列表,如果你想循环一些东西,它应该是一个列表......

    我更喜欢具有明确定义的对象的列表,这样可以验证输入:

      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.
    

    【讨论】:

    • 我可能有一些残留物可以让它与列表一起使用。您是否知道使用单个地图而不是地图列表的方法?
    • @jmreicha 如果你想循环一些我认为地图不是最好的选择,我认为它应该是一个列表,如果你不喜欢定义对象,只需使用list(any)
    • 那是公平的,可能是地图方法走错了路。
    • @jmreicha 现在只是为了澄清一下,我们可以遍历地图,terraform 在他们的文档中显示它:terraform.io/docs/language/meta-arguments/… 但我只会在非常简单的情况下使用它,比如他们显示的硬编码示例跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2020-12-09
    • 2020-08-11
    • 1970-01-01
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多