diff --git a/homeassistant/components/hassio/const.py b/homeassistant/components/hassio/const.py index a639833c381..15779b7a6b8 100644 --- a/homeassistant/components/hassio/const.py +++ b/homeassistant/components/hassio/const.py @@ -117,6 +117,7 @@ ISSUE_KEY_ADDON_BOOT_FAIL = "issue_addon_boot_fail" ISSUE_KEY_SYSTEM_DOCKER_CONFIG = "issue_system_docker_config" ISSUE_KEY_ADDON_DETACHED_ADDON_MISSING = "issue_addon_detached_addon_missing" ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED = "issue_addon_detached_addon_removed" +ISSUE_KEY_ADDON_DEPRECATED = "issue_addon_deprecated_addon" CORE_CONTAINER = "homeassistant" SUPERVISOR_CONTAINER = "hassio_supervisor" diff --git a/homeassistant/components/hassio/issues.py b/homeassistant/components/hassio/issues.py index 0486dc1f85f..ea1378c616b 100644 --- a/homeassistant/components/hassio/issues.py +++ b/homeassistant/components/hassio/issues.py @@ -42,6 +42,7 @@ from .const import ( EVENT_SUPERVISOR_UPDATE, EVENT_SUPPORTED_CHANGED, ISSUE_KEY_ADDON_BOOT_FAIL, + ISSUE_KEY_ADDON_DEPRECATED, ISSUE_KEY_ADDON_DETACHED_ADDON_MISSING, ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED, ISSUE_KEY_SYSTEM_DOCKER_CONFIG, @@ -78,6 +79,7 @@ ISSUE_KEYS_FOR_REPAIRS = { ISSUE_KEY_ADDON_DETACHED_ADDON_MISSING, ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED, "issue_system_disk_lifetime", + ISSUE_KEY_ADDON_DEPRECATED, } _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/hassio/repairs.py b/homeassistant/components/hassio/repairs.py index 0e8122c08b9..1e8a4e72020 100644 --- a/homeassistant/components/hassio/repairs.py +++ b/homeassistant/components/hassio/repairs.py @@ -17,6 +17,7 @@ from homeassistant.data_entry_flow import FlowResult from . import get_addons_info, get_issues_info from .const import ( ISSUE_KEY_ADDON_BOOT_FAIL, + ISSUE_KEY_ADDON_DEPRECATED, ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED, ISSUE_KEY_SYSTEM_DOCKER_CONFIG, PLACEHOLDER_KEY_ADDON, @@ -43,6 +44,7 @@ EXTRA_PLACEHOLDERS = { "storage_url": "/config/storage", }, ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED: HELP_URLS, + ISSUE_KEY_ADDON_DEPRECATED: HELP_URLS, } @@ -219,6 +221,7 @@ async def async_create_fix_flow( if issue and issue.key in { ISSUE_KEY_ADDON_DETACHED_ADDON_REMOVED, ISSUE_KEY_ADDON_BOOT_FAIL, + ISSUE_KEY_ADDON_DEPRECATED, }: return AddonIssueRepairFlow(hass, issue_id) diff --git a/homeassistant/components/hassio/strings.json b/homeassistant/components/hassio/strings.json index 393fe480057..956d991d96f 100644 --- a/homeassistant/components/hassio/strings.json +++ b/homeassistant/components/hassio/strings.json @@ -52,6 +52,19 @@ } } }, + "issue_addon_deprecated_addon": { + "title": "Installed add-on is deprecated", + "fix_flow": { + "step": { + "addon_execute_remove": { + "description": "Add-on {addon} is marked deprecated by the developer. This means it is no longer being maintained and so may break or become a security issue over time.\n\nSelecting **Submit** will uninstall this deprecated add-on. Alternatively, you can check [Home Assistant help]({help_url}) and the [community forum]({community_url}) for alternatives to migrate to." + } + }, + "abort": { + "apply_suggestion_fail": "Could not uninstall the add-on. Check the Supervisor logs for more details." + } + } + }, "issue_mount_mount_failed": { "title": "Network storage device failed", "fix_flow": { diff --git a/tests/components/hassio/test_repairs.py b/tests/components/hassio/test_repairs.py index 4234aab40c1..b0592261065 100644 --- a/tests/components/hassio/test_repairs.py +++ b/tests/components/hassio/test_repairs.py @@ -994,3 +994,90 @@ async def test_supervisor_issue_addon_boot_fail( assert not issue_registry.async_get_issue(domain="hassio", issue_id=issue_uuid.hex) supervisor_client.resolution.apply_suggestion.assert_called_once_with(sugg_uuid) + + +@pytest.mark.parametrize( + "all_setup_requests", [{"include_addons": True}], indirect=True +) +@pytest.mark.usefixtures("all_setup_requests") +async def test_supervisor_issue_deprecated_addon( + hass: HomeAssistant, + supervisor_client: AsyncMock, + hass_client: ClientSessionGenerator, + issue_registry: ir.IssueRegistry, +) -> None: + """Test fix flow for supervisor issue for deprecated add-on.""" + mock_resolution_info( + supervisor_client, + issues=[ + Issue( + type=IssueType.DEPRECATED_ADDON, + context=ContextType.ADDON, + reference="test", + uuid=(issue_uuid := uuid4()), + ), + ], + suggestions_by_issue={ + issue_uuid: [ + Suggestion( + type=SuggestionType.EXECUTE_REMOVE, + context=ContextType.ADDON, + reference="test", + uuid=(sugg_uuid := uuid4()), + auto=False, + ), + ] + }, + ) + + assert await async_setup_component(hass, "hassio", {}) + + repair_issue = issue_registry.async_get_issue( + domain="hassio", issue_id=issue_uuid.hex + ) + assert repair_issue + + client = await hass_client() + + resp = await client.post( + "/api/repairs/issues/fix", + json={"handler": "hassio", "issue_id": repair_issue.issue_id}, + ) + + assert resp.status == HTTPStatus.OK + data = await resp.json() + + flow_id = data["flow_id"] + assert data == { + "type": "form", + "flow_id": flow_id, + "handler": "hassio", + "step_id": "addon_execute_remove", + "data_schema": [], + "errors": None, + "description_placeholders": { + "reference": "test", + "addon": "test", + "help_url": "https://www.home-assistant.io/help/", + "community_url": "https://community.home-assistant.io/", + }, + "last_step": True, + "preview": None, + } + + resp = await client.post(f"/api/repairs/issues/fix/{flow_id}") + + assert resp.status == HTTPStatus.OK + data = await resp.json() + + flow_id = data["flow_id"] + assert data == { + "type": "create_entry", + "flow_id": flow_id, + "handler": "hassio", + "description": None, + "description_placeholders": None, + } + + assert not issue_registry.async_get_issue(domain="hassio", issue_id=issue_uuid.hex) + supervisor_client.resolution.apply_suggestion.assert_called_once_with(sugg_uuid)