📘

TerraformをHCLファイルではなくjsonで管理・実行する

2022/07/02に公開

概要

Terraformをhclファイルではなくjsonで管理・実行してみます。
基本的にはhclで実行・管理するのがスタンダードだと思うので、お試しでトライする感じです。

とはいえ、設定ファイルの類はとにかく種類が多く(ini, mysql系のconf, nginx系のconf, Ansibleのyaml...etc)、統一できたら嬉しいなぁという思いもあります。

可読性の観点からするとyamlの方がベターではありますが、今回はjsonで。

参考

Most Terraform configurations are written in the native Terraform language syntax, which is designed to be relatively easy for humans to read and update.

Terraform also supports an alternative syntax that is JSON-compatible. This syntax is useful when generating portions of a configuration programmatically, since existing JSON libraries can be used to prepare the generated configuration files.

The JSON syntax is defined in terms of the native syntax. Everything that can be expressed in native syntax can also be expressed in JSON syntax, but some constructs are more complex to represent in JSON due to limitations of the JSON grammar.

Terraform expects native syntax for files named with a .tf suffix, and JSON syntax for files named with a .tf.json suffix.

Terraform requires infrastructure configuration files written in either HashiCorp Configuration Language (HCL) or JSON syntax.

実手順

before: hclでplan

試験用に使うhclは以下のvpc定義用(vpc.tf)とします。

module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  name = var.name
  cidr = var.cidr

  azs             = var.azs
  private_subnets = var.private_subnets
  public_subnets  = var.public_subnets

  enable_nat_gateway = false
  enable_vpn_gateway = false

  private_subnet_tags = {
    Name = "private subnet of ${var.name}"
  }
  public_subnet_tags = {
    Name = "public subnet of ${var.name}"
  }
  tags = {
    Management = "Managed by Terraform"
    Name       = "${var.name}"
  }
  vpc_tags = {
    Name = var.name
  }
}

output "vpc_output" {
  value = module.vpc
}

output "output_public_subnets" {
  value = toset(module.vpc[*].public_subnets)
}

適用差分はありません。念のため。

[elis@operation-20220701-152700]$ terraform plan 
data.terraform_remote_state.vpc: Reading...
data.terraform_remote_state.vpc: Read complete after 0s
...

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

hcl2jsonをインストール

tmccombs/hcl2jsonを使用します。

以下手順はこちらに記載のとおり。

[elis@operation-20220701-153511]$ git clone https://github.com/tmccombs/hcl2json
Cloning into 'hcl2json'...
remote: Enumerating objects: 335, done.
remote: Counting objects: 100% (334/334), done.
remote: Compressing objects: 100% (169/169), done.
remote: Total 335 (delta 163), reused 306 (delta 149), pack-reused 1
Receiving objects: 100% (335/335), 83.96 KiB | 11.99 MiB/s, done.
Resolving deltas: 100% (163/163), done.
[elis@operation-20220701-153516]$ cd hcl2json
[elis@operation-20220701-153527]$ go build
go: downloading github.com/hashicorp/hcl/v2 v2.13.0
go: downloading golang.org/x/text v0.3.6
[elis@operation-20220701-153546]$ which hcl2json 
/usr/local/bin/hcl2json

hclをjsonへconvert

引数で対象ファイルを渡すと標準出力で返ってくるので、

[elis@operation-20220701-154313]$ hcl2json vpc.tf 
{
    "module": {
        "vpc": [
            {
                "azs": "${var.azs}",
                "cidr": "${var.cidr}",
                "enable_nat_gateway": false,
                "enable_vpn_gateway": false,
                "name": "${var.name}",
                "private_subnet_tags": {
                    "Name": "private subnet of ${var.name}"
                },
                "private_subnets": "${var.private_subnets}",
                "public_subnet_tags": {
                    "Name": "public subnet of ${var.name}"
                },
                "public_subnets": "${var.public_subnets}",
                "source": "terraform-aws-modules/vpc/aws",
                "tags": {
                    "Management": "Managed by Terraform",
                    "Name": "${var.name}"
                },
                "vpc_tags": {
                    "Name": "${var.name}"
                }
            }
        ]
    },
    "output": {
        "output_public_subnets": [
            {
                "value": "${toset(module.vpc[*].public_subnets)}"
            }
        ],
        "vpc_output": [
            {
                "value": "${module.vpc}"
            }
        ]
    }
}

以下のとおりリダイレクトで新ファイルに出力させる方が便利かもしれません。

[elis@operation-20220701-154318]$ hcl2json vpc.tf > vpc.tf.json

after: jsonでplan

それでは、作成したvpc.tf.jsonplanをかけてみます。

(オリジナルのvpc.tfは拡張子を変えるなり別のところに置いておくなりしましょう)

[ec2-user@operation-20220701-154910]$ terraform plan 
data.terraform_remote_state.vpc: Reading...
data.terraform_remote_state.vpc: Read complete after 1s
...

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

適用差分はなく、vpc.tf.jsonが正常に認識されていることがわかりました。

Discussion