Terraform 如何从地形列表中拾取图元
我正在terraform中创建一系列资源(在本例中为dynamo DB表)。我想将IAM策略应用于其中的子组。例如Terraform 如何从地形列表中拾取图元,terraform,Terraform,我正在terraform中创建一系列资源(在本例中为dynamo DB表)。我想将IAM策略应用于其中的子组。例如 resource "aws_dynamodb_table" "foo" { count = "${length(var.tables)}" name = "foo-${element(var.tables,count.index)}" tags { Name = "foo-${element(var.tables,count.index)}"
resource "aws_dynamodb_table" "foo" {
count = "${length(var.tables)}"
name = "foo-${element(var.tables,count.index)}"
tags {
Name = "foo-${element(var.tables,count.index)}"
Environment = "<unsure how to get this>"
Source = "<unsure how to get this>"
}
}
因此:
我想获取已创建的dynamo表的arn
,这些表具有c
(即名称为[“c:dev”,“c:qa”,“c:prod”]
)或prod
(即名称为[“a:prod”,“b:prod”,“c:prod”]
)的表
在terraform 0.11(甚至是0.12)上有什么明智的方法可以做到这一点吗
我希望:
environment
或source
)对dynamo db表资源进行分组,以便我可以对每个组应用一些策略{
"a": ["dev","qa","prod"],
"b": ["dev","qa","prod"],
"c": ["dev","qa","prod"]
}
或
这样可以很容易地找到每个资源的目标名称,因为我可以通过输入查找,但这只会给出名称,而不便于获取实际资源(因此,arn
s)
谢谢 Terraform 0.12解决方案是自动导出笛卡尔积(使用
setproduct
),并使用for
表达式将其塑造成适合您需要的形式。例如:
locals {
environments = ["dev", "qa", "prod"]
sources = ["a", "b", "c"]
tables = [for pair in setproduct(local.environments, local.sources) : {
environment = pair[0]
source = pair[1]
name = "${pair[1]}:${pair[0]}"
})
}
resource "aws_dynamodb_table" "foo" {
count = length(local.tables)
name = "foo-${local.tables[count.index].name}"
tags {
Name = "foo-${local.tables[count.index].name}"
Environment = local.tables[count.index].environment
Source = local.tables[count.index].source
}
}
在我写这篇文章的时候,每个功能的资源仍在开发中,但是在不久的将来Terraform v0.12的小版本中,应该可以通过使这些表实例都通过它们的名称而不是它们在本地表中的位置来进一步改进这一点。表
列表:
# (with the same "locals" block as in the above example)
resource "aws_dynamodb_table" "foo" {
for_each = { for t in local.tables : t.name => t }
name = "foo-${each.key}"
tags {
Name = "foo-${each.key}"
Environment = each.value.environment
Source = each.value.source
}
}
除了清除语法中的一些冗余之外,这个新的for_each
表单将使Terraform使用aws_dynamodb_table.foo[“a:dev”]
等地址来识别这个实例,而不是aws_dynamodb_table.foo[0]
,这意味着您可以自由地添加和删除两个初始列表的成员,而不会因为列表索引的更改而导致其他实例的混乱和替换
在Terraform0.11中,这类事情将更难实现。有一些通用模式可以帮助将某些仅0.12版本的结构转换为0.11版本的兼容功能,在这里可能会起作用:
- 如果结果仅是字符串值的映射,则可以使用
块模拟数据“null\u data\u source”
表达式返回的序列(其周围是方括号,而不是大括号)for
- 原则上,命名局部值中的Terraform 0.12对象可以替换为每个对象属性的局部值的单独简单贴图,使用每个贴图中的一组公共关键点
- Terraform 0.11没有
功能,但是对于这么小的序列,像在这里的问题中那样自己写出笛卡尔积并不是什么大问题setproduct
结果肯定会非常不美观,但我希望如果你应用上述想法并做出一些妥协,就有可能在Terraform 0.11上实现某种效果。我在阅读答案时,想,“响应者真的了解Terraform!”然后我看到它是
显然是智能的,这是有意义的。:-)是的,我想在0.12中实现它,但是这里的用例仍然有0.11依赖项,所以还不太可行。为了回答您的问题,我不能手工写出产品,因为它是传入的变量。我在示例中使用了locals
,以简化并使其易于运行。
{
"dev": ["a","b","c"],
"qa": ["a","b","c"],
"prod": ["a","b","c"]
}
locals {
environments = ["dev", "qa", "prod"]
sources = ["a", "b", "c"]
tables = [for pair in setproduct(local.environments, local.sources) : {
environment = pair[0]
source = pair[1]
name = "${pair[1]}:${pair[0]}"
})
}
resource "aws_dynamodb_table" "foo" {
count = length(local.tables)
name = "foo-${local.tables[count.index].name}"
tags {
Name = "foo-${local.tables[count.index].name}"
Environment = local.tables[count.index].environment
Source = local.tables[count.index].source
}
}
# (with the same "locals" block as in the above example)
resource "aws_dynamodb_table" "foo" {
for_each = { for t in local.tables : t.name => t }
name = "foo-${each.key}"
tags {
Name = "foo-${each.key}"
Environment = each.value.environment
Source = each.value.source
}
}