Ansible: Playbookの実行条件制御 `when` の使い方(3)

投稿者: | 2017-02-12

前々回前回に引き続き、今回も Playbook でのタスク制御を行なう when の使い方を勉強していきます。
今回でこのシリーズは最後です。

題材は、引き続き本家のドキュメント。

シリーズの記事はこちら。

Ansible: Playbookの実行条件制御 `when` の使い方(1)

Ansible: Playbookの実行条件制御 `when` の使い方(2)

Conditional Imports

こちらは、「高度な内容なのでスキップしても良いよー」と書かれている内容でした。

複数の環境やOSバージョンに一つの Playbook で処理を行なう、といったような場合にどう対応するかという内容のようです。
ここは when を使った条件評価ではないですが、変数を使った処理の切り替えのお話です。

---
- hosts: all
  remote_user: root
  vars_files:
    - "vars/common.yml"
    - [ "vars/{{ ansible_os_family }}.yml", "vars/os_defaults.yml" ]
  tasks:
  - name: make sure apache is running
    service: name={{ apache }} state=running

このサンプルでは、変数の ansible_os_family によって読み込み変数定義ファイルを切り替えています。
これによって、 RedHat 系の場合と Debian 系の場合で異なるパッケージ名(ここでは apache )に変数を設定できるようにしています。

---
# for vars/CentOS.yml
apache: httpd
somethingelse: 42

こんな感じですね。

ただし、これを利用するためには、事前に facterohai というパッケージを入れておかなければいけないようです。
Ansibleを使うのに事前にパッケージを入れる、、、というのもあれな感じですが、下記のようにコマンドベースでインストールできるようです。

# for facter
ansible -m yum -a "pkg=facter state=present"
ansible -m yum -a "pkg=ruby-json state=present"

# for ohai
ansible -m yum -a "pkg=ohai state=present"

Selecting Files And Templates Based On Variables

こちらも、「高度な内容なのでスキップしても良いよー」と書かれている内容でした。
しかし、諦めずに内容をみてみます。

タイトルは、「変数を基にしたファイルとテンプレートの選択」ですね。
早速、例を見てみましょう。

- name: template a file
  template: src={{ item }} dest=/etc/myapp/foo.conf
  with_first_found:
    - files:
       - {{ ansible_distribution }}.conf
       - default.conf
      paths:
       - search_location_one/somedir/
       - /opt/other_location/somedir/

まず with_first_found ですが、これは引数で取っている filespaths の中で最初にヒットしたものを利用する、、、というもののようです。
変数の ansible_distribution は Linuxのディストリビューション名を指しています。
つまり、 CentOSUbuntu によってconfファイルの指定を切り替える、という動きになりますね。

Register Variables

最後は、「変数への登録」です。
実行結果を保存しておいて、後から別のタスクで使えるようになります。

- name: test play
  hosts: all

  tasks:

      - shell: cat /etc/motd
        register: motd_contents

      - shell: echo "motd contains the word hi"
        when: motd_contents.stdout.find('hi') != -1

上記の例ですと、 /etc/motd の中身を motd_contents という変数に格納して、次のタスクの when で利用しています。
利用するときに motd_contents.stdout とすることで値を取り出していますね。

値を取り出すときに、 stdout_lines というものを使うことで行ごとに分解したリストとして扱うこともできます。
次の例を見てみましょう。

- name: registered variable usage as a with_items list
  hosts: all

  tasks:

      - name: retrieve the list of home directories
        command: ls /home
        register: home_dirs

      - name: add home dirs to the backup spooler
        file: path=/mnt/bkspool/{{ item }} src=/home/{{ item }} state=link
        with_items: "{{ home_dirs.stdout_lines }}"
        # same as with_items: "{{ home_dirs.stdout.split() }}"

こちらは、 ls /home の結果を home_dirs に格納しています。
システムに登録されているユーザの一覧と、ほぼ同じものが格納されていることになりますね。

これを、次のタスクで home_dirs.stdout_lines としてリストとの形で使っていますね。
(リストにする場合は、 home_dirs.stdout.split() という書き方でも良いようです。)

最後は、実行結果が「空」だった場合の判定方法です。

- name: check registered variable for emptiness
  hosts: all

  tasks:

      - name: list contents of directory
        command: ls mydir
        register: contents

      - name: check contents for emptiness
        debug: msg="Directory is empty"
        when: contents.stdout == ""

上記のように "" と比較することで、空であることの判定が行なえるようです。

まとめ

ここまでで、 when の使い方を中心とした、 Conditionals のページの内容を見てきました。

when だけでなく、変数なども有効に利用することで、色々な条件でタスクを実行したり、または読み込むファイルを制御したり、ということもできるようです。

うまく利用すれば、 Playbook をシンプルに書いていけるようになると思いますが、やりすぎると、それはそれで込み入って見通しが悪くなる可能性もありそうです。
知識をきちんと押さえた上で、必要な時に利用できるようになっていきたいですね。