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"
    },
  ]
}

我基本上想做的是以两种方式遍历这个变量:

  1. 为此列表中的每个不同的 CIDR 创建一个新的 google_compute_firewall 规则一次(有时可能是 1,有时可能是 10)
  2. 在每个 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 元参数的值在资源中被完全忽略。现在动态块正在 objectlistportprotocol 迭代特定 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 的文档以获取更多信息。