AWS CLI によりコマンドラインから制御したりする際、リクエストパラメータとして JSON ファイルが必要になることがあります。 CloudFront のキャッシュを削除したいときなんかがそうです。
AWS CLI のコマンドごとに、リクエストJSONを生成する専用スクリプトを書くという手もありますが、 シェル上でパイプやらリダイレクトやらを駆使していい感じに JSON を生成できるある程度汎用的なスクリプトにならんものか、 という思いから試してみた結果をここに記します。 どこかに既にあるものでしたらすみません。
コマンド引数は以下のようになっていて、JSON ファイルは標準入力から与えます。
filljson ${入力の型} ${キーパス} ${入力ファイル名}
標準入出力で JSON をやりとりするので以下のようにパイプでつなげることで
中間ファイルを作ることなく最終的なリクエスト JSON が得られます。
入力ファイル名のところには bash
や zsh
のプロセス置換機能を利用しています。
プロセス置換機能を使うとプログラム側からは単にファイルパスが渡ってくるように見えるので、
ファイルIOとして処理すればOKです。
cat json/cloudfront-invalidation.json |
filljson int InvalidationBatch.Paths.Quantity <(git diff --ignore-all-space --diff-filter=M --name-only HEAD^ HEAD public | wc -l) |
filljson [string] InvalidationBatch.Paths.Items <(git diff --ignore-all-space --diff-filter=M --name-only HEAD^ HEAD public | sed -e 's/^public//g') |
filljson string InvalidationBatch.CallerReference <(date +"osone3-%Y/%m/%d-%H:%k:%m" | tr -d '\n') |
jq . > request.json
プログラムの内容
コードはここで、
Go 言語で書いたので go get github.com/tmrtmhr/filljson
でコマンドをインストールできます。
リポジトリの js/filljson.js
に node.js で実装したものもあります。
どこかでエラーが出たら死にます(os.Exit(1)
)。
テストコードは少しだけ書きました。
入力としては配列を想定しておらず、オブジェクトのみなので map[string]interface{}
型を json.Unmarshal
に渡します。
var jsonData map[string]interface{}
err = json.Unmarshal(jsonStr, &jsonData)
取り出した値が interface{}
となっているので再度 map[string]interface{}
として型アサーションをつけます。
finger = finger[propName].(map[string]interface{})
参考:golang は ゆるふわに JSON を扱えまぁす!
雑感
標準入出力は偉大です。
GO言語的には特化した(たとえばCloudFront専用のJSON生成専用)コマンドを作ってきっちり型検査したほうが良さそうですが、 まあこういう書き方もできるということで御参考いただければ幸いです。