Terraform for_each是从地形集合中检索值的唯一方法吗?

Terraform for_each是从地形集合中检索值的唯一方法吗?,terraform,hcl,Terraform,Hcl,Terraform最近引入了集数据类型,描述如下: set(…):没有任何辅助标识符或顺序的唯一值的集合 很难找到关于如何从地形集合中检索值的文档。使用地图,您可以索引键: password = var.passwords["kevin"] 通过列表,您可以对元素编号进行索引: a_record = var.records[1] 但是,我不能使用这两种方法中的任何一种从集合中检索值,即使是只有一个项的集合 在其他地方,文档提到了将作为从集合中获取值的方法 variable

Terraform最近引入了
数据类型,描述如下:

set(…)
:没有任何辅助标识符或顺序的唯一值的集合

很难找到关于如何从地形集合中检索值的文档。使用地图,您可以索引键:

password = var.passwords["kevin"]
通过列表,您可以对元素编号进行索引:

a_record = var.records[1]
但是,我不能使用这两种方法中的任何一种从集合中检索值,即使是只有一个项的集合

在其他地方,文档提到了将
作为从集合中获取值的方法

variable "subnet_ids" {
  type = list(string)
}

resource "aws_instance" "server" {
  for_each = toset(var.subnet_ids)

  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"
  subnet_id     = each.key # note: each.key and each.value are the same for a set

  tags = {
    Name = "Server ${each.key}"
  }
}

每个元变量的
是否是访问集合中的值的唯一方法?

您也可以通过先将集合强制转换为列表,然后作为列表访问来切片集合

例如:

variable "set" {
  type = set(string)
  default = [
    "foo",
    "bar",
  ]
}

output "set" {
  value = var.set
}

output "set_first_element" {
  value = var.set[0]
}
这将导致错误,因为索引无法直接访问集合:

Error: Invalid index

  on main.tf line 14, in output "set_first_element":
  14:   value = var.set[0]

This value does not have any indices.
如果改为使用强制转换,则可以按预期访问它:

output "set_to_list_first_element" {
  value = tolist(var.set)[0]
}
请注意,这将返回
bar
,而不是
foo
。严格来说,地形中的集合是无序的,因此您根本不能依赖于顺序,并且仅在一次地形运行期间是一致的,但实际上,它们是稳定的,并且在以下情况下:

当集合转换为列表或元组时,元素将以任意顺序排列。如果集合的元素是字符串,它们将按字典顺序排列;其他元素类型的集合不保证元素的任何特定顺序

出现这种情况的主要原因是,如果您处理的资源或数据源返回Terraform 0.12中的集合类型,但需要使用单数值。一个基本的例子可能是这样的:

data "aws_subnet_ids" "private" {
  vpc_id = var.vpc_id

  tags = {
    Tier = "Private"
  }
}

resource "aws_instance" "app" {
  ami           = var.ami
  instance_type = "t2.micro"
  subnet_id     = tolist(data.aws_subnet_ids.example.ids)[0]
}
这将在标记为
Tier=Private
的子网中创建一个EC2实例,但不对其位置设置其他约束

当您能够使用
为每个
访问值时,您还可以使用以下参数循环一组:

然后输出以下内容:

list_comprehension_over_set = [
  "SSH",
  "HTTP",
]
set_of_objects = [
  {
    "port" = 22
    "service" = "ssh"
  },
  {
    "port" = 80
    "service" = "http"
  },
]

你能分享一下你是如何尝试从一个集合中访问元素的,以及你从中得到的错误吗?通常你只是把它放到一个列表中,然后把它切分……这不是我以前见过的,也不是我在Terraform的四年中必须自己做的,所以这个用例和那个评论(希望很快能得到答案)都让我感兴趣。除此之外,我会对这个问题说“是”,除了
for_each
不是一个元变量(很抱歉,太迂腐了)。为什么你会说
for_each
不是一个元变量?将它列为所有资源可用的元参数之一,尽管它比它更复杂,因为它也出现在
dynamic
块中,而其他块则不是(主要是因为
dynamic
需要它)。谢谢,这就是我最后要做的。。。它在整个示例中看起来更笨拙,因为它在较大变量的中间调用Telist-(),但它确实是个诀窍。这很有帮助。
variable "set_of_objects" {
  type = set(object({
    port    = number
    service = string
  }))

  default = [
    {
      port    = 22
      service = "ssh"
    },
    {
      port    = 80
      service = "http"
    },
  ]
}

output "set_of_objects" {
  value = var.set_of_objects
}

output "list_comprehension_over_set" {
  value = [ for obj in var.set_of_objects : upper(obj.service) ]
}
list_comprehension_over_set = [
  "SSH",
  "HTTP",
]
set_of_objects = [
  {
    "port" = 22
    "service" = "ssh"
  },
  {
    "port" = 80
    "service" = "http"
  },
]