4
0
forked from jakub/ansible

feat: refactor MikroTik backup playbook for improved structure and functionality

This commit is contained in:
martin.fencl
2026-07-29 15:18:36 +02:00
parent 8910bb1040
commit 04996b47f8
2 changed files with 149 additions and 127 deletions
-127
View File
@@ -1,127 +0,0 @@
# mikrotikbackup.yml
- name: Backup MikroTik configuration
hosts: mikrotiks
gather_facts: false
vars:
# This path is located on the Semaphore runner
backup_dir: /opt/mikrotik_backups
tasks:
- name: Ensure local backup directory exists
ansible.builtin.file:
path: "{{ backup_dir }}"
state: directory
mode: "0700"
delegate_to: localhost
run_once: true
- name: Generate backup timestamp
ansible.builtin.command:
argv:
- date
- --utc
- "+%Y-%m-%d_%H-%M-%S"
register: backup_timestamp
changed_when: false
delegate_to: localhost
- name: Get router identity
community.routeros.command:
commands:
- /system identity print
register: identity_result
changed_when: false
- name: Extract router identity line
ansible.builtin.set_fact:
router_identity_line: >-
{{
(
identity_result.stdout_lines[0]
| select('match', '^\s*name\s*:')
| list
| first
)
| default('', true)
}}
- name: Validate router identity output
ansible.builtin.assert:
that:
- router_identity_line | length > 0
fail_msg: >-
Could not parse RouterOS identity on
{{ inventory_hostname }}.
quiet: true
- name: Build safe router name
ansible.builtin.set_fact:
router_name: >-
{{
router_identity_line
| regex_replace('^\s*name\s*:\s*', '')
| trim
| regex_replace('[^A-Za-z0-9._-]+', '_')
| regex_replace('^_+|_+$', '')
}}
- name: Validate safe router name
ansible.builtin.assert:
that:
- router_name | length > 0
fail_msg: >-
Router identity on {{ inventory_hostname }}
cannot be converted to a safe filename.
quiet: true
- name: Set local backup filename
ansible.builtin.set_fact:
backup_file: >-
{{
backup_dir
~ '/'
~ router_name
~ '-'
~ backup_timestamp.stdout
~ '.rsc'
}}
- name: Export RouterOS configuration
community.routeros.command:
commands:
- /export terse show-sensitive
register: export_result
changed_when: false
no_log: true
- name: Validate exported configuration
ansible.builtin.assert:
that:
- export_result.stdout is defined
- export_result.stdout | length > 0
- export_result.stdout[0] | default('') | trim | length > 0
fail_msg: >-
RouterOS returned an empty configuration export
for {{ inventory_hostname }}.
quiet: true
no_log: true
- name: Save RouterOS configuration locally
ansible.builtin.copy:
content: "{{ export_result.stdout[0] | trim }}\n"
dest: "{{ backup_file }}"
mode: "0600"
delegate_to: localhost
no_log: true
diff: false
- name: Show backup result
ansible.builtin.debug:
msg: >-
MikroTik backup completed:
host={{ inventory_hostname }}
identity={{ router_name }}
file={{ backup_file }}
+149
View File
@@ -0,0 +1,149 @@
# mikrotikbackup_clean.yml
- name: Backup and/or Upgrade MikroTik
hosts: mikrotik_routers
gather_facts: no
vars:
backup_dir: /opt/mikrotik_backups/
tasks:
# ----------------------------
# Always: identity + timestamp
# ----------------------------
- name: Get router identity
community.routeros.command:
commands: /system identity print
register: identity_raw
tags: always
- name: Parse router name
set_fact:
router_name: "{{ identity_raw.stdout[0].split(': ')[1] | trim }}"
tags: always
- name: Get timestamp
ansible.builtin.command: date +%Y-%m-%d_%H-%M-%S
register: date_out
delegate_to: localhost
tags: always
- name: Set timestamp fact
set_fact:
ts: "{{ date_out.stdout }}"
tags: always
# ----------------------------
# Backup (tag: backup)
# ----------------------------
- name: Ensure local backup directory exists
ansible.builtin.file:
path: "{{ backup_dir }}"
state: directory
mode: "0755"
delegate_to: localhost
tags: [backup, never]
- name: Export router config
community.routeros.command:
commands: /export terse show-sensitive
register: export_cfg
tags: [backup, never]
- name: Save export locally
ansible.builtin.copy:
content: "{{ export_cfg.stdout[0] }}"
dest: "{{ backup_dir }}/{{ router_name }}-{{ ts }}.rsc"
delegate_to: localhost
tags: [backup, never]
# ----------------------------
# Upgrade (tag: upgrade)
# ----------------------------
- name: Check current and latest available package versions
community.routeros.command:
commands: /system package update check-for-updates
register: update_check
tags: [upgrade, never]
- name: Normalize update output
set_fact:
_update_text: "{{ update_check.stdout[0] | replace('\r', '') }}"
tags: [upgrade, never]
# ⬇️ Add this to see exactly what RouterOS returns before parsing
- name: Debug raw update output
ansible.builtin.debug:
msg: "{{ _update_text }}"
tags: [upgrade, never]
- name: Parse installed and latest versions
set_fact:
installed_version: >-
{{
(_update_text | regex_findall('(?:installed|current)-version:[ ]*([0-9A-Za-z.]+)'))[0]
if (_update_text | regex_findall('(?:installed|current)-version:[ ]*([0-9A-Za-z.]+)'))
else 'unknown'
}}
latest_version: >-
{{
(_update_text | regex_findall('(?:latest|newest)-version:[ ]*([0-9A-Za-z.]+)'))[0]
if (_update_text | regex_findall('(?:latest|newest)-version:[ ]*([0-9A-Za-z.]+)'))
else 'unknown'
}}
tags: [upgrade, never]
- name: Fail if versions could not be parsed
ansible.builtin.fail:
msg: >
Could not parse versions from update output.
Raw text was: {{ _update_text }}
when: installed_version == 'unknown' or latest_version == 'unknown'
tags: [upgrade, never]
- name: Debug parsed versions
ansible.builtin.debug:
msg:
- "Installed: {{ installed_version }}"
- "Latest: {{ latest_version }}"
tags: [upgrade, never]
- name: Skip upgrade if already on latest
ansible.builtin.debug:
msg: "Router {{ router_name }} is already on latest version {{ installed_version }}. Skipping upgrade."
when: installed_version == latest_version
tags: [upgrade, never]
- name: Trigger package download and install
community.routeros.command:
commands: /system package update install
register: upgrade_result
when: installed_version != latest_version
tags: [upgrade, never]
- name: Wait for router to come back online after reboot
community.routeros.command:
commands: /system resource print
register: reboot_wait
until: reboot_wait is not failed
retries: 30
delay: 15
when:
- installed_version != latest_version
- upgrade_result is not failed
tags: [upgrade, never]
- name: Confirm upgraded version
community.routeros.command:
commands: /system resource print
register: post_upgrade_info
when: installed_version != latest_version
tags: [upgrade, never]
- name: Show post-upgrade RouterOS version
ansible.builtin.debug:
msg: "{{ post_upgrade_info.stdout[0] | regex_search('version: .+') }}"
when: installed_version != latest_version
tags: [upgrade, never]