Apache の /etc/httpd/conf.d/*.conf
のような、所定の形式の名前でファイルを置いておけば読まれるようになる設定ファイルを対象サーバにコピーしたい場合、copy
モジュールでのディレクトリコピーや with_fileglob
との組み合わせが便利です。
例えば次のようなディレクトリ構成で、
ansible.cfg
hosts
httpd.yml
files/
etc/
httpd/
conf.d/
aaa.conf
bbb.conf
次の Playbook を、
---
- hosts: all
sudo: yes
tasks:
- copy: src={{ item }} dest=/etc/httpd/conf.d/
with_fileglob:
- files/etc/httpd/conf.d/*.conf
notify:
- httpd check
- httpd reload
handlers:
- name: httpd check
shell: httpd -t
- name: httpd reload
service: name=httpd state=reloaded
実行すると、
$ ansible-playbook httpd.yml
PLAY [all] ********************************************************************
TASK: [copy src={{ item }} dest=/etc/httpd/conf.d/] ***************************
changed: [192.0.2.123] => (item=/path/to/ansible/files/etc/httpd/conf.d/aaa.conf)
changed: [192.0.2.123] => (item=/path/to/ansible/files/etc/httpd/conf.d/bbb.conf)
NOTIFIED: [httpd check] *******************************************************
changed: [192.0.2.123]
NOTIFIED: [httpd reload] ******************************************************
changed: [192.0.2.123]
PLAY RECAP ********************************************************************
192.0.2.123 : ok=3 changed=3 unreachable=0 failed=0
対象サーバに conf.d
の中身がコピーされます。
$ ls /etc/httpd/conf.d/
aaa.conf bbb.conf
with_fileglob
を使わなくても src
でディレクトリを指定すれば大体同じことができます。
---
- hosts: all
sudo: yes
tasks:
- copy: src=files/etc/httpd/conf.d/ dest=/etc/httpd/conf.d/
notify:
- httpd check
- httpd reload
handlers:
- name: httpd check
shell: httpd -t
- name: httpd reload
service: name=httpd state=reloaded
ただ、この方法だとどのファイルに変更があったかがわからないのであまり使いません。
$ ansible-playbook httpd.yml
PLAY [all] ********************************************************************
TASK: [copy src=files/etc/httpd/conf.d/ dest=/etc/httpd/conf.d/] ******************
changed: [192.0.2.123]
NOTIFIED: [httpd check] *******************************************************
changed: [192.0.2.123]
NOTIFIED: [httpd reload] ******************************************************
changed: [192.0.2.123]
PLAY RECAP ********************************************************************
192.0.2.123 : ok=3 changed=3 unreachable=0 failed=0
とても便利な copy
モジュールですが、ローカルで削除したファイルを対象サーバでも自動的に削除したりすることはできません。
例えば、bbb.conf を削除したとして、
ansible.cfg
hosts
httpd.yml
files/
etc/
httpd/
conf.d/
aaa.conf
Playbook を実行しても削除はされません。
$ ansible-playbook httpd.yml
PLAY [all] ********************************************************************
TASK: [copy src={{ item }} dest=/etc/httpd/conf.d/] ***************************
ok: [192.0.2.123] => (item=/path/to/ansible/files/etc/httpd/conf.d/aaa.conf)
PLAY RECAP ********************************************************************
192.0.2.123 : ok=1 changed=0 unreachable=0 failed=0
この状況で bbb.conf を対象サーバから削除したければ file
モジュールで明示的に指定する必要があります。
---
- hosts: all
sudo: yes
tasks:
- copy: src={{ item }} dest=/etc/httpd/conf.d/
with_fileglob:
- files/etc/httpd/conf.d/*.conf
notify:
- httpd check
- httpd reload
- file: path={{ item }} state=absent
with_items:
- /etc/httpd/conf.d/bbb.conf
notify:
- httpd check
- httpd reload
handlers:
- name: httpd check
shell: httpd -t
- name: httpd reload
service: name=httpd state=reloaded
$ ansible-playbook httpd.yml
PLAY [all] ********************************************************************
TASK: [copy src={{ item }} dest=/etc/httpd/conf.d/] ***************************
ok: [192.0.2.123] => (item=/path/to/ansible/files/etc/httpd/conf.d/aaa.conf)
TASK: [file path={{ item }} state=absent] *************************************
changed: [192.0.2.123] => (item=/etc/httpd/conf.d/bbb.conf)
NOTIFIED: [httpd check] *******************************************************
changed: [192.0.2.123]
NOTIFIED: [httpd reload] ******************************************************
changed: [192.0.2.123]
PLAY RECAP ********************************************************************
192.0.2.123 : ok=4 changed=3 unreachable=0 failed=0
さすがにこれだとめんどくさいしモレもありそうなので、synchronize
モジュールを使ってローカルから削除されたファイルは対象サーバでも自動的に削除されるようにしました。
synchronize
でやりたいことはファイルの削除だけなので、余計なことが行われないように archive: no
や rsync_opts: [ --ignore-existing ]
を指定しています。
---
- hosts: all
sudo: yes
tasks:
- copy: src={{ item }} dest=/etc/httpd/conf.d/
with_fileglob:
- files/etc/httpd/conf.d/*.conf
notify:
- httpd check
- httpd reload
- synchronize:
src: files/etc/httpd/conf.d/
dest: /etc/httpd/conf.d/
archive: no
delete: yes
dirs: yes
rsync_opts: [ --ignore-existing ]
notify:
- httpd check
- httpd reload
handlers:
- name: httpd check
shell: httpd -t
- name: httpd reload
service: name=httpd state=reloaded
$ ansible-playbook httpd.yml
PLAY [all] ********************************************************************
TASK: [copy src={{ item }} dest=/etc/httpd/conf.d/] ***************************
ok: [192.0.2.123] => (item=/path/to/ansible/files/etc/httpd/conf.d/aaa.conf)
TASK: [synchronize ] **********************************************************
changed: [192.0.2.123 -> 127.0.0.1]
NOTIFIED: [httpd check] *******************************************************
changed: [192.0.2.123]
NOTIFIED: [httpd reload] ******************************************************
changed: [192.0.2.123]
PLAY RECAP ********************************************************************
192.0.2.123 : ok=4 changed=3 unreachable=0 failed=0
対象サーバで確認してみると、bbb.conf が削除されていることがわかります。
$ ls /etc/httpd/conf.d/
aaa.conf
copy と synchronize を併用する理由
copy
を使わずに synchronize
だけで設定ファイルをコピー&削除することも可能です。
が、それだと、
- どのファイルに変更があったか
-
--check --diff
で差分の事前確認
ができないので、併用するようにしてみました(対象サーバの台数が多くなるとそんなのいちいち見ていられないのでしょうけど)。