diff --git a/roles/postgres/files/rotate.py b/roles/postgres/files/rotate.py index e533114..2c3f71f 100755 --- a/roles/postgres/files/rotate.py +++ b/roles/postgres/files/rotate.py @@ -97,8 +97,26 @@ def cleanup(to_keep: list[Backup], to_remove: list[Backup], *, dry_run: bool = T for backup in to_remove: backup.path.unlink() - print(f"Used space: {len(to_keep)} files, {used_space} bytes") - print(f"Freed space: {len(to_remove)} files, {freed_space} bytes") + print(f"Used space: {len(to_keep)} files, {approximate_size(used_space)}") + print(f"Freed space: {len(to_remove)} files, {approximate_size(freed_space)}") + + +def approximate_size(size: int) -> str: + """Convert size in bytes to a human-readable form.""" + + units = { + 2**10: "KiB", + 2**20: "MiB", + 2**30: "GiB", + 2**40: "TiB", + 2**50: "PiB", + } + + for multiplier, name in reversed(units.items()): + if size >= multiplier: + return "{:.1f} {}".format(size / multiplier, name) + + return "{} B".format(size) def main(): diff --git a/roles/postgres/files/test_rotate.py b/roles/postgres/files/test_rotate.py index 025a5c5..e62d1e0 100644 --- a/roles/postgres/files/test_rotate.py +++ b/roles/postgres/files/test_rotate.py @@ -3,6 +3,8 @@ import pytest +import rotate + EXPECTED_FILES = [ "2024-06-27.tar.gz", @@ -123,3 +125,26 @@ def test_keep_pattern_does_not_match_anything(backups): ] ) assert sorted(item.name for item in backups.glob("*")) == EXPECTED_FILES + + +@pytest.mark.parametrize( + "size,expected", + [ + (0, "0 B"), + (1, "1 B"), + (1023, "1023 B"), + (1024, "1.0 KiB"), + (1025, "1.0 KiB"), + (1024 * 1024, "1.0 MiB"), + (5 * 1024 * 1024, "5.0 MiB"), + (1024 * 1024 * 1024, "1.0 GiB"), + (10 * 1024 * 1024 * 1024, "10.0 GiB"), + (1024 * 1024 * 1024 * 1024, "1.0 TiB"), + (13.5 * 1024 * 1024 * 1024 * 1024, "13.5 TiB"), + (1024 * 1024 * 1024 * 1024 * 1024, "1.0 PiB"), + (145.7 * 1024 * 1024 * 1024 * 1024 * 1024, "145.7 PiB"), + (1024 * 1024 * 1024 * 1024 * 1024 * 1024, "1024.0 PiB"), + ], +) +def test_approximate_size(size, expected): + assert rotate.approximate_size(size) == expected