考えなしでAWSを使っていると、とにかくわけのわからないIDがManagement Console上に並ぶことになる。少なくとも今使っているEC2インスタンスに紐付くEBSボリュームだけでもNameタグをつけることができないものかと考えたのでした。
AWS CLIのqueryオプション
AWS CLIにも抵抗は無くなってきたけど、まだまだ調べながらでないと使いこなせない。”–filters”で絞り込みができるけど、コマンドごとに使えるオプションを毎度確認しなければいけないの面倒だなと思っていたら、”–query”でもJMESPathとやらで実装されているかなり高機能な絞り込みができることがわかった。これだけできればjq使わなくても大丈夫そう。詳細はみんな大好きクラスメソッドさんのブログを。
Nameタグが空ではないEC2を取得
まずはNameタグを設定しているEC2のNameタグとアタッチされているEBSボリュームID一覧を取ってみる。この時点で既にかなりややこしい。”not_null”ではなく、”contains”を使えば部分一致で絞り込みもできる。
aws ec2 describe-instances ¥ --query 'Reservations[].Instances[?not_null(Tags[?Key==`Name`].Value)].[Tags[?Key==`Name`].Value,BlockDeviceMappings[].Ebs[].VolumeId]'
Nameタグが空のEBSボリュームを取得
結果的には使わなかったけど、空のものを抽出する場合はこんな感じで。Nameタグが設定されていないEBSボリュームIDを取ってみる。
aws ec2 describe-volumes ¥ --query 'Volumes[?Tags[?Key==`Name`].Value==`null`].VolumeId'
Nameタグが空のEBSボリュームにEC2のNameタグからNameタグをつけるスクリプト
結局シェルしか使えない自分はシェルで文字列操作。他の言語にもそろそろ手を出そう出そうと思い続けてもう何年になるだろう。最初に紹介した結果を”–output text”すると、NameタグとEBSボリュームID(スペース区切り)が交互に出力されることがわかった。配列っぽい処理を本当はもっと上手にできると思うのだけど、それでも何とかなって、どこでも使えるシェルから卒業できません。
#!/bin/bash
EC2NAME=
EBSIDS=
EBSNAME=
#Nameタグが空ではないEC2インスタンスのNameタグとEBSボリュームを取得しながらwhile文に流し込む
#NameタグとEBSボリュームが交互にlineに入る
aws ec2 describe-instances \
--query 'Reservations[].Instances[?not_null(Tags[?Key==`Name`].Value)].[Tags[?Key==`Name`].Value,BlockDeviceMappings[].Ebs[].VolumeId]' \
--output text \
| while read line
do
#Nameタグを変数に
if [ "$EC2NAME" = "" ]; then
EC2NAME=$line
EBSIDS=
continue
fi
#EBSボリュームIDを変数に
if [ "$EBSIDS" = "" ]; then
EBSIDS=$line
EBSNUM=1
#スペース区切りのボリュームIDをfor文に流し込む
for EBSID in $EBSIDS
do
#EBSボリュームのNameタグを取得
EBSNAME=`aws ec2 describe-volumes \
--query 'Volumes[].Tags[?Key==\`Name\`].Value' \
--filters "Name=volume-id,Values=$EBSID" \
--output text`
#EBSボリュームにNameタグが無いものにだけEC2のNameタグを加工したタグを設定
if [ "$EBSNAME" = "" ]; then
EBSNAME=EBS-$EC2NAME-$EBSNUM
echo "# aws ec2 create-tags --resources $EBSID --tags Key=Name,Value=$EBSNAME"
aws ec2 create-tags --resources $EBSID --tags Key=Name,Value=$EBSNAME
EBSNUM=$((EBSNUM+1))
fi
done
EC2NAME=
fi
done
EC2インスタンスにアタッチされたEBSボリュームが複数あったケースを考慮していない点はご愛嬌。あとはこれをcron的な何かに仕込んでおけば自動的にやってくれるはず。潜在的にこんな需要はけっこうあると思うのだけど。
相変わらず特殊文字の対処にも悪戦苦闘。EC2のNameタグを利用して、AMI作成時にAMI、Snapshotに自動でタグを付与するスクリプトも作りたい。