您还可以通过首先将集合转换为列表然后将其作为列表访问来对集合进行切片。
举个例子:
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.
如果您改为使用该tolist
函数强制转换它,那么您可以按预期访问它:
output "set_to_list_first_element" {
value = tolist(var.set)[0]
}
Outputs:
set = [
"bar",
"foo",
]
set_to_list_first_element = bar
请注意,这将返回bar
而不是foo
. 严格来说,集合在 Terraform 中是无序的,因此您根本不能依赖顺序,并且仅在一次 Terraform 运行期间保持一致,但实际上它们是稳定的,并且在set(string)
按字典顺序排序的情况下:
当集合转换为列表或元组时,元素将按任意顺序排列。如果集合的元素是字符串,它们将按字典顺序排列;其他元素类型的集合不保证任何特定的元素顺序。
出现这种情况的主要地方是,如果您正在处理在 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]
}
这将在标记为的子网中创建一个 EC2 实例,Tier = Private
但不会对其应在的位置设置其他限制。
虽然您提到能够访问值,但您也可以使用表达式for_each
循环遍历集合:for
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"
},
]