如何访问元组的第一个值并在 terraform 中创建列表?

How can I access first value of tuple and create a list in terraform?

我有一个可用区列表,我想在每个可用区中创建一个子网列表:

locals {
distict_az = tolist(["eu-west-1a", "eu-west-1b", "eu-west-1c"])
}

下面的数据源应该return一个元组。

data "aws_subnet_ids" "all_subnets" {
depends_on = [
  null_resource.next
]
count = length(local.distict_az)
vpc_id             = aws_vpc.virtual_network.id
filter {
  name   = "availabilityZone"
  values = ["${local.distict_az[count.index]}"]
}
}

以上数据来源return如下:

{
  "module": "module.cluster_aws.module.aws_network[0]",
  "mode": "data",
  "type": "aws_subnet_ids",
  "name": "all_subnets",
  "provider": "module.cluster_aws.provider[\"registry.terraform.io/hashicorp/aws\"]",
  "instances": [
    {
      "index_key": 0,
      "schema_version": 0,
      "attributes": {
        "filter": [
          {
            "name": "availabilityZone",
            "values": [
              "eu-west-1a"
            ]
          }
        ],
        "id": "vpc-01131c4180030ef3d",
        "ids": [
          "subnet-025a72306d7b94d03",
          "subnet-05f678ed690f0854a",
          "subnet-05fb3f9f2b2b5857a",
          "subnet-0e02ae5e08c62df02",
          "subnet-0fa45fd0f1b8e0d31"
        ],
        "tags": null,
        "vpc_id": "vpc-01131c4180030ef3d"
      },
      "sensitive_attributes": []
    },
    {
      "index_key": 1,
      "schema_version": 0,
      "attributes": {
        "filter": [
          {
            "name": "availabilityZone",
            "values": [
              "eu-west-1b"
            ]
          }
        ],
        "id": "vpc-01131c4180030ef3d",
        "ids": [
          "subnet-07c4811e4d7d10d21",
          "subnet-0b39190edb761ecf6"
        ],
        "tags": null,
        "vpc_id": "vpc-01131c4180030ef3d"
      },
      "sensitive_attributes": []
    },
    {
      "index_key": 2,
      "schema_version": 0,
      "attributes": {
        "filter": [
          {
            "name": "availabilityZone",
            "values": [
              "eu-west-1c"
            ]
          }
        ],
        "id": "vpc-01131c4180030ef3d",
        "ids": [
          "subnet-0769f8431f923f76e",
          "subnet-0a6a86a1eead531cd"
        ],
        "tags": null,
        "vpc_id": "vpc-01131c4180030ef3d"
      },
      "sensitive_attributes": []
    }
  ]
}

我正在纠结如何从每个 AZ 访问第一个子网并将其作为列表传递给下一个资源?

因此,例如,如果每个 AZ 各有 5 个子网,我想创建一个包含 3 个子网的列表(每个来自上面定义的 AZ)。所以我期待一个包含以下值的列表:

expected_list = tolist(["subnet-025a72306d7b94d03", "subnet-07c4811e4d7d10d21", "subnet-0769f8431f923f76e"])

顺序无关紧要。

我建议在这里要小心,因为如果您依赖任意排序,那么该排序可能会在未来发生变化,并对基于这些结果声明的资源造成重大的下游影响。

话虽如此,通过为每个可用区创建一组 all 子网 ID,以下内容将达到大部分目的:

locals {
  distict_az = toset(["eu-west-1a", "eu-west-1b", "eu-west-1c"])
}

data "aws_subnet_ids" "all_subnets" {
  for_each = local.distinct_az

  vpc_id = aws_vpc.virtual_network.id

  filter {
    name   = "availabilityZone"
    values = [each.key]
  }
}

locals {
  az_subnet_ids = tomap({
    for az, obj in data.aws_subnet_ids.all_subnets : az => toset(obj.ids)
  })
}

以上是相对安全的,因为它还没有对可用性区域或子网的排序做出任何假设。下一步需要对子网和可用性区域的排序做出 some 决定,既然你说顺序对你不重要,我将假设词汇排序字符串没问题,所以使用 sort:

locals {
  az_selected_subnet_ids = tomap({
    for az, ids in local.az_subnet_ids : az => sort(ids)[0]
  })
  # NOTE: The above will fail if any of the AZs has zero
  # ids, because there will be no zeroth element.

  # The following discards the keys of the map above and takes
  # just the values. This function is defined to sort the results
  # lexically by their corresponding keys, and so the result will
  # be in an order derived from the AZ name.
  all_selected_subnet_ids = values(az_selected_subnet_ids)
  # If the order of the selected subnet ids doesn't matter, I'd
  # recommend being explicit about that by using toset(values(...))
  # instead.
}

由于这是通过不可变 属性(可用区)选择子网并按 ID 对它们进行排序,因此每个子网的“第一个”应该保持不变,只要 AWS 通常分配词法上的新子网 ID大于之前发布的所有子网 ID,因为新的子网 ID 将因此出现在 sort 结果中。