LoginSignup
6
7

More than 5 years have passed since last update.

Ansibleで他のplaybookをincludeした際にpathが通らないとき

Last updated at Posted at 2017-06-16

はじめに

Ansibleで、あるRole内から別のRoleを呼び出したいことがあります。
例えば、処理A→処理B→処理Cというplaybookを実行したいとき、処理Bについては既存Roleが利用できる場合です。

処理AもCも単独のRoleにして、playbookから

Roles:
  - RoleA
  - RoleB
  - RoleC

のように実行してもいいのですが、できれば分割したくない。
そんな時はRoleA+Cの中でRoleBをinclude_roleモジュールで実行すればOKです。

しかし、

ansible.cfg
[defaults]
roles_path = ./roles

で指定したroles_path以外に置いたRoleはinclude_roleでは呼び出せません。

その場合、Playbookから他のPlaybookを呼び出すモジュールincludeを使うことになります。

しかし、includeしたplaybookにtemplateモジュールなどが含まれていると少々面倒です。
実際に試してみましょう。

sample

ディレクトリ構成

ディレクトリ構成
ansible.cfg
site.yml
hosts/local
roles/
|--include_other_playbook/
|  |--tasks/
|  |  |--main.yml
other_roles/
|--template_role/
|  |--tasks/
|  |  |--main.yml
|  |--templates/
|  |  |--template.j2

ansible.cfg

ansible.cfg
[defaults]
roles_path = ./roles

site.yml

---
- name: include_other_playbook
  hosts: targethost
  roles:
    - role: include_other_playbook

include_other_playbook

roles/include_other_playbook/tasks/main.yml
---
- debug: msg="1st"

- name: include template_role
  include: ../other_roles/template_role/tasks/main.yml

- debug: msg="2nd"

template_role

other_roles/template_role/tasks/main.yml
---
- name: template
  template:
    src: template.j2
    dest: /tmp/test
    owner: root
    group: root
    mode: '0644'

実行してみる

コマンド
$ ansible-playbook -i hosts/local -l targethost site.yml
結果
TASK [include_other_playbook : template dest=/tmp/test, src=template.j2, group=root, mode=0644, owner=root] ***
fatal: [targethost]: FAILED! => {"changed": false, "failed": true, "msg": "Unable to find 'template.j2' in expected paths."}

エラーになりました。テンプレートファイルが見つからないようです。
このtemplate_roleを単独実行すると成功するのに。。。

対処法

Ansibleでは、Role内でのcopyモジュールやtemplateモジュールのsourceディレクトリの起点は、Roleディレクトリ配下のfiles,templatesに限定されてしまいます。

しかも、includeした場合でも、実行中のRoleディレクトリ配下が参照されます。
つまり、今回の場合、include_other_playbook/templatesにもtemplate.j2を配置しないと見つけてくれません。

ディレクトリ構成
ansible.cfg
site.yml
hosts/local
roles/
|--include_other_playbook/
|  |--tasks/
|  |  |--main.yml
|  |--templates/
|  |  |--template.j2
other_roles/
|--template_role/
|  |--tasks/
|  |  |--main.yml
|  |--templates/
|  |  |--template.j2

しかし、これだと何のためにRoleにしているのか分からなくなってしまいます。
そこで、単独実行に影響を与えず、includeした際にパスを通す方法をご紹介します。

修正後

include_other_playbook

includeする際に、template_pathという変数を定義します。
ここにも書きましたが、相対パスを定義するためには一工夫必要です。

roles/include_other_playbook/tasks/main.yml
---
- debug: msg="1st"

- name: include template_role
  include: ../template_role/tasks/main.yml
  vars:
    template_path: "{{ inventory_dir }}/../roles/template_role/templates/template.j2"

- debug: msg="2nd"

template_role

srcにはinclude側で指定した変数を適用します。
ただし、単独実行に影響を与えないよう、defaultフィルタでデフォルト値を設定しておきます。

other_roles/template_role/tasks/main.yml
---
- name: template
  template:
    src: "{{ template_path | default('template.j2') }}"
    dest: /tmp/test
    owner: root
    group: root
    mode: '0644'

再度実行してみる

結果
TASK [include_other_playbook : debug msg=1st] **********************************
ok: [targethost] => {
    "msg": "1st"
}

TASK [include_other_playbook : template dest=/tmp/test, src={{ template_path | default('template.j2') }}, group=root, mode=0644, owner=root] ***
ok: [targethost]

TASK [include_other_playbook : debug msg=2nd] **********************************
ok: [targethost] => {
    "msg": "2nd"
}

成功しました。

まとめ

Ansibleはpath周りで融通が利かないことが多いのが難点だと思いますが、今回の方法を使えばincludeがより柔軟にできると思います。

6
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7