如何处理 terraform 中的可选动态块

How to handle optional dynamic blocks in terraform

我正在尝试使用动态块迭代资源“launchdarkly_feature_flag”变量,这些变量可能具有可选的嵌套对象 - “变体”(可以是 0 或 2+):

variable "feature_flags" {
  default = {
    flag_1 = {
      project_key = "project"
      key         = "number example"
      name        = "number example flag"
      description = "this is a multivariate flag with number variations."
      variation_type = "number"
      variations = {
        value = 100
      }
      variations = {
        value = 300
      }
      tags = ["example"]
    },
    flag_2 = {
      project_key = "project"
      key = "boolean example"
      name = "boolean example flag"
      description = "this is a boolean flag"
      variation_type = "boolean"
      tags = ["example2"]
    }
  }
}

我尝试了各种如何获取所有标志的方案,但总是遇到不同的问题。一段代码:

resource "launchdarkly_feature_flag" "ffs" {
  for_each = var.feature_flag_map
  project_key = each.value.project_key
  key  = each.value.key
  name = each.value.name
  description = each.value.description
  variation_type = each.value.variation_type
  
  # main problem here
  dynamic variations {
    for_each = lookup(each.value, "variations", {}) == {} ? {} : {
      content {
        value = each.value.variations.value
      }
    }
  }
  tags = each.value.tags
}

你能帮忙吗?我正在使用 0.14v 的 Terraform

第一步是告诉 Terraform 这个变量需要什么类型的值。虽然通常可以省略简单值的显式类型并让 Terraform 从 default 自动推断它,但当数据结构如此复杂时,最好告诉 Terraform 你的意图,因为这样你就可以避免它“猜测”不正确,结果给你令人困惑的错误信息。

以下看起来像是您显示的默认值的合适类型约束:

variable "feature_flags" {
  type = map(object({
    project_key    = string
    key            = string
    name           = string
    description    = string
    variation_type = string
    tags           = set(string)
    variations = list(object({
      value = string
    }))
  }))
}

写出类型后,Terraform 将保证任何 var.feature_flags 值都符合该类型约束,这意味着您可以根据值是 null 还是不是:

resource "launchdarkly_feature_flag" "ffs" {
  for_each = var.feature_flags

  project_key    = each.value.project_key
  key            = each.value.key
  name           = each.value.name
  description    = each.value.description
  variation_type = each.value.variation_type
  tags           = each.value.tags

  dynamic "variations" {
    for_each = each.value.variations != null ? each.value.variations : []
    content {
      variations.value.value
    }
  }
}

如上所述,Terraform 将要求 feature_flags 中的所有值都定义了所有属性,尽管调用者可以将它们设置为 null 以指示它们未设置。

在撰写本文时,在 Terraform v0.14 中,an experimental feature for marking attributes as optional 似乎一旦稳定下来就适合此用例。将部分或全部属性标记为 optional 将允许调用者省略它们,从而导致 Terraform 自动 将它们设置为 null,而不是调用者必须自己显式写出 null 值。

希望该功能在 v0.15 中得到稳定,届时您可以 return 添加 optional 注释到某些属性,而无需更改模块的任何其他内容。