Store information about add-ons and folders which could not be backed up (#145367)

* Store information about add-ons and folders which could not be backed up

* Address review comments
This commit is contained in:
Erik Montnemery 2025-05-26 16:07:33 +02:00 committed by GitHub
parent 0802fc8a21
commit 0260a03447
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 621 additions and 92 deletions

View File

@ -62,6 +62,7 @@ from .const import (
LOGGER, LOGGER,
) )
from .models import ( from .models import (
AddonInfo,
AgentBackup, AgentBackup,
BackupError, BackupError,
BackupManagerError, BackupManagerError,
@ -102,7 +103,9 @@ class ManagerBackup(BaseBackup):
"""Backup class.""" """Backup class."""
agents: dict[str, AgentBackupStatus] agents: dict[str, AgentBackupStatus]
failed_addons: list[AddonInfo]
failed_agent_ids: list[str] failed_agent_ids: list[str]
failed_folders: list[Folder]
with_automatic_settings: bool | None with_automatic_settings: bool | None
@ -110,7 +113,7 @@ class ManagerBackup(BaseBackup):
class AddonErrorData: class AddonErrorData:
"""Addon error class.""" """Addon error class."""
name: str addon: AddonInfo
errors: list[tuple[str, str]] errors: list[tuple[str, str]]
@ -646,9 +649,13 @@ class BackupManager:
for agent_backup in result: for agent_backup in result:
if (backup_id := agent_backup.backup_id) not in backups: if (backup_id := agent_backup.backup_id) not in backups:
if known_backup := self.known_backups.get(backup_id): if known_backup := self.known_backups.get(backup_id):
failed_addons = known_backup.failed_addons
failed_agent_ids = known_backup.failed_agent_ids failed_agent_ids = known_backup.failed_agent_ids
failed_folders = known_backup.failed_folders
else: else:
failed_addons = []
failed_agent_ids = [] failed_agent_ids = []
failed_folders = []
with_automatic_settings = self.is_our_automatic_backup( with_automatic_settings = self.is_our_automatic_backup(
agent_backup, await instance_id.async_get(self.hass) agent_backup, await instance_id.async_get(self.hass)
) )
@ -659,7 +666,9 @@ class BackupManager:
date=agent_backup.date, date=agent_backup.date,
database_included=agent_backup.database_included, database_included=agent_backup.database_included,
extra_metadata=agent_backup.extra_metadata, extra_metadata=agent_backup.extra_metadata,
failed_addons=failed_addons,
failed_agent_ids=failed_agent_ids, failed_agent_ids=failed_agent_ids,
failed_folders=failed_folders,
folders=agent_backup.folders, folders=agent_backup.folders,
homeassistant_included=agent_backup.homeassistant_included, homeassistant_included=agent_backup.homeassistant_included,
homeassistant_version=agent_backup.homeassistant_version, homeassistant_version=agent_backup.homeassistant_version,
@ -714,9 +723,13 @@ class BackupManager:
continue continue
if backup is None: if backup is None:
if known_backup := self.known_backups.get(backup_id): if known_backup := self.known_backups.get(backup_id):
failed_addons = known_backup.failed_addons
failed_agent_ids = known_backup.failed_agent_ids failed_agent_ids = known_backup.failed_agent_ids
failed_folders = known_backup.failed_folders
else: else:
failed_addons = []
failed_agent_ids = [] failed_agent_ids = []
failed_folders = []
with_automatic_settings = self.is_our_automatic_backup( with_automatic_settings = self.is_our_automatic_backup(
result, await instance_id.async_get(self.hass) result, await instance_id.async_get(self.hass)
) )
@ -727,7 +740,9 @@ class BackupManager:
date=result.date, date=result.date,
database_included=result.database_included, database_included=result.database_included,
extra_metadata=result.extra_metadata, extra_metadata=result.extra_metadata,
failed_addons=failed_addons,
failed_agent_ids=failed_agent_ids, failed_agent_ids=failed_agent_ids,
failed_folders=failed_folders,
folders=result.folders, folders=result.folders,
homeassistant_included=result.homeassistant_included, homeassistant_included=result.homeassistant_included,
homeassistant_version=result.homeassistant_version, homeassistant_version=result.homeassistant_version,
@ -970,7 +985,7 @@ class BackupManager:
password=None, password=None,
) )
await written_backup.release_stream() await written_backup.release_stream()
self.known_backups.add(written_backup.backup, agent_errors, []) self.known_backups.add(written_backup.backup, agent_errors, {}, {}, [])
return written_backup.backup.backup_id return written_backup.backup.backup_id
async def async_create_backup( async def async_create_backup(
@ -1208,7 +1223,11 @@ class BackupManager:
finally: finally:
await written_backup.release_stream() await written_backup.release_stream()
self.known_backups.add( self.known_backups.add(
written_backup.backup, agent_errors, unavailable_agents written_backup.backup,
agent_errors,
written_backup.addon_errors,
written_backup.folder_errors,
unavailable_agents,
) )
if not agent_errors: if not agent_errors:
if with_automatic_settings: if with_automatic_settings:
@ -1416,7 +1435,12 @@ class BackupManager:
# No issues with agents or folders, but issues with add-ons # No issues with agents or folders, but issues with add-ons
self._create_automatic_backup_failed_issue( self._create_automatic_backup_failed_issue(
"automatic_backup_failed_addons", "automatic_backup_failed_addons",
{"failed_addons": ", ".join(val.name for val in addon_errors.values())}, {
"failed_addons": ", ".join(
val.addon.name or val.addon.slug
for val in addon_errors.values()
)
},
) )
elif folder_errors and not (failed_agents or addon_errors): elif folder_errors and not (failed_agents or addon_errors):
# No issues with agents or add-ons, but issues with folders # No issues with agents or add-ons, but issues with folders
@ -1431,7 +1455,11 @@ class BackupManager:
{ {
"failed_agents": ", ".join(failed_agents) or "-", "failed_agents": ", ".join(failed_agents) or "-",
"failed_addons": ( "failed_addons": (
", ".join(val.name for val in addon_errors.values()) or "-" ", ".join(
val.addon.name or val.addon.slug
for val in addon_errors.values()
)
or "-"
), ),
"failed_folders": ", ".join(f for f in folder_errors) or "-", "failed_folders": ", ".join(f for f in folder_errors) or "-",
}, },
@ -1501,7 +1529,12 @@ class KnownBackups:
self._backups = { self._backups = {
backup["backup_id"]: KnownBackup( backup["backup_id"]: KnownBackup(
backup_id=backup["backup_id"], backup_id=backup["backup_id"],
failed_addons=[
AddonInfo(name=a["name"], slug=a["slug"], version=a["version"])
for a in backup["failed_addons"]
],
failed_agent_ids=backup["failed_agent_ids"], failed_agent_ids=backup["failed_agent_ids"],
failed_folders=[Folder(f) for f in backup["failed_folders"]],
) )
for backup in stored_backups for backup in stored_backups
} }
@ -1514,12 +1547,16 @@ class KnownBackups:
self, self,
backup: AgentBackup, backup: AgentBackup,
agent_errors: dict[str, Exception], agent_errors: dict[str, Exception],
failed_addons: dict[str, AddonErrorData],
failed_folders: dict[Folder, list[tuple[str, str]]],
unavailable_agents: list[str], unavailable_agents: list[str],
) -> None: ) -> None:
"""Add a backup.""" """Add a backup."""
self._backups[backup.backup_id] = KnownBackup( self._backups[backup.backup_id] = KnownBackup(
backup_id=backup.backup_id, backup_id=backup.backup_id,
failed_addons=[val.addon for val in failed_addons.values()],
failed_agent_ids=list(chain(agent_errors, unavailable_agents)), failed_agent_ids=list(chain(agent_errors, unavailable_agents)),
failed_folders=list(failed_folders),
) )
self._manager.store.save() self._manager.store.save()
@ -1540,21 +1577,38 @@ class KnownBackup:
"""Persistent backup data.""" """Persistent backup data."""
backup_id: str backup_id: str
failed_addons: list[AddonInfo]
failed_agent_ids: list[str] failed_agent_ids: list[str]
failed_folders: list[Folder]
def to_dict(self) -> StoredKnownBackup: def to_dict(self) -> StoredKnownBackup:
"""Convert known backup to a dict.""" """Convert known backup to a dict."""
return { return {
"backup_id": self.backup_id, "backup_id": self.backup_id,
"failed_addons": [
{"name": a.name, "slug": a.slug, "version": a.version}
for a in self.failed_addons
],
"failed_agent_ids": self.failed_agent_ids, "failed_agent_ids": self.failed_agent_ids,
"failed_folders": [f.value for f in self.failed_folders],
} }
class StoredAddonInfo(TypedDict):
"""Stored add-on info."""
name: str | None
slug: str
version: str | None
class StoredKnownBackup(TypedDict): class StoredKnownBackup(TypedDict):
"""Stored persistent backup data.""" """Stored persistent backup data."""
backup_id: str backup_id: str
failed_addons: list[StoredAddonInfo]
failed_agent_ids: list[str] failed_agent_ids: list[str]
failed_folders: list[str]
class CoreBackupReaderWriter(BackupReaderWriter): class CoreBackupReaderWriter(BackupReaderWriter):

View File

@ -13,9 +13,9 @@ from homeassistant.exceptions import HomeAssistantError
class AddonInfo: class AddonInfo:
"""Addon information.""" """Addon information."""
name: str name: str | None
slug: str slug: str
version: str version: str | None
class Folder(StrEnum): class Folder(StrEnum):

View File

@ -16,7 +16,7 @@ if TYPE_CHECKING:
STORE_DELAY_SAVE = 30 STORE_DELAY_SAVE = 30
STORAGE_KEY = DOMAIN STORAGE_KEY = DOMAIN
STORAGE_VERSION = 1 STORAGE_VERSION = 1
STORAGE_VERSION_MINOR = 6 STORAGE_VERSION_MINOR = 7
class StoredBackupData(TypedDict): class StoredBackupData(TypedDict):
@ -76,6 +76,11 @@ class _BackupStore(Store[StoredBackupData]):
# Version 1.6 adds agent retention settings # Version 1.6 adds agent retention settings
for agent in data["config"]["agents"]: for agent in data["config"]["agents"]:
data["config"]["agents"][agent]["retention"] = None data["config"]["agents"][agent]["retention"] = None
if old_minor_version < 7:
# Version 1.7 adds failing addons and folders
for backup in data["backups"]:
backup["failed_addons"] = []
backup["failed_folders"] = []
# Note: We allow reading data with major version 2 in which the unused key # Note: We allow reading data with major version 2 in which the unused key
# data["config"]["schedule"]["state"] will be removed. The bump to 2 is # data["config"]["schedule"]["state"] will be removed. The bump to 2 is

View File

@ -429,10 +429,19 @@ class SupervisorBackupReaderWriter(BackupReaderWriter):
for slug, errors in _addon_errors.items(): for slug, errors in _addon_errors.items():
try: try:
addon_info = await self._client.addons.addon_info(slug) addon_info = await self._client.addons.addon_info(slug)
addon_errors[slug] = AddonErrorData(name=addon_info.name, errors=errors) addon_errors[slug] = AddonErrorData(
addon=AddonInfo(
name=addon_info.name,
slug=addon_info.slug,
version=addon_info.version,
),
errors=errors,
)
except SupervisorError as err: except SupervisorError as err:
_LOGGER.debug("Error getting addon %s: %s", slug, err) _LOGGER.debug("Error getting addon %s: %s", slug, err)
addon_errors[slug] = AddonErrorData(name=slug, errors=errors) addon_errors[slug] = AddonErrorData(
addon=AddonInfo(name=None, slug=slug, version=None), errors=errors
)
_folder_errors = _collect_errors( _folder_errors = _collect_errors(
full_status, "backup_store_folders", "backup_folder_save" full_status, "backup_store_folders", "backup_folder_save"

View File

@ -114,21 +114,23 @@ async def test_agents_list_backups(
assert response["result"]["backups"] == [ assert response["result"]["backups"] == [
{ {
"addons": test_backup.addons, "addons": test_backup.addons,
"backup_id": test_backup.backup_id,
"date": test_backup.date,
"database_included": test_backup.database_included,
"folders": test_backup.folders,
"homeassistant_included": test_backup.homeassistant_included,
"homeassistant_version": test_backup.homeassistant_version,
"name": test_backup.name,
"extra_metadata": test_backup.extra_metadata,
"agents": { "agents": {
f"{DOMAIN}.{mock_config_entry.entry_id}": { f"{DOMAIN}.{mock_config_entry.entry_id}": {
"protected": test_backup.protected, "protected": test_backup.protected,
"size": test_backup.size, "size": test_backup.size,
} }
}, },
"backup_id": test_backup.backup_id,
"database_included": test_backup.database_included,
"date": test_backup.date,
"extra_metadata": test_backup.extra_metadata,
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": test_backup.folders,
"homeassistant_included": test_backup.homeassistant_included,
"homeassistant_version": test_backup.homeassistant_version,
"name": test_backup.name,
"with_automatic_settings": None, "with_automatic_settings": None,
} }
] ]
@ -152,21 +154,23 @@ async def test_agents_get_backup(
assert response["result"]["agent_errors"] == {} assert response["result"]["agent_errors"] == {}
assert response["result"]["backup"] == { assert response["result"]["backup"] == {
"addons": test_backup.addons, "addons": test_backup.addons,
"backup_id": test_backup.backup_id,
"date": test_backup.date,
"database_included": test_backup.database_included,
"folders": test_backup.folders,
"homeassistant_included": test_backup.homeassistant_included,
"homeassistant_version": test_backup.homeassistant_version,
"name": test_backup.name,
"extra_metadata": test_backup.extra_metadata,
"agents": { "agents": {
f"{DOMAIN}.{mock_config_entry.entry_id}": { f"{DOMAIN}.{mock_config_entry.entry_id}": {
"protected": test_backup.protected, "protected": test_backup.protected,
"size": test_backup.size, "size": test_backup.size,
} }
}, },
"backup_id": test_backup.backup_id,
"database_included": test_backup.database_included,
"date": test_backup.date,
"extra_metadata": test_backup.extra_metadata,
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": test_backup.folders,
"homeassistant_included": test_backup.homeassistant_included,
"homeassistant_version": test_backup.homeassistant_version,
"name": test_backup.name,
"with_automatic_settings": None, "with_automatic_settings": None,
} }

View File

@ -93,14 +93,16 @@ async def test_agents_list_backups(
} }
}, },
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2024-11-22T11:48:48.727189+01:00",
"database_included": True, "database_included": True,
"date": "2024-11-22T11:48:48.727189+01:00",
"extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0.dev0", "homeassistant_version": "2024.12.0.dev0",
"name": "Core 2024.12.0.dev0", "name": "Core 2024.12.0.dev0",
"failed_agent_ids": [],
"extra_metadata": {},
"with_automatic_settings": None, "with_automatic_settings": None,
} }
] ]
@ -129,14 +131,16 @@ async def test_agents_get_backup(
} }
}, },
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2024-11-22T11:48:48.727189+01:00",
"database_included": True, "database_included": True,
"date": "2024-11-22T11:48:48.727189+01:00",
"extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0.dev0", "homeassistant_version": "2024.12.0.dev0",
"extra_metadata": {},
"name": "Core 2024.12.0.dev0", "name": "Core 2024.12.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
} }

View File

@ -75,8 +75,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -102,8 +106,12 @@
'instance_id': 'unknown_uuid', 'instance_id': 'unknown_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',

View File

@ -23,8 +23,12 @@
'instance_id': 'abc123', 'instance_id': 'abc123',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -50,8 +54,12 @@
'instance_id': 'unknown_uuid', 'instance_id': 'unknown_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',

View File

@ -5,9 +5,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -40,7 +44,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -50,9 +54,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -86,7 +94,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -96,9 +104,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -131,7 +143,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -141,9 +153,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -177,7 +193,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -187,9 +203,19 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
dict({
'name': 'Test add-on',
'slug': 'test_addon',
'version': '1.0.0',
}),
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
'ssl',
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -226,7 +252,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -236,9 +262,19 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
dict({
'name': 'Test add-on',
'slug': 'test_addon',
'version': '1.0.0',
}),
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
'ssl',
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -276,7 +312,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -286,9 +322,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -325,7 +365,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -335,9 +375,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -375,7 +419,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -385,9 +429,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -424,7 +472,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -434,9 +482,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -474,7 +526,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -484,9 +536,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -526,7 +582,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -536,9 +592,13 @@
'backups': list([ 'backups': list([
dict({ dict({
'backup_id': 'abc123', 'backup_id': 'abc123',
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
]),
}), }),
]), ]),
'config': dict({ 'config': dict({
@ -579,7 +639,132 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1,
})
# ---
# name: test_store_migration[store_data6]
dict({
'data': dict({
'backups': list([
dict({
'backup_id': 'abc123',
'failed_addons': list([
dict({
'name': 'Test add-on',
'slug': 'test_addon',
'version': '1.0.0',
}),
]),
'failed_agent_ids': list([
'test.remote',
]),
'failed_folders': list([
'ssl',
]),
}),
]),
'config': dict({
'agents': dict({
'test.remote': dict({
'protected': True,
'retention': dict({
'copies': None,
'days': None,
}),
}),
}),
'automatic_backups_configured': True,
'create_backup': dict({
'agent_ids': list([
]),
'include_addons': None,
'include_all_addons': False,
'include_database': True,
'include_folders': None,
'name': None,
'password': 'hunter2',
}),
'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': 7,
'version': 1,
})
# ---
# name: test_store_migration[store_data6].1
dict({
'data': dict({
'backups': list([
dict({
'backup_id': 'abc123',
'failed_addons': list([
dict({
'name': 'Test add-on',
'slug': 'test_addon',
'version': '1.0.0',
}),
]),
'failed_agent_ids': list([
'test.remote',
]),
'failed_folders': list([
'ssl',
]),
}),
]),
'config': dict({
'agents': dict({
'test.remote': dict({
'protected': True,
'retention': dict({
'copies': None,
'days': None,
}),
}),
}),
'automatic_backups_configured': True,
'create_backup': dict({
'agent_ids': list([
'test-agent',
]),
'include_addons': None,
'include_all_addons': False,
'include_database': True,
'include_folders': None,
'name': None,
'password': 'hunter2',
}),
'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': 7,
'version': 1, 'version': 1,
}) })
# --- # ---

View File

@ -1312,7 +1312,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -1429,7 +1429,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -1546,7 +1546,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -1677,7 +1677,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -1955,7 +1955,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2070,7 +2070,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2185,7 +2185,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2302,7 +2302,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2421,7 +2421,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2538,7 +2538,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2659,7 +2659,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2784,7 +2784,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -2901,7 +2901,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -3018,7 +3018,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -3135,7 +3135,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -3252,7 +3252,7 @@
}), }),
}), }),
'key': 'backup', 'key': 'backup',
'minor_version': 6, 'minor_version': 7,
'version': 1, 'version': 1,
}) })
# --- # ---
@ -4397,8 +4397,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4478,8 +4482,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4540,8 +4548,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4586,8 +4598,12 @@
'instance_id': 'unknown_uuid', 'instance_id': 'unknown_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4643,8 +4659,12 @@
'instance_id': 'unknown_uuid', 'instance_id': 'unknown_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4698,8 +4718,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4760,8 +4784,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4823,8 +4851,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4886,9 +4918,19 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
dict({
'name': 'Test add-on',
'slug': 'test_addon',
'version': '1.0.0',
}),
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
'ssl',
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -4949,8 +4991,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5011,8 +5057,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5074,8 +5124,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5137,9 +5191,19 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
dict({
'name': 'Test add-on',
'slug': 'test_addon',
'version': '1.0.0',
}),
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
'test.remote', 'test.remote',
]), ]),
'failed_folders': list([
'ssl',
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5200,8 +5264,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5243,8 +5311,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5302,8 +5374,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5358,8 +5434,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5402,8 +5482,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5446,8 +5530,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5715,8 +5803,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5766,8 +5858,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5821,8 +5917,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5867,8 +5967,12 @@
'instance_id': 'unknown_uuid', 'instance_id': 'unknown_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5899,8 +6003,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -5951,8 +6059,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -6003,8 +6115,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',
@ -6055,8 +6171,12 @@
'instance_id': 'our_uuid', 'instance_id': 'our_uuid',
'with_automatic_settings': True, 'with_automatic_settings': True,
}), }),
'failed_addons': list([
]),
'failed_agent_ids': list([ 'failed_agent_ids': list([
]), ]),
'failed_folders': list([
]),
'folders': list([ 'folders': list([
'media', 'media',
'share', 'share',

View File

@ -36,6 +36,7 @@ from homeassistant.components.backup.agent import BackupAgentError
from homeassistant.components.backup.const import DATA_MANAGER from homeassistant.components.backup.const import DATA_MANAGER
from homeassistant.components.backup.manager import ( from homeassistant.components.backup.manager import (
AddonErrorData, AddonErrorData,
AddonInfo,
BackupManagerError, BackupManagerError,
BackupManagerExceptionGroup, BackupManagerExceptionGroup,
BackupManagerState, BackupManagerState,
@ -653,7 +654,9 @@ async def test_initiate_backup(
"database_included": include_database, "database_included": include_database,
"date": ANY, "date": ANY,
"extra_metadata": {"instance_id": "our_uuid", "with_automatic_settings": False}, "extra_metadata": {"instance_id": "our_uuid", "with_automatic_settings": False},
"failed_addons": [],
"failed_agent_ids": expected_failed_agent_ids, "failed_agent_ids": expected_failed_agent_ids,
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2025.1.0", "homeassistant_version": "2025.1.0",
@ -706,7 +709,9 @@ async def test_initiate_backup_with_agent_error(
"instance_id": "our_uuid", "instance_id": "our_uuid",
"with_automatic_settings": True, "with_automatic_settings": True,
}, },
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": [ "folders": [
"media", "media",
"share", "share",
@ -726,7 +731,9 @@ async def test_initiate_backup_with_agent_error(
"instance_id": "unknown_uuid", "instance_id": "unknown_uuid",
"with_automatic_settings": True, "with_automatic_settings": True,
}, },
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": [ "folders": [
"media", "media",
"share", "share",
@ -752,7 +759,9 @@ async def test_initiate_backup_with_agent_error(
"instance_id": "our_uuid", "instance_id": "our_uuid",
"with_automatic_settings": True, "with_automatic_settings": True,
}, },
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": [ "folders": [
"media", "media",
"share", "share",
@ -857,7 +866,9 @@ async def test_initiate_backup_with_agent_error(
"database_included": True, "database_included": True,
"date": ANY, "date": ANY,
"extra_metadata": {"instance_id": "our_uuid", "with_automatic_settings": False}, "extra_metadata": {"instance_id": "our_uuid", "with_automatic_settings": False},
"failed_addons": [],
"failed_agent_ids": ["test.remote"], "failed_agent_ids": ["test.remote"],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2025.1.0", "homeassistant_version": "2025.1.0",
@ -890,7 +901,9 @@ async def test_initiate_backup_with_agent_error(
assert hass_storage[DOMAIN]["data"]["backups"] == [ assert hass_storage[DOMAIN]["data"]["backups"] == [
{ {
"backup_id": "abc123", "backup_id": "abc123",
"failed_addons": [],
"failed_agent_ids": ["test.remote"], "failed_agent_ids": ["test.remote"],
"failed_folders": [],
} }
] ]
@ -1121,7 +1134,8 @@ async def delayed_boom(*args, **kwargs) -> tuple[NewBackup, Any]:
{"type": "backup/generate", "agent_ids": ["test.remote"]}, {"type": "backup/generate", "agent_ids": ["test.remote"]},
{ {
"test_addon": AddonErrorData( "test_addon": AddonErrorData(
name="Test Add-on", errors=[("test_error", "Boom!")] addon=AddonInfo(name="Test Add-on", slug="test", version="0.0"),
errors=[("test_error", "Boom!")],
) )
}, },
{}, {},
@ -1135,7 +1149,8 @@ async def delayed_boom(*args, **kwargs) -> tuple[NewBackup, Any]:
{"type": "backup/generate_with_automatic_settings"}, {"type": "backup/generate_with_automatic_settings"},
{ {
"test_addon": AddonErrorData( "test_addon": AddonErrorData(
name="Test Add-on", errors=[("test_error", "Boom!")] addon=AddonInfo(name="Test Add-on", slug="test", version="0.0"),
errors=[("test_error", "Boom!")],
) )
}, },
{}, {},
@ -1181,7 +1196,8 @@ async def delayed_boom(*args, **kwargs) -> tuple[NewBackup, Any]:
{"type": "backup/generate", "agent_ids": ["test.remote"]}, {"type": "backup/generate", "agent_ids": ["test.remote"]},
{ {
"test_addon": AddonErrorData( "test_addon": AddonErrorData(
name="Test Add-on", errors=[("test_error", "Boom!")] addon=AddonInfo(name="Test Add-on", slug="test", version="0.0"),
errors=[("test_error", "Boom!")],
) )
}, },
{Folder.MEDIA: [("test_error", "Boom!")]}, {Folder.MEDIA: [("test_error", "Boom!")]},
@ -1195,7 +1211,8 @@ async def delayed_boom(*args, **kwargs) -> tuple[NewBackup, Any]:
{"type": "backup/generate_with_automatic_settings"}, {"type": "backup/generate_with_automatic_settings"},
{ {
"test_addon": AddonErrorData( "test_addon": AddonErrorData(
name="Test Add-on", errors=[("test_error", "Boom!")] addon=AddonInfo(name="Test Add-on", slug="test", version="0.0"),
errors=[("test_error", "Boom!")],
) )
}, },
{Folder.MEDIA: [("test_error", "Boom!")]}, {Folder.MEDIA: [("test_error", "Boom!")]},
@ -1219,7 +1236,8 @@ async def delayed_boom(*args, **kwargs) -> tuple[NewBackup, Any]:
{"type": "backup/generate", "agent_ids": ["test.remote"]}, {"type": "backup/generate", "agent_ids": ["test.remote"]},
{ {
"test_addon": AddonErrorData( "test_addon": AddonErrorData(
name="Test Add-on", errors=[("test_error", "Boom!")] addon=AddonInfo(name="Test Add-on", slug="test", version="0.0"),
errors=[("test_error", "Boom!")],
) )
}, },
{Folder.MEDIA: [("test_error", "Boom!")]}, {Folder.MEDIA: [("test_error", "Boom!")]},
@ -1241,7 +1259,8 @@ async def delayed_boom(*args, **kwargs) -> tuple[NewBackup, Any]:
{"type": "backup/generate_with_automatic_settings"}, {"type": "backup/generate_with_automatic_settings"},
{ {
"test_addon": AddonErrorData( "test_addon": AddonErrorData(
name="Test Add-on", errors=[("test_error", "Boom!")] addon=AddonInfo(name="Test Add-on", slug="test", version="0.0"),
errors=[("test_error", "Boom!")],
) )
}, },
{Folder.MEDIA: [("test_error", "Boom!")]}, {Folder.MEDIA: [("test_error", "Boom!")]},
@ -2080,7 +2099,9 @@ async def test_receive_backup_agent_error(
"instance_id": "our_uuid", "instance_id": "our_uuid",
"with_automatic_settings": True, "with_automatic_settings": True,
}, },
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": [ "folders": [
"media", "media",
"share", "share",
@ -2100,7 +2121,9 @@ async def test_receive_backup_agent_error(
"instance_id": "unknown_uuid", "instance_id": "unknown_uuid",
"with_automatic_settings": True, "with_automatic_settings": True,
}, },
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": [ "folders": [
"media", "media",
"share", "share",
@ -2126,7 +2149,9 @@ async def test_receive_backup_agent_error(
"instance_id": "our_uuid", "instance_id": "our_uuid",
"with_automatic_settings": True, "with_automatic_settings": True,
}, },
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": [ "folders": [
"media", "media",
"share", "share",
@ -2256,7 +2281,9 @@ async def test_receive_backup_agent_error(
assert hass_storage[DOMAIN]["data"]["backups"] == [ assert hass_storage[DOMAIN]["data"]["backups"] == [
{ {
"backup_id": "abc123", "backup_id": "abc123",
"failed_addons": [],
"failed_agent_ids": ["test.remote"], "failed_agent_ids": ["test.remote"],
"failed_folders": [],
} }
] ]
@ -3571,7 +3598,9 @@ async def test_initiate_backup_per_agent_encryption(
"database_included": True, "database_included": True,
"date": ANY, "date": ANY,
"extra_metadata": {"instance_id": "our_uuid", "with_automatic_settings": False}, "extra_metadata": {"instance_id": "our_uuid", "with_automatic_settings": False},
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2025.1.0", "homeassistant_version": "2025.1.0",

View File

@ -124,14 +124,16 @@ async def test_onboarding_backup_info(
"backup.local": backup.manager.AgentBackupStatus(protected=True, size=0) "backup.local": backup.manager.AgentBackupStatus(protected=True, size=0)
}, },
backup_id="abc123", backup_id="abc123",
date="1970-01-01T00:00:00.000Z",
database_included=True, database_included=True,
date="1970-01-01T00:00:00.000Z",
extra_metadata={"instance_id": "abc123", "with_automatic_settings": True}, extra_metadata={"instance_id": "abc123", "with_automatic_settings": True},
failed_addons=[],
failed_agent_ids=[],
failed_folders=[],
folders=[backup.Folder.MEDIA, backup.Folder.SHARE], folders=[backup.Folder.MEDIA, backup.Folder.SHARE],
homeassistant_included=True, homeassistant_included=True,
homeassistant_version="2024.12.0", homeassistant_version="2024.12.0",
name="Test", name="Test",
failed_agent_ids=[],
with_automatic_settings=True, with_automatic_settings=True,
), ),
"def456": backup.ManagerBackup( "def456": backup.ManagerBackup(
@ -140,17 +142,19 @@ async def test_onboarding_backup_info(
"test.remote": backup.manager.AgentBackupStatus(protected=True, size=0) "test.remote": backup.manager.AgentBackupStatus(protected=True, size=0)
}, },
backup_id="def456", backup_id="def456",
date="1980-01-01T00:00:00.000Z",
database_included=False, database_included=False,
date="1980-01-01T00:00:00.000Z",
extra_metadata={ extra_metadata={
"instance_id": "unknown_uuid", "instance_id": "unknown_uuid",
"with_automatic_settings": True, "with_automatic_settings": True,
}, },
failed_addons=[],
failed_agent_ids=[],
failed_folders=[],
folders=[backup.Folder.MEDIA, backup.Folder.SHARE], folders=[backup.Folder.MEDIA, backup.Folder.SHARE],
homeassistant_included=True, homeassistant_included=True,
homeassistant_version="2024.12.0", homeassistant_version="2024.12.0",
name="Test 2", name="Test 2",
failed_agent_ids=[],
with_automatic_settings=None, with_automatic_settings=None,
), ),
} }

View File

@ -94,7 +94,15 @@ def mock_delay_save() -> Generator[None]:
"backups": [ "backups": [
{ {
"backup_id": "abc123", "backup_id": "abc123",
"failed_addons": [
{
"name": "Test add-on",
"slug": "test_addon",
"version": "1.0.0",
}
],
"failed_agent_ids": ["test.remote"], "failed_agent_ids": ["test.remote"],
"failed_folders": ["ssl"],
} }
], ],
"config": { "config": {
@ -243,6 +251,57 @@ def mock_delay_save() -> Generator[None]:
"minor_version": 6, "minor_version": 6,
"version": 1, "version": 1,
}, },
{
"data": {
"backups": [
{
"backup_id": "abc123",
"failed_addons": [
{
"name": "Test add-on",
"slug": "test_addon",
"version": "1.0.0",
}
],
"failed_agent_ids": ["test.remote"],
"failed_folders": ["ssl"],
}
],
"config": {
"agents": {
"test.remote": {
"protected": True,
"retention": {"copies": None, "days": None},
}
},
"automatic_backups_configured": True,
"create_backup": {
"agent_ids": [],
"include_addons": None,
"include_all_addons": False,
"include_database": True,
"include_folders": None,
"name": None,
"password": "hunter2",
},
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": None,
"retention": {
"copies": None,
"days": None,
},
"schedule": {
"days": [],
"recurrence": "never",
"state": "never",
"time": None,
},
},
},
"key": DOMAIN,
"minor_version": 7,
"version": 1,
},
], ],
) )
async def test_store_migration( async def test_store_migration(

View File

@ -87,14 +87,16 @@ TEST_MANAGER_BACKUP = ManagerBackup(
addons=[AddonInfo(name="Test", slug="test", version="1.0.0")], addons=[AddonInfo(name="Test", slug="test", version="1.0.0")],
agents={"test.test-agent": AgentBackupStatus(protected=True, size=0)}, agents={"test.test-agent": AgentBackupStatus(protected=True, size=0)},
backup_id="backup-1", backup_id="backup-1",
date="1970-01-01T00:00:00.000Z",
database_included=True, database_included=True,
date="1970-01-01T00:00:00.000Z",
extra_metadata={"instance_id": "abc123", "with_automatic_settings": True}, extra_metadata={"instance_id": "abc123", "with_automatic_settings": True},
failed_addons=[],
failed_agent_ids=[],
failed_folders=[],
folders=[Folder.MEDIA, Folder.SHARE], folders=[Folder.MEDIA, Folder.SHARE],
homeassistant_included=True, homeassistant_included=True,
homeassistant_version="2024.12.0", homeassistant_version="2024.12.0",
name="Test", name="Test",
failed_agent_ids=[],
with_automatic_settings=True, with_automatic_settings=True,
) )
@ -326,7 +328,15 @@ async def test_delete(
"backups": [ "backups": [
{ {
"backup_id": "abc123", "backup_id": "abc123",
"failed_addons": [
{
"name": "Test add-on",
"slug": "test_addon",
"version": "1.0.0",
}
],
"failed_agent_ids": ["test.remote"], "failed_agent_ids": ["test.remote"],
"failed_folders": ["ssl"],
} }
] ]
}, },

View File

@ -152,28 +152,32 @@ async def test_agents_list_backups(
"addons": [], "addons": [],
"agents": {"cloud.cloud": {"protected": False, "size": 34519040}}, "agents": {"cloud.cloud": {"protected": False, "size": 34519040}},
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2024-11-22T11:48:48.727189+01:00",
"database_included": True, "database_included": True,
"date": "2024-11-22T11:48:48.727189+01:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0.dev0", "homeassistant_version": "2024.12.0.dev0",
"name": "Core 2024.12.0.dev0", "name": "Core 2024.12.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
}, },
{ {
"addons": [], "addons": [],
"agents": {"cloud.cloud": {"protected": False, "size": 34519040}}, "agents": {"cloud.cloud": {"protected": False, "size": 34519040}},
"backup_id": "23e64aed", "backup_id": "23e64aed",
"date": "2024-11-22T11:48:48.727189+01:00",
"database_included": True, "database_included": True,
"date": "2024-11-22T11:48:48.727189+01:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0.dev0", "homeassistant_version": "2024.12.0.dev0",
"name": "Core 2024.12.0.dev0", "name": "Core 2024.12.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
}, },
] ]
@ -216,14 +220,16 @@ async def test_agents_list_backups_fail_cloud(
"addons": [], "addons": [],
"agents": {"cloud.cloud": {"protected": False, "size": 34519040}}, "agents": {"cloud.cloud": {"protected": False, "size": 34519040}},
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2024-11-22T11:48:48.727189+01:00",
"database_included": True, "database_included": True,
"date": "2024-11-22T11:48:48.727189+01:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0.dev0", "homeassistant_version": "2024.12.0.dev0",
"name": "Core 2024.12.0.dev0", "name": "Core 2024.12.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
}, },
), ),

View File

@ -49,11 +49,13 @@ TEST_AGENT_BACKUP_RESULT = {
"database_included": True, "database_included": True,
"date": "2025-01-01T01:23:45.678Z", "date": "2025-01-01T01:23:45.678Z",
"extra_metadata": {"with_automatic_settings": False}, "extra_metadata": {"with_automatic_settings": False},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0", "homeassistant_version": "2024.12.0",
"name": "Test", "name": "Test",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
} }

View File

@ -497,7 +497,9 @@ async def test_agent_info(
"database_included": True, "database_included": True,
"date": "1970-01-01T00:00:00+00:00", "date": "1970-01-01T00:00:00+00:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": ["share"], "folders": ["share"],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0", "homeassistant_version": "2024.12.0",
@ -517,7 +519,9 @@ async def test_agent_info(
"database_included": False, "database_included": False,
"date": "1970-01-01T00:00:00+00:00", "date": "1970-01-01T00:00:00+00:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": ["share"], "folders": ["share"],
"homeassistant_included": False, "homeassistant_included": False,
"homeassistant_version": None, "homeassistant_version": None,
@ -653,7 +657,9 @@ async def test_agent_get_backup(
"database_included": True, "database_included": True,
"date": "1970-01-01T00:00:00+00:00", "date": "1970-01-01T00:00:00+00:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": ["share"], "folders": ["share"],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0", "homeassistant_version": "2024.12.0",
@ -992,7 +998,7 @@ async def test_reader_writer_create(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"addon_info_side_effect", "addon_info_side_effect",
# Getting info fails for one of the addons, should fall back to slug # Getting info fails for one of the addons, should fall back to slug
[[Mock(), SupervisorError("Boom")]], [[Mock(slug="core_ssh", version="0.0.0"), SupervisorError("Boom")]],
) )
async def test_reader_writer_create_addon_folder_error( async def test_reader_writer_create_addon_folder_error(
hass: HomeAssistant, hass: HomeAssistant,

View File

@ -109,7 +109,9 @@ async def test_agents_list_backups(
"database_included": False, "database_included": False,
"date": "1970-01-01T00:00:00Z", "date": "1970-01-01T00:00:00Z",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": ["media", "share"], "folders": ["media", "share"],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0", "homeassistant_version": "2024.12.0",
@ -191,7 +193,9 @@ async def test_agents_upload(
"database_included": True, "database_included": True,
"date": "1970-01-01T00:00:00.000Z", "date": "1970-01-01T00:00:00.000Z",
"extra_metadata": {"instance_id": ANY, "with_automatic_settings": False}, "extra_metadata": {"instance_id": ANY, "with_automatic_settings": False},
"failed_addons": [],
"failed_agent_ids": [], "failed_agent_ids": [],
"failed_folders": [],
"folders": ["media", "share"], "folders": ["media", "share"],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0", "homeassistant_version": "2024.12.0",

View File

@ -91,14 +91,16 @@ async def test_agents_list_backups(
"onedrive.mock_drive_id": {"protected": False, "size": 34519040} "onedrive.mock_drive_id": {"protected": False, "size": 34519040}
}, },
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2024-11-22T11:48:48.727189+01:00",
"database_included": True, "database_included": True,
"date": "2024-11-22T11:48:48.727189+01:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0.dev0", "homeassistant_version": "2024.12.0.dev0",
"name": "Core 2024.12.0.dev0", "name": "Core 2024.12.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
} }
] ]
@ -143,14 +145,16 @@ async def test_agents_get_backup(
} }
}, },
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2024-11-22T11:48:48.727189+01:00",
"database_included": True, "database_included": True,
"date": "2024-11-22T11:48:48.727189+01:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2024.12.0.dev0", "homeassistant_version": "2024.12.0.dev0",
"name": "Core 2024.12.0.dev0", "name": "Core 2024.12.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
} }

View File

@ -342,14 +342,16 @@ async def test_agents_list_backups(
} }
}, },
"backup_id": "abcd12ef", "backup_id": "abcd12ef",
"date": "2025-01-09T20:14:35.457323+01:00",
"database_included": True, "database_included": True,
"date": "2025-01-09T20:14:35.457323+01:00",
"extra_metadata": {"instance_id": ANY, "with_automatic_settings": True}, "extra_metadata": {"instance_id": ANY, "with_automatic_settings": True},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2025.2.0.dev0", "homeassistant_version": "2025.2.0.dev0",
"name": "Automatic backup 2025.2.0.dev0", "name": "Automatic backup 2025.2.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
} }
] ]
@ -413,14 +415,16 @@ async def test_agents_list_backups_disabled_filestation(
} }
}, },
"backup_id": "abcd12ef", "backup_id": "abcd12ef",
"date": "2025-01-09T20:14:35.457323+01:00",
"database_included": True, "database_included": True,
"date": "2025-01-09T20:14:35.457323+01:00",
"extra_metadata": {"instance_id": ANY, "with_automatic_settings": True}, "extra_metadata": {"instance_id": ANY, "with_automatic_settings": True},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2025.2.0.dev0", "homeassistant_version": "2025.2.0.dev0",
"name": "Automatic backup 2025.2.0.dev0", "name": "Automatic backup 2025.2.0.dev0",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
}, },
), ),

View File

@ -86,14 +86,16 @@ async def test_agents_list_backups(
} }
}, },
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2025-02-10T17:47:22.727189+01:00",
"database_included": True, "database_included": True,
"date": "2025-02-10T17:47:22.727189+01:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2025.2.1", "homeassistant_version": "2025.2.1",
"name": "Automatic backup 2025.2.1", "name": "Automatic backup 2025.2.1",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
} }
] ]
@ -122,14 +124,16 @@ async def test_agents_get_backup(
} }
}, },
"backup_id": "23e64aec", "backup_id": "23e64aec",
"date": "2025-02-10T17:47:22.727189+01:00",
"database_included": True, "database_included": True,
"date": "2025-02-10T17:47:22.727189+01:00",
"extra_metadata": {}, "extra_metadata": {},
"failed_addons": [],
"failed_agent_ids": [],
"failed_folders": [],
"folders": [], "folders": [],
"homeassistant_included": True, "homeassistant_included": True,
"homeassistant_version": "2025.2.1", "homeassistant_version": "2025.2.1",
"name": "Automatic backup 2025.2.1", "name": "Automatic backup 2025.2.1",
"failed_agent_ids": [],
"with_automatic_settings": None, "with_automatic_settings": None,
} }