tkawachi Blog

CloudFormation の JSON を書くときの自分的ベスト

数ヶ月前に CloudFormation の JSON を書くにはどうしたらいいか考えた。 そのときはどこにも書かなかったが、今日思い出す機会があったのでメモしておこう。

背景: CloudFormation の JSON を書くのはつらい

AWS の CloudFormation を使おうと思ったら JSON を書かなければならない。 サンプルで提供されているJSONのひとつ を見てみて、自分にはとても書く気にはなれなかった。 理由は2つ。

1つめはコメントが書けないこと。 JSON として Description が書けるようになっているが、自由な行にコメントを書きたい。 コメントがないと後日見た時に意図が伝わらないことがあり、メンテナンスが困難になる。

2つめはJSONであるがゆえにDRYに書けないこと。 たとえばサンプル中に出てくる次の部分をみてみよう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"InboundHTTPPublicNetworkAclEntry" : {
  "Type" : "AWS::EC2::NetworkAclEntry",
  "Properties" : {
    "NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
    "RuleNumber" : "100",
    "Protocol" : "6",
    "RuleAction" : "allow",
    "Egress" : "false",
    "CidrBlock" : "0.0.0.0/0",
    "PortRange" : { "From" : "80", "To" : "80" }
  }
},

"InboundHTTPSPublicNetworkAclEntry" : {
  "Type" : "AWS::EC2::NetworkAclEntry",
  "Properties" : {
    "NetworkAclId" : { "Ref" : "PublicNetworkAcl" },
    "RuleNumber" : "101",
    "Protocol" : "6",
    "RuleAction" : "allow",
    "Egress" : "false",
    "CidrBlock" : "0.0.0.0/0",
    "PortRange" : { "From" : "443", "To" : "443" }
  }
},

げぇー。ほとんど同じ内容が書かれている。 違う部分を探すのが難しい。 プログラマがこれを見たら共通部をくくりだしたくなるのは自然だし、くくりだせないということがわかったら発狂するか無気力になるだろう。 大きな例になればなるほど、このような繰り返しが多数出現する。つらい。

解決策1. DSL

解決策のひとつは DSL を書いて JSON を生成する方法だ。 cloudformation-ruby-dsltroposphere や他にもいろいろ探せば出てくる。 DSLが問題を解決するか否かは、、まあDSL次第だ。 内部DSLの場合にはベースとなるプログラミング言語そのものの機能で問題を解消できる。 ざっと見たところ内部DSLを採用している例ばかりだった。

しかし、DSLを使うことで新たな問題が発生する。 CloudFormation には日々新たな機能が追加されており、DSLが機能をサポートするまでに時間がかかるのだ。 機能追加の速度が遅い場合にはこれは問題にはならないが、AWSはすごい速度で機能を追加してくる。 使いたいものが使いたいときに使えないようでは残念な気持ちになることが想像できる。

もちろんDSLに自分でpatchを当てればいいのだが、特定のDSLにそこまで思い入れがあるわけではない。 自分が求めているのは JSON を便利に書く方法であって、DSLではないということに気づいた。

解決策2. HOCON (Human Optimized Config Object Notation)

私は普段 Play framework を使って開発をしている。 Play で設定を書くときには HOCON というフォーマットを使う。 HOCON は JSON の superset であり、人間が読み書きするのに最適化されている(Human Optimized) 。 JSONを便利に書きたいのだから、HOCONこそ自分が求めるものだ(とその時は思った)。

HOCON を JSON に変換する方法が欲しかったので、コマンドラインツール hocon2json を作った。

問題は解決された(やった)。

敢えてこの方法の問題を挙げるとしたら、同僚に HOCON の書き方を教えなければならない点、コマンドラインツールをインストールしなければならない点だ。

解決策3. JavaScript/CoffeeScript

HOCONで問題は解決したものの、やっぱ HOCON マイナーだし、説明するのちょっとつらいな、という思いがしばらくくすぶっていた。 あるとき、JSONてそもそも JavaScript Object Notation の略だし、JavaScript で書けばいいんじゃないか、と思い立った。 JavaScript であれば知名度抜群でだれでも知っているし、コメントも簡単にかけるし、共通化も簡単だ。

実現方法は、JavaScript 内で JSON として使う Object を作って、 console.log(JSON.stringify(obj)) とするだけだ。 Pretty print したけば console.log(JSON.stringify(obj, null, 2)) とすれば良い。

今どきどこにいっても Node.js は入っている気がするし、もし無いときにも手元には必ずブラウザがあるので、ツールが無くて変換できないということは無いだろう。

CoffeeScript の実行環境も普及していると仮定すれば JavaScript の代わりに CoffeeScript で書いてもいいだろう。 その辺は普及の仮定と好みによる。

結論

CloudFormation の JSON を書くには JavaScript/CoffeeScript が自分的ベスト(今のところ)。

Comments