mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup.git
synced 2025-12-27 11:06:35 +00:00
refactor: migrate to src/ package + add DinD-based E2E runner with debug artifacts
- Replace legacy standalone scripts with a proper src-layout Python package (baudolo backup/restore/configure entrypoints via pyproject.toml) - Remove old scripts/files (backup-docker-to-local.py, recover-docker-from-local.sh, databases.csv.tpl, Todo.md) - Add Dockerfile to build the project image for local/E2E usage - Update Makefile: build image and run E2E via external runner script - Add scripts/test-e2e.sh: - start DinD + dedicated network - recreate DinD data volume (and shared /tmp volume) - pre-pull helper images (alpine-rsync, alpine) - load local baudolo:local image into DinD - run unittest E2E suite inside DinD and abort on first failure - on failure: dump host+DinD diagnostics and archive shared /tmp into artifacts/ - Add artifacts/ debug outputs produced by failing E2E runs (logs, events, tmp archive) https://chatgpt.com/share/694ec23f-0794-800f-9a59-8365bc80f435
This commit is contained in:
@@ -1,64 +1,36 @@
|
||||
# tests/unit/test_backup.py
|
||||
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
import importlib.util
|
||||
import sys
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
# Prevent actual directory creation in backup script import
|
||||
dummy_mkdir = lambda self, *args, **kwargs: None
|
||||
original_mkdir = pathlib.Path.mkdir
|
||||
pathlib.Path.mkdir = dummy_mkdir
|
||||
from baudolo.backup.app import requires_stop
|
||||
|
||||
# Create a virtual databases.csv in the project root for the module import
|
||||
test_dir = os.path.dirname(__file__)
|
||||
project_root = os.path.abspath(os.path.join(test_dir, '../../'))
|
||||
sys.path.insert(0, project_root)
|
||||
db_csv_path = os.path.join(project_root, 'databases.csv')
|
||||
with open(db_csv_path, 'w') as f:
|
||||
f.write('instance;database;username;password\n')
|
||||
|
||||
# Dynamically load the hyphenated script as module 'backup'
|
||||
script_path = os.path.join(project_root, 'backup-docker-to-local.py')
|
||||
spec = importlib.util.spec_from_file_location('backup', script_path)
|
||||
backup = importlib.util.module_from_spec(spec)
|
||||
sys.modules['backup'] = backup
|
||||
spec.loader.exec_module(backup)
|
||||
class TestRequiresStop(unittest.TestCase):
|
||||
@patch("baudolo.backup.app.get_image_info")
|
||||
def test_requires_stop_false_when_all_images_are_whitelisted(self, mock_get_image_info):
|
||||
# All containers use images containing allowed substrings
|
||||
mock_get_image_info.side_effect = [
|
||||
"repo/mastodon:v4",
|
||||
"repo/wordpress:latest",
|
||||
]
|
||||
containers = ["c1", "c2"]
|
||||
whitelist = ["mastodon", "wordpress"]
|
||||
self.assertFalse(requires_stop(containers, whitelist))
|
||||
|
||||
# Restore original mkdir
|
||||
pathlib.Path.mkdir = original_mkdir
|
||||
@patch("baudolo.backup.app.get_image_info")
|
||||
def test_requires_stop_true_when_any_image_is_not_whitelisted(self, mock_get_image_info):
|
||||
mock_get_image_info.side_effect = [
|
||||
"repo/mastodon:v4",
|
||||
"repo/nginx:latest",
|
||||
]
|
||||
containers = ["c1", "c2"]
|
||||
whitelist = ["mastodon", "wordpress"]
|
||||
self.assertTrue(requires_stop(containers, whitelist))
|
||||
|
||||
class TestIsImageWhitelisted(unittest.TestCase):
|
||||
@patch('backup.get_image_info')
|
||||
def test_returns_true_when_image_matches(self, mock_get_image_info):
|
||||
# Simulate a container image containing 'mastodon'
|
||||
mock_get_image_info.return_value = ['repo/mastodon:v4']
|
||||
images = ['mastodon', 'wordpress']
|
||||
self.assertTrue(
|
||||
backup.is_image_whitelisted('any_container', images),
|
||||
"Should return True when at least one image substring matches"
|
||||
)
|
||||
@patch("baudolo.backup.app.get_image_info")
|
||||
def test_requires_stop_true_when_whitelist_empty(self, mock_get_image_info):
|
||||
mock_get_image_info.return_value = "repo/anything:latest"
|
||||
self.assertTrue(requires_stop(["c1"], []))
|
||||
|
||||
@patch('backup.get_image_info')
|
||||
def test_returns_false_when_no_image_matches(self, mock_get_image_info):
|
||||
# Simulate a container image without matching substrings
|
||||
mock_get_image_info.return_value = ['repo/nginx:latest']
|
||||
images = ['mastodon', 'wordpress']
|
||||
self.assertFalse(
|
||||
backup.is_image_whitelisted('any_container', images),
|
||||
"Should return False when no image substring matches"
|
||||
)
|
||||
|
||||
@patch('backup.get_image_info')
|
||||
def test_returns_false_with_empty_image_list(self, mock_get_image_info):
|
||||
# Even if get_image_info returns something, an empty list yields False
|
||||
mock_get_image_info.return_value = ['repo/element:1.0']
|
||||
self.assertFalse(
|
||||
backup.is_image_whitelisted('any_container', []),
|
||||
"Should return False when the images list is empty"
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user