系列文章

概述

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. Go的语言特性有哪些

    摘要:本文由葡萄城技术团队于博客园原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 本文主要通过值传递和指针.字符串.数组.切片.集合.面向 ...

  2. ChatGPT的探索与实践-业务应用篇

    本篇文章主要介绍在实际的开发过程当中,如何使用GPT帮助开发,优化流程,恰逢今年京东20周年庆,文末会介绍如何与618大促实际的业务相结合,来提升应用价值.全是干货,且本文所有代码和脚本都是利用GPT ...

  3. Nextcloud允许不被信任的域访问 取消 trusted domains

    在服务器部署了Nextcloud,由于测试需要,经常从不同的地址访问,但是每次访问都要把域名添加到受信任域,反反复复修改也挺麻烦,暂时又没找到通配符或者禁用的方法. 不过网上提供了一个替代方法,动态生 ...

  4. SSH远程主机执行命令:s2c

    #!/bin/bash ip=$1 ip_num=$(echo $ip | awk -F\. '{print NF}') if [ $ip_num -eq 2 ]; then ip=192.168.$ ...

  5. UE构建基础和实践:五、CI/CD平台自动化打包

    序言 使用CI/CD平台构建(这里使用蓝盾平台)主要是通过平台脚本运行上一章的py脚本并传递参数(即把py中的参数开放给配置平台脚本配置). Build.py 重构 我们需要在py脚本里面解析和设置参 ...

  6. VScode 中golang 调试 F5,json文件内容更改 Go

    调试:在Vscode软件中调试.go文件代码 1.1.1 确保调试文件正常运行 准备好.go文件,并且该文件能正常运行,终端输入命令运行程序,如:go run time.go 测试代码: packag ...

  7. Crawpy - 一款python写的网站目录扫描工具

    国外网站看到的. 简贴一下谷歌翻译的介绍 是什么让这个工具与其他工具不同: 它被写入异步工作,允许达到最大限制.所以它非常快. 校准模式,自行应用过滤器 有一堆标志可以帮助你详细地模糊 给定状态代码和 ...

  8. 69.9K Star,最强开源内网穿透工具:frp

    作为一名开发者,有很多场景需要用到内网穿透,比如:我们在接入一些大平台做第三方应用时,在本地开发微信公众号工具的时候需要让微信平台能否访问到本地提供的接口.除此之外,还有很多其他场景,也会用到,比如: ...

  9. 浏览器端模块化方式es module详解

    在es module出现之前还有社区推出amd和cmd的规范,这两者还有其特定的编写方式,使用起来不算很方便.es module被官方推出来就成为了浏览器端实现模块化的一个很好的方案.   想要在浏览 ...

  10. Unity UGUI的InputField(输入框)组件的介绍及使用

    UGUI的InputField(输入框)组件的介绍及使用 1. 什么是UGUI的InputField组件? UGUI的InputField组件是Unity中的一个用户界面组件,用于接收用户的输入.它可 ...