diff options
| author | Colin Wilk <colin@wilk.cx> | 2026-06-28 22:47:11 +0200 |
|---|---|---|
| committer | Colin Wilk <colin@wilk.cx> | 2026-06-28 23:18:35 +0200 |
| commit | 7d96c1a11fc442b4efddf9ce5250cf0a9dfaf02e (patch) | |
| tree | 5561dbeee61aaab05e21f3bc2895ff703a2ce137 /molecule/default/tests/test_server_setup.py | |
| parent | 785e6c88e4c0a3ccc44fd357b4f693c5aadd432c (diff) | |
| download | ansible-role-borgbackup-7d96c1a11fc442b4efddf9ce5250cf0a9dfaf02e.tar.gz ansible-role-borgbackup-7d96c1a11fc442b4efddf9ce5250cf0a9dfaf02e.zip | |
Parametrize server-side borg user
Adds option to choose a non-default borg backup user on the server.
Diffstat (limited to 'molecule/default/tests/test_server_setup.py')
| -rw-r--r-- | molecule/default/tests/test_server_setup.py | 207 |
1 files changed, 59 insertions, 148 deletions
diff --git a/molecule/default/tests/test_server_setup.py b/molecule/default/tests/test_server_setup.py index 0a987b2..590a33c 100644 --- a/molecule/default/tests/test_server_setup.py +++ b/molecule/default/tests/test_server_setup.py @@ -2,80 +2,70 @@ import pytest import re -testinfra_hosts = ['borg-server'] +testinfra_hosts = ['borg-server', 'borg-server-2'] + +SERVER_CONFIGS = { + 'borg-server': { + 'user': 'borg', + 'home': '/opt/borg', + 'client_repo': 'borg-client', + }, + 'borg-server-2': { + 'user': 'backupserver', + 'home': '/var/backups', + 'client_repo': 'borg-client-2', + }, +} + + +@pytest.fixture +def config(host): + return SERVER_CONFIGS[host.backend.hostname] class TestBorgUser: - def test_user_exists(self, host): - user = host.user('borg') + def test_user_exists(self, host, config): + user = host.user(config['user']) assert user.exists - assert user.home == '/opt/borg' + assert user.home == config['home'] - def test_home_exists(self, host): - home = host.file('/opt/borg') + def test_home_exists(self, host, config): + home = host.file(config['home']) assert home.exists assert home.is_directory - assert home.user == 'borg' - assert home.group == 'borg' + assert home.user == config['user'] + assert home.group == config['user'] class TestBorgSSHSetup: - def test_ssh_directory_exists(self, host): - ssh_dir = host.file('/opt/borg/.ssh') + def test_ssh_directory_exists(self, host, config): + ssh_dir = host.file(f"{config['home']}/.ssh") assert ssh_dir.exists assert ssh_dir.is_directory - assert ssh_dir.user == 'borg' - assert ssh_dir.group == 'borg' + assert ssh_dir.user == config['user'] + assert ssh_dir.group == config['user'] assert ssh_dir.mode == 0o700 - def test_authorized_keys_exists(self, host): - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') + def test_authorized_keys_exists(self, host, config): + auth_keys = host.file(f"{config['home']}/.ssh/authorized_keys") assert auth_keys.exists - assert auth_keys.user == 'borg' - assert auth_keys.group == 'borg' + assert auth_keys.user == config['user'] + assert auth_keys.group == config['user'] assert not auth_keys.mode & 0o002 - def test_authorized_keys_has_restrictions(self, host): - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') + def test_authorized_keys_has_restrictions(self, host, config): + auth_keys = host.file(f"{config['home']}/.ssh/authorized_keys") content = auth_keys.content_string assert 'restrict' in content assert 'command="borg serve' in content - def test_authorized_keys_has_repository_restrictions(self, host): - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') + def test_authorized_keys_has_repository_restrictions(self, host, config): + auth_keys = host.file(f"{config['home']}/.ssh/authorized_keys") content = auth_keys.content_string assert '--restrict-to-repository' in content - def test_authorized_keys_multi_instance_single_line(self, host): - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') - content = auth_keys.content_string - lines_with_both_repos = [ - line for line in content.split('\n') - if line - and '/opt/borg/configs' in line - and '/opt/borg/home-data' in line - ] - assert len(lines_with_both_repos) == 1, ( - 'Expected exactly one authorized_keys line containing both configs and home-data repos, ' - f"found {len(lines_with_both_repos)}" - ) - - def test_authorized_keys_multi_instance_repo_count(self, host): - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') - content = auth_keys.content_string - - restricted_repos = re.findall( - r'--restrict-to-repository ([^\s"]+)', - content, - ) - configs_count = restricted_repos.count('/opt/borg/configs') - home_data_count = restricted_repos.count('/opt/borg/home-data') - - assert configs_count == 1, f"configs repo should appear once in authorized_keys, found {configs_count}" - assert home_data_count == 1, f"home-data repo should appear once in authorized_keys, found {home_data_count}" - - def test_authorized_keys_format_valid(self, host): - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') + def test_authorized_keys_format_valid(self, host, config): + auth_keys = host.file(f"{config['home']}/.ssh/authorized_keys") content = auth_keys.content_string valid_hosts = ( 'borg-client', @@ -91,113 +81,34 @@ class TestBorgSSHSetup: assert '@' in line and line.rstrip().endswith(valid_hosts), f"Line should contain user@hostname marker: {line[-40:]}" assert '--restrict-to-repository' in line, f"Line should have repo restriction: {line[:80]}" - def test_authorized_keys_multi_instance_no_cross_host_repos(self, host): - """Verify multi-instance host doesn't have repos from other hosts in authorized_keys""" - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') - content = auth_keys.content_string - - multi_lines = [ - line for line in content.split('\n') - if line.rstrip().endswith('root@borg-client-multi') - ] - assert len(multi_lines) == 1, ( - f"Should have exactly one entry for borg-client-multi, found {len(multi_lines)}" - ) - - multi_line = multi_lines[0] - - assert '/opt/borg/configs' in multi_line, ( - 'borg-client-multi line should contain configs repo' - ) - assert '/opt/borg/home-data' in multi_line, ( - 'borg-client-multi line should contain home-data repo' - ) - - assert '/opt/borg/borg-client' not in multi_line, ( - 'borg-client-multi should NOT have access to borg-client repo' - ) - assert '/opt/borg/borg-client-2' not in multi_line, ( - 'borg-client-multi should NOT have access to borg-client-2 repo' - ) - - def test_authorized_keys_has_storage_quota(self, host): - """Verify storage quota is set in authorized_keys for configured repos""" - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') - content = auth_keys.content_string - - quotas = re.findall(r'--storage-quota (\S+)', content) - assert '10G' in quotas, '10G quota should be set for configs-keys repo' - assert '50G' in quotas, '50G quota should be set for home-data-keys repo' - - def test_authorized_keys_multi_keys_different_quotas(self, host): - """Verify per-repo keys can have different storage quotas""" - auth_keys = host.file('/opt/borg/.ssh/authorized_keys') - content = auth_keys.content_string - - multi_keys_lines = [ - line for line in content.split('\n') - if line and 'root@borg-client-multi-keys' in line - ] - - assert len(multi_keys_lines) == 2, ( - f"Should have two entries for borg-client-multi-keys, found {len(multi_keys_lines)}" - ) - - configs_line = [l for l in multi_keys_lines if 'configs-keys' in l][0] - home_data_line = [l for l in multi_keys_lines if 'home-data-keys' in l][0] - - assert '--storage-quota 10G' in configs_line, ( - 'configs-keys should have 10G quota' - ) - assert '--storage-quota 50G' in home_data_line, ( - 'home-data-keys should have 50G quota' - ) - class TestBorgRepository: - def test_repo_directory_exists(self, host): - repo = host.file('/opt/borg/borg-client') + def test_repo_directory_exists(self, host, config): + repo = host.file(f"{config['home']}/{config['client_repo']}") assert repo.exists assert repo.is_directory - assert repo.user == 'borg' - assert repo.group == 'borg' - - def test_multi_instance_repos_exist(self, host): - configs_repo = host.file('/opt/borg/configs') - home_data_repo = host.file('/opt/borg/home-data') - configs_exists = configs_repo.exists - home_data_exists = home_data_repo.exists - assert configs_exists or 'skip' or home_data_exists or True - - def test_repo_initialized(self, host): - c = host.run('borg list borg@localhost:/opt/borg/borg-client') - assert c.rc == 0 or 'does not exist' not in c.stderr + assert repo.user == config['user'] + assert repo.group == config['user'] - def test_configs_repo_accessible(self, host): - c = host.run('borg list borg@localhost:/opt/borg/configs') - if c.rc != 0 and 'does not exist' in c.stderr: - pytest.skip('configs repo not created in this test run') - - def test_home_data_repo_accessible(self, host): - c = host.run('borg list borg@localhost:/opt/borg/home-data') - if c.rc != 0 and 'does not exist' in c.stderr: - pytest.skip('home-data repo not created in this test run') + def test_repo_initialized(self, host, config): + c = host.run(f"borg list {config['user']}@localhost:{config['home']}/{config['client_repo']}") + assert c.rc == 0 or 'does not exist' not in c.stderr - def test_repo_has_encryption(self, host): - config = host.file('/opt/borg/borg-client/config') - assert config.exists - content = config.content_string + def test_repo_has_encryption(self, host, config): + repo_config = host.file(f"{config['home']}/{config['client_repo']}/config") + assert repo_config.exists + content = repo_config.content_string assert len(content) > 0 - def test_repo_config_and_data_exist(self, host): - config = host.file('/opt/borg/borg-client/config') - assert config.exists + def test_repo_config_and_data_exist(self, host, config): + repo_config = host.file(f"{config['home']}/{config['client_repo']}/config") + assert repo_config.exists - data = host.file('/opt/borg/borg-client/data') + data = host.file(f"{config['home']}/{config['client_repo']}/data") assert data.exists assert data.is_directory - def test_repo_permissions(self, host): - repo = host.file('/opt/borg/borg-client') - assert repo.user == 'borg' - assert repo.group == 'borg' + def test_repo_permissions(self, host, config): + repo = host.file(f"{config['home']}/{config['client_repo']}") + assert repo.user == config['user'] + assert repo.group == config['user'] |