Idempotence shell in Ansible
nodejsをインストールするプレイブックを書いたんだけど、epelから入れると古いnodejsがインストールされてしまう問題があった。
そこで最新のnodejsをcentos7に入れるプレイブックに書きなおした。nodejs公式に案内されてるやり方で、まずcurl叩いてnodejs5系が入るリポジトリをインストールした。
こんな感じ。
- name: setup_5.x is downloaded
get_url: url=https://rpm.nodesource.com/setup_5.x dest=/tmp/setup_5.x
tags: nodejs
- name: nodesource repo is installed
become: yes
shell: bash /tmp/setup_5.x
tags: nodejs
ところが、shellモジュールは冪等性が担保されていないモジュールなので、ansible-playbook -i development site.yml
を実行するたびにchanged
になってしまいもやもや…。
そこでwhen文を使ってある条件の時は該当のタスクをスキップするようにした。
条件は/etc/yum.repos.d/nodesource-el.repo
が存在するかどうか。
判定方法はstatモジュールを使った。このstatモジュールを使った判定結果を、register変数に入れて、その変数の内容でタスクをスキップさせるか否か判定させるようにした。
こんな感じ。
- name: nodesource repo is already installed
stat: path=/etc/yum.repos.d/nodesource-el.repo
register: result
tags: nodejs
- name: setup_5.x is downloaded
get_url: url=https://rpm.nodesource.com/setup_5.x dest=/tmp/setup_5.x
when: not result.stat.exists
tags: nodejs
- name: nodesource repo is installed
become: yes
shell: bash /tmp/setup_5.x
when: not result.stat.exists
tags: nodejs
whenの条件でnot result.stat.exists
を指定することによって、nodesource-el.repo
が存在しない場合のみ、リポジトリを追加するタスクが実行されるようになった!
あとはyumモジュールで普通にnodejsパッケージを入れればnodejs5系が入る♡