- Add per-host rsync bandwidth limit overrides with inherit/unlimited semantics. - Store the effective bwlimit in run metadata/results and show it in host/run detail views. - Document recommended starting values for VPN and remote backups. ## Tests - `.venv/bin/python manage.py makemigrations --check --dry-run` - `.venv/bin/python manage.py test src.pobsync_backend.tests.test_django_config_source.DjangoConfigSourceTests.test_returns_effective_config_from_database src.pobsync_backend.tests.test_django_config_source.DjangoConfigSourceTests.test_host_can_disable_global_rsync_bandwidth_limit src.pobsync_backend.tests.test_configure_commands.ConfigureCommandsTests.test_configure_host_uses_global_retention_defaults src.pobsync_backend.tests.test_run_scheduled_config_source.RunScheduledConfigSourceTests.test_dry_run_applies_configured_bandwidth_limit src.pobsync_backend.tests.test_run_scheduled_config_source.RunScheduledConfigSourceTests.test_real_run_can_request_verbose_output_args --verbosity 2` - `.venv/bin/python manage.py test src.pobsync_backend.tests.test_views.ViewTests.test_create_host_config_form_creates_host src.pobsync_backend.tests.test_views.ViewTests.test_host_detail_renders_effective_config_preview src.pobsync_backend.tests.test_views.ViewTests.test_run_detail_renders_result_payload src.pobsync_backend.tests.test_views.ViewTests.test_host_config_form_updates_host_config --verbosity 2` - `.venv/bin/python manage.py check` Closes #51
75 lines
2.5 KiB
Python
75 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
from io import StringIO
|
|
|
|
from django.core.management import call_command
|
|
from django.test import TestCase
|
|
|
|
from pobsync_backend.config_source import DjangoConfigSource
|
|
from pobsync_backend.models import GlobalConfig, HostConfig, ScheduleConfig
|
|
|
|
|
|
class ConfigureCommandsTests(TestCase):
|
|
def test_configure_global_creates_structured_config(self) -> None:
|
|
out = StringIO()
|
|
|
|
call_command(
|
|
"configure_pobsync_global",
|
|
backup_root="/backups",
|
|
retention="daily=3,weekly=2,monthly=1,yearly=0",
|
|
stdout=out,
|
|
)
|
|
|
|
config = GlobalConfig.objects.get(name="default")
|
|
self.assertEqual(config.backup_root, "/backups")
|
|
self.assertEqual(config.retention_daily, 3)
|
|
self.assertIn("Created global config", out.getvalue())
|
|
|
|
def test_configure_host_uses_global_retention_defaults(self) -> None:
|
|
GlobalConfig.objects.create(
|
|
name="default",
|
|
backup_root="/backups",
|
|
retention_daily=5,
|
|
retention_weekly=4,
|
|
retention_monthly=3,
|
|
retention_yearly=2,
|
|
)
|
|
out = StringIO()
|
|
|
|
call_command(
|
|
"configure_pobsync_host",
|
|
"web-01",
|
|
address="web-01.example.test",
|
|
exclude_add=["/tmp/***"],
|
|
rsync_extra_arg=["--delete"],
|
|
rsync_bwlimit_kbps=4096,
|
|
stdout=out,
|
|
)
|
|
|
|
host = HostConfig.objects.get(host="web-01")
|
|
self.assertEqual(host.retention_daily, 5)
|
|
self.assertEqual(host.excludes_add, ["/tmp/***"])
|
|
self.assertEqual(host.rsync_extra_args, ["--delete"])
|
|
self.assertEqual(host.rsync_bwlimit_kbps, 4096)
|
|
|
|
effective = DjangoConfigSource().effective_config_for_host("web-01")
|
|
self.assertEqual(effective["retention"]["yearly"], 2)
|
|
self.assertEqual(effective["excludes_effective"], ["/tmp/***"])
|
|
self.assertEqual(effective["rsync"]["bwlimit_kbps"], 4096)
|
|
|
|
def test_configure_schedule_creates_sql_schedule(self) -> None:
|
|
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
|
|
out = StringIO()
|
|
|
|
call_command(
|
|
"configure_pobsync_schedule",
|
|
host.host,
|
|
schedule_expression="15 2 * * *",
|
|
prune=True,
|
|
stdout=out,
|
|
)
|
|
|
|
schedule = ScheduleConfig.objects.get(host=host)
|
|
self.assertEqual(schedule.cron_expr, "15 2 * * *")
|
|
self.assertTrue(schedule.prune)
|