1.やりたいこと
CloudfrontのInvalidationは正規表現が使えないので、
Management consoleから絶対パスを指定してリクエストする必要があります。
面倒なので、Document root配下のパス全てを自動的に洗い出し、
全部まとめてInvalidationをrequestするスクリプトを作って見ました。
2.スクリプト概要
スクリプトの処理の流れは以下の通り。
①:Document root配下をfindコマンドでリストし、ファイルにリダイレクトする
②:①の結果からDocuent root配下の文字列を削除する
(例えば/var/www/html
だった場合、その文字列を削除することでInvalidatoinで使うパスに成形する)
③:findコマンド結果の先頭行は空行になってしまうので、先頭行を削除する
④:CloudfrontにInvalidationリクエストするpythonスクリプト呼び出す
(pythonスクリプトで、listを読み込み、Invalidation request実行!!)
3.ソースコード
bashとpythonで実現します。2つを同じディレクトリに配置して、bash側を実行します。
実行するインスタンスにIAMロールを忘れずに(オンプレミスから実行する場合は、アクセスキーの設定)。
まずはbash側。固定値はこっちに設定しておきます。
#!/bin/sh
#ここでdistribution-idとdocument rootのパスを定義する
DIS_ID= "XXXXXXXXXXX"
DOCUMENT_ROOT="/var/www/html" #apache-default
#find結果出力先
F_PATH="./cf-invalidation-list.txt"
#requestを行うpythonスクリプトのパス
PG_PATH="./cf-invalidation.py"
#①:findコマンド実行
`find ${DOCUMENT_ROOT} -print > ${F_PATH}`
if [ $? != 0 ]; then
fail_exit "find command failed..."
fi
#②:document rootのプレフィックスを削除
`sed -i -e "s#${DOCUMENT_ROOT}##g" ${F_PATH}`
if [ $? != 0 ]; then
fail_exit "Excluding docunemt-root string failed..."
fi
#③:空行削除
`sed -i -e '/^$/d' ${F_PATH}`
if [ $? != 0 ]; then
fail_exit "Excluding docunemt-root string failed..."
fi
#④:listとdistribution-idを引数にしてpythonスクリプト呼び出し
python "${PG_PATH}" "${DIS_ID}" "${F_PATH}"
if [ $? != 0 ]; then
echo "Invalidation request failed..."
exit 1
fi
echo "Invalidation request success."
exit 0
続いてpython側。
# coding: UTF-8
import sys
import boto
import boto.cloudfront
#Max request number of invalidation at one time.
MAX_REQUEST_NUM = 1000
try:
argvs = sys.argv
argc = len(argvs)
# Checking the number of argument
if (argc != 3):
print "You must define two argument. <distribution-id> <invalidation-list-file-path>"
quit()
#set distribution-id
dis_id = argvs[1]
#set file-path of invalidation list
file_path = argvs[2]
# invalidation-paths
paths = []
#File open and create paths-list
f = open(file_path , 'r')
for line in f:
paths.append(line[:-1])
f.close
# If the number of paths over 1000 processing quit , because of AWS limit...
if(len(paths) > MAX_REQUEST_NUM):
print "The number of paths exceeds " + MAX_REQUEST_NUM + ". processing quit... Please set it under " + MAX_REQUEST_NUM + "."
quit()
#Connecting to Cloudfront...
cf = boto.cloudfront.CloudFrontConnection()
# Request invalidation to Cloudfront.
rs = cf.create_invalidation_request(dis_id,paths)
except Exception as e:
print "Unexpected error occured." + str(e)
問答無用でDocument root全部というのはやり過ぎ、、、という場合は、
手動でlistつくってpython側のスクリプトをdistribution-idとlistのパスを指定して実行すれば、
任意のパスをまとめてInvalidationするこもできます。
毎度のことですが、エラーハンドリングなどは適当なので、適宜工夫してあげてください。
最後に、、、
1000個毎にリクエストを分割することで、1000個以上のパスが読み込まれても大丈夫なようにしたい、とか、
servletなどで使われるパス(.doとか)はファイルの実体がないので拾いきれないがなんとかしたい、とか
改善ポイントはありますが、それはそのうちということで。。。