(bugfix) Surface rsync SSH failure details in run results
Include the selected SSH credential metadata and rsync log tail in dry-run and failed backup results so Django shows the actual SSH or rsync failure instead of only the exit code. Warn in host checks when a host still uses database-stored private key material, making it easier to spot old credentials after switching to generated filesystem keys.
This commit is contained in:
@@ -90,6 +90,7 @@ class DjangoConfigSourceTests(TestCase):
|
||||
self.assertIn("-oBatchMode=yes", cfg["ssh"]["options"])
|
||||
self.assertIn(f"-oIdentityFile={identity_file}", cfg["ssh"]["options"])
|
||||
self.assertIn(f"-oUserKnownHostsFile={known_hosts}", cfg["ssh"]["options"])
|
||||
self.assertEqual(cfg["ssh_credential"]["storage"], "database")
|
||||
|
||||
def test_host_ssh_credential_overrides_global_credential(self) -> None:
|
||||
global_credential = SshCredential.objects.create(name="global-key", private_key="GLOBAL")
|
||||
@@ -133,3 +134,4 @@ class DjangoConfigSourceTests(TestCase):
|
||||
cfg = DjangoConfigSource().effective_config_for_host("web-01")
|
||||
|
||||
self.assertIn(f"-oIdentityFile={identity_file}", cfg["ssh"]["options"])
|
||||
self.assertEqual(cfg["ssh_credential"]["storage"], "filesystem")
|
||||
|
||||
@@ -49,6 +49,24 @@ class RunScheduledConfigSourceTests(SimpleTestCase):
|
||||
self.assertEqual(result["host"], "web-01")
|
||||
run_rsync.assert_called_once()
|
||||
|
||||
def test_failed_dry_run_includes_log_tail(self) -> None:
|
||||
def fake_run_rsync(command, log_path, timeout_seconds):
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
log_path.write_text("Permission denied (publickey).\nrsync error\n", encoding="utf-8")
|
||||
return RsyncResult(exit_code=12, command=command)
|
||||
|
||||
with patch("pobsync.commands.run_scheduled.run_rsync", side_effect=fake_run_rsync):
|
||||
result = run_scheduled(
|
||||
prefix=Path("/missing-prefix"),
|
||||
host="web-01",
|
||||
dry_run=True,
|
||||
config_source=FakeConfigSource(),
|
||||
)
|
||||
|
||||
self.assertFalse(result["ok"])
|
||||
self.assertEqual(result["rsync"]["exit_code"], 12)
|
||||
self.assertEqual(result["rsync"]["log_tail"], ["Permission denied (publickey).", "rsync error"])
|
||||
|
||||
def test_successful_real_run_applies_prune_when_requested(self) -> None:
|
||||
with TemporaryDirectory() as tmp:
|
||||
prefix = Path(tmp) / "home"
|
||||
|
||||
Reference in New Issue
Block a user