From adfdeff84c79ba970aa3523d9d833a71907e4cf3 Mon Sep 17 00:00:00 2001 From: Mike Degatano Date: Wed, 27 Aug 2025 05:27:38 -0400 Subject: [PATCH] Use unhealthy/unsupported reason enums from aiohasupervisor (#150919) --- homeassistant/components/hassio/issues.py | 44 ++++--------------- tests/components/hassio/test_issues.py | 53 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/hassio/issues.py b/homeassistant/components/hassio/issues.py index 22406e86ba1..0486dc1f85f 100644 --- a/homeassistant/components/hassio/issues.py +++ b/homeassistant/components/hassio/issues.py @@ -10,7 +10,12 @@ from typing import Any, NotRequired, TypedDict from uuid import UUID from aiohasupervisor import SupervisorError -from aiohasupervisor.models import ContextType, Issue as SupervisorIssue +from aiohasupervisor.models import ( + ContextType, + Issue as SupervisorIssue, + UnhealthyReason, + UnsupportedReason, +) from homeassistant.core import HassJob, HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -59,42 +64,9 @@ INFO_URL_UNSUPPORTED = "https://www.home-assistant.io/more-info/unsupported" PLACEHOLDER_KEY_REASON = "reason" -UNSUPPORTED_REASONS = { - "apparmor", - "cgroup_version", - "connectivity_check", - "content_trust", - "dbus", - "dns_server", - "docker_configuration", - "docker_version", - "job_conditions", - "lxc", - "network_manager", - "os", - "os_agent", - "os_version", - "restart_policy", - "software", - "source_mods", - "supervisor_version", - "systemd", - "systemd_journal", - "systemd_resolved", - "virtualization_image", -} # Some unsupported reasons also mark the system as unhealthy. If the unsupported reason # provides no additional information beyond the unhealthy one then skip that repair. UNSUPPORTED_SKIP_REPAIR = {"privileged"} -UNHEALTHY_REASONS = { - "docker", - "duplicate_os_installation", - "oserror_bad_message", - "privileged", - "setup", - "supervisor", - "untrusted", -} # Keys (type + context) of issues that when found should be made into a repair ISSUE_KEYS_FOR_REPAIRS = { @@ -206,7 +178,7 @@ class SupervisorIssues: def unhealthy_reasons(self, reasons: set[str]) -> None: """Set unhealthy reasons. Create or delete repairs as necessary.""" for unhealthy in reasons - self.unhealthy_reasons: - if unhealthy in UNHEALTHY_REASONS: + if unhealthy in UnhealthyReason: translation_key = f"{ISSUE_KEY_UNHEALTHY}_{unhealthy}" translation_placeholders = None else: @@ -238,7 +210,7 @@ class SupervisorIssues: def unsupported_reasons(self, reasons: set[str]) -> None: """Set unsupported reasons. Create or delete repairs as necessary.""" for unsupported in reasons - UNSUPPORTED_SKIP_REPAIR - self.unsupported_reasons: - if unsupported in UNSUPPORTED_REASONS: + if unsupported in UnsupportedReason: translation_key = f"{ISSUE_KEY_UNSUPPORTED}_{unsupported}" translation_placeholders = None else: diff --git a/tests/components/hassio/test_issues.py b/tests/components/hassio/test_issues.py index a4ad0a4a004..ddcbe5708c6 100644 --- a/tests/components/hassio/test_issues.py +++ b/tests/components/hassio/test_issues.py @@ -163,6 +163,31 @@ async def test_unhealthy_issues( assert_repair_in_list(msg["result"]["issues"], unhealthy=True, reason="setup") +@pytest.mark.usefixtures("all_setup_requests") +@pytest.mark.parametrize("unhealthy_reason", list(UnhealthyReason)) +async def test_unhealthy_reasons( + hass: HomeAssistant, + supervisor_client: AsyncMock, + hass_ws_client: WebSocketGenerator, + unhealthy_reason: UnhealthyReason, +) -> None: + """Test all unhealthy reasons in client library are properly made into repairs with a translation.""" + mock_resolution_info(supervisor_client, unhealthy=[unhealthy_reason]) + + result = await async_setup_component(hass, "hassio", {}) + assert result + + client = await hass_ws_client(hass) + + await client.send_json({"id": 1, "type": "repairs/list_issues"}) + msg = await client.receive_json() + assert msg["success"] + assert len(msg["result"]["issues"]) == 1 + assert_repair_in_list( + msg["result"]["issues"], unhealthy=True, reason=unhealthy_reason.value + ) + + @pytest.mark.usefixtures("all_setup_requests") async def test_unsupported_issues( hass: HomeAssistant, @@ -190,6 +215,34 @@ async def test_unsupported_issues( assert_repair_in_list(msg["result"]["issues"], unhealthy=False, reason="os") +@pytest.mark.usefixtures("all_setup_requests") +@pytest.mark.parametrize( + "unsupported_reason", + [r for r in UnsupportedReason if r != UnsupportedReason.PRIVILEGED], +) +async def test_unsupported_reasons( + hass: HomeAssistant, + supervisor_client: AsyncMock, + hass_ws_client: WebSocketGenerator, + unsupported_reason: UnsupportedReason, +) -> None: + """Test all unsupported reasons in client library are properly made into repairs with a translation.""" + mock_resolution_info(supervisor_client, unsupported=[unsupported_reason]) + + result = await async_setup_component(hass, "hassio", {}) + assert result + + client = await hass_ws_client(hass) + + await client.send_json({"id": 1, "type": "repairs/list_issues"}) + msg = await client.receive_json() + assert msg["success"] + assert len(msg["result"]["issues"]) == 1 + assert_repair_in_list( + msg["result"]["issues"], unhealthy=False, reason=unsupported_reason.value + ) + + @pytest.mark.usefixtures("all_setup_requests") async def test_unhealthy_issues_add_remove( hass: HomeAssistant,