Add size in bytes to backups (#5473)

This commit is contained in:
Mike Degatano 2024-12-07 04:27:23 -05:00 committed by GitHub
parent 5a22599b93
commit d44e995aed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 53 additions and 6 deletions

View File

@ -54,6 +54,7 @@ from .const import (
ATTR_ADDITIONAL_LOCATIONS, ATTR_ADDITIONAL_LOCATIONS,
ATTR_BACKGROUND, ATTR_BACKGROUND,
ATTR_LOCATIONS, ATTR_LOCATIONS,
ATTR_SIZE_BYTES,
CONTENT_TYPE_TAR, CONTENT_TYPE_TAR,
) )
from .utils import api_process, api_validate from .utils import api_process, api_validate
@ -145,6 +146,7 @@ class APIBackups(CoreSysAttributes):
ATTR_DATE: backup.date, ATTR_DATE: backup.date,
ATTR_TYPE: backup.sys_type, ATTR_TYPE: backup.sys_type,
ATTR_SIZE: backup.size, ATTR_SIZE: backup.size,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_LOCATION: backup.location, ATTR_LOCATION: backup.location,
ATTR_LOCATIONS: backup.locations, ATTR_LOCATIONS: backup.locations,
ATTR_PROTECTED: backup.protected, ATTR_PROTECTED: backup.protected,
@ -216,6 +218,7 @@ class APIBackups(CoreSysAttributes):
ATTR_NAME: backup.name, ATTR_NAME: backup.name,
ATTR_DATE: backup.date, ATTR_DATE: backup.date,
ATTR_SIZE: backup.size, ATTR_SIZE: backup.size,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_COMPRESSED: backup.compressed, ATTR_COMPRESSED: backup.compressed,
ATTR_PROTECTED: backup.protected, ATTR_PROTECTED: backup.protected,
ATTR_SUPERVISOR_VERSION: backup.supervisor_version, ATTR_SUPERVISOR_VERSION: backup.supervisor_version,

View File

@ -59,6 +59,7 @@ ATTR_REVISION = "revision"
ATTR_SAFE_MODE = "safe_mode" ATTR_SAFE_MODE = "safe_mode"
ATTR_SEAT = "seat" ATTR_SEAT = "seat"
ATTR_SIGNED = "signed" ATTR_SIGNED = "signed"
ATTR_SIZE_BYTES = "size_bytes"
ATTR_STARTUP_TIME = "startup_time" ATTR_STARTUP_TIME = "startup_time"
ATTR_STATUS = "status" ATTR_STATUS = "status"
ATTR_SUBSYSTEM = "subsystem" ATTR_SUBSYSTEM = "subsystem"

View File

@ -6,6 +6,7 @@ from collections import defaultdict
from collections.abc import Awaitable from collections.abc import Awaitable
from copy import deepcopy from copy import deepcopy
from datetime import timedelta from datetime import timedelta
from functools import cached_property
import io import io
import json import json
import logging import logging
@ -213,12 +214,17 @@ class Backup(JobGroup):
key=location_sort_key, key=location_sort_key,
) )
@property @cached_property
def size(self) -> float: def size(self) -> float:
"""Return backup size.""" """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(): if not self.tarfile.is_file():
return 0 return 0
return round(self.tarfile.stat().st_size / 1048576, 2) # calc mbyte return self.tarfile.stat().st_size
@property @property
def is_new(self) -> bool: def is_new(self) -> bool:

View File

@ -25,8 +25,12 @@ from tests.common import get_fixture_path
from tests.const import TEST_ADDON_SLUG 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.""" """Test info endpoint."""
copy(get_fixture_path("backup_example.tar"), tmp_path / "test_backup.tar")
resp = await api_client.get("/backups/info") resp = await api_client.get("/backups/info")
result = await resp.json() result = await resp.json()
assert result["data"]["days_until_stale"] == 30 assert result["data"]["days_until_stale"] == 30
@ -35,10 +39,38 @@ async def test_info(api_client, coresys: CoreSys, mock_full_backup: Backup):
assert result["data"]["backups"][0]["content"]["homeassistant"] is True assert result["data"]["backups"][0]["content"]["homeassistant"] is True
assert len(result["data"]["backups"][0]["content"]["addons"]) == 1 assert len(result["data"]["backups"][0]["content"]["addons"]) == 1
assert result["data"]["backups"][0]["content"]["addons"][0] == "local_ssh" 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_list(api_client, coresys: CoreSys, mock_full_backup: Backup): 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")
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.""" """Test list endpoint."""
copy(get_fixture_path("backup_example.tar"), tmp_path / "test_backup.tar")
resp = await api_client.get("/backups") resp = await api_client.get("/backups")
result = await resp.json() result = await resp.json()
assert len(result["data"]["backups"]) == 1 assert len(result["data"]["backups"]) == 1
@ -46,6 +78,8 @@ async def test_list(api_client, coresys: CoreSys, mock_full_backup: Backup):
assert result["data"]["backups"][0]["content"]["homeassistant"] is True assert result["data"]["backups"][0]["content"]["homeassistant"] is True
assert len(result["data"]["backups"][0]["content"]["addons"]) == 1 assert len(result["data"]["backups"][0]["content"]["addons"]) == 1
assert result["data"]["backups"][0]["content"]["addons"][0] == "local_ssh" 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): async def test_options(api_client, coresys: CoreSys):

View File

@ -30,6 +30,7 @@ from supervisor.const import (
ATTR_ADDONS, ATTR_ADDONS,
ATTR_ADDONS_CUSTOM_LIST, ATTR_ADDONS_CUSTOM_LIST,
ATTR_DATE, ATTR_DATE,
ATTR_EXCLUDE_DATABASE,
ATTR_FOLDERS, ATTR_FOLDERS,
ATTR_HOMEASSISTANT, ATTR_HOMEASSISTANT,
ATTR_NAME, ATTR_NAME,
@ -580,7 +581,7 @@ def install_addon_example(coresys: CoreSys, repository):
@pytest.fixture @pytest.fixture
async def mock_full_backup(coresys: CoreSys, tmp_path) -> Backup: async def mock_full_backup(coresys: CoreSys, tmp_path) -> Backup:
"""Mock a full 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.new("Test", utcnow().isoformat(), BackupType.FULL)
mock_backup.repositories = ["https://github.com/awesome-developer/awesome-repo"] mock_backup.repositories = ["https://github.com/awesome-developer/awesome-repo"]
mock_backup.docker = {} mock_backup.docker = {}
@ -596,6 +597,7 @@ async def mock_full_backup(coresys: CoreSys, tmp_path) -> Backup:
mock_backup._data[ATTR_HOMEASSISTANT] = { mock_backup._data[ATTR_HOMEASSISTANT] = {
ATTR_VERSION: AwesomeVersion("2022.8.0"), ATTR_VERSION: AwesomeVersion("2022.8.0"),
ATTR_SIZE: 0, ATTR_SIZE: 0,
ATTR_EXCLUDE_DATABASE: False,
} }
coresys.backups._backups = {"test": mock_backup} coresys.backups._backups = {"test": mock_backup}
yield mock_backup yield mock_backup
@ -604,7 +606,7 @@ async def mock_full_backup(coresys: CoreSys, tmp_path) -> Backup:
@pytest.fixture @pytest.fixture
async def mock_partial_backup(coresys: CoreSys, tmp_path) -> Backup: async def mock_partial_backup(coresys: CoreSys, tmp_path) -> Backup:
"""Mock a partial 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.new("Test", utcnow().isoformat(), BackupType.PARTIAL)
mock_backup.repositories = ["https://github.com/awesome-developer/awesome-repo"] mock_backup.repositories = ["https://github.com/awesome-developer/awesome-repo"]
mock_backup.docker = {} mock_backup.docker = {}
@ -620,6 +622,7 @@ async def mock_partial_backup(coresys: CoreSys, tmp_path) -> Backup:
mock_backup._data[ATTR_HOMEASSISTANT] = { mock_backup._data[ATTR_HOMEASSISTANT] = {
ATTR_VERSION: AwesomeVersion("2022.8.0"), ATTR_VERSION: AwesomeVersion("2022.8.0"),
ATTR_SIZE: 0, ATTR_SIZE: 0,
ATTR_EXCLUDE_DATABASE: False,
} }
coresys.backups._backups = {"test": mock_backup} coresys.backups._backups = {"test": mock_backup}
yield mock_backup yield mock_backup