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系が入る♡