Updated to work around symlink issues
This commit is contained in:
@@ -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
|
||||||
Reference in New Issue
Block a user