系列文章
概述
Terraform 系列文章 介紹了使用 Grafana Terraform Provider, 基于 Terraform 的 IaC 方法論, 來批量自動化創(chuàng)建 Grafana 的各類資源, 包括 Dashboard/Datasource 等.
現(xiàn)在有這么一個現(xiàn)實需求:
出于權(quán)限控制的需求, 需要啟用 Folder Permissions, 限制指定的某幾個 team 可以有該 Folder 的 view 權(quán)限.
該如何實現(xiàn)巢掺???
解決方案
通過 Terraform 的 for_each
和 dynamic
blocks 實現(xiàn).
基本概念
Dynamic Blocks
在資源(resource
)等頂級塊結(jié)構(gòu)中,表達式通常只能在使用 name = expression
形式為參數(shù)賦值時使用劲蜻。這涵蓋了許多用途陆淀,但有些資源類型的參數(shù)中包含可重復嵌套的塊(block),這些塊通常代表與包含對象相關(guān)(或嵌入其中)的獨立對象:
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
塊類型動態(tài)構(gòu)建可重復嵌套的塊先嬉,如resource
轧苫、data
、provider
和 provisioner
塊都支持這種類型:
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"]
}
}
}
動態(tài)塊的作用與for
表達式很相似疫蔓,但它產(chǎn)生的是嵌套代碼塊含懊,而不是復數(shù)值。它遍歷給定的復數(shù)值衅胀,并為復數(shù)值的每個元素生成一個嵌套塊岔乔。
- 動態(tài)代碼塊的標簽(上例中的
"setting"
)指定了要生成的嵌套代碼塊的類型。 -
for_each
"參數(shù)提供了要遍歷的復合值滚躯。 -
iterator
參數(shù)(可選)設置了一個臨時變量的名稱重罪,該變量代表復數(shù)值的當前元素。如果省略哀九,變量名默認為dynamic
塊(上例中為"setting"
)的標簽剿配。 -
labels
參數(shù)(可選)是一個字符串列表,它按順序指定了要用于每個生成塊的塊標簽阅束。你可以在此值中使用臨時迭代變量呼胚。 - 嵌套的
content
塊定義了每個生成塊的主體。你可以在此塊中使用臨時迭代變量息裸。
由于 for_each
參數(shù)可接受任何集合或結(jié)構(gòu)值蝇更,因此可以使用 for
表達式或 splat 表達式來轉(zhuǎn)換現(xiàn)有集合。
迭代器對象(上例中的 setting
)有兩個屬性:
dynamic
代碼塊只能生成屬于正在配置的 resource 類型厨幻、data 源、provider 或 provisioner 的參數(shù)。不能生成 meta-argument 塊况脆,如lifecycle
和provisioner
塊饭宾,因為 Terraform 必須先處理這些參數(shù)塊,然后才能安全地評估表達式格了。
for_each
值必須是一個集合看铆,每個所需的嵌套塊包含一個元素。如果需要根據(jù)嵌套數(shù)據(jù)結(jié)構(gòu)或多個數(shù)據(jù)結(jié)構(gòu)的元素組合聲明資源實例盛末,可以使用 Terraform 表達式和函數(shù)推導出合適的值弹惦。有關(guān)此類情況的一些常見示例,請參閱 flatten
和 setproduct
函數(shù)悄但。
有些提供程序定義的資源類型包括相互嵌套的多層區(qū)塊棠隐。您可以在必要時動態(tài)生成這些嵌套結(jié)構(gòu),方法是將 dynamic
模塊嵌套在其他 dynamic
模塊的 content
部分中算墨。
例如宵荒,一個模塊可能會接受如下復雜的數(shù)據(jù)結(jié)構(gòu):
variable "load_balancer_origin_groups" {
type = map(object({
origins = set(object({
hostname = string
}))
}))
}
如果要定義一個 resource汁雷,其類型需要為每個 origin group 創(chuàng)建一個塊净嘀,然后為組內(nèi)的每個 origin 創(chuàng)建嵌套塊,則可以要求 Terraform 使用以下嵌套的 dynamic
塊動態(tài)生成該資源:
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
指向內(nèi)層代碼塊的當前元素膜眠。
如果一個特定的資源類型定義了嵌套塊,而這些嵌套塊的類型名稱與其父類中的一個類型名稱相同溜嗜,則可以在每個 dynamic
塊中使用 iterator
參數(shù)來選擇一個不同的迭代器符號宵膨,使兩者更容易區(qū)分。
過度使用 dynamic
塊會使配置變得難以閱讀和維護炸宵,因此我們建議僅在需要隱藏細節(jié)以便為可重用模塊構(gòu)建簡潔的用戶界面時使用它們辟躏。在可能的情況下,一定要按字面意思寫出嵌套模塊土全。
實戰(zhàn)
需求:
出于權(quán)限控制的需求, 需要啟用 Folder Permissions, 限制指定的某幾個 team 可以有該 Folder 的 view 權(quán)限.
對應的 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) 要添加/更新的權(quán)限項目捎琐。列表中沒有的項目將被刪除。
完成??????
???參考文檔
- Dynamic Blocks - Configuration Language | Terraform | HashiCorp Developer
- grafana_dashboard_permission | Resources | grafana/grafana | Terraform | Terraform Registry
三人行, 必有我?guī)? 知識共享, 天下為公. 本文由東風微鳴技術(shù)博客 EWhisper.cn 編寫.