mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Validate hassio backup settings (#138880)
* Validate hassio backup settings * Add snapshots * Don't reset addon and folder settings * Adapt to changes in BackupConfig.update
This commit is contained in:
parent
fb57284561
commit
0d8c449ff4
@ -16,7 +16,7 @@ from .agent import (
|
|||||||
BackupAgentPlatformProtocol,
|
BackupAgentPlatformProtocol,
|
||||||
LocalBackupAgent,
|
LocalBackupAgent,
|
||||||
)
|
)
|
||||||
from .config import BackupConfig
|
from .config import BackupConfig, CreateBackupParametersDict
|
||||||
from .const import DATA_MANAGER, DOMAIN
|
from .const import DATA_MANAGER, DOMAIN
|
||||||
from .http import async_register_http_views
|
from .http import async_register_http_views
|
||||||
from .manager import (
|
from .manager import (
|
||||||
@ -55,6 +55,7 @@ __all__ = [
|
|||||||
"BackupReaderWriter",
|
"BackupReaderWriter",
|
||||||
"BackupReaderWriterError",
|
"BackupReaderWriterError",
|
||||||
"CreateBackupEvent",
|
"CreateBackupEvent",
|
||||||
|
"CreateBackupParametersDict",
|
||||||
"CreateBackupStage",
|
"CreateBackupStage",
|
||||||
"CreateBackupState",
|
"CreateBackupState",
|
||||||
"Folder",
|
"Folder",
|
||||||
|
@ -33,6 +33,7 @@ from homeassistant.components.backup import (
|
|||||||
BackupReaderWriter,
|
BackupReaderWriter,
|
||||||
BackupReaderWriterError,
|
BackupReaderWriterError,
|
||||||
CreateBackupEvent,
|
CreateBackupEvent,
|
||||||
|
CreateBackupParametersDict,
|
||||||
CreateBackupStage,
|
CreateBackupStage,
|
||||||
CreateBackupState,
|
CreateBackupState,
|
||||||
Folder,
|
Folder,
|
||||||
@ -635,7 +636,25 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
|
|||||||
unsub()
|
unsub()
|
||||||
|
|
||||||
async def async_validate_config(self, *, config: BackupConfig) -> None:
|
async def async_validate_config(self, *, config: BackupConfig) -> None:
|
||||||
"""Validate backup config."""
|
"""Validate backup config.
|
||||||
|
|
||||||
|
Replace the core backup agent with the hassio default agent.
|
||||||
|
"""
|
||||||
|
core_agent_id = "backup.local"
|
||||||
|
create_backup = config.data.create_backup
|
||||||
|
if core_agent_id not in create_backup.agent_ids:
|
||||||
|
_LOGGER.debug("Backup settings don't need to be adjusted")
|
||||||
|
return
|
||||||
|
|
||||||
|
default_agent = await _default_agent(self._client)
|
||||||
|
_LOGGER.info("Adjusting backup settings to not include core backup location")
|
||||||
|
automatic_agents = [
|
||||||
|
agent_id if agent_id != core_agent_id else default_agent
|
||||||
|
for agent_id in create_backup.agent_ids
|
||||||
|
]
|
||||||
|
config.update(
|
||||||
|
create_backup=CreateBackupParametersDict(agent_ids=automatic_agents)
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_listen_job_events(
|
def _async_listen_job_events(
|
||||||
|
@ -625,7 +625,7 @@
|
|||||||
}),
|
}),
|
||||||
'create_backup': dict({
|
'create_backup': dict({
|
||||||
'agent_ids': list([
|
'agent_ids': list([
|
||||||
'backup.local',
|
'hassio.local',
|
||||||
'test-agent',
|
'test-agent',
|
||||||
]),
|
]),
|
||||||
'include_addons': None,
|
'include_addons': None,
|
||||||
|
@ -529,6 +529,7 @@ def resolution_suggestions_for_issue_fixture(supervisor_client: AsyncMock) -> As
|
|||||||
def supervisor_client() -> Generator[AsyncMock]:
|
def supervisor_client() -> Generator[AsyncMock]:
|
||||||
"""Mock the supervisor client."""
|
"""Mock the supervisor client."""
|
||||||
mounts_info_mock = AsyncMock(spec_set=["default_backup_mount", "mounts"])
|
mounts_info_mock = AsyncMock(spec_set=["default_backup_mount", "mounts"])
|
||||||
|
mounts_info_mock.default_backup_mount = None
|
||||||
mounts_info_mock.mounts = []
|
mounts_info_mock.mounts = []
|
||||||
supervisor_client = AsyncMock()
|
supervisor_client = AsyncMock()
|
||||||
supervisor_client.addons = AsyncMock()
|
supervisor_client.addons = AsyncMock()
|
||||||
|
130
tests/components/hassio/snapshots/test_backup.ambr
Normal file
130
tests/components/hassio/snapshots/test_backup.ambr
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_config_load_config_info[storage_data0]
|
||||||
|
dict({
|
||||||
|
'id': 1,
|
||||||
|
'result': dict({
|
||||||
|
'config': dict({
|
||||||
|
'agents': 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,
|
||||||
|
'next_automatic_backup': None,
|
||||||
|
'next_automatic_backup_additional': False,
|
||||||
|
'retention': dict({
|
||||||
|
'copies': None,
|
||||||
|
'days': None,
|
||||||
|
}),
|
||||||
|
'schedule': dict({
|
||||||
|
'days': list([
|
||||||
|
]),
|
||||||
|
'recurrence': 'never',
|
||||||
|
'time': None,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'success': True,
|
||||||
|
'type': 'result',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_config_load_config_info[storage_data1]
|
||||||
|
dict({
|
||||||
|
'id': 1,
|
||||||
|
'result': dict({
|
||||||
|
'config': dict({
|
||||||
|
'agents': dict({
|
||||||
|
}),
|
||||||
|
'create_backup': dict({
|
||||||
|
'agent_ids': list([
|
||||||
|
'test-agent1',
|
||||||
|
'hassio.local',
|
||||||
|
'test-agent2',
|
||||||
|
]),
|
||||||
|
'include_addons': list([
|
||||||
|
'addon1',
|
||||||
|
'addon2',
|
||||||
|
]),
|
||||||
|
'include_all_addons': True,
|
||||||
|
'include_database': True,
|
||||||
|
'include_folders': list([
|
||||||
|
'media',
|
||||||
|
'share',
|
||||||
|
]),
|
||||||
|
'name': None,
|
||||||
|
'password': None,
|
||||||
|
}),
|
||||||
|
'last_attempted_automatic_backup': None,
|
||||||
|
'last_completed_automatic_backup': None,
|
||||||
|
'next_automatic_backup': None,
|
||||||
|
'next_automatic_backup_additional': False,
|
||||||
|
'retention': dict({
|
||||||
|
'copies': None,
|
||||||
|
'days': None,
|
||||||
|
}),
|
||||||
|
'schedule': dict({
|
||||||
|
'days': list([
|
||||||
|
]),
|
||||||
|
'recurrence': 'never',
|
||||||
|
'time': None,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'success': True,
|
||||||
|
'type': 'result',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_config_load_config_info[storage_data2]
|
||||||
|
dict({
|
||||||
|
'id': 1,
|
||||||
|
'result': dict({
|
||||||
|
'config': dict({
|
||||||
|
'agents': dict({
|
||||||
|
}),
|
||||||
|
'create_backup': dict({
|
||||||
|
'agent_ids': list([
|
||||||
|
'test-agent1',
|
||||||
|
'hassio.local',
|
||||||
|
'test-agent2',
|
||||||
|
]),
|
||||||
|
'include_addons': list([
|
||||||
|
'addon1',
|
||||||
|
'addon2',
|
||||||
|
]),
|
||||||
|
'include_all_addons': False,
|
||||||
|
'include_database': True,
|
||||||
|
'include_folders': list([
|
||||||
|
'media',
|
||||||
|
'share',
|
||||||
|
]),
|
||||||
|
'name': None,
|
||||||
|
'password': None,
|
||||||
|
}),
|
||||||
|
'last_attempted_automatic_backup': None,
|
||||||
|
'last_completed_automatic_backup': None,
|
||||||
|
'next_automatic_backup': None,
|
||||||
|
'next_automatic_backup_additional': False,
|
||||||
|
'retention': dict({
|
||||||
|
'copies': None,
|
||||||
|
'days': None,
|
||||||
|
}),
|
||||||
|
'schedule': dict({
|
||||||
|
'days': list([
|
||||||
|
]),
|
||||||
|
'recurrence': 'never',
|
||||||
|
'time': None,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
'success': True,
|
||||||
|
'type': 'result',
|
||||||
|
})
|
||||||
|
# ---
|
@ -30,6 +30,7 @@ from aiohasupervisor.models.backups import LOCATION_CLOUD_BACKUP, LOCATION_LOCAL
|
|||||||
from aiohasupervisor.models.mounts import MountsInfo
|
from aiohasupervisor.models.mounts import MountsInfo
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.backup import (
|
from homeassistant.components.backup import (
|
||||||
DOMAIN as BACKUP_DOMAIN,
|
DOMAIN as BACKUP_DOMAIN,
|
||||||
@ -38,6 +39,7 @@ from homeassistant.components.backup import (
|
|||||||
BackupAgent,
|
BackupAgent,
|
||||||
BackupAgentPlatformProtocol,
|
BackupAgentPlatformProtocol,
|
||||||
Folder,
|
Folder,
|
||||||
|
store as backup_store,
|
||||||
)
|
)
|
||||||
from homeassistant.components.hassio import DOMAIN
|
from homeassistant.components.hassio import DOMAIN
|
||||||
from homeassistant.components.hassio.backup import RESTORE_JOB_ID_ENV
|
from homeassistant.components.hassio.backup import RESTORE_JOB_ID_ENV
|
||||||
@ -2466,3 +2468,94 @@ async def test_restore_progress_after_restart_unknown_job(
|
|||||||
assert response["success"]
|
assert response["success"]
|
||||||
assert response["result"]["last_non_idle_event"] is None
|
assert response["result"]["last_non_idle_event"] is None
|
||||||
assert response["result"]["state"] == "idle"
|
assert response["result"]["state"] == "idle"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"storage_data",
|
||||||
|
[
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"backup": {
|
||||||
|
"data": {
|
||||||
|
"backups": [],
|
||||||
|
"config": {
|
||||||
|
"agents": {},
|
||||||
|
"create_backup": {
|
||||||
|
"agent_ids": ["test-agent1", "hassio.local", "test-agent2"],
|
||||||
|
"include_addons": ["addon1", "addon2"],
|
||||||
|
"include_all_addons": True,
|
||||||
|
"include_database": True,
|
||||||
|
"include_folders": ["media", "share"],
|
||||||
|
"name": None,
|
||||||
|
"password": None,
|
||||||
|
},
|
||||||
|
"retention": {"copies": None, "days": None},
|
||||||
|
"last_attempted_automatic_backup": None,
|
||||||
|
"last_completed_automatic_backup": None,
|
||||||
|
"schedule": {
|
||||||
|
"days": [],
|
||||||
|
"recurrence": "never",
|
||||||
|
"state": "never",
|
||||||
|
"time": None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"key": DOMAIN,
|
||||||
|
"version": backup_store.STORAGE_VERSION,
|
||||||
|
"minor_version": backup_store.STORAGE_VERSION_MINOR,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backup": {
|
||||||
|
"data": {
|
||||||
|
"backups": [],
|
||||||
|
"config": {
|
||||||
|
"agents": {},
|
||||||
|
"create_backup": {
|
||||||
|
"agent_ids": ["test-agent1", "backup.local", "test-agent2"],
|
||||||
|
"include_addons": ["addon1", "addon2"],
|
||||||
|
"include_all_addons": False,
|
||||||
|
"include_database": True,
|
||||||
|
"include_folders": ["media", "share"],
|
||||||
|
"name": None,
|
||||||
|
"password": None,
|
||||||
|
},
|
||||||
|
"retention": {"copies": None, "days": None},
|
||||||
|
"last_attempted_automatic_backup": None,
|
||||||
|
"last_completed_automatic_backup": None,
|
||||||
|
"schedule": {
|
||||||
|
"days": [],
|
||||||
|
"recurrence": "never",
|
||||||
|
"state": "never",
|
||||||
|
"time": None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"key": DOMAIN,
|
||||||
|
"version": backup_store.STORAGE_VERSION,
|
||||||
|
"minor_version": backup_store.STORAGE_VERSION_MINOR,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.usefixtures("hassio_client")
|
||||||
|
async def test_config_load_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 loading stored backup config and reading it via 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)
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, BACKUP_DOMAIN, {BACKUP_DOMAIN: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
await client.send_json_auto_id({"type": "backup/config/info"})
|
||||||
|
assert await client.receive_json() == snapshot
|
||||||
|
Loading…
x
Reference in New Issue
Block a user