Introduce unique_id to BackupAgent (#136651)

* add unique_id to BackupAgent

* adjust tests
This commit is contained in:
Michael 2025-01-28 12:06:03 +01:00 committed by GitHub
parent 91ff31a3be
commit 8300fd2de8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 81 additions and 42 deletions

View File

@ -30,11 +30,12 @@ class BackupAgent(abc.ABC):
domain: str
name: str
unique_id: str
@cached_property
def agent_id(self) -> str:
"""Return the agent_id."""
return f"{self.domain}.{self.name}"
return f"{self.domain}.{self.unique_id}"
@abc.abstractmethod
async def async_download_backup(

View File

@ -32,6 +32,7 @@ class CoreLocalBackupAgent(LocalBackupAgent):
domain = DOMAIN
name = "local"
unique_id = "local"
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize the backup agent."""

View File

@ -306,7 +306,10 @@ async def backup_agents_info(
connection.send_result(
msg["id"],
{
"agents": [{"agent_id": agent_id} for agent_id in manager.backup_agents],
"agents": [
{"agent_id": agent.agent_id, "name": agent.name}
for agent in manager.backup_agents.values()
],
},
)

View File

@ -82,8 +82,7 @@ def async_register_backup_agents_listener(
class CloudBackupAgent(BackupAgent):
"""Cloud backup agent."""
domain = DOMAIN
name = DOMAIN
domain = name = unique_id = DOMAIN
def __init__(self, hass: HomeAssistant, cloud: Cloud[CloudClient]) -> None:
"""Initialize the cloud backup sync agent."""

View File

@ -133,7 +133,7 @@ class SupervisorBackupAgent(BackupAgent):
self._hass = hass
self._backup_dir = Path("/backups")
self._client = get_supervisor_client(hass)
self.name = name
self.name = self.unique_id = name
self.location = location
async def async_download_backup(

View File

@ -51,7 +51,7 @@ class KitchenSinkBackupAgent(BackupAgent):
def __init__(self, name: str) -> None:
"""Initialize the kitchen sink backup sync agent."""
super().__init__()
self.name = name
self.name = self.unique_id = name
self._uploads = [
AgentBackup(
addons=[AddonInfo(name="Test", slug="test", version="1.0.0")],

View File

@ -39,7 +39,7 @@ async def async_get_backup_agents(
return []
syno_datas: dict[str, SynologyDSMData] = hass.data[DOMAIN]
return [
SynologyDSMBackupAgent(hass, entry)
SynologyDSMBackupAgent(hass, entry, entry.unique_id)
for entry in entries
if entry.unique_id is not None
and (syno_data := syno_datas.get(entry.unique_id))
@ -76,11 +76,12 @@ class SynologyDSMBackupAgent(BackupAgent):
domain = DOMAIN
def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
def __init__(self, hass: HomeAssistant, entry: ConfigEntry, unique_id: str) -> None:
"""Initialize the Synology DSM backup agent."""
super().__init__()
LOGGER.debug("Initializing Synology DSM backup agent for %s", entry.unique_id)
self.name = entry.title
self.unique_id = unique_id
self.path = (
f"{entry.options[CONF_BACKUP_SHARE]}/{entry.options[CONF_BACKUP_PATH]}"
)

View File

@ -64,6 +64,7 @@ class BackupAgentTest(BackupAgent):
def __init__(self, name: str, backups: list[AgentBackup] | None = None) -> None:
"""Initialize the backup agent."""
self.name = name
self.unique_id = name
if backups is None:
backups = [
AgentBackup(

View File

@ -39,6 +39,7 @@
'agents': list([
dict({
'agent_id': 'backup.local',
'name': 'local',
}),
]),
}),
@ -97,6 +98,7 @@
'agents': list([
dict({
'agent_id': 'backup.local',
'name': 'local',
}),
]),
}),
@ -128,6 +130,7 @@
'agents': list([
dict({
'agent_id': 'backup.local',
'name': 'local',
}),
]),
}),
@ -159,6 +162,7 @@
'agents': list([
dict({
'agent_id': 'backup.local',
'name': 'local',
}),
]),
}),
@ -190,6 +194,7 @@
'agents': list([
dict({
'agent_id': 'backup.local',
'name': 'local',
}),
]),
}),

View File

@ -17,9 +17,11 @@
'agents': list([
dict({
'agent_id': 'backup.local',
'name': 'local',
}),
dict({
'agent_id': 'domain.test',
'agent_id': 'test.test',
'name': 'test',
}),
]),
}),

View File

@ -1203,8 +1203,8 @@ async def test_loading_platform_with_listener(
await ws_client.send_json_auto_id({"type": "backup/agents/info"})
resp = await ws_client.receive_json()
assert resp["result"]["agents"] == [
{"agent_id": "backup.local"},
{"agent_id": "test.remote1"},
{"agent_id": "backup.local", "name": "local"},
{"agent_id": "test.remote1", "name": "remote1"},
]
assert len(manager.local_backup_agents) == num_local_agents
@ -1220,8 +1220,8 @@ async def test_loading_platform_with_listener(
await ws_client.send_json_auto_id({"type": "backup/agents/info"})
resp = await ws_client.receive_json()
assert resp["result"]["agents"] == [
{"agent_id": "backup.local"},
{"agent_id": "test.remote2"},
{"agent_id": "backup.local", "name": "local"},
{"agent_id": "test.remote2", "name": "remote2"},
]
assert len(manager.local_backup_agents) == num_local_agents

View File

@ -146,7 +146,10 @@ async def test_agents_info(
assert response["success"]
assert response["result"] == {
"agents": [{"agent_id": "backup.local"}, {"agent_id": "cloud.cloud"}],
"agents": [
{"agent_id": "backup.local", "name": "local"},
{"agent_id": "cloud.cloud", "name": "cloud"},
],
}

View File

@ -34,6 +34,7 @@ from homeassistant.components.backup import (
BackupAgentPlatformProtocol,
Folder,
)
from homeassistant.components.hassio import DOMAIN
from homeassistant.components.hassio.backup import LOCATION_CLOUD_BACKUP
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
@ -252,11 +253,11 @@ async def setup_integration(
class BackupAgentTest(BackupAgent):
"""Test backup agent."""
domain = "test"
def __init__(self, name: str) -> None:
def __init__(self, name: str, domain: str = "test") -> None:
"""Initialize the backup agent."""
self.domain = domain
self.name = name
self.unique_id = name
async def async_download_backup(
self, backup_id: str, **kwargs: Any
@ -304,7 +305,10 @@ async def _setup_backup_platform(
@pytest.mark.parametrize(
("mounts", "expected_agents"),
[
(MountsInfo(default_backup_mount=None, mounts=[]), ["hassio.local"]),
(
MountsInfo(default_backup_mount=None, mounts=[]),
[BackupAgentTest("local", DOMAIN)],
),
(
MountsInfo(
default_backup_mount=None,
@ -321,7 +325,7 @@ async def _setup_backup_platform(
)
],
),
["hassio.local", "hassio.test"],
[BackupAgentTest("local", DOMAIN), BackupAgentTest("test", DOMAIN)],
),
(
MountsInfo(
@ -339,7 +343,7 @@ async def _setup_backup_platform(
)
],
),
["hassio.local"],
[BackupAgentTest("local", DOMAIN)],
),
],
)
@ -348,7 +352,7 @@ async def test_agent_info(
hass_ws_client: WebSocketGenerator,
supervisor_client: AsyncMock,
mounts: MountsInfo,
expected_agents: list[str],
expected_agents: list[BackupAgent],
) -> None:
"""Test backup agent info."""
client = await hass_ws_client(hass)
@ -361,7 +365,10 @@ async def test_agent_info(
assert response["success"]
assert response["result"] == {
"agents": [{"agent_id": agent_id} for agent_id in expected_agents],
"agents": [
{"agent_id": agent.agent_id, "name": agent.name}
for agent in expected_agents
],
}

View File

@ -55,7 +55,10 @@ async def test_agents_info(
assert response["success"]
assert response["result"] == {
"agents": [{"agent_id": "backup.local"}, {"agent_id": "kitchen_sink.syncer"}],
"agents": [
{"agent_id": "backup.local", "name": "local"},
{"agent_id": "kitchen_sink.syncer", "name": "syncer"},
],
}
config_entry = hass.config_entries.async_entries(DOMAIN)[0]
@ -66,7 +69,9 @@ async def test_agents_info(
response = await client.receive_json()
assert response["success"]
assert response["result"] == {"agents": [{"agent_id": "backup.local"}]}
assert response["result"] == {
"agents": [{"agent_id": "backup.local", "name": "local"}]
}
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
@ -76,7 +81,10 @@ async def test_agents_info(
assert response["success"]
assert response["result"] == {
"agents": [{"agent_id": "backup.local"}, {"agent_id": "kitchen_sink.syncer"}],
"agents": [
{"agent_id": "backup.local", "name": "local"},
{"agent_id": "kitchen_sink.syncer", "name": "syncer"},
],
}

View File

@ -208,8 +208,8 @@ async def test_agents_info(
assert response["success"]
assert response["result"] == {
"agents": [
{"agent_id": "synology_dsm.Mock Title"},
{"agent_id": "backup.local"},
{"agent_id": "synology_dsm.mocked_syno_dsm_entry", "name": "Mock Title"},
{"agent_id": "backup.local", "name": "local"},
],
}
@ -231,7 +231,7 @@ async def test_agents_not_loaded(
assert response["success"]
assert response["result"] == {
"agents": [
{"agent_id": "backup.local"},
{"agent_id": "backup.local", "name": "local"},
],
}
@ -251,8 +251,8 @@ async def test_agents_on_unload(
assert response["success"]
assert response["result"] == {
"agents": [
{"agent_id": "synology_dsm.Mock Title"},
{"agent_id": "backup.local"},
{"agent_id": "synology_dsm.mocked_syno_dsm_entry", "name": "Mock Title"},
{"agent_id": "backup.local", "name": "local"},
],
}
@ -269,7 +269,7 @@ async def test_agents_on_unload(
assert response["success"]
assert response["result"] == {
"agents": [
{"agent_id": "backup.local"},
{"agent_id": "backup.local", "name": "local"},
],
}
@ -299,7 +299,7 @@ async def test_agents_list_backups(
"name": "Automatic backup 2025.2.0.dev0",
"protected": True,
"size": 13916160,
"agent_ids": ["synology_dsm.Mock Title"],
"agent_ids": ["synology_dsm.mocked_syno_dsm_entry"],
"failed_agent_ids": [],
"with_automatic_settings": None,
}
@ -323,7 +323,9 @@ async def test_agents_list_backups_error(
assert response["success"]
assert response["result"] == {
"agent_errors": {"synology_dsm.Mock Title": "Failed to list backups"},
"agent_errors": {
"synology_dsm.mocked_syno_dsm_entry": "Failed to list backups"
},
"backups": [],
"last_attempted_automatic_backup": None,
"last_completed_automatic_backup": None,
@ -362,7 +364,7 @@ async def test_agents_list_backups_disabled_filestation(
"name": "Automatic backup 2025.2.0.dev0",
"protected": True,
"size": 13916160,
"agent_ids": ["synology_dsm.Mock Title"],
"agent_ids": ["synology_dsm.mocked_syno_dsm_entry"],
"failed_agent_ids": [],
"with_automatic_settings": None,
},
@ -429,7 +431,9 @@ async def test_agents_get_backup_error(
assert response["success"]
assert response["result"] == {
"agent_errors": {"synology_dsm.Mock Title": "Failed to list backups"},
"agent_errors": {
"synology_dsm.mocked_syno_dsm_entry": "Failed to list backups"
},
"backup": None,
}
@ -462,7 +466,7 @@ async def test_agents_download(
backup_id = "abcd12ef"
resp = await client.get(
f"/api/backup/download/{backup_id}?agent_id=synology_dsm.Mock Title"
f"/api/backup/download/{backup_id}?agent_id=synology_dsm.mocked_syno_dsm_entry"
)
assert resp.status == 200
assert await resp.content.read() == b"backup data"
@ -482,7 +486,7 @@ async def test_agents_download_not_existing(
)
resp = await client.get(
f"/api/backup/download/{backup_id}?agent_id=synology_dsm.Mock Title"
f"/api/backup/download/{backup_id}?agent_id=synology_dsm.mocked_syno_dsm_entry"
)
assert resp.reason == "Internal Server Error"
assert resp.status == 500
@ -524,7 +528,7 @@ async def test_agents_upload(
mocked_open.return_value.read = Mock(side_effect=[b"test", b""])
fetch_backup.return_value = test_backup
resp = await client.post(
"/api/backup/upload?agent_id=synology_dsm.Mock Title",
"/api/backup/upload?agent_id=synology_dsm.mocked_syno_dsm_entry",
data={"file": StringIO("test")},
)
@ -578,7 +582,7 @@ async def test_agents_upload_error(
SynologyDSMAPIErrorException("api", "500", "error")
)
resp = await client.post(
"/api/backup/upload?agent_id=synology_dsm.Mock Title",
"/api/backup/upload?agent_id=synology_dsm.mocked_syno_dsm_entry",
data={"file": StringIO("test")},
)
@ -609,7 +613,7 @@ async def test_agents_upload_error(
]
resp = await client.post(
"/api/backup/upload?agent_id=synology_dsm.Mock Title",
"/api/backup/upload?agent_id=synology_dsm.mocked_syno_dsm_entry",
data={"file": StringIO("test")},
)
@ -674,7 +678,9 @@ async def test_agents_delete_not_existing(
assert response["success"]
assert response["result"] == {
"agent_errors": {"synology_dsm.Mock Title": "Failed to delete the backup"}
"agent_errors": {
"synology_dsm.mocked_syno_dsm_entry": "Failed to delete the backup"
}
}
@ -701,7 +707,9 @@ async def test_agents_delete_error(
assert response["success"]
assert response["result"] == {
"agent_errors": {"synology_dsm.Mock Title": "Failed to delete the backup"}
"agent_errors": {
"synology_dsm.mocked_syno_dsm_entry": "Failed to delete the backup"
}
}
mock: AsyncMock = setup_dsm_with_filestation.file.delete_file
assert len(mock.mock_calls) == 1