带迭代的 Terraform 模板 jsonencoding

Terraform template jsonencoding with iterate

我正在寻找此模板的解决方案以获取正确的 JSON 文件。 正如您在这些部分中看到的那样,aws:RequestTag/*** 末尾缺少逗号。如果我在模板中使用逗号,那么我将在最后一个字符串的末尾有一个不必要的逗号。

我不知道 ${jsonencode()} 应该有帮助,但我仍然没有意识到它如何与 %{ for key in key_tag ~} 一起使用。

如有任何帮助,我将不胜感激。

地形:

resource "local_file" "enforcetags" {
  content = templatefile("${path.module}/enforcetags.tpl",
    {
      key_tag = ["development_prod", "production_prod", "rnd_prod"]
    }
  )
  filename = "./enforce_tags.json"
}

模板:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "ec2:*",
                "Resource": "*",
                "Condition": {
                    "ForAllValues:StringEquals": {
                        "aws:TagKeys": ${jsonencode([for key in key_tag : "${key}"])}
                    },
                    "StringEqualsIfExists": {
%{ for key in key_tag ~}
                    "aws:RequestTag/${key}": ${jsonencode([for key in key_tag : "${key}"])}
%{ endfor ~}
                    }
                }
            }
        ]
    }

输出:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "ec2:*",
                "Resource": "*",
                "Condition": {
                    "ForAllValues:StringEquals": {
                        "aws:TagKeys": ["development_prod","production_prod","rnd_prod"]
                    },
                    "StringEqualsIfExists": {

                       "aws:RequestTag/development_prod": ["development_prod","production_prod","rnd_prod"]
                       "aws:RequestTag/production_prod": ["development_prod","production_prod","rnd_prod"]
                       "aws:RequestTag/rnd_prod": ["development_prod","production_prod","rnd_prod"]
                    
                    }
                }
            }
        ]
    }

要在末尾加一个逗号,除了最后一个字符串应该是:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "ec2:*",
                "Resource": "*",
                "Condition": {
                    "ForAllValues:StringEquals": {
                        "aws:TagKeys": ${jsonencode([for key in key_tag : "${key}"])}
                    },
                    "StringEqualsIfExists": ${jsonencode(
                                {for key in key_tag: "aws:RequestTag/${key}" => key_tag})}
                }
            }
        ]
    }

在这里,您似乎 运行 遇到了尝试使用字符串连接生成有效 JSON 的典型挑战,这就是模板插值的有效方式。这个问题很常见,在 templatefile 文档页面中有专门的部分:Generating JSON or YAML from a template.

您可以通过遵循该部分中的建议并生成 整个 JSON 数据结构 jsonencode 来避免这种摩擦,而不仅仅是它的一些子部分就像您在共享的示例中所做的那样。您可以根据需要使用 Terraform 的普通表达式运算符生成动态部分。例如:

${jsonencode({
  Version = "2012-10-17"
  Statement = [
    {
      Sid      = "VisualEditor0"
      Effect   = "Allow"
      Action   = "ec2:*"
      Resource = "*"
      Condition = {
        "ForAllValues:StringEquals" = {
          "aws:TagKeys" = key_tag
        },
        "StringEqualsIfExists": {
          for key in key_tag : "aws:RequestTag/${key}" => key_tag
        }
      }
    }
  ],
})}

通过这种方法,您可以使用 Terraform 语法而不是 JSON 语法来定义数据结构,并让 jsonencode 负责将其编码为等效的有效 JSON。 jsonencode 保证始终生成有效的 JSON,包括所有预期位置的逗号,并且 Terraform 的对象语法无论如何不需要属性定义之间的逗号,因此您无需担心编写它们你自己。

(我还在上面稍微简化了你的 for 表达式,尽管这与你的问题没有直接关系。特别是,如果 key_tag 已经是一个序列类型那么 [for key in key_tag : "${key}"] 与直接写 key_tag 一样,因为那里没有发生实际的转换。)