Ansibleのモジュールを使っていて、get_urlモジュールの冪等性が気になったので動作を確認した。
何が問題か
get_urlモジュールは、wgetやcurlのように、外部からファイルをダウンロードしてくる訳だけど、ダウンロードに失敗してファイルが途中で切れていたりすると、その後のtar展開などで困る。
しかし、get_urlのデフォルト動作では、Playbookを再実行しても、壊れたファイルを見て「あ、もうダウンロード終わってるじゃん」となってしまい、ファイルを再取得してくれない。
おまけをつけると、ダウンロードしたファイルが更新された時だけ、その先のビルド処理を流したい。
解決方法
まず、get_url に sha256sum オプションを渡してあげる。
さらに force=yes
を渡してあげる。
すると、ファイルが既にあったら、最初にsha256sumチェックサムを見てくれて、チェックサムが違っていたら再度ダウンロードしてくれるようだ。
tar.gz をダウンロードして、build ディレクトリに展開するまでの処理はこんな感じでOKだった。{{変数}}は、どこかで定義する方向で。
---
- hosts: all
- tasks:
- name: download some tarball
get_url: url={{ download_url }} sha256sum={{ csum }}
dest=~/some.tar.gz force=True
register: downloaded_tarball
- name: check the final result already exists
stat: path={{ my_fruits }}
register: st
- name: find out if build is necessary.
set_fact:
need_to_build: "{{ st.stat.exists == False or st.stat.size == 0 or
downloaded_tarball | changed }}"
- name: cleanup the build directory
file: path={{ build_dir }} state=absent
when: need_to_build
- name: prepare the build directory
file: path={{ build_dir }} state=directory
when: need_to_build
- name: untar the tarball
command: tar -xzf ~/some.tar.gz -C {{ build_dir }}
--strip-components=1
when: need_to_build
副次効果
sha256sum を渡すと、「ダウンロード元のファイルがいつの間にか更新されてた」といった場合に、Playbookがそこで失敗するから気づくことができる。
サイトでは、some-latest.tar.gz みたいな形でファイルをダウンロード可能にしていることも多いので、なにげに便利。
sha256sum?
なんで、md5sumじゃなくてsha256sumなの?という気もするけれど、単に実装されていないだけの模様(一週間前にPRがcloseされた)。そのうち、普通に md5sum も利用できるようになりそう。
sha256sum は以下のコマンドで取れる。CentOS7の場合。
$ sha256sum /etc/passwd
5d48adec53a47b0a8e7025f21f8a9ad8f6694cfbc139a0f13eb69e4b04a49272 /etc/passwd
$ rpm -qf `which sha256sum`
coreutils-8.22-11.el7.x86_64
結論
冪等性が大切なときは、とりあえず、get_urlにチェックサムとforce=yes
オプションを渡すのがよさそう。
この手のツールでは「冪等性」という言葉をよく使うのだけれど、やっぱり書き方次第、書き手の気配り次第なんだと思う。