fix(deploy): propagate backup retention failures

This commit is contained in:
cesnimda
2026-11-11 14:59:12 +01:00
parent 3cca441874
commit e1c8e84502
9 changed files with 261 additions and 7 deletions
+61 -2
View File
@@ -175,11 +175,29 @@ class BackupRetentionTests(unittest.TestCase):
'set -euo pipefail',
'BACKUP_DIR=' + shlex.quote(folder.as_posix()),
'BACKUP_STAMP=synthetic',
'BACKUP_DAILY_RETENTION_DAYS=30',
'BACKUP_MONTHLY_RETENTION_COUNT=1',
'FAIL_OPERATION=' + shlex.quote(fail_operation),
'date() { echo 2099-01; }',
'upload_current_backup_set() { echo "UPLOAD WOULD START"; }',
'find() { if [[ "$*" == *-delete* ]]; then echo "PRUNING WOULD START"; fi; }',
'rm() { echo "CLEANUP REQUEST $1 $2"; }',
'find() {',
' if [[ "$*" == *-delete* ]]; then',
' echo "PRUNING WOULD START";',
' [ "$FAIL_OPERATION" != daily-find ]; return;',
' fi;',
' echo "MONTHLY ENUMERATION" >&2;',
' if [ "$FAIL_OPERATION" = empty-enumeration ]; then return 0; fi;',
' printf "%s/monthly/%s\\n" "$BACKUP_DIR" 2098-12 "$BACKUP_DIR" 2099-01 "$BACKUP_DIR" 2098-11;',
' [ "$FAIL_OPERATION" != monthly-find ];',
'}',
'sort() { if [ "$FAIL_OPERATION" = sort ]; then return 25; fi; command sort "$@"; }',
'rm() {',
' echo "CLEANUP REQUEST $1 $2";',
' if [ "$1" = -rf ]; then',
' echo "MONTHLY PRUNE ${3##*/}";',
' [ "$FAIL_OPERATION" != monthly-rm ];',
' fi;',
'}',
'cp() {',
' if [ "$FAIL_OPERATION" = cp ]; then',
' printf partial > "${@: -1}/partial"; return 23;',
@@ -206,6 +224,8 @@ class BackupRetentionTests(unittest.TestCase):
'jobtracker-files-synthetic.tar.gz': b'files fixture',
'.complete': b'synthetic\n'}, artifacts)
self.assertIn('PRUNING WOULD START', result.stdout)
self.assertEqual(['MONTHLY PRUNE 2098-11', 'MONTHLY PRUNE 2098-12'],
[line for line in result.stdout.splitlines() if line.startswith('MONTHLY PRUNE ')])
self.assertIn('UPLOAD WOULD START', result.stdout)
self.assertIn('DEPLOY WOULD CONTINUE', result.stdout)
@@ -234,6 +254,45 @@ class BackupRetentionTests(unittest.TestCase):
self.assertEqual({'jobtracker-db-earlier.sql.gz': b'earlier fixture', '.complete': b'earlier\n'}, artifacts)
self.assertIn('DEPLOY WOULD CONTINUE', result.stdout)
def test_daily_prune_failure_blocks_monthly_pruning_upload_and_deploy(self):
result, _ = self.retain('daily-find')
self.assertEqual(1, result.returncode, result.stdout + result.stderr)
self.assertIn('Daily backup retention failed', result.stdout)
self.assertNotIn('MONTHLY ENUMERATION', result.stderr)
self.assertNotIn('MONTHLY PRUNE', result.stdout)
self.assertNotIn('UPLOAD WOULD START', result.stdout)
self.assertNotIn('DEPLOY WOULD CONTINUE', result.stdout)
self.assertNotIn('Backup retention applied', result.stdout)
def test_monthly_enumeration_failure_blocks_pruning_upload_and_deploy(self):
for operation in ['monthly-find', 'sort']:
with self.subTest(operation=operation):
result, _ = self.retain(operation)
self.assertEqual(1, result.returncode, result.stdout + result.stderr)
self.assertIn('Could not enumerate monthly backups', result.stdout)
self.assertNotIn('MONTHLY PRUNE', result.stdout)
self.assertNotIn('UPLOAD WOULD START', result.stdout)
self.assertNotIn('DEPLOY WOULD CONTINUE', result.stdout)
self.assertNotIn('Backup retention applied', result.stdout)
def test_monthly_prune_failure_stops_before_remaining_months_upload_and_deploy(self):
result, _ = self.retain('monthly-rm')
self.assertEqual(1, result.returncode, result.stdout + result.stderr)
self.assertIn('Monthly backup retention failed', result.stdout)
self.assertIn('MONTHLY PRUNE 2098-11', result.stdout)
self.assertNotIn('MONTHLY PRUNE 2098-12', result.stdout)
self.assertNotIn('UPLOAD WOULD START', result.stdout)
self.assertNotIn('DEPLOY WOULD CONTINUE', result.stdout)
self.assertNotIn('Backup retention applied', result.stdout)
def test_empty_monthly_enumeration_does_not_request_removal(self):
result, _ = self.retain('empty-enumeration')
self.assertEqual(0, result.returncode, result.stdout + result.stderr)
self.assertNotIn('MONTHLY PRUNE', result.stdout)
self.assertIn('Backup retention applied', result.stdout)
self.assertIn('UPLOAD WOULD START', result.stdout)
self.assertIn('DEPLOY WOULD CONTINUE', result.stdout)
if __name__ == '__main__':
unittest.main()