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 でやってみました。
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
の実行結果に対してだけ使うのであれば充分かなと思います。
ついでにこいつをスクリプトに落とすと、雰囲気こんな感じ
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 使うようにしました。