Smily
Smily

Reputation: 2568

Ansible file check for multiple servers and files

I have a playbook which has three tasks that checks if a file exists, check the date modified is same and the checksum is same. It works fine for a server with one filename, its date and its checksum

Vars are serverA, file_name, time, chks1

But I have many servers and different files. How can I achieve this?

serverA,file1, dat1, chks1
serverA, file2, dat2, chks2
serverB, file3, dat3, chks3 etc…

Part of playbook:

---
- name: Check if file exists
  win_stat:
   path: "{{file_name}}"
  register: file

- name: Status 
  assert:
   that: file.stat.exists
   fail_msg: "Check failed"
   success_msg: "Check PASSED"
- name: Status modification
  assert:
   that: file.stat.lastwritetime|int  == time|int
   fail_msg: "Check failed"
   success_msg: "Check PASSED"

Upvotes: 0

Views: 1647

Answers (2)

Zeitounator
Zeitounator

Reputation: 44595

Solution 1: declare files in your inventory

If this is somewhat static, you can put this info in your inventory variables. Easiest way is in a host_vars/<inventory_hostname>.yml files for each host:

check_files:
  - name: file1
    time: date1
    checksum: chcks1
  - name: file2
    time: date2
    checksum: chks2

Just create a file for each server in your inventory with the corresponding declaration.

Then your tasks would simply look like this (adapted from your examples, not tested).

- name: Check if file exists
  win_stat:
    path: "{{ item.name }}"
  register: files
  loop: "{{ check_files }}"

- name: Status 
  assert:
    that: item.stat.exists
    fail_msg: "Check failed"
    success_msg: "Check PASSED"
  loop: "{{ files.results }}"

- name: Status modification
  assert:
    that: item.stat.lastwritetime | int  == item.item.time | int
    fail_msg: "Check failed"
    success_msg: "Check PASSED"
  loop: "{{ files.results }}"

Solution 2: declaration outside of inventory.

If your really want/need to keep those file declarations outside of your inventory and declare them at playbook/play level, you could create a data structure that still references the inventory name of the server, something like:

check_files:
  host1:
    - name: file1
      time: date1
      checksum: chks1
    - name: file2
      time: date2
      checksum: chks2
  host2:
    - name: filex
      time: timex
      checksum: chks

In this case, the previous example still works. You just have slightly change the loop element in the first task:

- name: Check if file exists
  win_stat:
    path: "{{ item.name }}"
  register: files
  loop: "{{ check_files[inventory_hostname] }}"

Notes

  • I kept the checksum in your data structure because you mentioned it, although it is not used at the moment in any of your sample tasks. You can use it the same way as time in the above examples.
  • The notation item.item.time is not a typing mistake. The loop is over results of the previous win_stat module run. So item references one of the currently looped results, while item.item references the item that was actually used when running that task (i.e. an actual file in your variables declaration)

Upvotes: 2

George Shuklin
George Shuklin

Reputation: 7867

The simplest answer would be do a code duplication and write this check as many times as you need. If you want to be a smart cookie and try to DRY, you may want to start to use host_vars (to keep there differences between servers), or, if you need this for few files for one server, to use import_tasks module with different values for 'vars' section for the task.

Upvotes: 0

Related Questions