Ansible: how to check multiple files exist in a remote folder from a list

Viewed 554

I'm tring to copy from my Ansible server (Ansible 2.11.2 on Oracle Linux 8.4) to remote host (CentOS 7) some files from a list (set in my variable file).
Now I need to check after copy if all are copied correctly, and check the checksum for each files.

My main task used to copy the files from Ansible to remote host is:
tasks/main.yum:

- name: Jenkins - Configuration | Copy plugin files
  copy:
    src: "files/plugins/{{item.vars_plugin_name}}"
    dest: "{{ vars_jenkins_home }}/plugins/"
    owner: jenkins
    group: jenkins
  loop: "{{ vars_plugin_files }}"
  notify: restart-jenkins

This is my vars file: vars/main.yml

vars_plugin_files:
  - vars_plugin_name: ansible.hpi
    vars_plugin_checksum: 471787b86173cc6ef0a2243ec12f9a3419d1ac51
  - vars_plugin_name: apache-httpcomponents-client-4-api.hpi
    vars_plugin_checksum: 2d1b3f9961e5484bb70a45be8deb88d96fc0bf95
  - vars_plugin_name: caffeine-api.hpi
    vars_plugin_checksum: 69d651b736ee06b18d9b0f3efe332ef0628dee37
  - vars_plugin_name: credentials.hpi
    vars_plugin_checksum: c93d41e6989319e497dd601295036313b8b666a9
  - vars_plugin_name: display-url-api.hpi
    vars_plugin_checksum: 4b698121ecda4aa07ef1d80dd50158738949e796
  - vars_plugin_name: git-client.hpi
    vars_plugin_checksum: 1ec3107ba44f1e98a909101c932f4e478182f02b
  - vars_plugin_name: git.hpi
    vars_plugin_checksum: 49a35f9f0c27089a1bad3c88311b00728e716cd3
  - vars_plugin_name: jsch.hpi
    vars_plugin_checksum: d7f8ce10821a5e8f76d7efd8e8aab19d8e914b92
  - vars_plugin_name: ldap.hpi
    vars_plugin_checksum: 26e3781bba24144efc66da706c6b39cc860b44f8
  - vars_plugin_name: mailer.hpi
    vars_plugin_checksum: 204c1bd78772a1408142425128de6eaa17813069
  - vars_plugin_name: plain-credentials.hpi
    vars_plugin_checksum: 1aecd466a0fb1af38917a90ddd8f30dba6309d53
  - vars_plugin_name: scm-api.hpi
    vars_plugin_checksum: 0e73425e7d07d553ddb637c3b57a3f7cc78d6ff7
  - vars_plugin_name: script-security.hpi
    vars_plugin_checksum: 2ae3bd3a02124304bbf84f1ec57b14ca44322c21
  - vars_plugin_name: ssh-credentials.hpi
    vars_plugin_checksum: aa58526e1491a4f44d4a6f7045ab01b6b7564534
  - vars_plugin_name: ssh.hpi
    vars_plugin_checksum: 9390055b936f3f51f329937dceead7e896a2e23e
  - vars_plugin_name: structs.hpi
    vars_plugin_checksum: 37b98115acc372cbdc517217ad45c74bd965e570
  - vars_plugin_name: trilead-api.hpi
    vars_plugin_checksum: 6f440d2136873ce92bbef1e14a878e88c8f9c633
  - vars_plugin_name: workflow-scm-step.hpi
    vars_plugin_checksum: b4fa0b9a07c0ac36fd502947aa0bb074604ac597
  - vars_plugin_name: workflow-step-api.hpi
    vars_plugin_checksum: b3eb4f90b8fcccba673cecb3b34cb9a19fa39772

Now how can test the files after I copied them on the remote host with the list in my var file. I need to perform this:

  • compare list of files in the remote folder with var list
  • compare checksum for each files with var list

Thanks for the support. Marco

2 Answers

Given the files at the remote host

admin@test_11:~ $ find /home/admin/local/jenkins/plugins/ -type f | xargs sha1
SHA1 (/home/admin/local/jenkins/plugins/credentials.hpi) = 5ceb410e2c54743b70ca92392a89dd2946e6f1c7
SHA1 (/home/admin/local/jenkins/plugins/ansible.hpi) = 25ebdd4c915ccb847c95610cea5e2f95fd9e9710
SHA1 (/home/admin/local/jenkins/plugins/caffeine-api.hpi) = fff9d3adfc318729922be735a40e5ff7d17a41b2

and the variables

    vars_jenkins_home: /home/admin/local/jenkins
    vars_plugin_files:
      - vars_plugin_name: ansible.hpi
        vars_plugin_checksum: 25ebdd4c915ccb847c95610cea5e2f95fd9e9710
      - vars_plugin_name: caffeine-api.hpi
        vars_plugin_checksum: fff9d3adfc318729922be735a40e5ff7d17a41b2
      - vars_plugin_name: credentials.hpi
        vars_plugin_checksum: 5ceb410e2c54743b70ca92392a89dd2946e6f1c7

Find the files including the checksums and create a dictionary, e.g.

- hosts: test_11
  tasks:
    - find:
        path: "{{ vars_jenkins_home }}/plugins"
        patterns: "*.hpi"
        get_checksum: true
      register: result
    - set_fact:
        _dict: "{{ dict(_names|zip(_chcks)) }}"
      vars:
        _names: "{{ result.files|map(attribute='path')|map('basename')|list }}"
        _chcks: "{{ result.files|map(attribute='checksum')|list }}"

gives

ok: [test_11] => 
  _dict:
    ansible.hpi: 25ebdd4c915ccb847c95610cea5e2f95fd9e9710
    caffeine-api.hpi: fff9d3adfc318729922be735a40e5ff7d17a41b2
    credentials.hpi: 5ceb410e2c54743b70ca92392a89dd2946e6f1c7

There are many options on how to compare the results. For example, create a dictionary and compare them

    - set_fact:
        dict_files: "{{ vars_plugin_files|
                        items2dict(key_name='vars_plugin_name',
                                   value_name='vars_plugin_checksum') }}"
    - debug:
        msg: "{{ dict_files == _dict }}"

gives

ok: [test_11] => 
  msg: true

If the dictionaries are different you might want to iterate the items, e.g.

    - debug:
        msg: "{{ item.vars_plugin_name }} checksum error."
      loop: "{{ vars_plugin_files }}"
      when: item.vars_plugin_checksum != _dict[item.vars_plugin_name]

As I understood you want to copy the files to the remote host and then check if the remote file has the checksum you have on your vars file. So you need to check the variable on file to the remote file checksum after the copy. Here goes my best shot:

This part remains untouched

- name: Jenkins - Configuration | Copy plugin files
  copy:
    src: "files/plugins/{{item.vars_plugin_name}}"
    dest: "{{ vars_jenkins_home }}/plugins/"
    owner: jenkins
    group: jenkins
  loop: "{{ vars_plugin_files }}"
  notify: restart-jenkins

Then here goes the trick, first of all we need to get the STAT of the remote files and store it:

- name: Stat of remote
  stat:
    path: "{{vars_jenkins_home}}/plugins/{{item.vars_plugin_name}}"
  loop: "{{ vars_plugin_files}}"
  register: file_stat

- name: Debug the result of the comparision
  debug:
    msg: "The local file -> {{ item.0.vars_plugin_name }} with the checksum (WROTTEN AS VAR ON THE FILE) {{ item.0.vars_plugin_checksum }}  And the remote file {{item.1.stat.path}} with  Checksum -> {{ item.1.stat.checksum}}"
  loop: "{{vars_plugin_files|zip(file_stat.results)|list}}"
  failed_when: "item.0.vars_plugin_checksum not in  item.1.stat.checksum"

I will try to elaborate a little bit, I don't know whats the exactly outcome you want but maybe explaining my point can help you on your way to make it.

First of all the loop, we need to loop 2 lists at the same time, the var_plugin_files that have the actual checksum var and the file_stat.results that have the actual CHECKSUM of the remote files. Then I will force the failure with the fail_when, so it will evaluate the value of the checksum var on the local file, vs the checksum of the remote file.

Multiple loop doc

Related