TL;DR
readonly escape_ansi=$(printf '\033') sed -e '/".*" => ".*"$/!b' \ -e '/^.*: *"\(.*\)" => "\1"$/!s/.*/'"$escape_ansi"'[31m&'"$escape_ansi"'[m/'
経緯
毎晩暑い日が続く日本、AWS の各種リソース管理を Terraform で行っている皆様におかれましては、 日々の業務において terraform plan をよくお使いになられていることと存じます*1。
そんな中、例えばこのような実行結果が表示されたとします:
.. .. (message) .. + aws_security_group.app ingress.#: "" => "1" ingress.0.cidr_blocks.#: "" => "1" ingress.0.cidr_blocks.0: "" => "192.0.2.0/24" ingress.0.from_port: "" => "80" ingress.0.protocol: "" => "tcp" ingress.0.to_port: "" => "80" -/+ aws_security_group.db ingress.#: "2" => "2" ingress.0.cidr_blocks.#: "1" => "1" ingress.0.cidr_blocks.0: "198.51.100.0/24" => "198.51.100.0/24" ingress.0.from_port: "3306" => "3306" ingress.0.protocol: "6" => "tcp" ingress.0.to_port: "3306" => "3306" ingress.1.cidr_blocks.#: "" => "1" ingress.1.cidr_blocks.0: "" => "203.0.113.0/24" ingress.1.from_port: "" => "5432" ingress.1.protocol: "" => "tcp" ingress.1.to_port: "" => "5432" -/+ aws_security_group.mail ingress.#: "2" => "1" ingress.0.cidr_blocks.#: "1" => "1" ingress.0.cidr_blocks.0: "198.51.100.0/24" => "198.51.100.0/24" ingress.0.from_port: "587" => "587" ingress.0.protocol: "6" => "tcp" ingress.0.to_port: "587" => "587" ingress.1.cidr_blocks.#: "1" => "" ingress.1.cidr_blocks.0: "198.51.100.0/24" => "" ingress.1.from_port: "995" => "" ingress.1.protocol: "6" => "" ingress.1.to_port: "995" => "" Apply complete! Resources: 1 added, 2 changed, 0 destroyed.
(実行結果はてきとうです)
各セキュリティーグループのルール数が2、3個なのでまだまだ見えますが、例えばルール数が20個とかになるとかなりの行数が目に入ります。その中で どの行(属性)が変更なのかぱっと見、わかりづらい と思うわけです。思いました。
まあそんなわけで、属性値に変更のある場所がわかりやすく見えればいいな、ということで、いくつか方法はあると思いますが、今回は sed でやってみました。
sed
readonly escape_ansi=$(printf '\033') sed -e '/".*" => ".*"$/!b' \ -e '/^.*: *"\(.*\)" => "\1"$/!s/.*/'"$escape_ansi"'[31m&'"$escape_ansi"'[m/'
"xx" => "yy"
という文字列(xxとyyは任意)を 含まない 行はスキップして次に進む"xx" => "xx"
という条件に一致しない(つまり左と右の""
内の値が 同じではない )場合 に、赤で色付けする
こんな感じでできました。パターンは単純なんですが terraform plan
の実行結果に対してだけ使うのであれば充分かなと思います。
ついでにこいつをスクリプトに落とすと、雰囲気こんな感じ
#!/bin/sh readonly escape_ansi=$(printf '\033') readonly program_name=$0 if [ -p /dev/stdin ] ; then cat - else if [ ! $# -ge 1 ] ; then echo "$0: [ERROR] You must specify file." exit 1; fi if [ ! -f "$1" ] ; then echo "$0: [ERROR] \"$1\" No such file." exit 1; fi cat "$1" fi | sed -e '/".*" => ".*"$/!b' \ -e '/^.*: *"\(.*\)" => "\1"$/!s/.*/'"$escape_ansi"'[31m&'"$escape_ansi"'[m/'
てきとうに tpdiff
とか名前で保存しておいて
$ terraform plan | tpdiff
こんな感じで、冒頭の画像のように表示されます。多分。
ひとまず
あたりでは動いているようです。
まとめ
sed 難しい
おまけ
当初、sed の色付けする部分を
-e $'/^.*: *"\\(.*\\)" => "\\1"$/!s/.*/\e[31m&\e[m/'
みたいな感じでやってたんですが、 POSIX 準拠してるかってチェックしてくれる shellcheck を使うと
fi | sed -e '/".*" => ".*"$/!b' -e $'/^.*: *"\\(.*\\)" => "\\1"$/!s/.*/\e[31m&\e[m/' ^-- SC2039: In POSIX sh, $'..' is undefined.
ってな感じで怒られたので、printf 使うようにしました。
*1:手元実行なんかせず、Atlasにお任せしてる人が多いのかもしれない