LoginSignup
2
2

More than 5 years have passed since last update.

CloudfrontのInvalidationを一括で行うスクリプト

Last updated at Posted at 2014-12-12

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側。固定値はこっちに設定しておきます。

cf-invalidation.sh
#!/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側。

cf-invalidation.py
# 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とか)はファイルの実体がないので拾いきれないがなんとかしたい、とか
改善ポイントはありますが、それはそのうちということで。。。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2