Home > OS >  Ansible: loop trough list of files of different users, sort by date, delete oldest x ones of each us
Ansible: loop trough list of files of different users, sort by date, delete oldest x ones of each us

Time:09-14

I am struggling with this issue since several days and would appreciate your help. I would like to check if the crontab file for several users exist on a host. If so, a backup shall be done and the oldest x backups shall be removed.

To achieve this I first check if the crontab exists:

- name: check if crontab exists
  ansible.builtin.stat:
    path: "/var/spool/cron/tabs/{{ item }}"
  loop: "{{ users }}"
  register: crontabFile

Then I perform a backup of the file:

- name: backup old crontab
  ansible.builtin.copy:
    src: "{{ item.stat.path }}"
    dest: "{{ item.stat.path }}_{{ ansible_date_time.iso8601_basic_short }}"
    mode: "preserve"
    remote_src: true
  loop: "{{ crontabFile.results }}"
  when: item.stat.exists

This works fine so far. Afterwards I check for existing backups:

- name: find backups of crontab
  ansible.builtin.find:
    paths: "{{ item.stat.path | dirname }}"
    patterns: "{{ item.stat.path | basename }}_*"
  loop: "{{ crontabFile.results }}"
  register: crontabBackup
  when: item.stat.exists

The next step would be to loop over the results of crontabBackup and remove the oldest x files of the backups for each user individually. The following does not work:

- name: delete oldest backups of crontab, keep last 5
  ansible.builtin.file:
    path: "{{ item }}"
    state: absent
  loop: "{{ (crontabBackup.results|selectattr('files', 'defined')|map(attribute='files')|flatten|sort(attribute='mtime')|map(attribute='path')|list)[:-5] }}"

What happens is, that a flat list of all files is generated and the oldest files of this list get removed. What I want is to sort the list per user and remove the files per user.

CodePudding user response:

After trying many different approaches, I think I've figured it out for myself. I will share my solution in case anyone is facing the same issue.

The solution is to use an outer loop that includes the inner loop via include_tasks as mentioned here.

# main.yml
- include_tasks: delete_backups_inner_loop.yml
  loop: "{{ crontabBackup.results|selectattr('files', 'defined')|map(attribute='files') }}"
  loop_control:
    loop_var: userLoop

# delete_backups_inner_loop.yml
- name: delete oldest backups of crontab, keep last 5
  ansible.builtin.file:
    path: "{{ item.path }}"
    state: absent
  loop: "{{ (userLoop|sort(attribute='mtime'))[:-5] }}"
  • Related