遍历对象图

时间:2020-05-18 20:14:27

标签: terraform

如何为以下内容进行for_each循环?

我想创建一个tfe_variable node_countvm_size。 我在wksp1wksp2中都需要这两个tfe_variables

variable "custom_variables" {
  type = map(object({
    node_count = number
    vm_size    = string
  }))

  default = {
    wksp1 = {
      node_count = 2
      vm_size    = "Standard_D2_v3"
    },
    wksp2 = {
      node_count = 5
      vm_size    = "Standard_D2_v5"
    }
  }
}

resource "tfe_variable" "custom" {
  for_each = {
    # for each workspace & variable in var.custom_variables create a tfe_variable
  }

  key          = each.value.name
  value        = each.value.value
  category     = "terraform"
  workspace_id = each.value.workspace_id
}

2 个答案:

答案 0 :(得分:3)

您真的很亲密!这里有几件事情要考虑:

选项1:多个tfe_variable资源

  1. 为您要创建的每个变量创建一个tfe_variable资源
  2. 确保您custom_variables映射中的键是工作区ID。
variable "custom_variables" {
  type = map(object({
    node_count = number
    vm_size    = string
  }))

  default = {
    wksp1_id = {
      node_count = 2
      vm_size    = "Standard_D2_v3"
    },
    wksp2_id = {
      node_count = 5
      vm_size    = "Standard_D2_v5"
    }
  }
}

resource "tfe_variable" "node_count" {
  for_each = var.custom_variables

  key          = "node_count"
  value        = each.value.node_count
  category     = "terraform"
  workspace_id = each.key
}

resource "tfe_variable" "vm_size" {
  for_each = var.custom_variables

  key          = "vm_size"
  value        = each.value.vm_size
  category     = "terraform"
  workspace_id = each.key
}

此选项的缺点是每个变量都需要额外的资源。

选项2:变量对象列表

  1. 定义每个变量的键,值和工作区ID的列表
  2. 使用count遍历列表
variable "custom_variables" {
  type = list(object({
    key          = string
    value        = string
    workspace_id = string
  }))
  default = [
    {
      key          = "node_count"
      value        = "2"
      workspace_id = "wksp1_id"
    },
    {
      key          = "node_count"
      value        = "5"
      workspace_id = "wksp2_id"
    },
    {
      key          = "vm_size"
      value        = "Standard_D2_v3"
      workspace_id = "wksp1_id"
    },
    {
      key          = "vm_size"
      value        = "Standard_D2_v5"
      workspace_id = "wksp2_id"
    }
  ]
}

resource "tfe_variable" "custom" {
  count = length(var.custom_variables)

  key          = var.custom_variables[count.index].key
  value        = var.custom_variables[count.index].value
  workspace_id = var.custom_variables[count.index].workspace_id
  category     = "terraform"
}

此方法也有一些缺点:

  • 变量定义中有大量重复的代码
  • 该值必须始终为同一类型

如果您在Terraform中遇到循环概念的问题,this blog post可能会为您提供帮助。

答案 1 :(得分:1)

for_each要记住的主要要求是,我们始终需要创建一个映射,该映射对于要创建的资源的每个实例都具有一个元素。在这种情况下,这意味着您需要一个每个元素每个工作空间一个变量的映射,因为tfe_variable在单个工作空间中描述了一个变量。

然后我们的工作是编写一个表达式,以将通过变量传入的对象映射值投影到每个变量具有单独元素的集合中。这是完成任务的一种方法,使用the flatten function的方式类似于an example in its documentation

locals {
  workspace_variables = flatten([
    for ws_name, ws in var.custom_variables : [
      for var_name, value in ws : {
        workspace = ws_name
        variable  = var_name
        value     = value
      }
    ]
  ])
}

上面的代码应产生一个local.workspace_variables,如下所示:

[
  { workspace = "wksp1", variable = "node_count", value = 2 },
  { workspace = "wksp1", variable = "vm_size", value = "Standard_D2_v3" },
  { workspace = "wksp2", variable = "node_count", value = 5 },
  { workspace = "wksp2", variable = "vm_size", value = "Standard_D2_v5" },
]

这现在满足了在每个所需的tfe_variable实例中拥有一个元素的要求,因此,我们剩下的唯一工作就是将其投影到地图中,以为每个元素提供唯一的标识符,并描述如何填充{{1} }基于这些对象的参数:

tfe_variable

我上面没有与之抗衡的一件事,是因为它不是您直接提出的问题,是resource "tfe_variable" "custom" { for_each = { for wsv in local.workspace_variables : "${wsv.workspace}.${wsv.variable}" => wsv } key = each.value.variable value = each.value.value category = "terraform" workspace_id = each.value.workspace } workspace_id的值。如果我没记错的话,该参数期望的是工作空间 id 而不是工作空间 name ,在这种情况下,tfe_variable可能需要稍微复杂一点的表达式论据。如果您已经拥有一个使用工作区名称作为关键字的workspace_id资源,那么类似的事情可能会起作用,例如:

tfe_workspace

如果您以不同的方式创建工作区,那么您可能必须在这里做一些更复杂的事情,但这与您最初提出的问题的主题相去甚远,因此在这里我不会尝试深入探讨。不过,如果您愿意,我很乐意尝试在此站点上的另一个问题中提供帮助。