前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Terraform 系列-使用Dynamic Blocks对Blocks进行迭代

Terraform 系列-使用Dynamic Blocks对Blocks进行迭代

作者头像
东风微鸣
发布2023-11-02 08:34:05
2200
发布2023-11-02 08:34:05
举报

系列文章

•Terraform 系列文章[1]•Grafana 系列文章[2]

概述

Terraform 系列文章[3] 介绍了使用 Grafana Terraform Provider, 基于 Terraform 的 IaC 方法论, 来批量自动化创建 Grafana 的各类资源, 包括 Dashboard/Datasource 等.

现在有这么一个现实需求:

出于权限控制的需求, 需要启用 Folder Permissions, 限制指定的某几个 team 可以有该 Folder 的 view 权限.

该如何实现?🤔

解决方案

通过 Terraform 的 for_eachdynamic blocks 实现.

基本概念

Dynamic Blocks

在资源(resource)等顶级块结构中,表达式通常只能在使用 name = expression 形式为参数赋值时使用。这涵盖了许多用途,但有些资源类型的参数中包含可重复嵌套的块(block),这些块通常代表与包含对象相关(或嵌入其中)的独立对象:

代码语言:javascript
复制
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
  name = "tf-test-name" # can use expressions here

  setting {
    # but the "setting" block is always a literal block
  }
}

您可以使用特殊的 dynamic 块类型动态构建可重复嵌套的块,如resourcedataproviderprovisioner 块都支持这种类型:

代码语言:javascript
复制
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
  name                = "tf-test-name"
  application         = "${aws_elastic_beanstalk_application.tftest.name}"
  solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6"

  dynamic "setting" {
    for_each = var.settings
    content {
      namespace = setting.value["namespace"]
      name = setting.value["name"]
      value = setting.value["value"]
    }
  }
}

动态块的作用与for表达式[4]很相似,但它产生的是嵌套代码块,而不是复数值。它遍历给定的复数值,并为复数值的每个元素生成一个嵌套块。

•动态代码块的标签(上例中的 "setting")指定了要生成的嵌套代码块的类型。•for_each "参数提供了要遍历的复合值。•iterator 参数(可选)设置了一个临时变量的名称,该变量代表复数值的当前元素。如果省略,变量名默认为 dynamic 块(上例中为 "setting")的标签。•labels 参数(可选)是一个字符串列表,它按顺序指定了要用于每个生成块的块标签。你可以在此值中使用临时迭代变量。•嵌套的 content 块定义了每个生成块的主体。你可以在此块中使用临时迭代变量。

由于 for_each 参数可接受任何集合或结构值,因此可以使用 for 表达式或 splat 表达式来转换现有集合。

迭代器对象(上例中的 setting)有两个属性:

key[5] 是当前元素的映射键或列表元素索引。如果 for_each 表达式产生了一个 set 值,则 keyvalue 相同。•value[6] 是当前元素的值。

dynamic 代码块只能生成属于正在配置的 resource 类型、data 源、provider 或 provisioner 的参数。不能生成 meta-argument 块,如lifecycleprovisioner块,因为 Terraform 必须先处理这些参数块,然后才能安全地评估表达式。

for_each 值必须是一个集合,每个所需的嵌套块包含一个元素。如果需要根据嵌套数据结构或多个数据结构的元素组合声明资源实例,可以使用 Terraform 表达式和函数推导出合适的值。有关此类情况的一些常见示例,请参阅 flatten[7] 和 setproduct[8]函数。

有些提供程序定义的资源类型包括相互嵌套的多层区块。您可以在必要时动态生成这些嵌套结构,方法是将 dynamic 模块嵌套在其他 dynamic 模块的 content 部分中。

例如,一个模块可能会接受如下复杂的数据结构:

代码语言:javascript
复制
variable "load_balancer_origin_groups" {
  type = map(object({
    origins = set(object({
      hostname = string
    }))
  }))
}

如果要定义一个 resource,其类型需要为每个 origin group 创建一个块,然后为组内的每个 origin 创建嵌套块,则可以要求 Terraform 使用以下嵌套的 dynamic 块动态生成该资源:

代码语言:javascript
复制
  dynamic "origin_group" {
    for_each = var.load_balancer_origin_groups
    content {
      name = origin_group.key

      dynamic "origin" {
        for_each = origin_group.value.origins
        content {
          hostname = origin.value.hostname
        }
      }
    }
  }

在使用嵌套的 dynamic 代码块时,尤其要注意每个代码块的迭代符号。在上例中,origin_group.value 指向外层代码块的当前元素,而 origin.value 指向内层代码块的当前元素。

如果一个特定的资源类型定义了嵌套块,而这些嵌套块的类型名称与其父类中的一个类型名称相同,则可以在每个 dynamic 块中使用 iterator 参数来选择一个不同的迭代器符号,使两者更容易区分。

过度使用 dynamic 块会使配置变得难以阅读和维护,因此我们建议仅在需要隐藏细节以便为可重用模块构建简洁的用户界面时使用它们。在可能的情况下,一定要按字面意思写出嵌套模块。

实战

需求:

出于权限控制的需求, 需要启用 Folder Permissions, 限制指定的某几个 team 可以有该 Folder 的 view 权限.

对应的 Terraform 代码如下:

代码语言:javascript
复制
locals {
    teams = {
        "dev",
        "busi",
        "ops",
        "data",
        "pm"
    }
}

resource "grafana_folder_permission" "foldersPermission" {

  folder_uid = "demo"

  dynamic "permissions" {
    for_each = local.teams
    content {
      team_id    = grafana_team.teams[each.key].id
      permission = "View"
    }
  }
}

说明:

permissions (Block Set, Min: 1) 要添加/更新的权限项目。列表中没有的项目将被删除。

完成🎉🎉🎉

📚️参考文档

•Dynamic Blocks - Configuration Language | Terraform | HashiCorp Developer[9]•grafana_dashboard_permission | Resources | grafana/grafana | Terraform | Terraform Registry[10]

References

[1] Terraform 系列文章: https://ewhisper.cn/tags/Terraform/ [2] Grafana 系列文章: https://ewhisper.cn/tags/Grafana/ [3] Terraform 系列文章: https://ewhisper.cn/tags/Terraform/ [4] for表达式: https://developer.hashicorp.com/terraform/language/expressions/for [5] key: https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks#key [6] value: https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks#value [7] flatten: https://developer.hashicorp.com/terraform/language/functions/flatten [8] setproduct: https://developer.hashicorp.com/terraform/language/functions/setproduct [9] Dynamic Blocks - Configuration Language | Terraform | HashiCorp Developer: https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks [10] grafana_dashboard_permission | Resources | grafana/grafana | Terraform | Terraform Registry: https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/dashboard_permission

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-10-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 东风微鸣技术博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 系列文章
  • 概述
  • 解决方案
  • 基本概念
    • Dynamic Blocks
    • 实战
    • 📚️参考文档
      • References
      相关产品与服务
      Grafana 服务
      Grafana 服务(TencentCloud Managed Service for Grafana,TCMG)是腾讯云基于社区广受欢迎的开源可视化项目 Grafana ,并与 Grafana Lab 合作开发的托管服务。TCMG 为您提供安全、免运维 Grafana 的能力,内建腾讯云多种数据源插件,如 Prometheus 监控服务、容器服务、日志服务 、Graphite 和 InfluxDB 等,最终实现数据的统一可视化。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档