在Terraform 0.12中创建地图时保留列表顺序?

时间:2020-10-08 18:15:46

标签: terraform terraform-provider-aws terraform0.12+

在我的配置中,我有以下代码片段-想法是将当前逻辑/语法从0.11更改为0.12。首先,我从列表创建地图,

my_vars = zipmap(
  var.foo_vars,
  flatten(data.terraform_remote_state.foo.*.outputs.some_id)
)

然后对其进行迭代以生成一些键值对。

...
"var": [for key in keys(local.my_vars) :
  {
    name  = key
    value = lookup(local.my_vars, key)
  }
],
...

这是相关的tfvars配置。

foo_vars = [
    "A",
    "B",
    "C"
]

问题在于,这种逻辑似乎并没有保留顺序,而且我想不出一种实现这一目标的好方法。据我了解,一旦您将列表变成zipmap的地图,订单就会重新计算。有什么办法可以保留原始订单?

我不受当前解决方案的束缚,所以也许有一种生成键/值的方法,而该键/值不需要先创建映射就可以只用两个列表来完成?

~ foo          = [
                        {
                            name  = "A"
                            value = "1"
                        },
                      - {
                          - name  = "B"
                          - value = "2"
                        },
                        {
                            name  = "C"
                            value = "3"
                        },
                      + {
                          + name      = "B"
                          + valueFrom = "2"
                        },
                    ]

1 个答案:

答案 0 :(得分:1)

这里重要的是,正如您所注意到的,Terraform的地图类型是无序地图,它仅通过元素的键而不是许可来标识元素。因此,如果遇到需要保留序列顺序的情况,则映射不适合使用数据结构。

我怀疑保持秩序井然并不是解决这里潜在问题的必要方法,但是我无法从您共享的信息中看出所有这些值的真实含义,所以我将假设您要做需要保留订单。如果仅由于使用count创建资源的多个实例而使用有序序列,则建议您考虑使用resource for_each,这可能使您可以解决以下问题:对var.foo_vars中的项目顺序不敏感的方式。


给定两个相同长度的列表,您可以通过编写for expression来生成一个新列表,该列表将每个列表中的相应元素组合在一起:

locals {
  my_vars = [
    for i, some_id in data.terraform_remote_state.foo.*.outputs.some_id : {
      name  = var.foo_vars[i]
      value = some_id
    }
  ]
}

以上内容基于以下事实:一个列表中的i索引值与另一列表中相同索引的元素相关联,因此我们可以使用数据源实例中的i来访问var.foo_vars的相应元素。