有没有办法在不必在局部变量中创建新变量的情况下进行嵌套 for 循环?

Is there a way to have a nested for loop without having to create a new variable in locals?

在 terraform v0.14.4 上

我的变量如下所示:

variable "my_config" {
  type = object({
    instances = set(string)
    locations = set(string)
  })
  default = {
    locations = [
      "us",
      "asia"
    ]
    instances = [
      "instance1",
      "instance2"
    ]
  }

我想遍历资源中的这个 var 并为每个位置 + 实例创建一个资源实例。资源的“名称”字段也将是 "<LOCATION>_<INSTANCE>"

我可以在 locals 中创建一个新的 var 来读取 my_config var 并生成一个新的 var,如下所示:

[
  "us_instance1",
  "us_instance2",
  "asia_instance1",
  "asia_instance2",
]

不过,我宁愿不从这个现有的 var 生成新的 terraform var。是否可以在 foreach 循环中直接在资源定义中聚合这两个列表?或者是在本地创建新数据结构的唯一方法?

编辑

我无法获得在资源定义中工作所提供的答案中的展平示例。我收到此错误:The given "for_each" argument value is unsuitable: the "for_each" argument must be a map, or set of strings, and you have provided a value of type tuple. 如果类型为 set(string)list(string),则会发生此错误。

# This works
output "test" {
  value = flatten(
    [
      for location in var.my_config.locations : [
        for instance in var.my_config.instances : "${location}_${instance}"
      ]
    ]
  )
}

# This throws the error
resource "null_resource" "test" {
  for_each = flatten(
    [
      for location in var.my_config.locations : [
        for instance in var.my_config.instances : "${location}_${instance}"
      ]
    ]
  )
  provisioner "local-exec" {
    command = "echo test"
  }
}

实现return值:

[
  "us_instance1",
  "us_instance2",
  "asia_instance1",
  "asia_instance2",
]

通过输入变量 my_config,您可以:

flatten([for location in var.my_config.locations : [
  for instance in var.my_config.instances : "${location}_${instance}"
]])

是否在 locals 块中定义它取决于您。如果您多次计划 re-using 这个值,那么将它定义为 local 会更有效。如果您打算只使用它一次,那么不在 locals.

中定义它肯定更有意义

请注意,这还假定 my_config 类型为 object(list(string))。问题中没有给出类型,但如果类型不是,那么代码会变得更加模糊。

关于在资源范围内将此值用作 for_each meta-argument 值的其他问题,需要将其转换为类型 set(string)。这可以使用 toset 函数轻松完成:

resource "resource" "this" {
  for_each = toset(<expression above or variable with return value of above assigned to it>)
}