Updated to work around symlink issues

This commit is contained in:
2026-03-13 16:19:28 -07:00
parent 05525e776a
commit 9f929ac5ee

View File

@@ -2,6 +2,12 @@
# ============================================================================= # =============================================================================
# hypervisor_backup_config — main tasks # hypervisor_backup_config — main tasks
# ============================================================================= # =============================================================================
# Strategy:
# - Create a tarball on the remote node (handles symlinks, permissions cleanly)
# - Fetch the tarball to Semaphore host
# - For git: extract into repo path, add/commit/push, clean up
# - For local: leave tarball on the node, rotate old ones
# - For sftp: transfer tarball to remote, clean up temp
- name: Gather date/time facts - name: Gather date/time facts
ansible.builtin.setup: ansible.builtin.setup:
@@ -25,25 +31,49 @@
msg: "hypervisor_type '{{ hypervisor_type }}' is not supported. Use proxmox or xcpng." msg: "hypervisor_type '{{ hypervisor_type }}' is not supported. Use proxmox or xcpng."
when: hypervisor_type not in ['proxmox', 'xcpng'] when: hypervisor_type not in ['proxmox', 'xcpng']
# ── Create tarball on remote node ─────────────────────────────────────────────
# Done once — reused by all destinations
- name: Create config tarball on node
ansible.builtin.shell: |
tar czf /tmp/{{ pve_config_backup_filename }}.tar.gz \
--ignore-failed-read \
--dereference \
{{ pve_config_backup_paths | join(' ') }} 2>/dev/null || true
echo "done"
register: node_tarball
changed_when: true
# ── Git backup ──────────────────────────────────────────────────────────────── # ── Git backup ────────────────────────────────────────────────────────────────
- name: Git backup - name: Git backup
when: "'git' in (pve_config_backup_destinations | map(attribute='type') | list)" when: "'git' in (pve_config_backup_destinations | map(attribute='type') | list)"
block: block:
- name: Git | Ensure git base path exists on Semaphore host - name: Git | Ensure extract path exists on Semaphore host
ansible.builtin.file: ansible.builtin.file:
path: "{{ pve_config_git_repo_dir }}/{{ pve_config_git_base_path }}" path: "{{ pve_config_git_repo_dir }}/{{ pve_config_git_base_path }}"
state: directory state: directory
mode: '0755' mode: '0755'
delegate_to: localhost delegate_to: localhost
- name: Git | Copy config files from node to repo - name: Git | Fetch tarball from node to Semaphore host
ansible.builtin.fetch: ansible.builtin.fetch:
src: "{{ item }}" src: "/tmp/{{ pve_config_backup_filename }}.tar.gz"
dest: "{{ pve_config_git_repo_dir }}/{{ pve_config_git_base_path }}/" dest: "/tmp/{{ pve_config_backup_filename }}.tar.gz"
flat: false flat: true
fail_on_missing: false
loop: "{{ pve_config_backup_paths }}" - name: Git | Extract tarball into repo path
ignore_errors: true ansible.builtin.shell: |
tar xzf /tmp/{{ pve_config_backup_filename }}.tar.gz \
-C {{ pve_config_git_repo_dir }}/{{ pve_config_git_base_path }} \
--strip-components=0 2>/dev/null || true
echo "extracted"
delegate_to: localhost
changed_when: true
- name: Git | Clean up local temp tarball
ansible.builtin.file:
path: "/tmp/{{ pve_config_backup_filename }}.tar.gz"
state: absent
delegate_to: localhost
- name: Git | Check if there are changes to commit - name: Git | Check if there are changes to commit
ansible.builtin.shell: | ansible.builtin.shell: |
@@ -84,20 +114,16 @@
- name: Local backup - name: Local backup
when: "'local' in (pve_config_backup_destinations | map(attribute='type') | list)" when: "'local' in (pve_config_backup_destinations | map(attribute='type') | list)"
block: block:
- name: Local | Ensure backup dir exists - name: Local | Ensure backup dir exists on node
ansible.builtin.file: ansible.builtin.file:
path: "{{ pve_config_local_backup_dir }}" path: "{{ pve_config_local_backup_dir }}"
state: directory state: directory
mode: '0700' mode: '0700'
- name: Local | Create gzipped tarball of config paths - name: Local | Move tarball to backup dir
ansible.builtin.shell: | ansible.builtin.shell: |
tar czf {{ pve_config_local_backup_dir }}/{{ pve_config_backup_filename }}.tar.gz \ cp /tmp/{{ pve_config_backup_filename }}.tar.gz \
--ignore-failed-read \ {{ pve_config_local_backup_dir }}/{{ pve_config_backup_filename }}.tar.gz
{% for path in pve_config_backup_paths %}{{ path }} {% endfor %}
echo "Created: {{ pve_config_backup_filename }}.tar.gz"
register: local_backup_result
changed_when: true changed_when: true
- name: Local | Remove old backups beyond keep limit - name: Local | Remove old backups beyond keep limit
@@ -105,7 +131,6 @@
ls -1t {{ pve_config_local_backup_dir }}/{{ hypervisor_type }}_{{ client_id | lower | replace('-','_') | replace(' ','_') }}_{{ inventory_hostname }}_config_*.tar.gz 2>/dev/null \ ls -1t {{ pve_config_local_backup_dir }}/{{ hypervisor_type }}_{{ client_id | lower | replace('-','_') | replace(' ','_') }}_{{ inventory_hostname }}_config_*.tar.gz 2>/dev/null \
| tail -n +{{ (pve_config_backup_keep | int) + 1 }} \ | tail -n +{{ (pve_config_backup_keep | int) + 1 }} \
| xargs -r rm -f | xargs -r rm -f
echo "Rotation complete"
changed_when: false changed_when: false
- name: Local | Log result - name: Local | Log result
@@ -118,15 +143,14 @@
block: block:
- name: SFTP | Validate required vars are set - name: SFTP | Validate required vars are set
ansible.builtin.fail: ansible.builtin.fail:
msg: "sftp destination requires pve_config_sftp_host, pve_config_sftp_user to be set" msg: "sftp destination requires pve_config_sftp_host and pve_config_sftp_user to be set"
when: pve_config_sftp_host == "" or pve_config_sftp_user == "" when: pve_config_sftp_host == "" or pve_config_sftp_user == ""
- name: SFTP | Create local temp tarball first - name: SFTP | Fetch tarball to Semaphore host first
ansible.builtin.shell: | ansible.builtin.fetch:
tar czf /tmp/{{ pve_config_backup_filename }}.tar.gz \ src: "/tmp/{{ pve_config_backup_filename }}.tar.gz"
--ignore-failed-read \ dest: "/tmp/{{ pve_config_backup_filename }}.tar.gz"
{% for path in pve_config_backup_paths %}{{ path }} {% endfor %} flat: true
changed_when: true
- name: SFTP | Transfer tarball to remote host - name: SFTP | Transfer tarball to remote host
ansible.builtin.shell: | ansible.builtin.shell: |
@@ -138,14 +162,21 @@
cd {{ pve_config_sftp_remote_dir }} cd {{ pve_config_sftp_remote_dir }}
put /tmp/{{ pve_config_backup_filename }}.tar.gz put /tmp/{{ pve_config_backup_filename }}.tar.gz
EOF EOF
delegate_to: localhost
changed_when: true changed_when: true
- name: SFTP | Remove temp tarball - name: SFTP | Clean up local temp tarball
ansible.builtin.file: ansible.builtin.file:
path: "/tmp/{{ pve_config_backup_filename }}.tar.gz" path: "/tmp/{{ pve_config_backup_filename }}.tar.gz"
state: absent state: absent
delegate_to: localhost
- name: SFTP | Log result - name: SFTP | Log result
ansible.builtin.debug: ansible.builtin.debug:
msg: "Config backed up via sftp: {{ pve_config_sftp_host }}:{{ pve_config_sftp_remote_dir }}/{{ pve_config_backup_filename }}.tar.gz" msg: "Config backed up via sftp: {{ pve_config_sftp_host }}:{{ pve_config_sftp_remote_dir }}/{{ pve_config_backup_filename }}.tar.gz"
# ── Clean up temp tarball on node ─────────────────────────────────────────────
- name: Clean up temp tarball on node
ansible.builtin.file:
path: "/tmp/{{ pve_config_backup_filename }}.tar.gz"
state: absent