通过YAML进行查询,并为for_each循环创建自定义的local



让我向您介绍我们的设置。我们有一个/apps文件夹,其中包括一些yml文件:

/apps
|___ testing-one.yml
|___ testing-two.yml

应用程序/测试一个。yml

name: testing one
hostnames:
- name: testing-a
external: true
internal: true
internal_stages: ["dev","qs"]
- name: testing-b
external: true
internal: true
internal_stages: ["dev","qs"]

应用程序/测试两个。yml

name: testing-two
hostnames:
- name: testing-x
external: true
internal: true
internal_stages: ["dev","qs"]

正如您所看到的,一些文件在hostnames下只有一个条目,另一些则有两个条目。为了进一步自定义List,我们创建了一个本地变量,该变量保存apps/文件夹下每个文件的数据。

applications = [for filename in fileset(path.module, "apps/*.yml") : yamldecode(file(filename))]

local.applications的输出如下:

+ name = [
+ {
+ hostnames = [
+ {
+ external        = true
+ internal        = true
+ internal_stages = [
+ "dev",
+ "qs",
]
+ name            = "testing-a"
},
+ {
+ external        = true
+ internal        = true
+ internal_stages = [
+ "dev",
+ "qs",
]
+ name            = "testing-b"
},
]
+ name      = "testing one"
},
+ {
+ hostnames = [
+ {
+ external        = true
+ internal        = true
+ internal_stages = [
+ "dev",
+ "qs",
]
+ name            = "testing-x"
},
]
+ name      = "testing-two"
},
]

我们需要什么

对于以后的资源创建,我们需要一个具有以下值的映射。

  1. 对于hostname下的每个name条目,创建一个映射,其中keytesting-a(hostname.name的值(,valuetesting one(仅name的值(

类似这样的东西:

[
{testing-a: testing one},
{testing-b: testing one},
{testing-x: testing-two}
]

为什么我们需要这种类型的地图

稍后,我们必须创建一个包含for_each的资源,该资源使用列表的键和值。

resource "local_file" "foo" {
for_each = {for key, value in local.final_list : key => value}
content  = each.key
filename = each.value
}

我该如何解决此问题?

以下局部变量输出您的预期结果,我相信:

final_list = flatten([for app in local.applications : [
for host in app.hostnames : {
(host.name) = app.name
}
]])

我在创建一个名为";out_test";如下所示:

+ out_test = [
+ {
+ testing-a = "testing one"
},
+ {
+ testing-b = "testing one"
},
+ {
+ testing-x = "testing-two"
},
]

正如Marko所提到的,您需要将其转换为for_each的映射,您可以按如下方式内联,或者更干净的方法是使用merge函数包装局部变量,如果您能够:

resource "local_file" "foo" {
for_each = { for key, value in merge(local.final_list...) : key => value }
content  = each.key
filename = each.value
}