ディレクトリを再帰的にコピーしますandすべての。j2ファイルをテンプレートとしてレンダリングします。このために、現在次の行を使用しています。
- template: >
src=/src/conf.d/{{ item }}
dest=/dest/conf.d/{{ item|replace('.j2','') }}
with_lines: find /src/conf.d/ -type f -printf "%P\n"
今、私はこのディレクトリから管理されていないファイルを削除する方法を探しています。たとえば、/src/conf.d/
からファイル/テンプレートを削除する場合、Ansibleが/dest/conf.d/
からも削除します。
これを行う方法はありますか? rsync --delete
をいじってみましたが、サフィックス.j2
が削除されたテンプレートに問題がありました。
リストの上部にある 'managed_files'として定義された変数を想定して、このようにします。
- Shell: ls -1 /some/dir
register: contents
- file: path=/some/dir/{{ item }} state=absent
with_items: contents.stdout_lines
when: item not in managed_files
Nginxファイルを使用してこれを行います。テンプレートから取得した特別な順序にする必要がありますが、管理されていないものは削除します。
# loop through the nginx sites array and create a conf for each file in order
# file will be name 01_file.conf, 02_file.conf etc
- name: nginx_sites conf
template: >
src=templates/nginx/{{ item.1.template }}
dest={{ nginx_conf_dir }}/{{ '%02d' % item.0 }}_{{ item.1.conf_name|default(item.1.template) }}
owner={{ user }}
group={{ group }}
mode=0660
with_indexed_items: nginx_sites
notify:
- restart nginx
register: nginx_sites_confs
# flatten and map the results into simple list
# unchanged files have attribute dest, changed have attribute path
- set_fact:
nginx_confs: "{{ nginx_sites_confs.results|selectattr('dest', 'string')|map(attribute='dest')|list + nginx_sites_confs.results|selectattr('path', 'string')|map(attribute='path')|select|list }}"
when: nginx_sites
# get contents of conf dir
- Shell: ls -1 {{ nginx_conf_dir }}/*.conf
register: contents
when: nginx_sites
# so we can delete the ones we don't manage
- name: empty old confs
file: path="{{ item }}" state=absent
with_items: contents.stdout_lines
when: nginx_sites and item not in nginx_confs
(ご覧のとおり)トリックは、テンプレートとwith_itemsが登録結果で異なる属性を持つことです。次に、それらを管理するファイルのリストに変換してから、ディレクトリのリストを取得し、そのリストにないものを削除します。
既にファイルのリストがある場合は、少ないコードで実行できます。しかし、この場合、インデックス付きリストを作成しているので、マップとともにリストも作成する必要があります。
このケースで私の経験を共有したいと思います。
2.2からAnsibleにはwith_filetreeループがあり、dirs、リンク、静的ファイル、さらには(!)テンプレートをアップロードする簡単な方法を提供します。構成ディレクトリの同期を保つ最良の方法です。
- name: etc config - Create directories
file:
path: "{{ nginx_conf_dir }}/{{ item.path }}"
state: directory
mode: 0755
with_filetree: etc/nginx
when: item.state == 'directory'
- name: etc config - Creating configuration files from templates
template:
src: "{{ item.src }}"
dest: "{{ nginx_conf_dir }}/{{ item.path | regex_replace('\\.j2$', '') }}"
mode: 0644
with_filetree: etc/nginx
when:
- item.state == "file"
- item.path | match('.+\.j2$') | bool
- name: etc config - Creating staic configuration files
copy:
src: "{{ item.src }}"
dest: "{{ nginx_conf_dir }}/{{ item.path }}"
mode: 0644
with_filetree: etc/nginx
when:
- item.state == "file"
- not (item.path | match('.+\.j2$') | bool)
- name: etc config - Recreate symlinks
file:
src: "{{ item.src }}"
dest: "{{ nginx_conf_dir }}/{{ item.path }}"
state: link
force: yes
mode: "{{ item.mode }}"
with_filetree: etc/nginx
when: item.state == "link"
次に、config dirから未使用のファイルを削除することができます。簡単だ。アップロードされたファイルのリストを収集し、ファイルはリモートサーバーに存在します。次に差分を削除します。
ただし、config dirにアンマネージファイルが必要な場合があります。 find
の-Prune
機能を使用して、管理されていないファイルのあるフォルダーをクリアしないようにしました。
PS _(Y)_管理されていないファイルをいくつか削除した後
- name: etc config - Gathering managed files
set_fact:
__managed_file_path: "{{ nginx_conf_dir }}/{{ item.path | regex_replace('\\.j2$', '') }}"
with_filetree: etc/nginx
register: __managed_files
- name: etc config - Convert managed files to list
set_fact: managed_files="{{ __managed_files.results | map(attribute='ansible_facts.__managed_file_path') | list }}"
- name: etc config - Gathering exist files (excluding .ansible_keep-content dirs)
Shell: find /etc/nginx -mindepth 1 -type d -exec test -e '{}/.ansible_keep-content' \; -Prune -o -print
register: exist_files
changed_when: False
- name: etc config - Delete unmanaged files
file: path="{{ item }}" state=absent
with_items: "{{ exist_files.stdout_lines }}"
when:
- item not in managed_files
ここに私が思いついたものがあります:
-テンプレート:src =/source/directory {{item}}。j2 dest =/target/directory/{{item}} register:template_results with_items: -a_list.txt -of_all.txt -templates.txt -set_fact: managed_files: "{{template_results.results | selectattr( ' invocation '、' defined ')| map(attribute =' invocation.module_args.dest ')| list}} " -debug: var:managed_files 冗長性:0 -find: パス: "/target/directory/" パターン:" * .txt " 登録: all_files -set_fact: files_to_delete: "{{all_files.files | map(attribute = 'path')| difference(managed_files)}}" - debug: var:all_files verbosity:0 -debug: var:files_to_delete verbosity:0 -ファイル:path = {{item}} state = absent with_items: "{{files_to_delete}}"
長所:削除中に複数の「スキップされた」エントリが表示されるのを防ぎます。
短所:検索/削除を行う前に複数のテンプレートタスクを実行する場合は、各template_results.resultsを連結する必要があります。
これを処理する方法はいくつかありますが、テンプレートステップの前にタスクのターゲットディレクトリを完全に空にすることは可能でしょうか?または、テンプレート化されたファイルを一時ディレクトリにドロップし、その後のステップでdelete + renameを実行しますか?
通常、ファイルを削除しませんが、-unmanaged
接尾辞を名前に追加します。サンプルのansibleタスク:
- name: Get sources.list.d files
Shell: grep -r --include=\*.list -L '^# Ansible' /etc/apt/sources.list.d || true
register: grep_unmanaged
changed_when: grep_unmanaged.stdout_lines
- name: Add '-unmanaged' suffix
Shell: rename 's/$/-unmanaged/' {{ item }}
with_items: grep_unmanaged.stdout_lines
[〜#〜]説明[〜#〜]
Grepコマンドの使用:
-r
は再帰的検索を行います--include=\*.list
-再帰検索中に拡張子が.listのファイルのみを取得する-L '^# Ansible'
-「#Ansible」で始まる行がないファイル名を表示します|| true
-これはエラーを無視するために使用されます。 Ansibleのignore_errors
も機能しますが、Ansibleエラーを無視する前に、ansible-playbookの実行中にansibleが赤色で表示します(少なくとも私にとっては)。次に、grepコマンドの出力を変数として登録します。 grepで出力が表示されたら、このタスクを変更済みとして設定します(changed_when
行がこれを担当します)。
次のタスクでは、grep出力(つまり、grepによって返されるファイル名)を反復処理し、renameコマンドを実行して各ファイルにサフィックスを追加します。
それで全部です。次回コマンドを実行すると、最初のタスクは緑色になり、2番目のタスクはスキップされます。
どうやらこれは現時点ではansibleでは不可能です。私はIRCでmdehaanと会話しました。そして、それは 有向非巡回グラフ を持たないansibleに要約され、このようなことを非常に難しくしています。
例についてmdehaanに尋ねるsudoers.dディレクトリを正式に管理し、次のことを思いつきました。
14:17 < mdehaan> Robe: http://Pastebin.com/yrdCZB0y
14:19 < Robe> mdehaan: HM
14:19 < Robe> mdehaan: that actually looks relatively sane
14:19 < mdehaan> thanks :)
14:19 < Robe> the problem I'm seeing is that I'd have to gather the managed files myself
14:19 < mdehaan> you would yes
14:19 < mdehaan> ALMOST
14:20 < mdehaan> you could do a fileglob and ... well, it would be a little gross
[..]
14:32 < mdehaan> eh, theoretical syntax, nm
14:33 < mdehaan> I could do it by writing a lookup plugin that filtered a list
14:34 < mdehaan> http://Pastebin.com/rjF7QR24
14:34 < mdehaan> if that plugin existed, for instance, and iterated across lists in A that were also in B