web-dev-qa-db-ja.com

ansible-管理されていないファイルをディレクトリから削除しますか?

ディレクトリを再帰的にコピーします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が削除されたテンプレートに問題がありました。

41
Michael Krupp

リストの上部にある '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
49
user2645850

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が登録結果で異なる属性を持つことです。次に、それらを管理するファイルのリストに変換してから、ディレクトリのリストを取得し、そのリストにないものを削除します。

既にファイルのリストがある場合は、少ないコードで実行できます。しかし、この場合、インデックス付きリストを作成しているので、マップとともにリストも作成する必要があります。

11
dalore

このケースで私の経験を共有したいと思います。

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
5
dmOx

ここに私が思いついたものがあります:

-テンプレート: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」に結果が記録されます
  • 結果は、各テンプレートの「dest」の単純なリストを取得するためにマングルされます。スキップされたテンプレート(when条件により表示されないため)には「呼び出し」属性がないため、除外されます。
  • 次に、「find」を使用して、特に記述されていない限り存在しないすべてのファイルのリストを取得します。
  • 次に、これは、存在するファイルの生のリストを取得するためにマングルされ、「存在するはずの」ファイルは削除されます。
  • 残りの「files_to_delete」は削除されます。

長所:削除中に複数の「スキップされた」エントリが表示されるのを防ぎます。

短所:検索/削除を行う前に複数のテンプレートタスクを実行する場合は、各template_results.resultsを連結する必要があります。

3
Chris Cogdon

これを処理する方法はいくつかありますが、テンプレートステップの前にタスクのターゲットディレクトリを完全に空にすることは可能でしょうか?または、テンプレート化されたファイルを一時ディレクトリにドロップし、その後のステップでdelete + renameを実行しますか?

2
Tybstar

通常、ファイルを削除しませんが、-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番目のタスクはスキップされます。

1
ahes

どうやらこれは現時点では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
0
Michael Renner