はじめに
Ansibleで変数が定義されていれば処理を行い、定義されていなければ処理を行わないというロジックはwhen: var_x is defined
あるいはwhen: var_x is not defined
で簡単に書ける。このような変数が大量にあるときのいい書き方を考える。
実行version: Ansible 2.6
yum installを例に
ミドルウェア/ライブラリ/言語などのinstallを一手に引き受けるroleを作成する。各ミドルウェアの設定roleでinstallしてもいいのだが、yum install以外にやることがないものもあるし、install処理をまとめて可読性を上げたり、依存関係の問題が起きにくいようにする目的もあって、一手に引き受けるroleを作成する。
Nginx, Apache, MySQL, Redis等のメジャーでどんなプロジェクトでも大抵使うミドルウェアのinstallはデフォルトで行ってもいいのだが、Node.js, MongoDB, RabbitMQ等は使わないプロジェクトも多く、変数が定義されたときだけinstallするようにしたい。
メジャーミドルウェアは何も考えずwith_items
とyum
でinstallするとして、追加ミドルウェアの処理を考えたい。
when: var_x is definedをひとつずつ書く
yumリポジトリを追加する場合、template
やcopy
で追加する場合はwith_items
でまとめて各ミドルウェアのリポジトリファイルをリモートサーバに送れるが、curlとbashを組み合わせてinstallするような仕組みの場合は次のようにひとつずつ実行するしかない。
- name: get repository(erlang)
shell: |
curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | bash -
args:
creates: /etc/yum.repos.d/rabbitmq_erlang.repo
when: rabbitmq is defined
- name: get repository(rabbitmq)
shell: |
curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | bash -
args:
creates: /etc/yum.repos.d/rabbitmq_rabbitmq-server.repo
when: rabbitmq is defined
with_items + when: item.required
リポジトリ追加と違ってyum installを実行する場合はyum
モジュールを使って統一的に実行できるためwith_items
でループさせる。このときwith_items
に渡すリストの定義方法に工夫ができる。
通常は次のように単純なリストを渡す。
- name: install basic middlewares
yum:
name: "{{ item }}"
state: installed
enablerepo: "nginx,{{ mysql.version }}-community,epel,remi,remi-{{ php.version }}"
with_items:
- nginx
- httpd
- httpd-devel
- mod_ssl
- mysql-community-server
- mysql-community-devel
- redis
略
今回は単純なリストではなくdict
にして渡す。dict
の要素としてyum.name
やyum.enablerepo
に渡す値を定義しているのだが、「Ansibleで変数が定義されているかどうかで処理の実行可否をわける」という目的のために定義するrequired
という要素が重要になる。
- name: install other middlewares
yum:
name: "{{ item.name }}"
state: installed
enablerepo: "{{ item.repo }}"
when: item.required
with_items:
- { name: nodejs, repo: "epel,nodesource", required: "{{ nodejs is defined }}" }
- { name: mongodb-org, repo: "epel,mongodb-org", required: "{{ mongo is defined }}" }
- { name: mongodb-org-server, repo: "epel,mongodb-org", required: "{{ mongo is defined }}" }
- { name: erlang, repo: "epel,rabbitmq_erlang", required: "{{ rabbitmq is defined }}" }
- { name: rabbitmq-server, repo: "epel,rabbitmq_rabbitmq-server", required: "{{ rabbitmq is defined }}" }
required: "{{ var_x is defined }}"
をすることで、変数が定義されているときはrequired: true
、定義されていない時はrequired: false
として解釈される。そのためwhen: item.required
で各ループ処理時に条件判定させることで実行可否を分けることができる。