Make the time for automated backups configurable (#135825)

* Make the time for automated backups configurable

* Store time as a string, use None to indicate default time

* Don't add jitter if the time is set by user

* Include time of next automatic backup in response to backup/info

* Update tests

* Rename recurrence to state

* Include scheduled backup time in backup/config/info response

* Address review comments

* Update cloud test

* Add test for store migration

* Address review comments
This commit is contained in:
Erik Montnemery
2025-01-20 12:57:46 +01:00
committed by GitHub
parent 8020bec47b
commit 43da828a51
10 changed files with 629 additions and 122 deletions

View File

@@ -14,6 +14,7 @@ from homeassistant.components.backup import (
BackupAgentPlatformProtocol,
BackupReaderWriterError,
Folder,
store,
)
from homeassistant.components.backup.agent import BackupAgentUnreachableError
from homeassistant.components.backup.const import DATA_MANAGER, DOMAIN
@@ -70,9 +71,7 @@ DEFAULT_STORAGE_DATA: dict[str, Any] = {
"copies": None,
"days": None,
},
"schedule": {
"state": "never",
},
"schedule": {"state": "never", "time": None},
},
}
@@ -305,7 +304,8 @@ async def test_delete_with_errors(
hass_storage[DOMAIN] = {
"data": storage_data,
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
}
await setup_backup_integration(
hass, with_hassio=False, backups={LOCAL_AGENT_ID: [TEST_BACKUP_ABC123]}
@@ -924,11 +924,12 @@ async def test_agents_info(
"retention": {"copies": 3, "days": 7},
"last_attempted_automatic_backup": "2024-10-26T04:45:00+01:00",
"last_completed_automatic_backup": "2024-10-26T04:45:00+01:00",
"schedule": {"state": "daily"},
"schedule": {"state": "daily", "time": None},
},
},
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
},
},
{
@@ -948,11 +949,12 @@ async def test_agents_info(
"retention": {"copies": 3, "days": None},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": None,
"schedule": {"state": "never"},
"schedule": {"state": "never", "time": None},
},
},
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
},
},
{
@@ -972,11 +974,12 @@ async def test_agents_info(
"retention": {"copies": None, "days": 7},
"last_attempted_automatic_backup": "2024-10-27T04:45:00+01:00",
"last_completed_automatic_backup": "2024-10-26T04:45:00+01:00",
"schedule": {"state": "never"},
"schedule": {"state": "never", "time": None},
},
},
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
},
},
{
@@ -996,11 +999,12 @@ async def test_agents_info(
"retention": {"copies": None, "days": None},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": None,
"schedule": {"state": "mon"},
"schedule": {"state": "mon", "time": None},
},
},
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
},
},
{
@@ -1020,30 +1024,35 @@ async def test_agents_info(
"retention": {"copies": None, "days": None},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": None,
"schedule": {"state": "sat"},
"schedule": {"state": "sat", "time": None},
},
},
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
},
},
],
)
@patch("homeassistant.components.backup.config.random.randint", Mock(return_value=600))
async def test_config_info(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
freezer: FrozenDateTimeFactory,
snapshot: SnapshotAssertion,
hass_storage: dict[str, Any],
storage_data: dict[str, Any] | None,
) -> None:
"""Test getting backup config info."""
client = await hass_ws_client(hass)
await hass.config.async_set_time_zone("Europe/Amsterdam")
freezer.move_to("2024-11-13T12:01:00+01:00")
hass_storage.update(storage_data)
await setup_backup_integration(hass)
await hass.async_block_till_done()
client = await hass_ws_client(hass)
await client.send_json_auto_id({"type": "backup/config/info"})
assert await client.receive_json() == snapshot
@@ -1060,17 +1069,17 @@ async def test_config_info(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"schedule": "daily",
"schedule": {"state": "daily", "time": "06:00"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"schedule": "mon",
"schedule": {"state": "mon"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"schedule": "never",
"schedule": {"state": "never"},
},
{
"type": "backup/config/update",
@@ -1081,59 +1090,63 @@ async def test_config_info(
"name": "test-name",
"password": "test-password",
},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": 3, "days": 7},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": 3, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 7},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": 3},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"days": 7},
"schedule": "daily",
"schedule": {"state": "daily"},
},
],
)
@patch("homeassistant.components.backup.config.random.randint", Mock(return_value=600))
async def test_config_update(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
freezer: FrozenDateTimeFactory,
snapshot: SnapshotAssertion,
command: dict[str, Any],
hass_storage: dict[str, Any],
) -> None:
"""Test updating the backup config."""
client = await hass_ws_client(hass)
await hass.config.async_set_time_zone("Europe/Amsterdam")
freezer.move_to("2024-11-13T12:01:00+01:00")
await setup_backup_integration(hass)
await hass.async_block_till_done()
client = await hass_ws_client(hass)
await client.send_json_auto_id({"type": "backup/config/info"})
assert await client.receive_json() == snapshot
@@ -1146,6 +1159,11 @@ async def test_config_update(
assert await client.receive_json() == snapshot
await hass.async_block_till_done()
# Trigger store write
freezer.tick(60)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert hass_storage[DOMAIN] == snapshot
@@ -1156,7 +1174,17 @@ async def test_config_update(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"schedule": "someday",
"schedule": "blah",
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"schedule": {"state": "someday"},
},
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"schedule": {"time": "early"},
},
{
"type": "backup/config/update",
@@ -1205,6 +1233,7 @@ async def test_config_update_errors(
"time_2",
"attempted_backup_time",
"completed_backup_time",
"scheduled_backup_time",
"backup_calls_1",
"backup_calls_2",
"call_args",
@@ -1215,10 +1244,11 @@ async def test_config_update_errors(
# No config update
[],
"2024-11-11T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-13T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-13T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
1,
2,
BACKUP_CALL,
@@ -1230,14 +1260,15 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "daily",
"schedule": {"state": "daily"},
}
],
"2024-11-11T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-13T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-13T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
1,
2,
BACKUP_CALL,
@@ -1248,14 +1279,15 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "mon",
"schedule": {"state": "mon"},
}
],
"2024-11-11T04:45:00+01:00",
"2024-11-18T04:45:00+01:00",
"2024-11-25T04:45:00+01:00",
"2024-11-18T04:45:00+01:00",
"2024-11-18T04:45:00+01:00",
"2024-11-18T04:55:00+01:00",
"2024-11-25T04:55:00+01:00",
"2024-11-18T04:55:00+01:00",
"2024-11-18T04:55:00+01:00",
"2024-11-18T04:55:00+01:00",
1,
2,
BACKUP_CALL,
@@ -1266,7 +1298,45 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "never",
"schedule": {"state": "mon", "time": "03:45"},
}
],
"2024-11-11T03:45:00+01:00",
"2024-11-18T03:45:00+01:00",
"2024-11-25T03:45:00+01:00",
"2024-11-18T03:45:00+01:00",
"2024-11-18T03:45:00+01:00",
"2024-11-18T03:45:00+01:00",
1,
2,
BACKUP_CALL,
None,
),
(
[
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": {"state": "daily", "time": "03:45"},
}
],
"2024-11-11T03:45:00+01:00",
"2024-11-12T03:45:00+01:00",
"2024-11-13T03:45:00+01:00",
"2024-11-12T03:45:00+01:00",
"2024-11-12T03:45:00+01:00",
"2024-11-12T03:45:00+01:00",
1,
2,
BACKUP_CALL,
None,
),
(
[
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": {"state": "never"},
}
],
"2024-11-11T04:45:00+01:00",
@@ -1274,6 +1344,7 @@ async def test_config_update_errors(
"2034-11-11T13:00:00+01:00",
"2024-11-11T04:45:00+01:00",
"2024-11-11T04:45:00+01:00",
None,
0,
0,
None,
@@ -1284,14 +1355,15 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "daily",
"schedule": {"state": "daily"},
}
],
"2024-10-26T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-13T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-13T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
"2024-11-12T04:55:00+01:00",
1,
2,
BACKUP_CALL,
@@ -1302,14 +1374,15 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "mon",
"schedule": {"state": "mon"},
}
],
"2024-10-26T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-13T04:45:00+01:00",
"2024-11-12T04:45:00+01:00", # missed event uses daily schedule once
"2024-11-12T04:45:00+01:00", # missed event uses daily schedule once
"2024-11-12T04:55:00+01:00",
"2024-11-13T04:55:00+01:00",
"2024-11-12T04:55:00+01:00", # missed event uses daily schedule once
"2024-11-12T04:55:00+01:00", # missed event uses daily schedule once
"2024-11-12T04:55:00+01:00",
1,
1,
BACKUP_CALL,
@@ -1320,7 +1393,7 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "never",
"schedule": {"state": "never"},
}
],
"2024-10-26T04:45:00+01:00",
@@ -1328,6 +1401,7 @@ async def test_config_update_errors(
"2034-11-12T12:00:00+01:00",
"2024-10-26T04:45:00+01:00",
"2024-10-26T04:45:00+01:00",
None,
0,
0,
None,
@@ -1338,14 +1412,15 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "daily",
"schedule": {"state": "daily"},
}
],
"2024-11-11T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-13T04:45:00+01:00",
"2024-11-12T04:45:00+01:00", # attempted to create backup but failed
"2024-11-12T04:55:00+01:00",
"2024-11-13T04:55:00+01:00",
"2024-11-12T04:55:00+01:00", # attempted to create backup but failed
"2024-11-11T04:45:00+01:00",
"2024-11-12T04:55:00+01:00",
1,
2,
BACKUP_CALL,
@@ -1356,14 +1431,15 @@ async def test_config_update_errors(
{
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"schedule": "daily",
"schedule": {"state": "daily"},
}
],
"2024-11-11T04:45:00+01:00",
"2024-11-12T04:45:00+01:00",
"2024-11-13T04:45:00+01:00",
"2024-11-12T04:45:00+01:00", # attempted to create backup but failed
"2024-11-12T04:55:00+01:00",
"2024-11-13T04:55:00+01:00",
"2024-11-12T04:55:00+01:00", # attempted to create backup but failed
"2024-11-11T04:45:00+01:00",
"2024-11-12T04:55:00+01:00",
1,
2,
BACKUP_CALL,
@@ -1371,7 +1447,7 @@ async def test_config_update_errors(
),
],
)
@patch("homeassistant.components.backup.config.BACKUP_START_TIME_JITTER", 0)
@patch("homeassistant.components.backup.config.random.randint", Mock(return_value=600))
async def test_config_schedule_logic(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
@@ -1384,6 +1460,7 @@ async def test_config_schedule_logic(
time_2: str,
attempted_backup_time: str,
completed_backup_time: str,
scheduled_backup_time: str,
backup_calls_1: int,
backup_calls_2: int,
call_args: Any,
@@ -1406,13 +1483,14 @@ async def test_config_schedule_logic(
"retention": {"copies": None, "days": None},
"last_attempted_automatic_backup": last_completed_automatic_backup,
"last_completed_automatic_backup": last_completed_automatic_backup,
"schedule": {"state": "daily"},
"schedule": {"state": "daily", "time": None},
},
}
hass_storage[DOMAIN] = {
"data": storage_data,
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
}
create_backup.side_effect = create_backup_side_effect
await hass.config.async_set_time_zone("Europe/Amsterdam")
@@ -1426,6 +1504,10 @@ async def test_config_schedule_logic(
result = await client.receive_json()
assert result["success"]
await client.send_json_auto_id({"type": "backup/info"})
result = await client.receive_json()
assert result["result"]["next_automatic_backup"] == scheduled_backup_time
freezer.move_to(time_1)
async_fire_time_changed(hass)
await hass.async_block_till_done()
@@ -1471,7 +1553,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": None, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1510,7 +1592,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 3, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1549,7 +1631,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 3, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1578,7 +1660,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 3, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1622,7 +1704,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 2, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1666,7 +1748,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 2, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1705,7 +1787,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 2, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1744,7 +1826,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 0, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1788,7 +1870,7 @@ async def test_config_schedule_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 0, "days": None},
"schedule": "daily",
"schedule": {"state": "daily"},
},
{
"backup-1": MagicMock(
@@ -1852,13 +1934,14 @@ async def test_config_retention_copies_logic(
"retention": {"copies": None, "days": None},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": last_backup_time,
"schedule": {"state": "daily"},
"schedule": {"state": "daily", "time": None},
},
}
hass_storage[DOMAIN] = {
"data": storage_data,
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
}
get_backups.return_value = (backups, get_backups_agent_errors)
delete_backup.return_value = delete_backup_agent_errors
@@ -1922,7 +2005,7 @@ async def test_config_retention_copies_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": None, "days": None},
"schedule": "never",
"schedule": {"state": "never"},
},
{
"backup-1": MagicMock(
@@ -1958,7 +2041,7 @@ async def test_config_retention_copies_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 3, "days": None},
"schedule": "never",
"schedule": {"state": "never"},
},
{
"backup-1": MagicMock(
@@ -1994,7 +2077,7 @@ async def test_config_retention_copies_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 3, "days": None},
"schedule": "never",
"schedule": {"state": "never"},
},
{
"backup-1": MagicMock(
@@ -2035,7 +2118,7 @@ async def test_config_retention_copies_logic(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test.test-agent"]},
"retention": {"copies": 2, "days": None},
"schedule": "never",
"schedule": {"state": "never"},
},
{
"backup-1": MagicMock(
@@ -2109,13 +2192,14 @@ async def test_config_retention_copies_logic_manual_backup(
"retention": {"copies": None, "days": None},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": None,
"schedule": {"state": "daily"},
"schedule": {"state": "daily", "time": None},
},
}
hass_storage[DOMAIN] = {
"data": storage_data,
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
}
get_backups.return_value = (backups, get_backups_agent_errors)
delete_backup.return_value = delete_backup_agent_errors
@@ -2236,7 +2320,7 @@ async def test_config_retention_copies_logic_manual_backup(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 2},
"schedule": "never",
"schedule": {"state": "never"},
}
],
{
@@ -2272,7 +2356,7 @@ async def test_config_retention_copies_logic_manual_backup(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 2},
"schedule": "never",
"schedule": {"state": "never"},
}
],
{
@@ -2308,7 +2392,7 @@ async def test_config_retention_copies_logic_manual_backup(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 3},
"schedule": "never",
"schedule": {"state": "never"},
}
],
{
@@ -2344,7 +2428,7 @@ async def test_config_retention_copies_logic_manual_backup(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 2},
"schedule": "never",
"schedule": {"state": "never"},
}
],
{
@@ -2385,7 +2469,7 @@ async def test_config_retention_copies_logic_manual_backup(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 2},
"schedule": "never",
"schedule": {"state": "never"},
}
],
{
@@ -2421,7 +2505,7 @@ async def test_config_retention_copies_logic_manual_backup(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 2},
"schedule": "never",
"schedule": {"state": "never"},
}
],
{
@@ -2457,7 +2541,7 @@ async def test_config_retention_copies_logic_manual_backup(
"type": "backup/config/update",
"create_backup": {"agent_ids": ["test-agent"]},
"retention": {"copies": None, "days": 0},
"schedule": "never",
"schedule": {"state": "never"},
}
],
{
@@ -2529,13 +2613,14 @@ async def test_config_retention_days_logic(
"retention": {"copies": None, "days": stored_retained_days},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": last_backup_time,
"schedule": {"state": "never"},
"schedule": {"state": "never", "time": None},
},
}
hass_storage[DOMAIN] = {
"data": storage_data,
"key": DOMAIN,
"version": 1,
"version": store.STORAGE_VERSION,
"minor_version": store.STORAGE_VERSION_MINOR,
}
get_backups.return_value = (backups, get_backups_agent_errors)
delete_backup.return_value = delete_backup_agent_errors