【问题标题】:terraform - Iterate over two linked resourcesterraform - 遍历两个链接的资源
【发布时间】:2020-11-28 01:35:50
【问题描述】:

我正在尝试编写一些代码来接受这样的输入结构:

  projects = {
    "project1" = {
      namespaces = ["mynamespace1"]
     },
    "project2" = {
      namespaces = ["mynamespace2", "mynamespace3"]
    }
  }

并使用 for_each 提供多个资源,这将导致:

resource "rancher2_project" "project1" {
  provider   = rancher2.admin
  cluster_id = module.k8s_cluster.cluster_id

  wait_for_cluster = true
}

resource "rancher2_project" "project2" {
  provider   = rancher2.admin
  cluster_id = module.k8s_cluster.cluster_id

  wait_for_cluster = true
}

resource "rancher2_namespace" "mynamespace1" {
  provider    = rancher2.admin
    project_id  = rancher2_project.project1.id
   
  depends_on = [rancher2_project.project1]
}

resource "rancher2_namespace" "mynamespace2" {
  provider    = rancher2.admin
    project_id  = rancher2_project.project2.id
   
  depends_on = [rancher2_project.project2]
}

resource "rancher2_namespace" "mynamespace3" {
  provider    = rancher2.admin
    project_id  = rancher2_project.project2.id
   
  depends_on = [rancher2_project.project2]
}

命名空间依赖于项目,需要将生成的 id 传递到命名空间。

有什么好的方法可以动态地做到这一点吗?我们可能有很多项目/命名空间。

感谢您的帮助和建议。

【问题讨论】:

  • 您的示例不是迭代 2 个提供程序配置,而是超过 2 个使用相同提供程序但不同项目的资源。你在你的例子中遗漏了什么吗?
  • 我的错误应该是超过 2 个资源。

标签: terraform


【解决方案1】:

基于数据结构系统地生成资源的多个实例的典型答案是resource for_each。资源for_each 的主要要求是拥有一个地图,其中包含您要创建的每个资源实例的一个元素。

在您的情况下,您似乎每个项目需要一个 rancher2_project,然后每对项目和命名空间需要一个 rancher2_namespace。因此,您当前的数据结构对于 rancher2_project 资源已经足够了:

resource "rancher2_project" "example" {
  for_each = var.projects
  provider = rancher2.admin

  cluster_id       = module.k8s_cluster.cluster_id
  wait_for_cluster = true
}

上面会声明两个资源实例,地址如下:

  • rancher2_project.example["project1"]
  • rancher2_project.example["project2"]

您目前没有每个 命名空间 有一个元素的地图,因此需要做更多工作才能从输入数据结构中导出合适的值。这种情况的常见模式是flattening nested structures for for_each 使用the flatten function

locals {
  project_namespaces = flatten([
    for pk, proj in var.projects : [
      for nsk in proj.namespaces : {
        project_key   = pk
        namespace_key = ns
        project_id    = rancher2_project.example[pk].id
      }
    ]
  ])
}

resource "rancher2_namespace" "example" {
  for_each = {
    for obj in local.project_namespaces :
    "${obj.project_key}.${obj.namespace_key}" => obj
  }
  provider = rancher2.admin

  project_id = each.value.project_id
}

这会生成一个代表所有项目和命名空间对的对象列表,然后for_each 参数将其转换为使用复合键的映射,其中包括项目和命名空间键,以确保它们都是唯一的。因此,生成的实例将具有以下地址:

  • rancher2_namespace.example["project1.mynamespace1"]
  • rancher2_namespace.example["project2.mynamespace2"]
  • rancher2_namespace.example["project2.mynamespace3"]

【讨论】:

  • 非常感谢您的详细解释,我查看了flatten函数但不明白如何在命名空间资源中使用它。 for in an for_each .. (0-0)
  • 我可以使用 count 和类似的东西来做命名空间:local.project_namespaces[count.index].namespace_name,这样你就不需要再从列表到地图的转换了。你怎么看?
【解决方案2】:

这似乎也有效:

resource "rancher2_namespace" "example" {
  count      = length(local.project_namespaces)
  provider   = rancher2.admin
  name       = local.project_namespaces[count.index].namespace_name
  project_id = local.project_namespaces[count.index].project_id
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-08
    • 2019-07-23
    • 1970-01-01
    • 2020-11-27
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多