mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup-cleanup.git
synced 2026-01-08 16:32:13 +00:00
fix: apply --force-keep to timestamp subdirectories instead of backup folders
- Change --force-keep semantics to skip the last N subdirectories inside each backup-docker-to-local folder - Remove old behavior that skipped entire backup folders in --all mode - Update CLI help text to reflect the new behavior - Align unit and E2E tests with timestamp-based force-keep semantics https://chatgpt.com/share/695d1ed9-44f0-800f-a236-e903c61036cb
This commit is contained in:
@@ -41,10 +41,19 @@ if __name__ == "__main__":
|
||||
class CleanbackE2EForceKeepTests(unittest.TestCase):
|
||||
"""
|
||||
E2E test that validates --force-keep in --all mode.
|
||||
It creates two backup folders directly under /Backups so --all can find them:
|
||||
|
||||
The current behavior is:
|
||||
- In --all mode, cleanback discovers each /Backups/<ID>/backup-docker-to-local/*
|
||||
- Within each backup-docker-to-local folder, subdirs are sorted by name
|
||||
- With --force-keep N, the last N subdirs in that folder are skipped (kept)
|
||||
|
||||
This test creates two backup folders under /Backups so --all can find them:
|
||||
/Backups/<prefix>-01/backup-docker-to-local/{good,bad}
|
||||
/Backups/<prefix>-02/backup-docker-to-local/{good,bad}
|
||||
With --force-keep 1, the last (sorted) backup folder (<prefix>-02) is skipped.
|
||||
|
||||
With --force-keep 1:
|
||||
- In each folder, "good" is the last (sorted) and is skipped (kept)
|
||||
- "bad" is processed and deleted
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
@@ -123,7 +132,7 @@ class CleanbackE2EForceKeepTests(unittest.TestCase):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def test_all_mode_force_keep_skips_last_backup_folder(self):
|
||||
def test_all_mode_force_keep_skips_last_timestamp_subdir_per_backup_folder(self):
|
||||
env = os.environ.copy()
|
||||
env["PATH"] = f"{self.bin_dir}:{env.get('PATH', '')}"
|
||||
|
||||
@@ -148,13 +157,12 @@ class CleanbackE2EForceKeepTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(proc.returncode, 0, msg=proc.stderr or proc.stdout)
|
||||
|
||||
# First backup folder (<prefix>-01) should be processed: bad removed, good kept
|
||||
self.assertTrue(self.b1_good.exists(), "b1 good should remain")
|
||||
# In each folder, sorted subdirs are: bad, good -> good is skipped, bad is processed
|
||||
self.assertTrue(self.b1_good.exists(), "b1 good should remain (skipped)")
|
||||
self.assertFalse(self.b1_bad.exists(), "b1 bad should be deleted")
|
||||
|
||||
# Last backup folder (<prefix>-02) should be skipped entirely: both remain
|
||||
self.assertTrue(self.b2_good.exists(), "b2 good should remain (skipped)")
|
||||
self.assertTrue(self.b2_bad.exists(), "b2 bad should remain (skipped)")
|
||||
self.assertFalse(self.b2_bad.exists(), "b2 bad should be deleted")
|
||||
|
||||
self.assertIn("Summary:", proc.stdout)
|
||||
|
||||
|
||||
@@ -153,10 +153,10 @@ class CleanupBackupsUsingDirvalTests(unittest.TestCase):
|
||||
self.assertFalse(self.timeoutC.exists())
|
||||
self.assertTrue(self.goodX.exists())
|
||||
self.assertFalse(self.badY.exists())
|
||||
|
||||
def test_all_mode_force_keep_skips_last_backup_folder(self):
|
||||
# Given backup folders: ID1, ID2 (sorted)
|
||||
# --force-keep 1 should skip ID2 completely.
|
||||
|
||||
def test_all_mode_force_keep_skips_last_timestamp_subdir_per_backup_folder(self):
|
||||
# Subdirs are sorted by name.
|
||||
# --force-keep 1 skips the last subdir inside each backup-docker-to-local folder.
|
||||
rc, out, err, _ = self.run_main(
|
||||
[
|
||||
"--backups-root",
|
||||
@@ -175,14 +175,14 @@ class CleanupBackupsUsingDirvalTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(rc, 0, msg=err or out)
|
||||
|
||||
# ID1 should be processed
|
||||
self.assertTrue(self.goodA.exists())
|
||||
self.assertFalse(self.badB.exists())
|
||||
self.assertFalse(self.timeoutC.exists())
|
||||
# ID1 sorted: badB, goodA, timeoutC -> timeoutC is skipped, others processed
|
||||
self.assertTrue(self.goodA.exists(), "goodA should remain")
|
||||
self.assertFalse(self.badB.exists(), "badB should be deleted")
|
||||
self.assertTrue(self.timeoutC.exists(), "timeoutC should be skipped (kept)")
|
||||
|
||||
# ID2 should be untouched
|
||||
self.assertTrue(self.goodX.exists())
|
||||
self.assertTrue(self.badY.exists())
|
||||
# ID2 sorted: badY, goodX -> goodX is skipped, badY processed
|
||||
self.assertTrue(self.goodX.exists(), "goodX should be skipped (kept)")
|
||||
self.assertFalse(self.badY.exists(), "badY should be processed and deleted")
|
||||
|
||||
def test_dirval_missing_errors(self):
|
||||
rc, out, err, _ = self.run_main(
|
||||
|
||||
Reference in New Issue
Block a user