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

本文涉及的产品
可观测可视化 Grafana 版,10个用户账号 1个月
简介: Terraform 系列 - 使用 Dynamic Blocks 对 Blocks 进行迭代

概述

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

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

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

该如何实现?🤔

解决方案

通过 Terraform 的 for_eachdynamic blocks 实现.

基本概念

Dynamic Blocks

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

resource "aws_elastic_beanstalk_environment" "tfenvtest" {
  name = "tf-test-name" # can use expressions here
  setting {
    # but the "setting" block is always a literal block
  }
}
TERRAFORM

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

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

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

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

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

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

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

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

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

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

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

variable "load_balancer_origin_groups" {
  type = map(object({
    origins = set(object({
      hostname = string
    }))
  }))
}
TERRAFORM

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

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
      }
    }
  }
}
TERRAFORM

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

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

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

实战

需求:

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

对应的 Terraform 代码如下:

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"
    }
  }
}
TERRAFORM

说明:

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

完成🎉🎉🎉

📚️参考文档

相关文章
|
7月前
|
存储 运维 Linux
【MinIO异常】Storage reached its minimum free drive threshold 的解决方案
【MinIO异常】Storage reached its minimum free drive threshold 的解决方案
212 0
|
11天前
|
DataWorks 数据管理 大数据
DataWorks操作报错合集之出现报错 "ERROR: Total memory used by all existing queries exceeded memory limitation."如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
24 2
|
8月前
CF1550B Maximum Cost Deletion(分段比较)
CF1550B Maximum Cost Deletion(分段比较)
20 0
|
10月前
|
机器人 BI 人工智能
The Blocks Problem(问题的抽象)
The Blocks Problem(问题的抽象)
57 0
The Blocks Problem(问题的抽象)
|
缓存
AS项目一直Indexing paused due to batch updated
AS项目一直Indexing paused due to batch updated
104 0
|
供应链
PAT (Advanced Level) Practice - 1079 Total Sales of Supply Chain(25 分)
PAT (Advanced Level) Practice - 1079 Total Sales of Supply Chain(25 分)
117 0
SAP RETAIL WA01创建分配表报错- No allocation rule allowed for allocation strategies or variants-
SAP RETAIL WA01创建分配表报错- No allocation rule allowed for allocation strategies or variants-
SAP RETAIL WA01创建分配表报错- No allocation rule allowed for allocation strategies or variants-
|
SQL Oracle 算法
PostgreSQL 12 preview - plan_cache_mode参数控制强制使用plan cache或强制custom plan (force_custom_plan and force_generic_plan)
标签 PostgreSQL , plan_cache_mode 背景 plan cache在OLTP中,可以大幅降低生成sql parser, 执行计划的开销。 但是在某些场景中,plan cache可能成为问题,比如AP类型的场景中,由于SQL 输入条件的变化(通常AP业务涉及的条件可能比较容易出现这样的问题),可能导致plan cache并不是最佳的执行计划。
1266 0