(refactor) Remove obsolete global config JSON storage

Drop the unused GlobalConfig.data field and remove the remaining YAML
config path helpers from PobsyncPaths.

Keep HostConfig.config as runtime state for preflight data, and relabel it
in the admin so it no longer reads as legacy compatibility storage.
This commit is contained in:
2026-05-21 02:46:09 +02:00
parent 2642f14e49
commit 86873bd035
9 changed files with 19 additions and 40 deletions

View File

@@ -317,7 +317,6 @@ def run_scheduled(
"duration_seconds": None, "duration_seconds": None,
"base": _base_meta_from_path(base_dir, link_dest), "base": _base_meta_from_path(base_dir, link_dest),
"rsync": {"exit_code": None, "command": cmd, "stats": {}}, "rsync": {"exit_code": None, "command": cmd, "stats": {}},
# Keep existing fields for future expansion / compatibility with current structure.
"overrides": {"includes": [], "excludes": [], "base": None}, "overrides": {"includes": [], "excludes": [], "base": None},
} }

View File

@@ -94,7 +94,6 @@ GLOBAL_SCHEMA = Schema(
), ),
"logging": FieldSpec(dict, required=False, schema=LOGGING_SCHEMA), "logging": FieldSpec(dict, required=False, schema=LOGGING_SCHEMA),
"output": FieldSpec(dict, required=False, schema=OUTPUT_SCHEMA), "output": FieldSpec(dict, required=False, schema=OUTPUT_SCHEMA),
# Used by `init-host` as a convenience default
"retention_defaults": FieldSpec( "retention_defaults": FieldSpec(
dict, dict,
required=False, required=False,

View File

@@ -8,14 +8,6 @@ from pathlib import Path
class PobsyncPaths: class PobsyncPaths:
home: Path # usually /opt/pobsync home: Path # usually /opt/pobsync
@property
def config_dir(self) -> Path:
return self.home / "config"
@property
def hosts_dir(self) -> Path:
return self.config_dir / "hosts"
@property @property
def state_dir(self) -> Path: def state_dir(self) -> Path:
return self.home / "state" return self.home / "state"
@@ -28,11 +20,6 @@ class PobsyncPaths:
def logs_dir(self) -> Path: def logs_dir(self) -> Path:
return self.home / "logs" return self.home / "logs"
@property
def global_config_path(self) -> Path:
return self.config_dir / "global.yaml"
@property @property
def central_log_path(self) -> Path: def central_log_path(self) -> Path:
return self.logs_dir / "pobsync.log" return self.logs_dir / "pobsync.log"

View File

@@ -50,7 +50,6 @@ class GlobalConfigAdmin(admin.ModelAdmin):
), ),
("Defaults", {"fields": ("default_source_root", "default_destination_subdir", "excludes_default")}), ("Defaults", {"fields": ("default_source_root", "default_destination_subdir", "excludes_default")}),
("Retention defaults", {"fields": ("retention_daily", "retention_weekly", "retention_monthly", "retention_yearly")}), ("Retention defaults", {"fields": ("retention_daily", "retention_weekly", "retention_monthly", "retention_yearly")}),
("Compatibility data", {"fields": ("data",), "classes": ("collapse",)}),
("Timestamps", {"fields": ("created_at", "updated_at"), "classes": ("collapse",)}), ("Timestamps", {"fields": ("created_at", "updated_at"), "classes": ("collapse",)}),
) )
@@ -76,7 +75,7 @@ class HostConfigAdmin(admin.ModelAdmin):
("Source", {"fields": ("source_root", "includes", "excludes_add", "excludes_replace")}), ("Source", {"fields": ("source_root", "includes", "excludes_add", "excludes_replace")}),
("Rsync override", {"fields": ("rsync_extra_args",)}), ("Rsync override", {"fields": ("rsync_extra_args",)}),
("Retention", {"fields": ("retention_daily", "retention_weekly", "retention_monthly", "retention_yearly")}), ("Retention", {"fields": ("retention_daily", "retention_weekly", "retention_monthly", "retention_yearly")}),
("Compatibility data", {"fields": ("config",), "classes": ("collapse",)}), ("Runtime state", {"fields": ("config",), "classes": ("collapse",)}),
("Timestamps", {"fields": ("created_at", "updated_at"), "classes": ("collapse",)}), ("Timestamps", {"fields": ("created_at", "updated_at"), "classes": ("collapse",)}),
) )

View File

@@ -0,0 +1,14 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("pobsync_backend", "0010_remove_globalconfig_pobsync_home"),
]
operations = [
migrations.RemoveField(
model_name="globalconfig",
name="data",
),
]

View File

@@ -36,7 +36,6 @@ class GlobalConfig(TimestampedModel):
retention_weekly = models.PositiveIntegerField(default=8) retention_weekly = models.PositiveIntegerField(default=8)
retention_monthly = models.PositiveIntegerField(default=12) retention_monthly = models.PositiveIntegerField(default=12)
retention_yearly = models.PositiveIntegerField(default=0) retention_yearly = models.PositiveIntegerField(default=0)
data = models.JSONField(default=dict, blank=True)
class Meta: class Meta:
verbose_name = "global config" verbose_name = "global config"

View File

@@ -10,7 +10,7 @@ from pobsync_backend.models import BackupRun, GlobalConfig, HostConfig, Schedule
class AdminDisplayTests(TestCase): class AdminDisplayTests(TestCase):
def test_admin_hides_old_global_state_field_and_uses_compatibility_label(self) -> None: def test_admin_hides_old_global_state_fields_and_labels_host_runtime_state(self) -> None:
site = AdminSite() site = AdminSite()
global_admin = GlobalConfigAdmin(GlobalConfig, site) global_admin = GlobalConfigAdmin(GlobalConfig, site)
host_admin = HostConfigAdmin(HostConfig, site) host_admin = HostConfigAdmin(HostConfig, site)
@@ -21,7 +21,9 @@ class AdminDisplayTests(TestCase):
fieldset_names = [name for name, _options in [*global_fieldsets, *host_fieldsets]] fieldset_names = [name for name, _options in [*global_fieldsets, *host_fieldsets]]
self.assertNotIn("pobsync_home", global_fields) self.assertNotIn("pobsync_home", global_fields)
self.assertIn("Compatibility data", fieldset_names) self.assertNotIn("data", global_fields)
self.assertIn("Runtime state", fieldset_names)
self.assertNotIn("Compatibility data", fieldset_names)
self.assertNotIn("Legacy JSON", fieldset_names) self.assertNotIn("Legacy JSON", fieldset_names)
def test_host_admin_links_to_related_snapshots_and_runs(self) -> None: def test_host_admin_links_to_related_snapshots_and_runs(self) -> None:

View File

@@ -19,12 +19,6 @@ class ConfigRepositoryTests(TestCase):
retention_weekly=4, retention_weekly=4,
retention_monthly=3, retention_monthly=3,
retention_yearly=1, retention_yearly=1,
data={
"backup_root": "/ignored",
"ssh": {"user": "ignored", "port": 22, "options": []},
"unknown": "must-not-leak",
"retention_defaults": {"daily": 99, "weekly": 99, "monthly": 99, "yearly": 99},
},
) )
HostConfig.objects.create( HostConfig.objects.create(
host="web-01", host="web-01",

View File

@@ -22,20 +22,6 @@ class DjangoConfigSourceTests(TestCase):
retention_weekly=4, retention_weekly=4,
retention_monthly=3, retention_monthly=3,
retention_yearly=1, retention_yearly=1,
data={
"backup_root": "/ignored",
"ssh": {"user": "root", "port": 22, "options": []},
"rsync": {
"binary": "rsync",
"args": ["--archive"],
"timeout_seconds": 0,
"bwlimit_kbps": 0,
"extra_args": ["--numeric-ids"],
},
"defaults": {"source_root": "/", "destination_subdir": ""},
"excludes_default": ["/proc/***"],
"retention_defaults": {"daily": 7, "weekly": 4, "monthly": 3, "yearly": 1},
},
) )
HostConfig.objects.create( HostConfig.objects.create(
host="web-01", host="web-01",