Não é segredo que o terraform é compatível com o JSON. Ou ainda melhor, que o HCL é compatível com o JSON, possuindo a sua própria sintaxe JSON. Essas documentações são principalmente focadas, como seus nomes sugerem, na sintaxe HCL e em como se pode declarar nela recursos, variáveis, etc.
Isso traz uma consequência interessante, no entanto. Você pode usar JSON para declarar objetos no Terraform.
O exemplo abaixo foi retirado da documentação do resource aws_iam_role e atualizado para usar a sintaxe JSON. É um código Terraform perfeitamente válido.
resource "aws_iam_role" "test_role" {
name = "test_role"
# A função "jsonencode" converte
# o resultado da expressão Terraform para uma string JSON válida.
assume_role_policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Sid": "",
"Principal": {
"Service": "ec2.amazonaws.com"
}
},
]
})
tags = {
tag-key = "tag-value"
}
}
É um truque particularmente útil quando você está integrando a configuração de resources que aceitam JSON como entrada, como o atributo assume_role_policy do resource aws_iam_role, e evita a necessidade de converter a sintaxe JSON para HCL, declarar o objeto JSON em um arquivo separado ou usar recursos alternativos, como o data source aws_iam_role_policy_document. Também é mais fácil de ler do que usar strings Heredoc ou uma string JSON inline (onde você precisaria escapar as aspas).
Como bônus, você pode misturar a sintaxe JSON com expressões Terraform - HCL e JSON são intercambiáveis nesse caso. Por exemplo, poderíamos usar o abaixo para declarar a política de um determinado repositório ECR, permitindo a extração de imagens de uma lista de contas. Isso está mais próximo dos exemplos de políticas IAM que você pode encontrar na documentação da AWS.
resource "aws_ecr_repository" "test_repo" {
name = "test_repo"
repository_policy_text = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPull",
"Effect": "Allow",
"Principal": {
"AWS": [
for account_id in var.account_ids :
"arn:aws:iam::${account_id}:root"
]
},
"Action": [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer"
]
}
]
})
}
Isso é tudo, e é algo que venho usando há bastante tempo e que não encontrei muitas discussões sobre. Espero que você ache essa dica útil e que ela possa te economizar algum tempo. Boa codificação!