Handle not available add-on in hassio add-on manager (#84943)
* Handle not available add-on in hassio add-on manager * Fix zwave_js tests * Fix sky connect tests * Fix matter tests * Fix yellow tests * Update hardware tests
This commit is contained in:
parent
240e1fd8f3
commit
94b80db968
9 changed files with 81 additions and 3 deletions
|
@ -70,6 +70,7 @@ def api_error(
|
|||
class AddonInfo:
|
||||
"""Represent the current add-on info state."""
|
||||
|
||||
available: bool
|
||||
hostname: str | None
|
||||
options: dict[str, Any]
|
||||
state: AddonState
|
||||
|
@ -144,6 +145,7 @@ class AddonManager:
|
|||
self._logger.debug("Add-on store info: %s", addon_store_info)
|
||||
if not addon_store_info["installed"]:
|
||||
return AddonInfo(
|
||||
available=addon_store_info["available"],
|
||||
hostname=None,
|
||||
options={},
|
||||
state=AddonState.NOT_INSTALLED,
|
||||
|
@ -154,6 +156,7 @@ class AddonManager:
|
|||
addon_info = await async_get_addon_info(self._hass, self.addon_slug)
|
||||
addon_state = self.async_get_addon_state(addon_info)
|
||||
return AddonInfo(
|
||||
available=addon_info["available"],
|
||||
hostname=addon_info["hostname"],
|
||||
options=addon_info["options"],
|
||||
state=addon_state,
|
||||
|
@ -184,6 +187,11 @@ class AddonManager:
|
|||
@api_error("Failed to install the {addon_name} add-on")
|
||||
async def async_install_addon(self) -> None:
|
||||
"""Install the managed add-on."""
|
||||
addon_info = await self.async_get_addon_info()
|
||||
|
||||
if not addon_info.available:
|
||||
raise AddonError(f"{self.addon_name} add-on is not available anymore")
|
||||
|
||||
await async_install_addon(self._hass, self.addon_slug)
|
||||
|
||||
@api_error("Failed to uninstall the {addon_name} add-on")
|
||||
|
@ -196,6 +204,9 @@ class AddonManager:
|
|||
"""Update the managed add-on if needed."""
|
||||
addon_info = await self.async_get_addon_info()
|
||||
|
||||
if not addon_info.available:
|
||||
raise AddonError(f"{self.addon_name} add-on is not available anymore")
|
||||
|
||||
if addon_info.state is AddonState.NOT_INSTALLED:
|
||||
raise AddonError(f"{self.addon_name} add-on is not installed")
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ def addon_not_installed_fixture(
|
|||
addon_store_info: AsyncMock, addon_info: AsyncMock
|
||||
) -> AsyncMock:
|
||||
"""Mock add-on not installed."""
|
||||
addon_store_info.return_value["available"] = True
|
||||
return addon_info
|
||||
|
||||
|
||||
|
@ -41,10 +42,12 @@ def mock_addon_installed(
|
|||
) -> AsyncMock:
|
||||
"""Mock add-on already installed but not running."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "stopped",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["hostname"] = "core-test-addon"
|
||||
addon_info.return_value["state"] = "stopped"
|
||||
addon_info.return_value["version"] = "1.0.0"
|
||||
|
@ -67,6 +70,7 @@ def addon_store_info_fixture() -> Generator[AsyncMock, None, None]:
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_store_info"
|
||||
) as addon_store_info:
|
||||
addon_store_info.return_value = {
|
||||
"available": False,
|
||||
"installed": None,
|
||||
"state": None,
|
||||
"version": "1.0.0",
|
||||
|
@ -81,6 +85,7 @@ def addon_info_fixture() -> Generator[AsyncMock, None, None]:
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_info",
|
||||
) as addon_info:
|
||||
addon_info.return_value = {
|
||||
"available": False,
|
||||
"hostname": None,
|
||||
"options": {},
|
||||
"state": None,
|
||||
|
@ -180,6 +185,26 @@ async def test_not_installed_raises_exception(
|
|||
assert str(err.value) == "Test add-on is not installed"
|
||||
|
||||
|
||||
async def test_not_available_raises_exception(
|
||||
addon_manager: AddonManager,
|
||||
addon_store_info: AsyncMock,
|
||||
addon_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Test addon not available raises exception."""
|
||||
addon_store_info.return_value["available"] = False
|
||||
addon_info.return_value["available"] = False
|
||||
|
||||
with pytest.raises(AddonError) as err:
|
||||
await addon_manager.async_install_addon()
|
||||
|
||||
assert str(err.value) == "Test add-on is not available anymore"
|
||||
|
||||
with pytest.raises(AddonError) as err:
|
||||
await addon_manager.async_update_addon()
|
||||
|
||||
assert str(err.value) == "Test add-on is not available anymore"
|
||||
|
||||
|
||||
async def test_get_addon_discovery_info(
|
||||
addon_manager: AddonManager, get_addon_discovery_info: AsyncMock
|
||||
) -> None:
|
||||
|
@ -222,6 +247,7 @@ async def test_get_addon_info_not_installed(
|
|||
) -> None:
|
||||
"""Test get addon info when addon is not installed.."""
|
||||
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
||||
available=True,
|
||||
hostname=None,
|
||||
options={},
|
||||
state=AddonState.NOT_INSTALLED,
|
||||
|
@ -243,6 +269,7 @@ async def test_get_addon_info(
|
|||
"""Test get addon info when addon is installed."""
|
||||
addon_installed.return_value["state"] = addon_info_state
|
||||
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
||||
available=True,
|
||||
hostname="core-test-addon",
|
||||
options={},
|
||||
state=addon_state,
|
||||
|
@ -308,18 +335,29 @@ async def test_set_addon_options_error(
|
|||
|
||||
|
||||
async def test_install_addon(
|
||||
addon_manager: AddonManager, install_addon: AsyncMock
|
||||
addon_manager: AddonManager,
|
||||
install_addon: AsyncMock,
|
||||
addon_store_info: AsyncMock,
|
||||
addon_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Test install addon."""
|
||||
addon_store_info.return_value["available"] = True
|
||||
addon_info.return_value["available"] = True
|
||||
|
||||
await addon_manager.async_install_addon()
|
||||
|
||||
assert install_addon.call_count == 1
|
||||
|
||||
|
||||
async def test_install_addon_error(
|
||||
addon_manager: AddonManager, install_addon: AsyncMock
|
||||
addon_manager: AddonManager,
|
||||
install_addon: AsyncMock,
|
||||
addon_store_info: AsyncMock,
|
||||
addon_info: AsyncMock,
|
||||
) -> None:
|
||||
"""Test install addon raises error."""
|
||||
addon_store_info.return_value["available"] = True
|
||||
addon_info.return_value["available"] = True
|
||||
install_addon.side_effect = HassioAPIError("Boom")
|
||||
|
||||
with pytest.raises(AddonError) as err:
|
||||
|
@ -341,6 +379,7 @@ async def test_schedule_install_addon(
|
|||
assert addon_manager.task_in_progress() is True
|
||||
|
||||
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
||||
available=True,
|
||||
hostname="core-test-addon",
|
||||
options={},
|
||||
state=AddonState.INSTALLING,
|
||||
|
@ -676,6 +715,7 @@ async def test_schedule_update_addon(
|
|||
assert addon_manager.task_in_progress() is True
|
||||
|
||||
assert await addon_manager.async_get_addon_info() == AddonInfo(
|
||||
available=True,
|
||||
hostname="core-test-addon",
|
||||
options={},
|
||||
state=AddonState.UPDATING,
|
||||
|
|
|
@ -67,6 +67,7 @@ def addon_store_info_fixture():
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_store_info"
|
||||
) as addon_store_info:
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": None,
|
||||
"state": None,
|
||||
"version": "1.0.0",
|
||||
|
@ -81,6 +82,7 @@ def addon_info_fixture():
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_info",
|
||||
) as addon_info:
|
||||
addon_info.return_value = {
|
||||
"available": True,
|
||||
"hostname": None,
|
||||
"options": {},
|
||||
"state": None,
|
||||
|
|
|
@ -69,6 +69,7 @@ def addon_store_info_fixture():
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_store_info"
|
||||
) as addon_store_info:
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": None,
|
||||
"state": None,
|
||||
"version": "1.0.0",
|
||||
|
@ -83,6 +84,7 @@ def addon_info_fixture():
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_info",
|
||||
) as addon_info:
|
||||
addon_info.return_value = {
|
||||
"available": True,
|
||||
"hostname": None,
|
||||
"options": {},
|
||||
"state": None,
|
||||
|
|
|
@ -67,6 +67,7 @@ def addon_store_info_fixture():
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_store_info"
|
||||
) as addon_store_info:
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": None,
|
||||
"state": None,
|
||||
"version": "1.0.0",
|
||||
|
@ -81,6 +82,7 @@ def addon_info_fixture():
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_info",
|
||||
) as addon_info:
|
||||
addon_info.return_value = {
|
||||
"available": True,
|
||||
"hostname": None,
|
||||
"options": {},
|
||||
"state": None,
|
||||
|
|
|
@ -80,6 +80,7 @@ def addon_store_info_fixture() -> Generator[AsyncMock, None, None]:
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_store_info"
|
||||
) as addon_store_info:
|
||||
addon_store_info.return_value = {
|
||||
"available": False,
|
||||
"installed": None,
|
||||
"state": None,
|
||||
"version": "1.0.0",
|
||||
|
@ -94,6 +95,7 @@ def addon_info_fixture() -> Generator[AsyncMock, None, None]:
|
|||
"homeassistant.components.hassio.addon_manager.async_get_addon_info",
|
||||
) as addon_info:
|
||||
addon_info.return_value = {
|
||||
"available": False,
|
||||
"hostname": None,
|
||||
"options": {},
|
||||
"state": None,
|
||||
|
@ -108,6 +110,7 @@ def addon_not_installed_fixture(
|
|||
addon_store_info: AsyncMock, addon_info: AsyncMock
|
||||
) -> AsyncMock:
|
||||
"""Mock add-on not installed."""
|
||||
addon_store_info.return_value["available"] = True
|
||||
return addon_info
|
||||
|
||||
|
||||
|
@ -117,10 +120,12 @@ def addon_installed_fixture(
|
|||
) -> AsyncMock:
|
||||
"""Mock add-on already installed but not running."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "stopped",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["hostname"] = "core-matter-server"
|
||||
addon_info.return_value["state"] = "stopped"
|
||||
addon_info.return_value["version"] = "1.0.0"
|
||||
|
@ -133,10 +138,12 @@ def addon_running_fixture(
|
|||
) -> AsyncMock:
|
||||
"""Mock add-on already running."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "started",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["hostname"] = "core-matter-server"
|
||||
addon_info.return_value["state"] = "started"
|
||||
addon_info.return_value["version"] = "1.0.0"
|
||||
|
@ -152,10 +159,12 @@ def install_addon_fixture(
|
|||
async def install_addon_side_effect(hass: HomeAssistant, slug: str) -> None:
|
||||
"""Mock install add-on."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "stopped",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["state"] = "stopped"
|
||||
addon_info.return_value["version"] = "1.0.0"
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ async def test_install_addon(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
assert addon_store_info.call_count == 2
|
||||
assert addon_store_info.call_count == 3
|
||||
assert install_addon.call_count == 1
|
||||
assert install_addon.call_args == call(hass, "core_matter_server")
|
||||
assert start_addon.call_count == 1
|
||||
|
|
|
@ -30,6 +30,7 @@ def mock_addon_info(addon_info_side_effect):
|
|||
side_effect=addon_info_side_effect,
|
||||
) as addon_info:
|
||||
addon_info.return_value = {
|
||||
"available": False,
|
||||
"hostname": None,
|
||||
"options": {},
|
||||
"state": None,
|
||||
|
@ -53,6 +54,7 @@ def mock_addon_store_info(addon_store_info_side_effect):
|
|||
side_effect=addon_store_info_side_effect,
|
||||
) as addon_store_info:
|
||||
addon_store_info.return_value = {
|
||||
"available": False,
|
||||
"installed": None,
|
||||
"state": None,
|
||||
"version": "1.0.0",
|
||||
|
@ -64,10 +66,12 @@ def mock_addon_store_info(addon_store_info_side_effect):
|
|||
def mock_addon_running(addon_store_info, addon_info):
|
||||
"""Mock add-on already running."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "started",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["state"] = "started"
|
||||
addon_info.return_value["version"] = "1.0.0"
|
||||
return addon_info
|
||||
|
@ -77,10 +81,12 @@ def mock_addon_running(addon_store_info, addon_info):
|
|||
def mock_addon_installed(addon_store_info, addon_info):
|
||||
"""Mock add-on already installed but not running."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "stopped",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["state"] = "stopped"
|
||||
addon_info.return_value["version"] = "1.0.0"
|
||||
return addon_info
|
||||
|
@ -89,6 +95,7 @@ def mock_addon_installed(addon_store_info, addon_info):
|
|||
@pytest.fixture(name="addon_not_installed")
|
||||
def mock_addon_not_installed(addon_store_info, addon_info):
|
||||
"""Mock add-on not installed."""
|
||||
addon_store_info.return_value["available"] = True
|
||||
return addon_info
|
||||
|
||||
|
||||
|
@ -126,10 +133,12 @@ def install_addon_side_effect_fixture(addon_store_info, addon_info):
|
|||
async def install_addon(hass, slug):
|
||||
"""Mock install add-on."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "stopped",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["state"] = "stopped"
|
||||
addon_info.return_value["version"] = "1.0.0"
|
||||
|
||||
|
@ -162,10 +171,12 @@ def start_addon_side_effect_fixture(addon_store_info, addon_info):
|
|||
async def start_addon(hass, slug):
|
||||
"""Mock start add-on."""
|
||||
addon_store_info.return_value = {
|
||||
"available": True,
|
||||
"installed": "1.0.0",
|
||||
"state": "started",
|
||||
"version": "1.0.0",
|
||||
}
|
||||
addon_info.return_value["available"] = True
|
||||
addon_info.return_value["state"] = "started"
|
||||
|
||||
return start_addon
|
||||
|
|
|
@ -536,6 +536,7 @@ async def test_abort_hassio_discovery_for_other_addon(
|
|||
async def test_usb_discovery(
|
||||
hass,
|
||||
supervisor,
|
||||
addon_not_installed,
|
||||
install_addon,
|
||||
addon_options,
|
||||
get_addon_discovery_info,
|
||||
|
|
Loading…
Add table
Reference in a new issue