"""Tests for systemd service and timer configuration""" import pytest testinfra_hosts = ['borg-client', 'borg-client-2', 'borg-client-multi', 'borg-client-nonroot', 'borg-client-multi-keys'] CLIENT_CONFIGS = { 'borg-client': { 'user': 'root', 'server': 'borg-server', 'schedule': '*-*-* 02:00:00', 'success_exit_status': False, }, 'borg-client-2': { 'user': 'root', 'server': 'borg-server-2', 'schedule': '*-*-* 03:00:00', 'success_exit_status': True, }, 'borg-client-nonroot': { 'user': 'backupuser', 'server': 'borg-server', 'schedule': '*-*-* 02:00:00', 'success_exit_status': False, }, } MULTI_INSTANCE_CONFIGS = { 'borg-client-multi': { 'user': 'root', 'repos': ['configs', 'home-data'], 'schedules': { 'configs': '*-*-* 02:00:00', 'home-data': '*-*-* 04:00:00', }, }, 'borg-client-multi-keys': { 'user': 'root', 'repos': ['configs-keys', 'home-data-keys'], 'schedules': { 'configs-keys': '*-*-* 02:00:00', 'home-data-keys': '*-*-* 04:00:00', }, }, } @pytest.fixture def config(host): hostname = host.backend.hostname if hostname in CLIENT_CONFIGS: return {'type': 'single', **CLIENT_CONFIGS[hostname]} return {'type': 'multi', **MULTI_INSTANCE_CONFIGS[hostname]} class TestSystemdServiceFile: def test_service_file_exists(self, host, config): if config['type'] == 'single': service = host.file(f"/etc/systemd/system/borg_backup@{config['server']}.service") assert service.exists assert service.user == 'root' assert service.group == 'root' assert service.mode == 0o644 else: for repo in config['repos']: service = host.file(f"/etc/systemd/system/borg_backup@{repo}.service") assert service.exists assert service.user == 'root' assert service.group == 'root' def test_service_content(self, host, config): if config['type'] == 'single': service = host.file(f"/etc/systemd/system/borg_backup@{config['server']}.service") assert service.contains('[Unit]') assert service.contains('[Service]') assert service.contains('[Install]') assert service.contains('Type=oneshot') assert service.contains('ExecStart=/usr/local/bin/run_borg_backup') else: for repo in config['repos']: service = host.file(f"/etc/systemd/system/borg_backup@{repo}.service") assert service.contains('[Unit]') assert service.contains('[Service]') assert service.contains('[Install]') assert service.contains('Type=oneshot') def test_service_user(self, host, config): if config['type'] == 'single': service = host.file(f"/etc/systemd/system/borg_backup@{config['server']}.service") assert service.contains(f"User={config['user']}") assert service.contains(f"Group={config['user']}") else: for repo in config['repos']: service = host.file(f"/etc/systemd/system/borg_backup@{repo}.service") assert service.contains(f"User={config['user']}") assert service.contains(f"Group={config['user']}") def test_success_exit_status(self, host, config): if config['type'] != 'single': return service = host.file(f"/etc/systemd/system/borg_backup@{config['server']}.service") assert service.exists if config['success_exit_status']: assert service.contains('SuccessExitStatus=1 TEMPFAIL') else: assert not service.contains('SuccessExitStatus=') class TestSystemdTimerFile: def test_timer_file_exists(self, host, config): if config['type'] == 'single': timer = host.file(f"/etc/systemd/system/borg_backup@{config['server']}.timer") assert timer.exists assert timer.user == 'root' assert timer.group == 'root' assert timer.mode == 0o644 else: for repo in config['repos']: timer = host.file(f"/etc/systemd/system/borg_backup@{repo}.timer") assert timer.exists def test_timer_content(self, host, config): if config['type'] == 'single': timer = host.file(f"/etc/systemd/system/borg_backup@{config['server']}.timer") assert timer.contains('[Unit]') assert timer.contains('[Timer]') assert timer.contains('[Install]') assert timer.contains('OnCalendar=') assert timer.contains('AccuracySec=') else: for repo in config['repos']: timer = host.file(f"/etc/systemd/system/borg_backup@{repo}.timer") assert timer.contains('[Unit]') assert timer.contains('[Timer]') assert timer.contains('[Install]') assert timer.contains('OnCalendar=') assert timer.contains('AccuracySec=') def test_timer_schedule(self, host, config): if config['type'] == 'single': timer = host.file(f"/etc/systemd/system/borg_backup@{config['server']}.timer") assert f"OnCalendar={config['schedule']}" in timer.content_string else: for repo in config['repos']: timer = host.file(f"/etc/systemd/system/borg_backup@{repo}.timer") assert f"OnCalendar={config['schedules'][repo]}" in timer.content_string class TestSystemdState: def test_timer_enabled(self, host, config): if config['type'] == 'single': timer_name = f"borg_backup@{config['server']}.timer" c = host.run(f"systemctl is-enabled {timer_name}") assert c.rc == 0 assert c.stdout.strip() == 'enabled' else: for repo in config['repos']: c = host.run(f"systemctl is-enabled borg_backup@{repo}.timer") assert c.rc == 0 assert c.stdout.strip() == 'enabled' def test_timer_active(self, host, config): if config['type'] == 'single': timer_name = f"borg_backup@{config['server']}.timer" c = host.run(f"systemctl is-active {timer_name}") assert c.rc == 0 else: for repo in config['repos']: c = host.run(f"systemctl is-active borg_backup@{repo}.timer") assert c.rc == 0 def test_daemon_reload_ok(self, host, config): c = host.run('systemctl daemon-reload') assert c.rc == 0