AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79577581
Accepted
Andrew Mitchell
Andrew Mitchell
Asked: 2025-04-16 23:46:08 +0800 CST2025-04-16 23:46:08 +0800 CST 2025-04-16 23:46:08 +0800 CST

Terraform for_each 不支持动态块

  • 772

我正在尝试编写一些 terraform 代码,它将采用嵌套对象并创建资源,通常这将通过动态块来完成,但所讨论的资源不支持这一点,并且想知道是否有人对解决这个问题的最佳方法有任何想法。

配置如下:

 dashboards = {
  "Test Dashboards" = {
    folder_name = "Test Folder"
    dashboards = [
      {
        file.          = "test.json"
        overwrite      = true
      },
      {
        file           = "test1.json"
        overwrite      = false
      }
    ]
  }
}

然后在资源创建中,通常会是这样的:

resource "grafana_dashboard" "dashboards" {
  for_each    = var.dashboards
  folder      = each.value.folder_name
  dynamic "dashboard" {
    for_each = each.value.dashboards
      content {
        config_json    = file("../../dashboards/${dashboards.value["file"]}")
        overwrite      = dashboards.value["overwrite"]
      }
  }
}

但是动态块不支持此资源,唯一的方法是我不想重复配置,因为如果有意义的话,它可能与多个资源共享。

foreach
  • 2 2 个回答
  • 31 Views

2 个回答

  • Voted
  1. Best Answer
    Martin Atkins
    2025-04-17T08:28:50+08:002025-04-17T08:28:50+08:00

    在真正回答这个问题之前,我认为有必要澄清一些术语上的分歧:您将输入变量称为“仪表板”,但根据您赋予它的值,它似乎是文件夹的集合,每个文件夹包含一个或多个仪表板。

    因此,我认为您真正grafana_folder需要的是的每个元素的一个实例var.dashboards,然后是grafana_dashboard所有文件夹中列出的每个不同仪表板的一个实例。

    那么,您在这里所做的本质上是扁平化嵌套结构for_each中描述的问题的 Grafana 版本,因此您可以按照如下方式调整其中描述的方法。

    首先,让我们声明一个输入变量以确保我们同意它的类型:

    # NOTE: I renamed this just to clarify that it's a collection
    # of folders, rather than of dashboards directly. You can
    # rename it back if you prefer.
    variable "dashboard_folders" {
      type = map(object({
        folder_name = string
        dashboards = set(object({
          file      = string
          overwrite = optional(bool, false)
        }))
      }))
    }
    

    由于此变量已经是一个映射,并且对于您想要声明的每个“文件夹”已经有一个元素,因此您可以直接使用此值for_each来声明多个实例grafana_folder:

    resource "grafana_folder" "dashboards" {
      for_each = var.dashboard_folders
    
      uid   = each.key
      title = each.value.folder_name
    }
    

    仪表板本身比较棘手,因为您需要首先将此数据结构投影到适合一次描述所有仪表板的形状:它必须是一个集合,每个仪表板一个元素,而不是每个文件夹一个元素。这就是flatten:

    locals {
      dashboards = flatten([
        for folder_key, folder in var.dashboard_folders : [
          for dashboard in folder.dashboards : {
            folder_key = folder_key
            file       = dashboard.file
            overwrite  = dashboard.overwrite
          }
        ]
      ])
    }
    

    local.dashboards现在是所有仪表板的平面集合,每个仪表板都知道其所属文件夹的密钥。

    剩下的唯一要求就是将其投影到一个映射中,其中每个元素都有一个唯一的键,Terraform 可以使用它来跟踪哪个资源实例属于它。如果您能保证每个仪表板都有唯一的file参数,那么这可能是合适的,我假设在本例中情况确实如此,但如果情况并非如此,则需要引入另一个值来唯一地跟踪每个文件夹中的每个仪表板。

    resource "grafana_dashboard" "all" {
      for_each = {
        for dashboard in local.dashboards :
        "${dashboard.folder_key}:${dashboard.file}" => dashboard
      }
    
      folder      = grafana_folder.dashboards[each.value.folder_key].id
      config_json = file(each.value.file)
      overwrite   = each.value.overwrite
    }
    

    这使用folder_key每个对象的属性将每个仪表板与其对应的文件夹对象连接起来,因此这应该描述 Grafana 中的层次结构,该层次结构等同于所描述的层次结构var.dashboard_folders。

    • 1
  2. Ross Bush
    2025-04-17T03:27:19+08:002025-04-17T03:27:19+08:00

    这可能无法编译;但是,您可以尝试类似的构造,看看它是否能满足您的需求。其思路是将仪表板扁平化/投影到 dashboard_content 结构中,每个 dashboards [] 项对应一个元素,并设置父键 -> folder_name。folder_name 必须唯一,因为这将决定资源的绑定方式。第二个循环在动态部分将扁平化的子项与父项连接起来。

    我从未尝试将动态部分中的项目绑定到外部范围中的项目,因此我不确定内部循环是否会编译,但可能值得一试。

    # This is a flattened projection of var.dashboards . It will contain one entry for each item in dashboards[]
    #[
    # { folder_name = "Test Folder", file="test.json", overwrite= "true"}
    # { folder_name = "Test Folder", file="test1.json", overwrite= "false"}
    #]
    
    locals{
      dashboard_contents = flatten([
        for x, dashboard in var.dashboards : [
          for y, dashboard_content in dashboard.dashboards : {      
    
            folder_name = dashbopard.folder_name,
            file = dashboard_content.file,
            overwrite = dashboard.overwrite
          }
        ]
      ])
    }
    
    resource "grafana_dashboard" "dashboards" {
      for_each    = ( for dashboard in var.dashboards : dashboard.folder_name => dashboard}
      folder      = dashboard.folder_name
      dynamic "dashboard" {
        for_each = { for dashboard_contents in local.dashboard_contents : dashboard_contents.file => dashboard_contents if dashboard_contents.folder ==  dashboard.folder_name}       
          content {
            config_json    = file("../../dashboards/${dashboard_contents.file}")
            overwrite      = dashboard_contents.overwrite
          }
      }
    }
    
    • 0

相关问题

  • 在 Makefile foreach 中同步打印

  • Svelte Kit 如何从为循环项指定唯一 ID 中受益?不这样做会对性能产生哪些影响?

  • Tcl的foreach不设置变量

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve