此要求的一个初始问题是它需要一个动态的环境列表,但需要多个单独的输出值。为了完成这项工作,您需要使环境输入单独的值或生成描述环境的单个输出值。
# Variant with a fixed set of environments (v0.11 syntax)
variable "production_environment_name" {
type = "string"
default = "production"
}
variable "non_production_environment_name" {
type = "string"
default = "non-production"
}
resource "aws_iam_group" "production_access" {
name = "access-${var.production_environment_name}"
}
resource "aws_iam_group" "non_production_access" {
name = "access-${var.non_production_environment_name}"
}
output "access_production" {
value = "aws_iam_group.production_access.arn"
}
output "access_non_production" {
value = "aws_iam_group.non_production_access.arn"
}
# Variant with dynamic set of environments (v0.11 syntax)
variable "environments" {
type = "list"
default = ["production", "non_production"]
}
resource "aws_iam_group" "access" {
count = "${length(var.environments)}"
name = "access-${var.environments[count.index]}"
}
output "access" {
value = "${aws_iam_group.access.*.arn}"
}
这里的关键是输入变量和输出值必须具有相同的形式,这样我们才能在对象之间进行所有必要的引用。在第二个示例中,环境名称以列表的形式提供,组 ARN 也以列表的形式提供,以便索引在两者之间对应。
您还可以使用output "access" 表达式的变体将两者与zipmap 结合起来,并获得一个以环境名称为键的映射,这可能更方便调用者使用:
output "access" {
value = "${zipmap(var.environments, aws_iam_group.access.*.arn)}"
}
Terraform 0.12 中的新功能允许对此进行一些整理。这是生成地图的版本的惯用 Terraform 0.12 等效版本:
# Variant with dynamic set of environments (v0.12 syntax)
variable "environments" {
type = set(string)
default = ["production", "non_production"]
}
resource "aws_iam_group" "access" {
for_each = var.environments
name = "access-${each.key}"
}
output "access" {
value = { for env, group in aws_iam_group.access : env => group.arn }
}
除了语法模式略有不同外,这个 0.12 示例还有一个额外的实际优势:Terraform 将跟踪地址为 aws_iam_group.access["production"] 和 aws_iam_group.access["non_production"] 的那些 IAM 组,因此环境名称在 @987654331 中的位置@list 并不重要,并且可以添加和删除环境,而不会由于列表元素重新编号而潜在地干扰其他环境中的组。
它通过使用resource for_each 实现这一点,这使得aws_iam_group.access 显示为对象映射,其中环境名称是键,而count 使其成为对象列表。