系列文章

概述

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

您可以使用特殊的 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"]
}
}
}

动态块的作用与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
}))
}))
}

如果要定义一个 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
}
}
}
}

在使用嵌套的 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"
}
}
}

说明:

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

完成

️参考文档

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.

Terraform 系列-使用Dynamic Blocks对Blocks进行迭代的更多相关文章

  1. Terraform 系列-Terraform 项目的典型文件布局

    系列文章 Terraform 系列文章 典型文件布局 - modules/ - services/ - webserver-cluster/ - examples/ - main.tf - outpu ...

  2. Terraform 系列-什么是 IaC?

    系列文章 Terraform 系列文章 前言 聊到 Terraform, 必然绕不开 IaC 这个概念?那么,什么是 IaC? 基本概念 基础架构即代码 (Infrastructure as Code ...

  3. Terraform 系列-Terraform 简介

    系列文章 Terraform 系列文章 前言 最近在使用 Terraform 来置备 OCI 的 Always Free Tier, 发现它非常好用.总结学习下:Terraform 的基础知识. 什么 ...

  4. Terraform 系列-Terraform Cloud 比 Terraform OSS 有哪些增强?

    系列文章 Terraform 系列文章 前言 最近在使用 Terraform Cloud 来置备 OCI 的 Always Free Tier, 发现它非常好用,相比 Terraform OSS, 用 ...

  5. 浅谈Dynamic 关键字系列之一:dynamic 就是Object(转)

    C# 4.0提供了一个dynamic 关键字,那么什么是dynamic,究竟dynamic是如何工作的呢? 从最简单的示例开始: static void Main(string[] args) { d ...

  6. [LeetCode系列]爬梯问题的递归解法转换为迭代解法

    有一个n阶的梯子, 你每次只能爬1阶或2阶, 请问共有多少种登顶的爬法?(正好爬完n阶, 不能多也不能少) 本题最优解是直接套用菲波那切数列即可(因为菲波那切数列的第n个元素正好等于第n-1个元素和第 ...

  7. C语言工具---Code::Blocks

    Code::Blocks Code::Blocks 是一个开源的全功能的跨平台C/C++集成开发环境. Code::Blocks是开放源码软件.由纯粹的C++语言开发完成,它使用了著名的图形界面库wx ...

  8. 为什么我选择使用 Blocks(块)

    扯淡:到了新公司接手新框架之后,发现大量的使用Blocks,之前很多时候都是使用代理,突然面对这个陌生的语法,特地科普总结了一番. 什么是Blocks 一句话概括就是,带有局部变量的匿名函数(即不带名 ...

  9. 【转】教你爱上Blocks(闭包)

    Block 与传统代码相比较更加轻量,调用简洁方便,而且可以返回多个参数,使用Block可以让代码更加具有易读性,而我们在写回调时,也可以直接写在函数内部,而不用再去写一个回调函数 Block 闭包 ...

  10. POJ 1052 Plato's Blocks

      Plato's Blocks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 734   Accepted: 296 De ...

随机推荐

  1. 数据安全没保证?GaussDB(for Redis)为你保驾护航

    摘要:GaussDB (for Redis)通过账号管理.权限隔离.高危命令禁删/重命名.安全IP免密登录.实例回收站等企业级特性,保障用户数据库数据和信息安全. 本文分享自华为云社区<数据安全 ...

  2. 说说 Linux 的 curl 命令

    cURL,熟悉 Linux 的同学,没有人不知道这个命令吧:) 它有非常非常多的参数,我这里就不复制粘贴了,有需要可以 -h 或者谷歌搜索看看. 我从实用性的角度,说下我比较常用的几个参数: -v:啰 ...

  3. 2021-3-13 xml的增删改查

    public void XmlAdd(string filename, List<People> pList) { try { List<People> peoples = X ...

  4. pandas 显示所有的行和列

    import pandas as pd # 显示所有列,所有行 pd.set_option('display.max_columns', None) pd.set_option('display.ma ...

  5. node.js中kafka的封装和高并发消费限流优雅降级以及egg-kafka的封装说明

    HI!,你好,我是zane,zanePerfor是一款我开发的一个前端性能监控平台,现在支持web浏览器端和微信小程序端. 我定义为一款完整,高性能,高可用的前端性能监控系统,这是未来会达到的目的,现 ...

  6. [golang]使用mTLS双向加密认证http通信

    前言 假设一个场景,服务端部署在内网,客户端需要通过暴露在公网的nginx与服务端进行通信.为了避免在公网进行 http 明文通信造成的信息泄露,nginx与客户端之间的通信应当使用 https 协议 ...

  7. Java下载多个网络文件并打成压缩包

    需求:浏览器访问后台的http地址后,后台将多个网络文件打成压缩包返回给浏览器,用户可以通过浏览器直接下载压缩包. 实现: 根据文件链接把文件下载下来并且转成字节码  ,代码: package com ...

  8. 全景VR KRPano项目打包成安卓APP快速简易教程

    有时候,我们可能不想把我们制作的全景VR项目发布到网站上,而是想把它作为一个手机应用来使用或者分享.这样,我们就可以更好地保护我们的作品,也可以更方便地展示给客户或者朋友.本文将介绍一种简单的方法,让 ...

  9. 使用JAVA调用KRPANO加密XML

    KRPano自带的命令行工具krpanotools可以加密XML,具体的参数说明如下语法:   krpanotools32.exe encrypt [OPTIONS] inputfiles input ...

  10. RocketMQ 消息重试与死信队列

    RocketMQ 消息重试与死信队列 RocketMQ 前面系列文章如下: RocketMQ系列(一) 基本介绍 RocketMQ 系列(二) 环境搭建 RocketMQ 系列(三) 集成 Sprin ...