Update hassio backup agents on mount added or removed (#133344)

* Update hassio backup agents on mount added or removed

* Address review comments
This commit is contained in:
Erik Montnemery 2024-12-16 15:37:29 +01:00 committed by GitHub
parent a34992c0b5
commit 14f4f8aeb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 99 additions and 0 deletions

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import asyncio import asyncio
from collections.abc import AsyncIterator, Callable, Coroutine, Mapping from collections.abc import AsyncIterator, Callable, Coroutine, Mapping
import logging
from pathlib import Path from pathlib import Path
from typing import Any, cast from typing import Any, cast
@ -32,6 +33,8 @@ from .const import DOMAIN, EVENT_SUPERVISOR_EVENT
from .handler import get_supervisor_client from .handler import get_supervisor_client
LOCATION_CLOUD_BACKUP = ".cloud_backup" LOCATION_CLOUD_BACKUP = ".cloud_backup"
MOUNT_JOBS = ("mount_manager_create_mount", "mount_manager_remove_mount")
_LOGGER = logging.getLogger(__name__)
async def async_get_backup_agents( async def async_get_backup_agents(
@ -49,6 +52,37 @@ async def async_get_backup_agents(
return agents return agents
@callback
def async_register_backup_agents_listener(
hass: HomeAssistant,
*,
listener: Callable[[], None],
**kwargs: Any,
) -> Callable[[], None]:
"""Register a listener to be called when agents are added or removed."""
@callback
def unsub() -> None:
"""Unsubscribe from job events."""
unsub_signal()
@callback
def handle_signal(data: Mapping[str, Any]) -> None:
"""Handle a job signal."""
if (
data.get("event") != "job"
or not (event_data := data.get("data"))
or event_data.get("name") not in MOUNT_JOBS
or event_data.get("done") is not True
):
return
_LOGGER.debug("Mount added or removed %s, calling listener", data)
listener()
unsub_signal = async_dispatcher_connect(hass, EVENT_SUPERVISOR_EVENT, handle_signal)
return unsub
def _backup_details_to_agent_backup( def _backup_details_to_agent_backup(
details: supervisor_backups.BackupComplete, details: supervisor_backups.BackupComplete,
) -> AgentBackup: ) -> AgentBackup:

View File

@ -514,11 +514,14 @@ def resolution_suggestions_for_issue_fixture(supervisor_client: AsyncMock) -> As
@pytest.fixture(name="supervisor_client") @pytest.fixture(name="supervisor_client")
def supervisor_client() -> Generator[AsyncMock]: def supervisor_client() -> Generator[AsyncMock]:
"""Mock the supervisor client.""" """Mock the supervisor client."""
mounts_info_mock = AsyncMock(spec_set=["mounts"])
mounts_info_mock.mounts = []
supervisor_client = AsyncMock() supervisor_client = AsyncMock()
supervisor_client.addons = AsyncMock() supervisor_client.addons = AsyncMock()
supervisor_client.discovery = AsyncMock() supervisor_client.discovery = AsyncMock()
supervisor_client.homeassistant = AsyncMock() supervisor_client.homeassistant = AsyncMock()
supervisor_client.host = AsyncMock() supervisor_client.host = AsyncMock()
supervisor_client.mounts.info.return_value = mounts_info_mock
supervisor_client.os = AsyncMock() supervisor_client.os = AsyncMock()
supervisor_client.resolution = AsyncMock() supervisor_client.resolution = AsyncMock()
supervisor_client.supervisor = AsyncMock() supervisor_client.supervisor = AsyncMock()

View File

@ -231,6 +231,68 @@ async def test_agent_delete_backup(
supervisor_client.backups.remove_backup.assert_called_once_with(backup_id) supervisor_client.backups.remove_backup.assert_called_once_with(backup_id)
@pytest.mark.usefixtures("hassio_client")
@pytest.mark.parametrize(
("event_data", "mount_info_calls"),
[
(
{
"event": "job",
"data": {"name": "mount_manager_create_mount", "done": True},
},
1,
),
(
{
"event": "job",
"data": {"name": "mount_manager_create_mount", "done": False},
},
0,
),
(
{
"event": "job",
"data": {"name": "mount_manager_remove_mount", "done": True},
},
1,
),
(
{
"event": "job",
"data": {"name": "mount_manager_remove_mount", "done": False},
},
0,
),
({"event": "job", "data": {"name": "other_job", "done": True}}, 0),
(
{
"event": "other_event",
"data": {"name": "mount_manager_remove_mount", "done": True},
},
0,
),
],
)
async def test_agents_notify_on_mount_added_removed(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
supervisor_client: AsyncMock,
event_data: dict[str, Any],
mount_info_calls: int,
) -> None:
"""Test the listener is called when mounts are added or removed."""
client = await hass_ws_client(hass)
assert supervisor_client.mounts.info.call_count == 1
assert supervisor_client.mounts.info.call_args[0] == ()
supervisor_client.mounts.info.reset_mock()
await client.send_json_auto_id({"type": "supervisor/event", "data": event_data})
response = await client.receive_json()
assert response["success"]
await hass.async_block_till_done()
assert supervisor_client.mounts.info.call_count == mount_info_calls
@pytest.mark.usefixtures("hassio_client") @pytest.mark.usefixtures("hassio_client")
async def test_reader_writer_create( async def test_reader_writer_create(
hass: HomeAssistant, hass: HomeAssistant,