はじめに
同じパッケージであるにも関わらず、ディストリビューションで名称が違う場合があります。またインストールパス/設定ファイルのパスが微妙に違う場合があります。
たとえばApache2.4のパッケージ名は、CentOS7の場合は「httpd」ですが、Amazon Linuxの場合は「httpd24」となります。タスクごとにwhen句で指定しても良いのですが、同じ値を複数個所で使う場合はPlaybookが煩雑になります。
このような場合、ディストリビューション/OS環境ごとに変数をあらかじめ定義し、切り替えられたら便利です。またこの制御をグローバルに行う(≒Role呼び出し元のPlaybookで制御する)のではなく、Roleに閉じた範囲で制御できた方が見通しが良くなります。
このようなケースの解決策を以下にまとめます。
TL;DR
- vars(roles/????/vars/main.yml)の中ではwhen句で切り替えられない
- 各Roleのタスク(roles/????/tasks/main.yml)で、include_varsを使う
- include_varsと併せてwhen句を使う
試してみる
環境
CentOS7とAmazon Linuxで動作を確認しました。
いずれもVirtual BoxとVagrantでローカルにVMを作った環境となります。
必要な設定ファイル、Playbookは下記に公開しています。
https://github.com/tmiki/server-config
CentOS7
OS: CentOS Linux release 7.5.1804 (Core)
Python: 2.7.5
Ansible: 2.7.0
Amazon Linux
OS: Amazon Linux AMI 2017.03
Python: 2.7.12
Ansible: 2.6.4
Ansible Playbookディレクトリ構成
Ansible Playbookのディレクトリ構成は下記であるとします。
/path/to/ansible-playbooks/
- ansible.cfg
- ssh_config
- sys_local.yml ### ローカルホスト用のPlaybook。この中で各種Roleを読み込む。
- hosts/ ### 環境ごとのホスト、変数の定義。今回は省略。
- roles/ ### 各種Roleを格納しているディレクトリ
- common/
- common_httpd/ ### 今回はこのRoleの中の話になります。
- common_supervisor/
- :
- :
Playbookの定義
まず、OSディストリビューションごとに変数定義ファイルを用意します。名前は、vars-CentOS7.ymlとvars-AmazonLinux.ymlとします。
これらのvarsファイルの中で、「httpd_package_name」変数を定義します。
---
httpd_package_name: httpd
---
httpd_package_name: httpd24
タスクから下記のように指定します。when句でOSディストリビューションごとに読み込むvarsファイルを切り替えています。
実際にApacheをインストールするyumモジュールの「name」パラメータに、上記で定義した「httpd_package_name」変数を渡しています。
---
- name: Configure packages' name for AmazonLinux
include_vars: vars-AmazonLinux.yml
when: (ansible_distribution == "Amazon")
- name: Configure packages' name for CentOS7
include_vars: vars-CentOS7.yml
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")
- name: Install Apache2.4
yum: name="{{httpd_package_name}}" state=present update_cache=yes
解説・補足
想定していないOSディストリビューションで実行する
このPlaybookを、CentOS7/AmazonLinux以外のディストリビューションで実行するとエラーとなります。「httpd_package_name」変数が未定義状態になるので。
include_varsに変数を指定する。
「include_vars」を指定している個所は通常のPlaybookのタスクファイルであるため、任意の変数が利用できます。
したがって、下記のような指定も可能です。
- name: Configure packages' name for each distributions
include_vars: vars-{{ansible_distribution}}{{ansible_distribution_major_version}}.yml
CentOSやUbuntuでは「ansible_distribution_major_version」が正しく設定されるので上記で問題なく動きます。
Amazon Linuxは「ansible_distribution_major_version」が「NA」になりますので、注意が必要です。
# 恐らくAmazon Linux 2は当該値が2になるのではないかと思いますが、未検証
とはいえこの場合、「NA」は単なる文字列なので、「vars-AmazonNA.yml」というファイルを置いておけば事足ります。
ちなみに、「ansible -m setup localhost」の結果はそれぞれ下記のようになります。
$ ansible -m setup localhost
### ※途中省略
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "7",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "7.5.1804",
### ※途中省略
$ ansible -m setup localhost
### ※途中省略
"ansible_distribution": "Amazon",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/system-release",
"ansible_distribution_file_variety": "Amazon",
"ansible_distribution_major_version": "NA",
"ansible_distribution_release": "NA",
"ansible_distribution_version": "2017.03",
### ※途中省略