JSON5でCloudFormationのテンプレートを書いてみる
こんにちは、虎塚です。
CloudFormationのテンプレートをJSONで書く時、ファイルが巨大になってくると読み書きが大変ですよね。バリデーションや入力補完などのエディタサポートがもっと欲しいという話もありますが、今日はフォーマットの話にフォカースしてみます。
こんな要望はありませんでしょうか?
- コメントを書きたい
- ブロックコメントを書きたい
- あわよくば日本語でコメントを書きたい
- Description要素などの長文文字列が読みづらいので何とかしたい
- 配列要素の末尾にカンマを許して欲しい
- 要素をコピーアンドペーストするたびに、カンマを付けたり消したりしたくない
CloudFormationのテンプレートに限らず、JSONにはこれらの問題が付き物なので、拡張フォーマットがいくつか存在します。
今回はそれらの中の1つであるJSON5でCloudFormationのテンプレートを書いてみます。
JSON5でテンプレートを書く
元となるテンプレート
題材として、AWSが提供しているサンプルテンプレートを見てみましょう。
上記のテンプレート群から1つ選択して、JSON5に書き換えてみます。ここでは、EC2WithEBSPIOPs.templateを使いました。
Amazon EC2 インスタンスと、プロビジョンド IOP を備えた EBS ボリュームを作成します。
AWS CloudFormation サンプルテンプレート – アジアパシフィック(東京)リージョン
というテンプレートです(実際のJSONファイル)。
JSON5で書いてみる
上のテンプレートに、JSON5で使える要素を加えて改変すると、次のようになります。
{ "AWSTemplateFormatVersion" : "2010-09-09", /* 2014年8月 XYZ案件向けベーステンプレート -- 複数行コメントのテスト */ // 複数行にわたる文字列をバックスペースで区切って改行するテスト "Description" : "AWS CloudFormation Sample Template EC2WithEBSPIOPs: \ Create an Amazon EC2 instance running the Amazon Linux AMI with \ a new EBS volume attached that has provisioned IOPs. \ The instance and the volume are pinned to the same availability zone. \ We recommend that you do untargeted launches rather than pinning instances this way.\ The AMI is chosen based on the region in which the stack is run. \ **WARNING** This template creates an Amazon EC2 instance and an EBS Volume. \ You will be billed for the AWS resources used if you create a stack from this template.", "Parameters" : { "KeyName": { "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instance", "Type": "String", "MinLength": "1", "MaxLength": "255", "AllowedPattern" : "[\\x20-\\x7E]*", "ConstraintDescription" : "can contain only ASCII characters." }, "SSHFrom" : { "Description" : "Lockdown SSH access (default can be accessed from anywhere)", "Type" : "String", "MinLength": "9", "MaxLength": "18", "Default" : "0.0.0.0/0", "AllowedPattern" : "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", "ConstraintDescription" : "must be a valid CIDR range of the form x.x.x.x/x." } }, // 新しいAMIが出たら差し替えること -- 1行コメントのテスト "Mappings" : { "RegionMap" : { "us-east-1" : { "AMI" : "ami-aecd60c7" }, "us-west-2" : { "AMI" : "ami-48da5578" }, "us-west-1" : { "AMI" : "ami-734c6936" }, "eu-west-1" : { "AMI" : "ami-6d555119" }, "ap-southeast-1" : { "AMI" : "ami-3c0b4a6e" }, "ap-southeast-2" : { "AMI" : "ami-bd990e87" }, "ap-northeast-1" : { "AMI" : "ami-2819aa29" }, // 配列の末尾要素にカンマを足すテスト(いわゆるケツカンマ) "sa-east-1" : { "AMI" : "ami-fe36e8e3" }, } }, "Resources" : { "EC2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ], "InstanceType" : "m1.large", "KeyName" : { "Ref" : "KeyName" }, "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]}, "EbsOptimized" : "true" } }, "InstanceSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable SSH access via port 22", "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHFrom" } } ] } }, "MountPoint" : { "Type" : "AWS::EC2::VolumeAttachment", "Properties" : { "InstanceId" : { "Ref" : "EC2Instance" }, "VolumeId" : { "Ref" : "NewVolume" }, "Device" : "/dev/sdh" } }, "NewVolume" : { "Type" : "AWS::EC2::Volume", "Properties" : { "Size" : "100", "VolumeType" : "io1", "Iops" : "100", "AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ]} } } }, "Outputs" : { "InstanceId" : { "Description" : "InstanceId of the newly created EC2 instance", "Value" : { "Ref" : "EC2Instance" } } } }
- コメントを書いた
- ブロックコメント(複数行コメント)を書いた
- 日本語でコメントを書いた
- 長文文字列を改行した
- 配列要素の末尾にカンマを付けた
このような変更を加えました。このファイルをEC2WithEBSPIOPs.json5という名前で保存します。
JSON5のインストール
上のファイルをCloudFormationのテンプレートとして利用するには、JSON5からJSONへと変換する必要があります。
JSON5 to JSONのコンバートコマンドを使うために、JSON5をインストールしましょう。
Mac OS X 10.9.4 (13E28) で動作確認しました。
node.jsのインストール
Node.jsをインストールします。HomeBrewを使うと簡単です。
brew caskを使う場合、次のコマンドを実行します。
brew cask install node
この時、Node.jsの実行環境と一緒にnpm(パッケージ管理ツール)もインストールされます。
JSON5のインストール
npmでJSON5をインストールします。グローバル領域にインストールする場合、次のコマンドを実行します。
% sudo npm install -g json5 Password: /usr/local/bin/json5 -> /usr/local/lib/node_modules/json5/lib/cli.js json5@0.2.0 /usr/local/lib/node_modules/json5 % which json5 /usr/local/bin/json5
JSON5をJSONへ変換する
次のコマンドを実行するだけで、JSON5からJSONへ変換できます。
json5 -c EC2WithEBSPIOPs.json5
EC2WithEBSPIOPs.jsonというファイルが、カレントディレクトリに生成されます。
確認
EC2WithEBSPIOPs.jsonを指定して、CloudFormationでスタックを作ってみましょう。
JSONファイルなので当たり前ではありますが、改変前のテンプレートと同様に、まったく問題なくスタックが作成されました。
ちょっとしたコツ
Macでのバックスラッシュの入力方法
複数行の文字列を改行するために、バックスラッシュを入力するとき、Macでエンマーク(¥)を使うとエラーになってしまいます。Macでバックスラッシュを入力するには、「optionキー + ¥」を入力します。
文字列の中にマルチバイト文字を入れてはいけない
JSON5ではコメントでマルチバイト文字が使えるので、つい文字列の中に日本語を書いてしまうことがありますが、CloudFormationのテンプレートとしては使えませんので気をつけましょう。
文字列中にマルチバイト文字がある状態でコンバートを実行しても成功するので、気づきにくいところです。注意しましょう。
数字や真偽値のダブルクォーテーションは外さない
数字や真偽値にダブルクォーテーションを付けなくてよいのも、JSON5の魅力のひとつです。しかし、それらも文字列として扱わなければ、CloudFormationのテンプレートとしてはエラーになります。
おわりに
誰かが作った巨大なテンプレートを読み解く時はもちろん、テンプレートを他の人へ引き継ぐ時などに、テンプレートへ注釈を書きたくなったら、JSON5を使ってみてもいいかもしれませんね。
それでは、また。