Guest User

Untitled

a guest
Jul 16th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.63 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
  4. function msg() {
  5. printf "$*" >&2
  6. }
  7.  
  8. # ヘルプメッセージ
  9. function usage() {
  10. printf "usage: %s <EC2 Instance ID> [<AMI ID>]\n\n" ${0##*/} >&2
  11. exit
  12. }
  13.  
  14. # 英小文字 -> 英大文字
  15. function toupper() {
  16. echo $1 | tr 'a-z' 'A-Z'
  17. }
  18. #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
  19.  
  20. EC2_INSTANCE_ID=$1
  21. AMI_ID=$2
  22.  
  23. # 必要なコマンドがインストールされているか確認
  24. cmd_list='
  25. aws
  26. jq
  27. '
  28. cmd_miss=0
  29.  
  30. for cmd in $(echo $cmd_list | xargs); do
  31. if [ "$(which $cmd 2>&1)" = "" ]; then
  32. echo "ERROR: コマンドが見つかりません: $cmd"
  33. cmd_miss=1
  34. fi
  35. done
  36. if [ $cmd_miss != 0 ]; then exit; fi
  37.  
  38. # 引数の確認
  39. if [ "$EC2_INSTANCE_ID" = "" ]; then
  40. # EC2_INSTANCE_ID の指定がなかったら終了
  41. usage
  42. fi
  43.  
  44. # クレデンシャルの確認(クレデンシャルが設定されていなかったら終了)
  45. msg "checking identity...\r"
  46. aws sts get-caller-identity >/dev/null || exit
  47. msg " \r"
  48.  
  49. # 必要な情報の収集
  50.  
  51. ## EC2インスタンスからデバイス名とボリュームIDのリスト取得
  52. ## ex) [{"DeviceName":"/dev/sda1","VolumeId":"vol-1234abcd"}, {...}]
  53. msg "collecting volume devices...\r" >&2
  54. EC2_DESCRIBE_JSON=$(aws ec2 describe-instances --instance-ids ${EC2_INSTANCE_ID})
  55. if [ "$?" != "0" ]; then
  56. # EC2インスタンスの情報収集で失敗したら終了
  57. usage
  58. fi
  59. dev_vol_json=$(echo $EC2_DESCRIBE_JSON | jq -c '.[][]|.Instances[].BlockDeviceMappings[]|{"DeviceName":.DeviceName,"VolumeId":.Ebs.VolumeId}')
  60. DEVICES=$(echo ${dev_vol_json} | jq -r '.DeviceName' | sort)
  61. DEVICES_UPCASE=$(echo $DEVICES | sed -Ee 's|/[^ ]*/||'g | tr 'a-z' 'A-Z')
  62. msg " \r"
  63.  
  64. if [ "$AMI_ID" != "" ]; then
  65. # AMIから取得したデバイスリストと比較して確認
  66. msg "checking ami...\r"
  67. AMI_DESCRIBE_JSON=$(aws ec2 describe-images --image-ids ${AMI_ID})
  68. AMI_DEVICES=$(echo $AMI_DESCRIBE_JSON | jq -r '.[][].BlockDeviceMappings[].DeviceName' | sort)
  69. if [ "$DEVICES" != "$AMI_DEVICES" ]; then
  70. echo "ERROR: 指定されたEC2インスタンスとAMIのデバイスが合っていません"
  71. usage
  72. fi
  73. msg " \r"
  74.  
  75. # AMIからスナップショットIDを取得
  76. msg "collecting snapshot ids from ami...\r"
  77. dev_snap_json=$(echo $AMI_DESCRIBE_JSON | jq -c '.[][].BlockDeviceMappings[]|{"DeviceName":.DeviceName,"SnapshotId":.Ebs.SnapshotId}')
  78. msg " \r"
  79. mode=0
  80. note=''
  81. else
  82. # AMI ID の指定がなかったらテンプレートモード
  83. # テンプレートモード
  84. AMI_ID="***"
  85. mode=1
  86. note='
  87. # 実行時に、下記環境変数に手動でパラメータを補って下さい(***の部分)
  88. # AMI_ID
  89. # SNAP_ID_(デバイス名)
  90. '
  91. fi
  92.  
  93. # 各ボリュームのタグ・AZ・タイプ情報を取得
  94. msg "collecting volume infos...\r"
  95. vol_info_json=$(
  96. for vol_id in $(echo ${dev_vol_json} | jq -r '.VolumeId'); do
  97. aws ec2 describe-volumes --volume-id ${vol_id} \
  98. | jq -c '.[][]|{"VolumeId":.VolumeId,"Tags":.Tags,"AvailabilityZone":.AvailabilityZone,"VolumeType":.VolumeType}'
  99. done
  100. )
  101. msg " \r\n"
  102.  
  103. #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
  104.  
  105. ### 結果をもとに環境変数に登録
  106. show_SNAP_ID() {
  107. for dev in $DEVICES; do
  108. case $mode in
  109. 0)
  110. snap_id=$(echo ${dev_snap_json} | jq -r '.|select(.DeviceName=="'${dev}'").SnapshotId')
  111. ;;
  112. *)
  113. snap_id="***"
  114. ;;
  115. esac
  116. printf "SNAP_ID_%s=%s\n" $(toupper ${dev##*/}) $snap_id
  117. done
  118. for DEV in $DEVICES_UPCASE; do
  119. printf "echo SNAP_ID_%s = \${SNAP_ID_%s}\n" $DEV $DEV
  120. done
  121. }
  122.  
  123. ### スナップショットからEBSボリューム作成
  124. show_cmd_create_volume_new() {
  125. for dev in $DEVICES; do
  126. vol_id=$(echo ${dev_vol_json} | jq -r '.|select(.DeviceName=="'${dev}'").VolumeId')
  127. AZ=$(echo ${vol_info_json} | jq -r '.|select(.VolumeId=="'${vol_id}'").AvailabilityZone')
  128. TYPE=$(echo ${vol_info_json} | jq -r '.|select(.VolumeId=="'${vol_id}'").VolumeType')
  129. # /dev/sda1 -> SDA1
  130. DEV=$(toupper ${dev##*/})
  131.  
  132. printf "NEW_VOLUME_%s=\$(aws ec2 create-volume --availability-zone %s --volume-type %s --snapshot-id \${SNAP_ID_%s} | jq -r '.VolumeId')\n" $DEV $AZ $TYPE $DEV
  133. done
  134. for DEV in $DEVICES_UPCASE; do
  135. printf "echo NEW_VOLUME_%s = \${NEW_VOLUME_%s}\n" $DEV $DEV
  136. done
  137. }
  138.  
  139. ### 結果をもとに環境変数に登録
  140. show_CUR_VOLUME() {
  141. for dev in $DEVICES; do
  142. DEV=$(toupper ${dev##*/})
  143. vol_id=$(echo ${dev_vol_json} | jq -r '.|select(.DeviceName=="'${dev}'").VolumeId')
  144. printf "CUR_VOLUME_%s=%s\n" $DEV $vol_id
  145. done
  146. for DEV in $DEVICES_UPCASE; do
  147. printf "echo CUR_VOLUME_%s = \${CUR_VOLUME_%s}\n" $DEV $DEV
  148. done
  149. }
  150.  
  151. ### 現在のEBSボリュームのタグ情報を確認 -- CUR
  152. ### 新しいEBSボリュームのタグ情報を確認 -- NEW
  153. show_cmd_describe_volumes_tags() {
  154. for DEV in $DEVICES_UPCASE; do
  155. printf "aws ec2 describe-volumes --volume-ids \${%s_VOLUME_%s} | jq -rc '.Volumes[]|.Attachments[].Device,.Tags' | xargs -n2\n" $1 $DEV
  156. done
  157. }
  158.  
  159. ### 新規EBSボリュームにタグを付与
  160. show_cmd_create_tags() {
  161. for dev in $DEVICES; do
  162. DEV=$(toupper ${dev##*/})
  163. vol_id=$(echo ${dev_vol_json} | jq -r '.|select(.DeviceName=="'${dev}'").VolumeId')
  164. vol_tags=$(echo ${vol_info_json} | jq -c '.|select(.VolumeId=="'${vol_id}'")|.Tags')
  165.  
  166. if [ "$vol_tags" = "null" ]; then
  167. echo "# Tagなし : $vol_id - NEW_VOLUME_$DEV"
  168. else
  169. tag_name=''
  170. tag_other=''
  171. for tagpair in $(echo "$vol_tags" | jq -c '.[]'); do
  172. key=$(echo $tagpair | jq -r .Key)
  173. value=$(echo $tagpair | jq -r .Value)
  174. # Name -> それ以外の順で表示
  175. case "$key" in
  176. Name | name)
  177. tag_name="$tag_name $(printf 'Key=%s,Value=%s' $key $value)"
  178. ;;
  179. *)
  180. tag_other="$tag_other $(printf 'Key=%s,Value=%s' $key $value)"
  181. ;;
  182. esac
  183. done
  184. printf 'aws ec2 create-tags --resources ${NEW_VOLUME_%s} --tags%s%s\n' $DEV "$tag_name" "$tag_other"
  185. fi
  186. done
  187. }
  188.  
  189. ### 差分確認(日付やAttachments以外の差分を確認する)
  190. show_cmd_diff() {
  191. for DEV in $DEVICES_UPCASE; do
  192. printf 'diff -ub <(aws ec2 describe-volumes --volume-ids ${CUR_VOLUME_%s}) <(aws ec2 describe-volumes --volume-ids ${NEW_VOLUME_%s})\n' $DEV $DEV
  193. done
  194. }
  195.  
  196. ### ボリュームのデタッチ
  197. show_cmd_detach_volume() {
  198. for DEV in $DEVICES_UPCASE; do
  199. printf "aws ec2 detach-volume --volume-id \${CUR_VOLUME_%s}\n" $DEV
  200. done
  201. }
  202.  
  203. ### デタッチされたことの確認(availableになっていること) -- CUR
  204. ### アタッチされたことの確認(in-useになっていること) -- NEW
  205. show_cmd_describe_volumes_status() {
  206. printf 'aws ec2 describe-volumes --volume-ids'
  207. for DEV in $DEVICES_UPCASE; do
  208. printf " \${%s_VOLUME_%s}" $1 $DEV
  209. done
  210. printf " | jq -r '.Volumes[]|.VolumeId,.State' | xargs -n2\n"
  211. }
  212.  
  213. ### ボリュームのアタッチ
  214. show_cmd_attach_volume() {
  215. for dev in $DEVICES; do
  216. DEV=$(toupper ${dev##*/})
  217. printf "aws ec2 attach-volume --volume-id \${NEW_VOLUME_%s} --instance-id \${EC2_INSTANCE_ID} --device %s\n" $DEV $dev
  218. done
  219. }
  220.  
  221. ### 標準出力が端末のときは色を付ける
  222. cmd_colorize() {
  223. if [ -t 1 ]; then
  224. ruby -pe '$_.gsub!(/\A([^#*]+)?(***)?(#.*)?(\s*)?\Z/, "\e[97m\\1\e[93;1;4m\\2\e[m\e[32m\\3\e[m\\4")'
  225. else
  226. cat
  227. fi
  228. }
  229.  
  230. #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
  231.  
  232. # コメント行を緑色にしつつ出力
  233. cat <<EOF | cmd_colorize
  234. # --------------------------------------------------------------------------------
  235. # ${0##*/} $*
  236. # --------------------------------------------------------------------------------
  237. $note
  238. EC2_INSTANCE_ID=${EC2_INSTANCE_ID}
  239. AMI_ID=${AMI_ID}
  240. echo EC2_INSTANCE_ID = \${EC2_INSTANCE_ID}
  241. echo AMI_ID = \${AMI_ID}
  242.  
  243. ### AMIからスナップショットIDを確認
  244. aws ec2 describe-images --image-ids \${AMI_ID} | jq -r '.Images[].BlockDeviceMappings[]|.DeviceName,.Ebs.SnapshotId' | xargs -n2
  245.  
  246. ### 結果をもとに環境変数に登録
  247. $( show_SNAP_ID )
  248.  
  249. ### スナップショットからEBSボリューム作成
  250. $( show_cmd_create_volume_new )
  251.  
  252. ### EC2インスタンスに接続されているEBSボリュームのIDを確認
  253. aws ec2 describe-instances --instance-ids \${EC2_INSTANCE_ID} | jq -r '.[][].Instances[].BlockDeviceMappings[]|.DeviceName,.Ebs.VolumeId' | xargs -n2
  254.  
  255. ### 結果をもとに環境変数に登録
  256. $( show_CUR_VOLUME )
  257.  
  258. ### 現在のEBSボリュームのタグ情報を確認
  259. $( show_cmd_describe_volumes_tags CUR )
  260.  
  261. ### 新規EBSボリュームにタグを付与
  262. $( show_cmd_create_tags )
  263.  
  264. ### 新しいEBSボリュームのタグ情報を確認
  265. $( show_cmd_describe_volumes_tags NEW )
  266.  
  267. ### 差分確認(日付やAttachments以外の差分を確認する)
  268. $( show_cmd_diff )
  269.  
  270. ### インスタンス停止
  271. echo \${EC2_INSTANCE_ID} # ${EC2_INSTANCE_ID}
  272. aws ec2 stop-instances --instance-ids \${EC2_INSTANCE_ID}
  273. aws ec2 wait instance-stopped --instance-ids \${EC2_INSTANCE_ID} && echo 'stopped.'
  274.  
  275. ### ボリュームのデタッチ
  276. $( show_cmd_detach_volume )
  277.  
  278. ### デタッチされたことの確認(availableになっていること)
  279. $( show_cmd_describe_volumes_status CUR )
  280.  
  281. ### ボリュームのアタッチ
  282. $( show_cmd_attach_volume )
  283.  
  284. ### アタッチされたことの確認(in-useになっていること)
  285. $( show_cmd_describe_volumes_status NEW )
  286.  
  287. ### インスタンス起動
  288. aws ec2 start-instances --instance-ids \${EC2_INSTANCE_ID}
  289. aws ec2 wait instance-running --instance-ids \${EC2_INSTANCE_ID} && echo 'running.'
  290. aws ec2 wait instance-status-ok --instance-ids \${EC2_INSTANCE_ID} && echo 'status ok.'
  291. EOF
Add Comment
Please, Sign In to add comment