首页 > 解决方案 > terraform - 遍历两个链接的资源

问题描述

我正在尝试编写一些代码,这些代码将采用如下输入结构:

  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 传递到命名空间。

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

感谢您的任何帮助和建议。

标签: terraform

解决方案


基于数据结构系统地生成资源的多个实例的典型答案是resourcefor_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"]

您当前没有每个namespace一个元素的映射,因此需要做更多工作才能从输入数据结构中导出合适的值。这种情况的一个常见模式是扁平化嵌套结构以for_each使用flatten函数

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"]

推荐阅读