銀色うつ時間

思い出すたび何か胸につっかえてるだけ

Ansibleで冪等性を保つためにはfailed_whenとかstatを使うと便利

構成管理ツールとしてAnsibleを使って開発環境を作っているんだけど(本番でも使えるようにとかはまだできてない)、特定のコマンドの実行結果によって次の処理をスキップするかどうかみたいなのを制御したい場面がある。

例えばcentos6.xでnginxの設定を行いたいとすると、以下のようになる。

- name: get nginx rpm
  get_url: url="http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm" dest="/var/tmp/nginx-release-centos-6-0.el6.ngx.noarch.rpm"
- name: add nginx rpm
  yum: name=/var/tmp/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
- name: install nginx
  yum: name=nginx state=present
- name: register service
  service: name=nginx enabled=yes
- name: add conf file
  copy: src=../files/extra.conf dest=/etc/nginx/conf.d
- name: move default conf
  shell: mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.backup

確かにこれでもnginxのインストールと必要な設定は行えるが、このままでは冪等性が担保されない。Ansibleのコアモジュールの多くは冪等性をチェックしているが、shellモジュールなどの冪等性は担保されない。対象のサーバに対してこのスクリプトを実行した場合、2回目移行もdefault.confをmvしようとしてエラーになるだろう。

幸いAnsibleにはregisterという出力を変数に格納できる仕組みがあるので、それを利用するとよい。

- name: is nginx already installed
   shell: which nginx
   register: which_nginx

# (中略)

- name: move default conf
  shell: mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.backup

しかし、これではエラーとなってしまう。Ansibleは終了ステータスが0以外のものを原則エラーとして解釈するからだ。which nginxでnginxが存在しなかった場合、no nginx foundのようなものがエラー出力に出てしまうから、ハンドリングする必要がある。

結果、以下のように書くのがよい。

- name: is nginx already installed
   shell: which nginx
   register: which_nginx
   failed_when: which_nginx not in [0, 1]

# (中略)

- name: move default conf
  shell: mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.backup
  when: which_nginx.rc == 1

failed_whenは値に記述した結果のBooleanでタスクの成功可否を判定する。failed_whenを使うことで終了ステータスの正常・エラーに関わらずタスク自体は通過させ、以後はそこで宣言した変数のステータスや出力内容を見ながらタスクを実行するかスキップするか決めるようにするとよいと思う。

余談だが、特定ファイルの存在確認をするためには以下のようなやり方がある

- name: check default conf
  stat: path=/etc/nginx/conf.d/default.conf
  register: is_exists
- name: move default conf
  shell: mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.backup
  when: is_exists.stat.md5 is defined

statモジュールを利用して変数にset、md5ハッシュ値が存在するかどうかで以降のタスクを制御する。