'restore backup file created with Copy

If a backup file is created using Copy (with backup=yes), for example, with this task:

 - name: copy file
      copy: 
        dest: path/to/dest
        src: path/to/src
        backup: yes

If the file path/to/dest already exists, it will be moved in a file looking like path/to/dest.12345.2006-07-08@09:10:11

Is there a way to restore it, or to get the filename of the backup file in order to restore it ?



Solution 1:[1]

The absolute file name of the backup file (if generated, so if "changed" is true), is returned in the output object backup_file, so (take the following as pseudocode as I am not testing it):

- name: copy file
  copy: 
     dest: path/to/dest
     src: path/to/src
     backup: yes
  register: copy_file

- debug: var=copy_file.backup_file

- name: restore backup
  copy:
     dest: path/to/dest
     src: copy_file.backup_file
     remote_src: true
  when: copy_file.changed and some condition of yours

See: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html#return-backup_file

Solution 2:[2]

@guido has demonstrated in his answer how to use the backup_file attribute returned by the copy module. As pointed out in my different comments, this is really handy if:

  • you want to restore the file during the same run of ansible
  • you store the value somewhere when copying (e.g. a var in memory cache, a db entry, a file on disk...) in one run and retrieve it in a later run to perform your restore action.

Here is an other solution you can use if you don't have that info or you don't want to manage that. For clarity sake, I took the case where you want to restore the latest backup file available on disk. You can perfectly adapt that to meet any other specific requirement.

The basic workflow:

  • list all the backup files available on the target disk.
  • choose the most recent one.
  • copy that file back in place.

Note that although my demo playbook targets localhost, it will work with any target provided the file has backup candidates. I'll let you harden this point your own way and according to your own requirements.

Prior to running my playbook, I created a file and copied it several times with a random content creating backups each time. I used the following playbook to do so:

---
- name: Create some file with backup
  hosts: localhost
  gather_facts: false

  vars:
    my_file: /tmp/test_restore/toto.txt

  tasks:
    - name: copy file
      copy:
        dest: "{{ my_file }}"
        content: "{{ 1000 | random }}"
        backup: true

The resulting folder content is as follow:

/tmp/test_restore/
??? toto.txt
??? toto.txt.14644.2020-12-19@10:39:43~
??? toto.txt.14752.2020-12-19@10:39:45~
??? toto.txt.14861.2020-12-19@10:39:48~

Now comes the restore playbook:

---
- name: Restore latest file backup
  hosts: localhost
  gather_facts: false

  vars:
    my_file: /tmp/test_restore/toto.txt

  tasks:
    - name: "Find all backups for {{ my_file }}"
      find:
        recurse: no
        paths:
          - "{{ my_file | dirname }}"
        patterns:
          - '{{ my_file | basename }}\..*~'
        use_regex: true
      register: find_backup

    - name: Select the latest backup found on disk
      set_fact:
        latest_backup: "{{ (find_backup.files | sort(attribute='mtime') | last).path }}"

    - name: Show the latest selected backup
      debug:
        var: latest_backup

    - name: "Restore latest backup of {{ my_file }}"
      copy:
        src: "{{ latest_backup }}"
        remote_src: true
        dest: "{{ my_file }}"

Which gives:

PLAY [Restore latest file backup] ******************************************************************************************************************************************************************************************************

TASK [Find all backups for /tmp/test_restore/toto.txt] *********************************************************************************************************************************************************************************
ok: [localhost]

TASK [Select the latest backup found on disk] ******************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Show the latest selected backup] *************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "latest_backup": "/tmp/test_restore/toto.txt.14861.2020-12-19@10:39:48~"
}

TASK [Restore latest backup of /tmp/test_restore/toto.txt] *****************************************************************************************************************************************************************************
changed: [localhost]

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

If you run that playbook a second time, the last task will report ok instead of changed, demonstrating if needed that the file has the same content as the latest backup.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 4wk_
Solution 2