ansibleは2つのディレクトリにあるすべてのファイルを比較し、違いを印刷します。

ansibleは2つのディレクトリにあるすべてのファイルを比較し、違いを印刷します。

私は2つのディレクトリを持っています

$ tree dir{1..2}
dir1
├── file1
└── file2
dir2
├── file1
└── file2

ansibleを使用してdir1のすべてのファイルをdir2のすべてのファイルと比較し、次のように違いを印刷したいと思います。

output:
${file1} from ${dir1}:
diff content

${file1} from ${dir2}:
diff content

すべてのファイルを繰り返して違いを印刷します。

以下は、修正する必要のあるansibleスニペットです。

---
- name: Compare files in two directories
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Find files in directory 1
      find:
        paths: ~/dir1
        file_type: file
      register: dir1_files

    - name: Find files in directory 2
      find:
        paths: ~/dir2
        file_type: file
      register: dir2_files

    - name: Compare files
      shell: diff dir1/file1 dir2/file1 ## how can I make sure path changes but filenames stay same using variables
      loop: "{{ dir1_files.files }}"
      register: diff_output
      changed_when: false
      failed_when: diff_output.rc == 1

    - name: Print differences
      debug:
        msg: |
          {{ item.item.path }} from dir1:
          {{ item.stdout }}
          {{ item.item.path }} from dir2:
          {{ item.stdout }}
      loop: "{{ diff_output.results }}"
      when: item.stdout_lines | length > 0

Vladimirの回答で提案されたコードについては、次の結果が表示されます。

TASK [debug] *****************************************************************************************************************************************
ok: [localhost] => {
    "msg": "file2 from dir1: \n  1,2c1,2\n  < abc123\n  < def456\n  ---\n  > abc101\n  > def111\nfile2 from dir2: \n  1,2c1,2\n  < abc123\n  < def456\n  ---\n  > abc101\n  > def111\nfile1 from dir1: \n  1,2c1,2\n  < 123abc\n  < 456def\n  ---\n  > 101abc\n  > 111def\nfile1 from dir2: \n  1,2c1,2\n  < 123abc\n  < 456def\n  ---\n  > 101abc\n  > 111def\n"
}

答え1

たとえば、与えられたファイル

shell> ssh admin@test_11 ls -1 /tmp/dir[1,2]
/tmp/dir1:
file1
file2

/tmp/dir2:
file1
file2
shell> ssh admin@test_13 ls -1 /tmp/dir[1,2]
/tmp/dir1:

/tmp/dir2:

そして違い

shell> ssh admin@test_11 diff /tmp/dir1/file1 /tmp/dir2/file1
31,32d30
< User1:*:1002:1004:My User1:/home/User1:/bin/sh
< MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
shell> ssh admin@test_11 diff /tmp/dir1/file2 /tmp/dir2/file2
33,34d32
< alice:*:1004:1006:Alice:/home/alice:/bin/sh
< bob:*:1005:1007:Bob:/home/bob:/bin/sh

変数宣言

  dir1: /tmp/dir1
  dir2: /tmp/dir2
  dir1_files: "{{ out_dir1.files|map(attribute='path') }}"
  dir2_files: "{{ out_dir2.files|map(attribute='path') }}"

そしてファイルを探す

    - find:
        paths: "{{ dir1 }}"
        file_type: file
      register: out_dir1
    - find:
        paths: "{{ dir2 }}"
        file_type: file
      register: out_dir2

共有ファイルを探します。変数宣言

  files_common: "{{ dir1_files|map('basename')|
                    intersect(dir2_files|map('basename')) }}"

test_11とtest_13をそれぞれ提供します(要約)。

  files_common:
  - file1
  - file2

  files_common: []

共有ファイルを比較してください。これらのエラーは無視する必要があります。違い返品RC=1ファイルが異なる場合

  - command: "diff {{ dir1 }}/{{ item }} {{ dir2 }}/{{ item }}"
    loop: "{{ files_common }}"
    ignore_errors: true
    register: out_diff

レポートを作成し、

    - debug:
        msg: |
          {% for i in out_diff.results %}
          {{ i.cmd|join(' ') }}: |
            {{ i.stdout|indent(2) }}
          {% endfor %}

test_11とtest_13をそれぞれ提供します(要約)。

  msg: |-
    diff /tmp/dir1/file1 /tmp/dir2/file1: |
      31,32d30
      < User1:*:1002:1004:My User1:/home/User1:/bin/sh
      < MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
    diff /tmp/dir1/file2 /tmp/dir2/file2: |
      33,34d32
      < alice:*:1004:1006:Alice:/home/alice:/bin/sh
      < bob:*:1005:1007:Bob:/home/bob:/bin/sh

  msg: ""

テストのための完全なプレイブックの例

- hosts: all

  vars:

    dir1: /tmp/dir1
    dir2: /tmp/dir2
    dir1_files: "{{ out_dir1.files|map(attribute='path') }}"
    dir2_files: "{{ out_dir2.files|map(attribute='path') }}"
    files_common: "{{ dir1_files|map('basename')|
                      intersect(dir2_files|map('basename')) }}"
    
    
  tasks:

    - find:
        paths: "{{ dir1 }}"
        file_type: file
      register: out_dir1
    - find:
        paths: "{{ dir2 }}"
        file_type: file
      register: out_dir2
    - debug:
        var: files_common

    - command: "diff {{ dir1 }}/{{ item }} {{ dir2 }}/{{ item }}"
      loop: "{{ files_common }}"
      ignore_errors: true
      register: out_diff
    - debug:
        msg: |
          {% for i in out_diff.results %}
          {{ i.cmd|join(' ') }}: |
            {{ i.stdout|indent(2) }}
          {% endfor %}

尋ねる:「私はmsgモジュールの出力が好きではありません。Qが出力セクションで提供したものと似た形式を好みます。

答え:もちろんです。以下のテンプレートをお試しください。これが気に入らない場合は、質問を編集して希望の例を提供してください。

    - debug:
        msg: |
          {% for i in out_diff.results %}
          {{ i.cmd.1|basename }} from {{ i.cmd.1|dirname }}: 
            {{ i.stdout|indent(2) }}
          {{ i.cmd.2|basename }} from {{ i.cmd.2|dirname }}: 
            {{ i.stdout|indent(2) }}
          {% endfor %}

出力形式はコールバックによって異なります。バラよりDEFAULT_STDOUT_CALLBACK。使用する場合ansible.buildin.defaultコールバック設定 ANSIBLE_CALLBACK_RESULT_FORMAT=yaml

shell> ANSIBLE_STDOUT_CALLBACK=default ANSIBLE_CALLBACK_RESULT_FORMAT=yaml ansible-playbook pb.yml

  ...
ok: [test_11] => 
    msg: |-
        file1 from /tmp/dir1:
          31,32d30
          < User1:*:1002:1004:My User1:/home/User1:/bin/sh
          < MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
        file1 from /tmp/dir2:
          31,32d30
          < User1:*:1002:1004:My User1:/home/User1:/bin/sh
          < MyUser1:*:1003:1005:My User1:/home/MyUser1:/bin/sh
        file2 from /tmp/dir1:
          33,34d32
          < alice:*:1004:1006:Alice:/home/alice:/bin/sh
          < bob:*:1005:1007:Bob:/home/bob:/bin/sh
        file2 from /tmp/dir2:
          33,34d32
          < alice:*:1004:1006:Alice:/home/alice:/bin/sh
          < bob:*:1005:1007:Bob:/home/bob:/bin/sh
ok: [test_13] => 
    msg: ""

バラより

shell> ansible-doc -t callback ansible.builtin.default

関連情報