From 0698339964e9289e9347834c91de25eb3ff8f963 Mon Sep 17 00:00:00 2001 From: Colin Wilk Date: Tue, 23 Jun 2026 13:21:35 +0200 Subject: test: add tests for systemd exist success status --- defaults/main.yml | 20 +++++++++------- molecule/default/converge.yml | 28 +++++++++++++++------- molecule/default/molecule.yml | 17 +++++++++++-- .../tests/test_systemd_success_exit_status.py | 12 ++++++++++ 4 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 molecule/default/tests/test_systemd_success_exit_status.py diff --git a/defaults/main.yml b/defaults/main.yml index c594c21..337ca76 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -27,14 +27,13 @@ # borg client under this host. # This defaults to the borg_server_host which will work as long as the inventory # hostnames are globally reachable. -borg_server_host_url: '{{ borg_server_host }}' +borg_server_host_url: "{{ borg_server_host }}" # The home directory of the borg user that is created on the borg server. # All borg borg client repositories will be saved in this directory on the borg # server. e.g. /opt/borg/client1 /opt/borg/client2 borg_server_user_home: /opt/borg - ################################################################################ # Borg Repository Configuration # See: https://borgbackup.readthedocs.io/en/stable/usage/serve.html @@ -45,7 +44,7 @@ borg_server_user_home: /opt/borg # This setting is mostly relevant if you use multiple repositories per # borg-client in which case you have to set a custom repo names / formats to # avoid clashes. -borg_repo_name: '{{ inventory_hostname }}' +borg_repo_name: "{{ inventory_hostname }}" # Should the repo be append only? (--append-only) # This will deny any request to delete data from the backup repository coming @@ -56,7 +55,6 @@ borg_repo_name: '{{ inventory_hostname }}' # See https://borgbackup.readthedocs.io/en/stable/usage/notes.html#append-only-mode-forbid-compaction borg_mode_append_only: false - ################################################################################ # Borg Backup Configuration # See: https://borgbackup.readthedocs.io/en/stable/usage/create.html @@ -69,7 +67,7 @@ borg_mode_append_only: false # Most of the time the default option is fine. # For more information about the borg placeholder see # https://borgbackup.readthedocs.io/en/stable/usage/help.html#borg-help-placeholders -borg_backup_name_format: '{hostname}-{now:%Y-%m-%dT%H:%M:%S}' +borg_backup_name_format: "{hostname}-{now:%Y-%m-%dT%H:%M:%S}" # Borg has a few compression modes to those from: # none, lz4, zstd[,L], zlib[,L], lzma[,L], auto,C[,L], obfuscate,SPEC,C[,L]. @@ -95,7 +93,7 @@ borg_excluded_dirs: [] # The passphrase will be stored in plaintext inside the backup script. # For more information about the borg passphrase see # https://borgbackup.readthedocs.io/en/stable/quickstart.html#passphrase-notes -borg_passphrase: '' +borg_passphrase: "" # Since borg encrypts the backups on the borg-server you should save the # encryption keys somewhere to another machine to be able to recover the backup @@ -107,7 +105,7 @@ borg_passphrase: '' # If wish to encrypt the decryption keys, you look into third party tools for # that such as ansible-vault, git-crypt or a completely separate secrets # management system. -borg_decryption_keys_yaml_path: '{{ inventory_dir }}/decryption_keys.yml' +borg_decryption_keys_yaml_path: "{{ inventory_dir }}/decryption_keys.yml" # The role creates a script for backing up with the configured parameters that # the regular systemd service then executes. This specifies the default location @@ -120,6 +118,10 @@ borg_decryption_keys_yaml_path: '{{ inventory_dir }}/decryption_keys.yml' # See: `borg_backup_argument` variable. borg_backup_script_location: /usr/local/bin/run_borg_backup +################################################################################ +# Borg Backup SystemD configuration +################################################################################ + # Name of the systemd timer that is created for the borg service. # The borg backup argument is appended to the timer name, meaning the timer will # be called {{ borg_backup_timer_name }}@{{ borg_backup_argument }} @@ -153,12 +155,12 @@ borg_backup_service_successful_exit_status: [] # meaning it should be unique per target. # By default, we use borg_server_host_url, which is fine as long as you don't # need multiple backup repositories from the same client on the same server. -borg_backup_argument: '{{ borg_server_host_url }}' +borg_backup_argument: "{{ borg_server_host_url }}" # Configures the systemd timer for how regularly to run the backup. By default, # the backup will run every night attacker 2AM. For more information on how to # configure this, see: systemd.timer(5) -borg_systemd_oncalendar: '*-*-* 02:00:00' +borg_systemd_oncalendar: "*-*-* 02:00:00" # Specify the accuracy the timer shall elapse with. By default, we use 60min # to distribute the load on the backup server. For more information on how to diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 7212eb2..995ccd0 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -1,11 +1,14 @@ --- - name: Converge - hosts: borg-client + hosts: + - borg-client + - borg-client-success-exit-status + serial: 1 pre_tasks: - # This would usually be set by the user globally on their ansible - # repository and can be a security risk to do automatically. We will - # however set the variable here in the pre_tasks since it is for testing. + # This would usually be set by the user globally on their ansible + # repository and can be a security risk to do automatically. We will + # however set the variable here in the pre_tasks since it is for testing. - name: Set borg server openssh key variable become: true block: @@ -14,7 +17,7 @@ name: sshd state: started become: true - delegate_to: '{{ borg_server_host }}' + delegate_to: "{{ borg_server_host }}" - name: Fetch ssh_key ansible.builtin.command: > @@ -27,14 +30,21 @@ - name: Set ssh_key ansible.builtin.set_fact: borg_server_host_ssh_key: '{{ borg_server_ssh_keyscan.stdout - | split(" ") - | reject("search", borg_server_host) - | join(" ") }}' + | split(" ") + | reject("search", borg_server_host) + | join(" ") }}' + + - name: Allow additional successful exit codes on alternate client + ansible.builtin.set_fact: + borg_backup_service_successful_exit_status: + - 1 + - TEMPFAIL + when: inventory_hostname == 'borg-client-success-exit-status' vars: borg_server_host: borg-server borg_server_user_home: /opt/borg - borg_decryption_keys_yaml_path: '{{ playbook_dir }}/decryption_keys.yml' + borg_decryption_keys_yaml_path: "{{ playbook_dir }}/decryption_keys.yml" borg_included_dirs: - /etc - /home diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index fc7a266..a64575b 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -10,7 +10,20 @@ driver: platforms: - name: borg-client - image: ${MOLECULE_DISTRO_CLIENT:-debian:10} + image: ${MOLECULE_DISTRO_CLIENT:-debian:12} + dockerfile: Dockerfile.j2 + pre_build_image: false + privileged: true + docker_networks: + - name: molecule-container-net + driver_options: + # Setting the mtu size due to issues with docker and VPN + com.docker.network.driver.mtu: 1420 + networks: + - name: molecule-container-net + + - name: borg-client-success-exit-status + image: ${MOLECULE_DISTRO_CLIENT:-debian:12} dockerfile: Dockerfile.j2 pre_build_image: false privileged: true @@ -23,7 +36,7 @@ platforms: - name: molecule-container-net - name: borg-server - image: ${MOLECULE_DISTRO_SERVER:-debian:10} + image: ${MOLECULE_DISTRO_SERVER:-debian:12} dockerfile: Dockerfile.j2 pre_build_image: false privileged: true diff --git a/molecule/default/tests/test_systemd_success_exit_status.py b/molecule/default/tests/test_systemd_success_exit_status.py new file mode 100644 index 0000000..8f2e242 --- /dev/null +++ b/molecule/default/tests/test_systemd_success_exit_status.py @@ -0,0 +1,12 @@ +testinfra_hosts = ["borg-client", "borg-client-success-exit-status"] + + +def test_systemd_service_success_exit_status(host): + service = host.file("/etc/systemd/system/borg_backup@borg-server.service") + + assert service.exists + + if host.backend.get_hostname() == "borg-client-success-exit-status": + assert service.contains(r"^SuccessExitStatus=1 TEMPFAIL$") + else: + assert not service.contains(r"^SuccessExitStatus=") -- cgit v1.2.3