0

First I used the shell module to send a command that will count the number of files in each path and register the output into a variable.

- name: Count files in backups
  shell:
    cmd: ls | wc -l
    chdir: '{{ item }}'
  with_items:
    - '/home/backups/{{ domain_name }}/fullWP'
    - '/home/backups/{{ domain_name }}/coreWP'
    - '/home/backups/{{ domain_name }}/mysql'
    - '/home/backups/{{ domain_name }}/archive'
    - '/home/backups/{{ domain_name }}/config'
  register: number_files
  tags: clear.files

The following task is supposed to run a command to each file path that counted more than 10 files in the directory.

- name: Delete the oldest backups
  shell:
    cmd: ls -t | tail -n +11 | xargs rm
    chdir: '{{ item }}'
  with_items:
    - '/home/backups/{{ domain_name }}/fullWP'
    - '/home/backups/{{ domain_name }}/coreWP'
    - '/home/backups/{{ domain_name }}/mysql'
    - '/home/backups/{{ domain_name }}/archive'
    - '/home/backups/{{ domain_name }}/config'
  when: number_files.stdout > 10 == true
  tags: clear.oldFiles

My error tells me that I have an undefined variable but am unsure how to fix this.

"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'value'\n\
Gee_k
  • 71
  • 2
  • 12

1 Answers1

0

For example, see the playbook below.

  • Use find module to create a list of the files result.files.

  • In the next task create list files_rm of the files to be removed. Sort the list by mtime (atime and ctime are also available), map the attribute path and select all items in the list but first backup_keep (10).

  • For security reason, the removal of the files is disabled by default.

shell> cat pb.yml
- hosts: localhost
  vars:
    backup_dir: backups
    backup_keep: 10
    dry_run: true
  tasks:
    - find:
        path: "{{ backup_dir }}"
      register: result
    - set_fact:
        files_rm: "{{ (result.files|
                      sort(attribute='mtime', reverse=true)|
                      map(attribute='path')|
                      list)[backup_keep:] }}"
    - debug:
        var: files_rm
    - file:
        state: absent
        path: "{{ item }}"
      loop: "{{ files_rm }}"
      when: not dry_run|bool

Example

Let's create 5 files in the directory backups

shell> for i in {1..5}; do touch backups/backup-$i; done
shell> tree backups/
backups/
├── backup-1
├── backup-2
├── backup-3
├── backup-4
└── backup-5

0 directories, 5 files

For testing, let's set backup_keep: 3 to keep the last 3 backup files. The playbook gives (abridged)

shell> ansible-playbook pb.yml

TASK [debug] ****
ok: [localhost] => 
  files_rm:
  - backups/backup-2
  - backups/backup-1

TASK [file] ****
skipping: [localhost] => (item=backups/backup-2) 
skipping: [localhost] => (item=backups/backup-1)

This is what we want. Obsolete 2 backup files will be removed. Let's remove the files. The playbook gives (abridged)

shell> ansible-playbook pb.yml -e "dry_run=False"

TASK [debug] ****
ok: [localhost] => 
  files_rm:
  - backups/backup-2
  - backups/backup-1

TASK [file] ****
changed: [localhost] => (item=backups/backup-2)
changed: [localhost] => (item=backups/backup-1)
shell> tree backups/
backups/
├── backup-3
├── backup-4
└── backup-5

0 directories, 3 files

The playbook is idempotent

shell> ansible-playbook pb.yml -e "dry_run=False"

ok: [localhost] => 
  files_rm: []
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
  • My debug is telling me that the variable 'file_rm' is undefined. set_fact does not seem to be working. – Gee_k Jun 25 '20 at 01:41
  • Hi thank you for your reply. I still do not understand why 'set_fact' is not registering the variable. Otherwise it looks like this would work, I think I may just use the script module instead to run a shell script on the remote machine with will achieve what I am trying to do. – Gee_k Jun 26 '20 at 19:38
  • @Wannabe Geek, pipes in ansible command module don't work, you need to go with shell module for using pipes. Check out the answer at this [link](https://stackoverflow.com/questions/24679591/ansible-command-module-says-that-is-illegal-character) – Zarak1 Jun 27 '20 at 06:44