![](/img/trans.png)
[英]With Terraform resource aws_route53_record, import AWS route 53 records from a json file
[英]Terraform 0.12 AWS resource containing JSON built from variable
要在 AWS 組織中預置標簽策略,我需要從變量構建 JSON content
。 對標簽策略、scp等進行集中管理,可以隨處應用更改:重命名、添加、刪除標簽等。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
profile = "default"
region = "us-west-1"
}
我面臨的問題是:我將如何構建 JSON 對象?
示例變量/標簽映射:
# tag_policies.tf
variable "resource_tags" {
description = "Central resource tags"
type = list( object( {
name = string
tags = map(string)
} ) )
default = [
{
name = "Environment"
tags = {
prod = "crn::env:prod"
lab = "crn::env:lab"
dev = "crn::env:dev"
}
}
]
}
到目前為止,我嘗試過的是使用 HCL 模板標簽,但在遍歷標簽名稱映射時,我最終得到了一個,
逗號太多。 這對於帶有標記名稱子圖的join()
工作正常,但如果我嘗試包裝模板標記,則不起作用。 我為什么要嘗試這個? 因為我的想法用完了。
# vars.tf
resource "aws_organizations_policy" "root-tag-policy" {
name = "RootTagPolicy"
type = "TAG_POLICY"
content = <<CONTENT
{
"tags": {
%{ for tag in var.resource_tags_env ~}
"${tag.name}": {
"tag_key": {
"@@assign": "${tag.name}",
"@@operators_allowed_for_child_policies": [ "@@none" ]
},
"tag_value": { "@@assign": [ "${join( ", ", values( tag.tags ) )}" ] }
},
%{ endfor ~}
}
}
CONTENT
}
解決方案實際上非常簡單:使用for
表達式迭代標記並用大括號{ … }
將其括起來以返回一個對象( =>
返回元組)。
最后jsonencode()
關心將 HCL key = value
語法轉換為正確的 JSON。
resource "aws_organizations_policy" "root-tag-policy" {
name = "RootTagPolicy"
type = "TAG_POLICY"
content = jsonencode( [ for key, tag in var.resource_tags: {
"${tag.name}" = {
"tag_key" = {
"@@assign" = tag.name,
"@@operators_allowed_for_child_policies" = [ "@@none" ]
},
"tag_value" = { "@@assign" = [ join( ", ", values( tag.tags ) ) ] }
}
} ] )
}
編輯這仍然不起作用,因為我忘記了整個 JSON 對象需要包裝在tags: {}
。
kaiser 的回答顯示了一個很好的通用方法:構建一個合適的數據結構,然后將其傳遞給jsonencode
以從中獲取有效的 JSON 字符串。
這是一個我認為與原始問題中的字符串模板匹配的示例:
content = jsonencode({
tags = {
for tag in var.resource_tags_env : tag.name => {
tag_key = {
"@@assign" = tag.name
"@@operators_allowed_for_child_policies" = ["@@none"]
}
tag_value = {
"@@assign" = values(tag.tags)
}
}
}
})
我不熟悉aws_organizations_policy
資源類型,所以如果我在這里弄錯了一些細節,我很抱歉,但希望您可以調整上面的示例以生成您需要的 JSON 數據結構。
閱讀@martin-atkins 的回答后,我終於明白了for
是如何作用於objects
和maps
。 =>
箭頭之前的 var 實際上是結果對象的一部分。 (這讓我非常困惑,因為我將它與其他語言的箭頭函數和參數進行了比較。)
該過程的第一部分是構建地圖地圖。 主要原因是我不想在變量映射中約定name
鍵。 這可能會導致稍后處理約定,應該不惜一切代價避免這種情況,因為如果不密切注意或意識到它可能是一個陷阱。 所以key
實際上是現在的name
。
variable "resource_tags" {
description = "Central resource tags"
type = map(
map(string)
)
default = {
Environment = {
common = "grn::env:common"
prod = "grn::env:prod"
stage = "grn::env:stage"
dev = "grn::env:dev"
demo = "grn::env:demo"
lab = "grn::env:lab"
},
Foo = {
bar = "baz"
}
}
}
content
為 JSON 在了解{ "tags": { … } }
中的鍵只是=>
之前的部分后,我可以將最終資源減少到以下塊。
resource "aws_organizations_policy" "root-tag-policy" {
name = "RootTagPolicy"
description = "Tag policies, assigned to the root org."
type = "TAG_POLICY"
content = jsonencode({
tags = {
for key, tags in var.resource_tags : key => {
tag_key = {
"@@assign" = key
"@@operators_allowed_for_child_policies" = ["@@none"]
}
tag_value = {
"@@assign" = values( tags )
}
}
}
})
}
在resource
塊后添加以下output
語句:
output "debug" {
value = aws_organizations_policy.tp_root-tag-policy.content
}
現在apply
(或plan
或refresh
)此資源。 這種方式更快。 然后從apply
或refresh
運行輸出構建的debug
。
$ terraform apply -target=aws_organizations_policy.root-tag-policy
…things happening…
$ terraform output debug | json_pp
小貼士:
output
直接通過管道傳輸到json_pp
或jq
以便您可以讀取它。jq .
如果你想在上面進行驗證。 如果您看到輸出,則表示它是有效的。 否則你應該收到0
作為響應。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.