Ansible ローカルのテンプレートファイルリストをリモートのファイルリストと一致させる


定義

ローカルサーバー:Ansibleを動かすサーバー
リモートサーバー:Ansibleによりコンフィグ配付するサーバー。

はじめに

Ansibleを実行するローカルサーバー側の特定ディレクトリに.j2ファイルを配置してリモートに設定。
その際ローカルサーバーのディレクトリの内容を丸々リモートのディレクトリに設定、というのはよくやるかと思います。

ローカルのテンプレートを持ってくイメージ
- name: "set nagios template file"
  template:
    src: "{{ item }}"
    dest: "/tmp/template_test/{{ item | basename | regex_replace('\\.j2$','') }}"
    mode: 0644
  with_fileglob:
    - "../templates/confs/*.j2"

この方法の問題は不要になったファイルをローカルから消したり、リネームしたりしてもリモートにファイルが残り続けてしまうことかと思います。
当初は削除対象一覧の変数を作る方法も考えましたが、管理が非常に面倒なのであきらめました。

ということで、削除前にリモートのファイルをローカルと比較して、存在しなければ削除するようにしました。
なお、再帰は考えていなかったので子ディレクトリもやりたければ複数書くことになります。

不格好ですができたはできたので備忘のために投稿します。
パスなどはべた書きしたので必要に応じて変数化してください。

やりかた

- name: "リモートサーバーのファイル一覧を取得"
  find:
    paths: "/tmp/template_test/"
    patterns: "*"
    file_type: "file"
  register: _template_remote_server_conf_files
- name: "リモートサーバーのファイル名のみをカンマ区切りで取得"
  set_fact:
    _template_remote_server_conf_filename: "{% for filename in _template_remote_server_conf_files.files | map(attribute='path') | list %}{{ filename | basename }}{% if not loop.last %},{% endif %}{% endfor %}"
- name: "リモートのファイル名をリスト化して取得"
  set_fact:
    template_remote_server_conf_filename:
      "{{ _template_remote_server_conf_filename.split(',') }}"

- name: "ローカルのテンプレートファイル一覧を取得"
  find:
    paths: "/etc/ansible/roles/settemplates/templates/confs/"
    patterns: "*"
    file_type: "file"
  register: "_template_ansible_server_conf_files"
  delegate_to: "localhost"
  run_once: "true"
- name: "ローカルのテンプレートファイル名のみをカンマ区切りで取得"
  set_fact:
    _template_ansible_server_conf_filename: "{% for filename in _template_ansible_server_conf_files.files | map(attribute='path') | list %}{{ filename | basename | regex_replace('\\.j2$','') }}{% if not loop.last %},{% endif %}{% endfor %}"
- name: "ローカルのファイル名をリスト化して取得"
  set_fact:
    template_ansible_server_conf_filename:
      "{{ _template_ansible_server_conf_filename.split(',') }}"

- name: "リモートにあってローカルにないファイル名のファイルを削除"
  file:
    paths: "/tmp/settemplates/{{ item }}"
    state: "absent"
  when:
    - "item != ''"
    - "item not in template_ansible_server_conf_filename"
  with_items: "{{ template_nagios_server_conf_filename }}"

お願い

Ansibleは趣味でいじり始めて1年程度で、無理やりこねくり回した感が溢れているかと思います。
他に良いやり方があれば是非教えて下さい。
正直モジュールが無いわけない気がするのですが見つけられませんでした。