Fix load of backup store (#133024)

* Fix load of backup store

* Tweak type annotations in test

* Fix tests

* Remove the new test

* Remove snapshots
This commit is contained in:
Erik Montnemery 2024-12-12 16:54:21 +01:00 committed by GitHub
parent 0b18e51a13
commit 3d201690ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 46 deletions

View File

@ -33,8 +33,8 @@ class StoredBackupConfig(TypedDict):
"""Represent the stored backup config.""" """Represent the stored backup config."""
create_backup: StoredCreateBackupConfig create_backup: StoredCreateBackupConfig
last_attempted_strategy_backup: datetime | None last_attempted_strategy_backup: str | None
last_completed_strategy_backup: datetime | None last_completed_strategy_backup: str | None
retention: StoredRetentionConfig retention: StoredRetentionConfig
schedule: StoredBackupSchedule schedule: StoredBackupSchedule
@ -59,6 +59,16 @@ class BackupConfigData:
include_folders = None include_folders = None
retention = data["retention"] retention = data["retention"]
if last_attempted_str := data["last_attempted_strategy_backup"]:
last_attempted = dt_util.parse_datetime(last_attempted_str)
else:
last_attempted = None
if last_attempted_str := data["last_completed_strategy_backup"]:
last_completed = dt_util.parse_datetime(last_attempted_str)
else:
last_completed = None
return cls( return cls(
create_backup=CreateBackupConfig( create_backup=CreateBackupConfig(
agent_ids=data["create_backup"]["agent_ids"], agent_ids=data["create_backup"]["agent_ids"],
@ -69,8 +79,8 @@ class BackupConfigData:
name=data["create_backup"]["name"], name=data["create_backup"]["name"],
password=data["create_backup"]["password"], password=data["create_backup"]["password"],
), ),
last_attempted_strategy_backup=data["last_attempted_strategy_backup"], last_attempted_strategy_backup=last_attempted,
last_completed_strategy_backup=data["last_completed_strategy_backup"], last_completed_strategy_backup=last_completed,
retention=RetentionConfig( retention=RetentionConfig(
copies=retention["copies"], copies=retention["copies"],
days=retention["days"], days=retention["days"],
@ -80,10 +90,20 @@ class BackupConfigData:
def to_dict(self) -> StoredBackupConfig: def to_dict(self) -> StoredBackupConfig:
"""Convert backup config data to a dict.""" """Convert backup config data to a dict."""
if self.last_attempted_strategy_backup:
last_attempted = self.last_attempted_strategy_backup.isoformat()
else:
last_attempted = None
if self.last_completed_strategy_backup:
last_completed = self.last_completed_strategy_backup.isoformat()
else:
last_completed = None
return StoredBackupConfig( return StoredBackupConfig(
create_backup=self.create_backup.to_dict(), create_backup=self.create_backup.to_dict(),
last_attempted_strategy_backup=self.last_attempted_strategy_backup, last_attempted_strategy_backup=last_attempted,
last_completed_strategy_backup=self.last_completed_strategy_backup, last_completed_strategy_backup=last_completed,
retention=self.retention.to_dict(), retention=self.retention.to_dict(),
schedule=self.schedule.to_dict(), schedule=self.schedule.to_dict(),
) )

View File

@ -2,12 +2,14 @@
from __future__ import annotations from __future__ import annotations
from asyncio import Future
from collections.abc import Generator from collections.abc import Generator
from pathlib import Path from pathlib import Path
from unittest.mock import MagicMock, Mock, patch from unittest.mock import AsyncMock, MagicMock, Mock, patch
import pytest import pytest
from homeassistant.components.backup.manager import WrittenBackup
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .common import TEST_BACKUP_PATH_ABC123 from .common import TEST_BACKUP_PATH_ABC123
@ -62,6 +64,22 @@ CONFIG_DIR = {
CONFIG_DIR_DIRS = {Path(".storage"), Path("backups"), Path("tmp_backups")} CONFIG_DIR_DIRS = {Path(".storage"), Path("backups"), Path("tmp_backups")}
@pytest.fixture(name="create_backup")
def mock_create_backup() -> Generator[AsyncMock]:
"""Mock manager create backup."""
mock_written_backup = MagicMock(spec_set=WrittenBackup)
mock_written_backup.backup.backup_id = "abc123"
mock_written_backup.open_stream = AsyncMock()
mock_written_backup.release_stream = AsyncMock()
fut = Future()
fut.set_result(mock_written_backup)
with patch(
"homeassistant.components.backup.CoreBackupReaderWriter.async_create_backup"
) as mock_create_backup:
mock_create_backup.return_value = (MagicMock(), fut)
yield mock_create_backup
@pytest.fixture(name="mock_backup_generation") @pytest.fixture(name="mock_backup_generation")
def mock_backup_generation_fixture( def mock_backup_generation_fixture(
hass: HomeAssistant, mocked_json_bytes: Mock, mocked_tarfile: Mock hass: HomeAssistant, mocked_json_bytes: Mock, mocked_tarfile: Mock

View File

@ -1,8 +1,6 @@
"""Tests for the Backup integration.""" """Tests for the Backup integration."""
from asyncio import Future
from collections.abc import Generator from collections.abc import Generator
from datetime import datetime
from typing import Any from typing import Any
from unittest.mock import ANY, AsyncMock, MagicMock, call, patch from unittest.mock import ANY, AsyncMock, MagicMock, call, patch
@ -17,7 +15,6 @@ from homeassistant.components.backup.manager import (
CreateBackupEvent, CreateBackupEvent,
CreateBackupState, CreateBackupState,
NewBackup, NewBackup,
WrittenBackup,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
@ -89,22 +86,6 @@ def mock_delay_save() -> Generator[None]:
yield yield
@pytest.fixture(name="create_backup")
def mock_create_backup() -> Generator[AsyncMock]:
"""Mock manager create backup."""
mock_written_backup = MagicMock(spec_set=WrittenBackup)
mock_written_backup.backup.backup_id = "abc123"
mock_written_backup.open_stream = AsyncMock()
mock_written_backup.release_stream = AsyncMock()
fut = Future()
fut.set_result(mock_written_backup)
with patch(
"homeassistant.components.backup.CoreBackupReaderWriter.async_create_backup"
) as mock_create_backup:
mock_create_backup.return_value = (MagicMock(), fut)
yield mock_create_backup
@pytest.fixture(name="delete_backup") @pytest.fixture(name="delete_backup")
def mock_delete_backup() -> Generator[AsyncMock]: def mock_delete_backup() -> Generator[AsyncMock]:
"""Mock manager delete backup.""" """Mock manager delete backup."""
@ -798,12 +779,8 @@ async def test_agents_info(
"password": "test-password", "password": "test-password",
}, },
"retention": {"copies": 3, "days": 7}, "retention": {"copies": 3, "days": 7},
"last_attempted_strategy_backup": datetime.fromisoformat( "last_attempted_strategy_backup": "2024-10-26T04:45:00+01:00",
"2024-10-26T04:45:00+01:00" "last_completed_strategy_backup": "2024-10-26T04:45:00+01:00",
),
"last_completed_strategy_backup": datetime.fromisoformat(
"2024-10-26T04:45:00+01:00"
),
"schedule": {"state": "daily"}, "schedule": {"state": "daily"},
}, },
}, },
@ -838,12 +815,8 @@ async def test_agents_info(
"password": None, "password": None,
}, },
"retention": {"copies": None, "days": 7}, "retention": {"copies": None, "days": 7},
"last_attempted_strategy_backup": datetime.fromisoformat( "last_attempted_strategy_backup": "2024-10-27T04:45:00+01:00",
"2024-10-27T04:45:00+01:00" "last_completed_strategy_backup": "2024-10-26T04:45:00+01:00",
),
"last_completed_strategy_backup": datetime.fromisoformat(
"2024-10-26T04:45:00+01:00"
),
"schedule": {"state": "never"}, "schedule": {"state": "never"},
}, },
}, },
@ -1205,12 +1178,8 @@ async def test_config_schedule_logic(
"password": "test-password", "password": "test-password",
}, },
"retention": {"copies": None, "days": None}, "retention": {"copies": None, "days": None},
"last_attempted_strategy_backup": datetime.fromisoformat( "last_attempted_strategy_backup": last_completed_strategy_backup,
last_completed_strategy_backup "last_completed_strategy_backup": last_completed_strategy_backup,
),
"last_completed_strategy_backup": datetime.fromisoformat(
last_completed_strategy_backup
),
"schedule": {"state": "daily"}, "schedule": {"state": "daily"},
}, },
} }
@ -1486,7 +1455,7 @@ async def test_config_retention_copies_logic(
}, },
"retention": {"copies": None, "days": None}, "retention": {"copies": None, "days": None},
"last_attempted_strategy_backup": None, "last_attempted_strategy_backup": None,
"last_completed_strategy_backup": datetime.fromisoformat(last_backup_time), "last_completed_strategy_backup": last_backup_time,
"schedule": {"state": "daily"}, "schedule": {"state": "daily"},
}, },
} }
@ -1699,7 +1668,7 @@ async def test_config_retention_days_logic(
}, },
"retention": {"copies": None, "days": None}, "retention": {"copies": None, "days": None},
"last_attempted_strategy_backup": None, "last_attempted_strategy_backup": None,
"last_completed_strategy_backup": datetime.fromisoformat(last_backup_time), "last_completed_strategy_backup": last_backup_time,
"schedule": {"state": "never"}, "schedule": {"state": "never"},
}, },
} }