[toc]
Terraformでオートスケール設定をしています。設定の記述が簡単なのが良いですね。 パッケージやOSのアップデートなどにBlue-Green Deploymentにしたいなと考えていまして、 BlueとGreenのオートスケーリンググループ(ASG)の台数を設定ファイルに外だし(variables.tfvarsなど)にしたいと考えていました。
ASGの台数はデプロイ状況によって可変であるため、スクリプトで設定ファイルを変更しようと考えていました。 しかし、Terraformの設定ファイルはHCL(HashiCorp Configuration Language)というJSON互換でありながらも形式が全く異なるため、パースをどうするかを考えていました。 Terraform及び周辺ツールのソースやドキュメントを漁りながら調べた結果、Go言語で書かれているHashicorp製のHCLライブラリが使えることがわかりました。 今回は、そのライブラリを使ってHCLのパースと生成方法についてサンプルスクリプトを元に紹介します。
サンプル
サンプルはGitHubに公開しています。 https://github.com/ohsawa0515/hcl_parse_sample
試し方は簡単です。
パッケージ管理ツールであるgolang/depを使いますので、まだ入れていない場合はgo get
します。
$ go get -u github.com/golang/dep/cmd/dep
dep ensure
すると依存パッケージ(hashicorp/hcl
)がvendorディレクトリ以下にダウンロードされます。
$ dep ensure
あとはgo run
すれば実行されます。
variables.tfvars
をパース、中身を編集して、HCLを生成した結果を標準出力します。
パース
jsonやyamlと同じようにUnmarshal
関数を使うだけなので簡単です。
https://github.com/ohsawa0515/hcl_parse_sample/blob/master/main.go#L23-L30
d, err := ioutil.ReadFile("./variables.tfvars")
if err != nil {
log.Fatal(err)
}
variables := Variables{}
hcl.Unmarshal(d, &variables)
値を書き換えやすくするため、データ構造に合わせて構造体を定義していましたが、ただパースするだけならinterface型で十分です。
生成
パースに比べて生成が若干面倒くさいです。というのも、jsonやyamlのようなMarshal
関数がないからです。また、Marshal
相当の上手いこと生成してくれる関数は実装されていませんでした。
なので、一旦JSON型として生成した後、HCL型にパースし直して整形&出力するといった方法をとりました。
回りくどい方法ですが、これ以外の方法が見つからなかったです。もっと効率の良いやり方があればコメントください。
json2hclというJSONとHCLを相互変換するツールを参考にしています。
https://github.com/ohsawa0515/hcl_parse_sample/blob/master/main.go#L52-L66
b, err := json.Marshal(variables)
if err != nil {
log.Fatal(err.Error())
}
ast, err := hcl.ParseBytes(b)
if err != nil {
log.Fatal(err.Error())
}
out := new(bytes.Buffer)
if err := printer.Fprint(out, ast); err != nil {
log.Fatal(err.Error())
}
fmt.Println(out)
最後に
HCLファイルをパース及び生成する方法を紹介しました。
ただ、Keyにダブルクオーテーションが入ったりと若干不満があるので、hcl.Marshal
を早く実装してもらいたいものです。