Ansible fetch does not overwrite target

I have created a task to do a backup of my Mikrotik switches every morning, and copy the backup file to a shared folder on my Ansible server (Debian 12).

Ansible are installed from apt:
ansible: 7.7.0+dfsg-3+deb12u1
ansible-core: 2.14.18-0+deb12u2

My playbook:

- name: Backup all RouterOS switches
  hosts: routeros
  gather_facts: no
  remote_user: ansible

  tasks:

  - name: Run backup and check to see if output says its saved
    community.routeros.command:
      commands: /system/backup/save dont-encrypt=yes name=/auto
      retries: 1
      wait_for: result[0] contains Configuration backup saved

  - name: Retrieve the backup file from RouterOS
    ansible.builtin.fetch:
      src: auto.backup
      dest: /mnt/backup/routeros/{{ inventory_hostname }}.backup
      flat: true

The backup file are created successfully on the Mikrotik device.
But if the file already exists in the backup dir on the Ansible server, it is not replaced.
The fetch job works 100% if I delete the target files before I run the playbook.
There is no overwrite option in the fetch module, so is there another module I could try?

I do not want to delete the backup file before I know that it will be replaced.
As a developer I could fix this with a few lines in a bash script, but I would like for it to work in a playbook.

@bobbysock Welcome to the Ansible Forum.

What you are doing looks correct, I wonder if there is a bug with fetch on systems that might be able to generate the checksum

Can you run with ansible-playbook -vvv and reply with the verbose output for the Retrieve the backup file from RouterOS step.

Or you could try using ansible.netcommon.net_get module

Based on the description of fetch I’d expect this to work.

The version of ansible-core you’re running is past its EOL date, and likely doesn’t have up-to-date versions of the modules.

I’d suggest (at least in a virtual environment) installing an up-to-date version following the Installing Ansible with pip (or Installing Ansbile with pipx if you prefer) guide and see if the issue persist.

1 Like

@Lyle_McKarns Good spot, I totally missed the very old versions.

@bobbysock In case you need them, here are the porting guides:

1 Like

I’m trying to install PIP (which I do not like), and will see if I can upgrade the module to something that works.
As a 60 year old programmer based on Pascal, C+ and other common languages, I will say I do hate containers. And by hate, I mean HATE! ā€œapt purge docker*ā€
So I hope there is some way for me to use this without those technologies.
I can live with pip, it’s not that bad, just.. well.. bad.

What did pip ever do to you?

i suspect it is not just pip, but ā€˜language based package managers’ … some of us prefer the system package managers when it comes to host installations, for many reasons, specially if we are/were sysadmins.

2 Likes

Maybe. Things can get complicated when you need something that isn’t packaged up by the OS’s package manager though. Alas, not everything can be as elegant as ā€œC+ā€.

As @Lyle_McKarns suggested above, pipx is nicer than pip for installing Ansible.

ansible -m flame_war -a 'state=started msg=And there is also uv' all

3 Likes

I gave up on pip. I managed to get a newer version of Ansible installed on my Ubuntu server with pipx, but I still get warnings like ā€œansible-pylibssh not installed, falling back to paramikoā€.

I solved it with a shell script instead, after spending hours trying to get either pylibssh or paramiko to work.
As a developer, this is frustrating, and easily solved with creating my own scripts.
I just hoped I could find a package that just worked, kind of like set and forget.

I have a deja-vu feeling from the last time I tried a pip thing on ubuntu years ago, with kind of the same result.

But thank you all for good tips and comments!
This looks like a good and healthy community. I may be back, but no promises :slight_smile:

EDIT:
It looks like I’m back for the moment.
Found a way to run my script in ansible as a local command:

 - name: Run backup on the specified host
    local_action: ansible.builtin.command /usr/local/sbin/backup-routeros.sh {{ inventory_hostname }}

And for those that are interested, here is my local script:

#!/bin/bash

HOSTNAME=$1

res=$(ssh ansible@$HOSTNAME -i ~/.ssh/id_ansible "/system/backup/save dont-encrypt=yes name=/auto")

#Truncating result because it has a CR at the end
s=${res:0:26}

if [ "$s" == "Configuration backup saved" ]; then
  scp -i ~/.ssh/id_ansible ansible@$HOSTNAME:/auto.backup /mnt/backup/routeros/$HOSTNAME.backup
else
  echo "Error creating backup on host $HOSTNAME"
fi
1 Like

On Ubuntu:

sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

Docs

1 Like