Skip to content

Commit

Permalink
Add size in bytes to backups (#5473)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdegat01 authored Dec 7, 2024
1 parent 5a22599 commit d44e995
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 6 deletions.
3 changes: 3 additions & 0 deletions supervisor/api/backups.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
ATTR_ADDITIONAL_LOCATIONS,
ATTR_BACKGROUND,
ATTR_LOCATIONS,
ATTR_SIZE_BYTES,
CONTENT_TYPE_TAR,
)
from .utils import api_process, api_validate
Expand Down Expand Up @@ -145,6 +146,7 @@ def _list_backups(self):
ATTR_DATE: backup.date,
ATTR_TYPE: backup.sys_type,
ATTR_SIZE: backup.size,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_LOCATION: backup.location,
ATTR_LOCATIONS: backup.locations,
ATTR_PROTECTED: backup.protected,
Expand Down Expand Up @@ -216,6 +218,7 @@ async def backup_info(self, request):
ATTR_NAME: backup.name,
ATTR_DATE: backup.date,
ATTR_SIZE: backup.size,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_COMPRESSED: backup.compressed,
ATTR_PROTECTED: backup.protected,
ATTR_SUPERVISOR_VERSION: backup.supervisor_version,
Expand Down
1 change: 1 addition & 0 deletions supervisor/api/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
ATTR_SAFE_MODE = "safe_mode"
ATTR_SEAT = "seat"
ATTR_SIGNED = "signed"
ATTR_SIZE_BYTES = "size_bytes"
ATTR_STARTUP_TIME = "startup_time"
ATTR_STATUS = "status"
ATTR_SUBSYSTEM = "subsystem"
Expand Down
10 changes: 8 additions & 2 deletions supervisor/backups/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from collections.abc import Awaitable
from copy import deepcopy
from datetime import timedelta
from functools import cached_property
import io
import json
import logging
Expand Down Expand Up @@ -213,12 +214,17 @@ def locations(self) -> list[str | None]:
key=location_sort_key,
)

@property
@cached_property
def size(self) -> float:
"""Return backup size."""
return round(self.size_bytes / 1048576, 2) # calc mbyte

@cached_property
def size_bytes(self) -> int:
"""Return backup size in bytes."""
if not self.tarfile.is_file():
return 0
return round(self.tarfile.stat().st_size / 1048576, 2) # calc mbyte
return self.tarfile.stat().st_size

@property
def is_new(self) -> bool:
Expand Down
38 changes: 36 additions & 2 deletions tests/api/test_backups.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@
from tests.const import TEST_ADDON_SLUG


async def test_info(api_client, coresys: CoreSys, mock_full_backup: Backup):
async def test_info(
api_client, coresys: CoreSys, mock_full_backup: Backup, tmp_path: Path
):
"""Test info endpoint."""
copy(get_fixture_path("backup_example.tar"), tmp_path / "test_backup.tar")

resp = await api_client.get("/backups/info")
result = await resp.json()
assert result["data"]["days_until_stale"] == 30
Expand All @@ -35,17 +39,47 @@ async def test_info(api_client, coresys: CoreSys, mock_full_backup: Backup):
assert result["data"]["backups"][0]["content"]["homeassistant"] is True
assert len(result["data"]["backups"][0]["content"]["addons"]) == 1
assert result["data"]["backups"][0]["content"]["addons"][0] == "local_ssh"
assert result["data"]["backups"][0]["size"] == 0.01
assert result["data"]["backups"][0]["size_bytes"] == 10240


async def test_backup_more_info(
api_client, coresys: CoreSys, mock_full_backup: Backup, tmp_path: Path
):
"""Test info endpoint."""
copy(get_fixture_path("backup_example.tar"), tmp_path / "test_backup.tar")

async def test_list(api_client, coresys: CoreSys, mock_full_backup: Backup):
resp = await api_client.get("/backups/test/info")
result = await resp.json()
assert result["data"]["slug"] == "test"
assert result["data"]["homeassistant"] == "2022.8.0"
assert len(result["data"]["addons"]) == 1
assert result["data"]["addons"][0] == {
"name": "SSH",
"size": 0,
"slug": "local_ssh",
"version": "1.0.0",
}
assert result["data"]["size"] == 0.01
assert result["data"]["size_bytes"] == 10240
assert result["data"]["homeassistant_exclude_database"] is False


async def test_list(
api_client, coresys: CoreSys, mock_full_backup: Backup, tmp_path: Path
):
"""Test list endpoint."""
copy(get_fixture_path("backup_example.tar"), tmp_path / "test_backup.tar")

resp = await api_client.get("/backups")
result = await resp.json()
assert len(result["data"]["backups"]) == 1
assert result["data"]["backups"][0]["slug"] == "test"
assert result["data"]["backups"][0]["content"]["homeassistant"] is True
assert len(result["data"]["backups"][0]["content"]["addons"]) == 1
assert result["data"]["backups"][0]["content"]["addons"][0] == "local_ssh"
assert result["data"]["backups"][0]["size"] == 0.01
assert result["data"]["backups"][0]["size_bytes"] == 10240


async def test_options(api_client, coresys: CoreSys):
Expand Down
7 changes: 5 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
ATTR_ADDONS,
ATTR_ADDONS_CUSTOM_LIST,
ATTR_DATE,
ATTR_EXCLUDE_DATABASE,
ATTR_FOLDERS,
ATTR_HOMEASSISTANT,
ATTR_NAME,
Expand Down Expand Up @@ -580,7 +581,7 @@ def install_addon_example(coresys: CoreSys, repository):
@pytest.fixture
async def mock_full_backup(coresys: CoreSys, tmp_path) -> Backup:
"""Mock a full backup."""
mock_backup = Backup(coresys, Path(tmp_path, "test_backup"), "test", None)
mock_backup = Backup(coresys, Path(tmp_path, "test_backup.tar"), "test", None)
mock_backup.new("Test", utcnow().isoformat(), BackupType.FULL)
mock_backup.repositories = ["https://github.com/awesome-developer/awesome-repo"]
mock_backup.docker = {}
Expand All @@ -596,6 +597,7 @@ async def mock_full_backup(coresys: CoreSys, tmp_path) -> Backup:
mock_backup._data[ATTR_HOMEASSISTANT] = {
ATTR_VERSION: AwesomeVersion("2022.8.0"),
ATTR_SIZE: 0,
ATTR_EXCLUDE_DATABASE: False,
}
coresys.backups._backups = {"test": mock_backup}
yield mock_backup
Expand All @@ -604,7 +606,7 @@ async def mock_full_backup(coresys: CoreSys, tmp_path) -> Backup:
@pytest.fixture
async def mock_partial_backup(coresys: CoreSys, tmp_path) -> Backup:
"""Mock a partial backup."""
mock_backup = Backup(coresys, Path(tmp_path, "test_backup"), "test", None)
mock_backup = Backup(coresys, Path(tmp_path, "test_backup.tar"), "test", None)
mock_backup.new("Test", utcnow().isoformat(), BackupType.PARTIAL)
mock_backup.repositories = ["https://github.com/awesome-developer/awesome-repo"]
mock_backup.docker = {}
Expand All @@ -620,6 +622,7 @@ async def mock_partial_backup(coresys: CoreSys, tmp_path) -> Backup:
mock_backup._data[ATTR_HOMEASSISTANT] = {
ATTR_VERSION: AwesomeVersion("2022.8.0"),
ATTR_SIZE: 0,
ATTR_EXCLUDE_DATABASE: False,
}
coresys.backups._backups = {"test": mock_backup}
yield mock_backup
Expand Down

0 comments on commit d44e995

Please sign in to comment.