Prepare backup store to read version 2 (#136149)

This commit is contained in:
Erik Montnemery 2025-01-21 14:37:44 +01:00 committed by GitHub
parent 5b49ba563e
commit a2cbaef264
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 234 additions and 35 deletions

View File

@ -102,7 +102,7 @@ class BackupConfigData:
schedule=BackupSchedule( schedule=BackupSchedule(
days=days, days=days,
recurrence=ScheduleRecurrence(data["schedule"]["recurrence"]), recurrence=ScheduleRecurrence(data["schedule"]["recurrence"]),
state=ScheduleState(data["schedule"]["state"]), state=ScheduleState(data["schedule"].get("state", ScheduleState.NEVER)),
time=time, time=time,
), ),
) )

View File

@ -57,7 +57,9 @@ class _BackupStore(Store[StoredBackupData]):
data["config"]["schedule"]["days"] = [state] data["config"]["schedule"]["days"] = [state]
data["config"]["schedule"]["recurrence"] = "custom_days" data["config"]["schedule"]["recurrence"] = "custom_days"
if old_major_version > 1: # Note: We allow reading data with major version 2.
# Reject if major version is higher than 2.
if old_major_version > 2:
raise NotImplementedError raise NotImplementedError
return data return data

View File

@ -1,5 +1,5 @@
# serializer version: 1 # serializer version: 1
# name: test_store_migration # name: test_store_migration[store_data0]
dict({ dict({
'data': dict({ 'data': dict({
'backups': list([ 'backups': list([
@ -41,3 +41,131 @@
'version': 1, 'version': 1,
}) })
# --- # ---
# name: test_store_migration[store_data0].1
dict({
'data': dict({
'backups': list([
dict({
'backup_id': 'abc123',
'failed_agent_ids': list([
'test.remote',
]),
}),
]),
'config': dict({
'create_backup': dict({
'agent_ids': list([
'test-agent',
]),
'include_addons': None,
'include_all_addons': False,
'include_database': True,
'include_folders': None,
'name': None,
'password': None,
}),
'last_attempted_automatic_backup': None,
'last_completed_automatic_backup': None,
'retention': dict({
'copies': None,
'days': None,
}),
'schedule': dict({
'days': list([
]),
'recurrence': 'never',
'state': 'never',
'time': None,
}),
}),
}),
'key': 'backup',
'minor_version': 2,
'version': 1,
})
# ---
# name: test_store_migration[store_data1]
dict({
'data': dict({
'backups': list([
dict({
'backup_id': 'abc123',
'failed_agent_ids': list([
'test.remote',
]),
}),
]),
'config': dict({
'create_backup': dict({
'agent_ids': list([
]),
'include_addons': None,
'include_all_addons': False,
'include_database': True,
'include_folders': None,
'name': None,
'password': None,
}),
'last_attempted_automatic_backup': None,
'last_completed_automatic_backup': None,
'retention': dict({
'copies': None,
'days': None,
}),
'schedule': dict({
'days': list([
]),
'recurrence': 'never',
'time': None,
}),
'something_from_the_future': 'value',
}),
}),
'key': 'backup',
'minor_version': 2,
'version': 1,
})
# ---
# name: test_store_migration[store_data1].1
dict({
'data': dict({
'backups': list([
dict({
'backup_id': 'abc123',
'failed_agent_ids': list([
'test.remote',
]),
}),
]),
'config': dict({
'create_backup': dict({
'agent_ids': list([
'test-agent',
]),
'include_addons': None,
'include_all_addons': False,
'include_database': True,
'include_folders': None,
'name': None,
'password': None,
}),
'last_attempted_automatic_backup': None,
'last_completed_automatic_backup': None,
'retention': dict({
'copies': None,
'days': None,
}),
'schedule': dict({
'days': list([
]),
'recurrence': 'never',
'state': 'never',
'time': None,
}),
}),
}),
'key': 'backup',
'minor_version': 2,
'version': 1,
})
# ---

View File

@ -1,7 +1,10 @@
"""Tests for the Backup integration.""" """Tests for the Backup integration."""
from collections.abc import Generator
from typing import Any from typing import Any
from unittest.mock import patch
import pytest
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.backup.const import DOMAIN from homeassistant.components.backup.const import DOMAIN
@ -9,14 +12,20 @@ from homeassistant.core import HomeAssistant
from .common import setup_backup_integration from .common import setup_backup_integration
from tests.typing import WebSocketGenerator
async def test_store_migration(
hass: HomeAssistant, @pytest.fixture(autouse=True)
hass_storage: dict[str, Any], def mock_delay_save() -> Generator[None]:
snapshot: SnapshotAssertion, """Mock the delay save constant."""
) -> None: with patch("homeassistant.components.backup.store.STORE_DELAY_SAVE", 0):
"""Test migrating the backup store.""" yield
hass_storage[DOMAIN] = {
@pytest.mark.parametrize(
"store_data",
[
{
"data": { "data": {
"backups": [ "backups": [
{ {
@ -47,8 +56,68 @@ async def test_store_migration(
}, },
"key": DOMAIN, "key": DOMAIN,
"version": 1, "version": 1,
},
{
"data": {
"backups": [
{
"backup_id": "abc123",
"failed_agent_ids": ["test.remote"],
} }
],
"config": {
"create_backup": {
"agent_ids": [],
"include_addons": None,
"include_all_addons": False,
"include_database": True,
"include_folders": None,
"name": None,
"password": None,
},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": None,
"retention": {
"copies": None,
"days": None,
},
"schedule": {
"days": [],
"recurrence": "never",
"time": None,
},
"something_from_the_future": "value",
},
},
"key": DOMAIN,
"version": 2,
},
],
)
async def test_store_migration(
hass: HomeAssistant,
hass_storage: dict[str, Any],
hass_ws_client: WebSocketGenerator,
snapshot: SnapshotAssertion,
store_data: dict[str, Any],
) -> None:
"""Test migrating the backup store."""
hass_storage[DOMAIN] = store_data
await setup_backup_integration(hass) await setup_backup_integration(hass)
await hass.async_block_till_done() await hass.async_block_till_done()
# Check migrated data
assert hass_storage[DOMAIN] == snapshot
# Update settings, then check saved data
client = await hass_ws_client(hass)
await client.send_json_auto_id(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
}
)
result = await client.receive_json()
assert result["success"]
await hass.async_block_till_done()
assert hass_storage[DOMAIN] == snapshot assert hass_storage[DOMAIN] == snapshot