mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-13 20:26:29 +00:00
Trigger auto-update through Core WebSocket call (#5896)
* Trigger auto-update through Core WebSocket call Instead of auto-updating add-ons on Supervisor side trigger an update through Core via a WebSocket command. This makes sure that the backup is categorized correctly and all backup features like retention are applied. * Add pytest * Fix pytest * Fix pytest * Fix pytest * Fix pytest * Fix pytest cleaner * Set timestamp of add-on far into the past
This commit is contained in:
parent
b5a7e521ae
commit
6e6fe5ba39
@ -32,6 +32,7 @@ class WSType(StrEnum):
|
|||||||
SUPERVISOR_EVENT = "supervisor/event"
|
SUPERVISOR_EVENT = "supervisor/event"
|
||||||
BACKUP_START = "backup/start"
|
BACKUP_START = "backup/start"
|
||||||
BACKUP_END = "backup/end"
|
BACKUP_END = "backup/end"
|
||||||
|
HASSIO_UPDATE_ADDON = "hassio/update/addon"
|
||||||
|
|
||||||
|
|
||||||
class WSEvent(StrEnum):
|
class WSEvent(StrEnum):
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
"""A collection of tasks."""
|
"""A collection of tasks."""
|
||||||
|
|
||||||
import asyncio
|
|
||||||
from collections.abc import Awaitable
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from ..addons.const import ADDON_UPDATE_CONDITIONS
|
from ..addons.const import ADDON_UPDATE_CONDITIONS
|
||||||
from ..backups.const import LOCATION_CLOUD_BACKUP
|
from ..backups.const import LOCATION_CLOUD_BACKUP
|
||||||
from ..const import AddonState
|
from ..const import ATTR_TYPE, AddonState
|
||||||
from ..coresys import CoreSysAttributes
|
from ..coresys import CoreSysAttributes
|
||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
AddonsError,
|
AddonsError,
|
||||||
@ -15,7 +13,7 @@ from ..exceptions import (
|
|||||||
HomeAssistantError,
|
HomeAssistantError,
|
||||||
ObserverError,
|
ObserverError,
|
||||||
)
|
)
|
||||||
from ..homeassistant.const import LANDINGPAGE
|
from ..homeassistant.const import LANDINGPAGE, WSType
|
||||||
from ..jobs.decorator import Job, JobCondition, JobExecutionLimit
|
from ..jobs.decorator import Job, JobCondition, JobExecutionLimit
|
||||||
from ..plugins.const import PLUGIN_UPDATE_CONDITIONS
|
from ..plugins.const import PLUGIN_UPDATE_CONDITIONS
|
||||||
from ..utils.dt import utcnow
|
from ..utils.dt import utcnow
|
||||||
@ -106,7 +104,6 @@ class Tasks(CoreSysAttributes):
|
|||||||
)
|
)
|
||||||
async def _update_addons(self):
|
async def _update_addons(self):
|
||||||
"""Check if an update is available for an Add-on and update it."""
|
"""Check if an update is available for an Add-on and update it."""
|
||||||
start_tasks: list[Awaitable[None]] = []
|
|
||||||
for addon in self.sys_addons.all:
|
for addon in self.sys_addons.all:
|
||||||
if not addon.is_installed or not addon.auto_update:
|
if not addon.is_installed or not addon.auto_update:
|
||||||
continue
|
continue
|
||||||
@ -131,16 +128,21 @@ class Tasks(CoreSysAttributes):
|
|||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Run Add-on update sequential
|
|
||||||
# avoid issue on slow IO
|
|
||||||
_LOGGER.info("Add-on auto update process %s", addon.slug)
|
_LOGGER.info("Add-on auto update process %s", addon.slug)
|
||||||
try:
|
# Call Home Assistant Core to update add-on to make sure that backups
|
||||||
if start_task := await self.sys_addons.update(addon.slug, backup=True):
|
# get created through the Home Assistant Core API (categorized correctly).
|
||||||
start_tasks.append(start_task)
|
# Ultimately auto updates should be handled by Home Assistant Core itself
|
||||||
except AddonsError:
|
# through a update entity feature.
|
||||||
_LOGGER.error("Can't auto update Add-on %s", addon.slug)
|
message = {
|
||||||
|
ATTR_TYPE: WSType.HASSIO_UPDATE_ADDON,
|
||||||
await asyncio.gather(*start_tasks)
|
"addon": addon.slug,
|
||||||
|
"backup": True,
|
||||||
|
}
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Sending update add-on WebSocket command to Home Assistant Core: %s",
|
||||||
|
message,
|
||||||
|
)
|
||||||
|
await self.sys_homeassistant.websocket.async_send_command(message)
|
||||||
|
|
||||||
@Job(
|
@Job(
|
||||||
name="tasks_update_supervisor",
|
name="tasks_update_supervisor",
|
||||||
|
@ -8,7 +8,8 @@ from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, patch
|
|||||||
from awesomeversion import AwesomeVersion
|
from awesomeversion import AwesomeVersion
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from supervisor.const import CoreState
|
from supervisor.addons.addon import Addon
|
||||||
|
from supervisor.const import ATTR_VERSION_TIMESTAMP, CoreState
|
||||||
from supervisor.coresys import CoreSys
|
from supervisor.coresys import CoreSys
|
||||||
from supervisor.exceptions import HomeAssistantError
|
from supervisor.exceptions import HomeAssistantError
|
||||||
from supervisor.homeassistant.api import HomeAssistantAPI
|
from supervisor.homeassistant.api import HomeAssistantAPI
|
||||||
@ -230,3 +231,37 @@ async def test_core_backup_cleanup(
|
|||||||
assert not coresys.backups.get("7fed74c8")
|
assert not coresys.backups.get("7fed74c8")
|
||||||
assert new_tar.exists()
|
assert new_tar.exists()
|
||||||
assert not old_tar.exists()
|
assert not old_tar.exists()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_update_addons_auto_update_success(
|
||||||
|
tasks: Tasks,
|
||||||
|
coresys: CoreSys,
|
||||||
|
tmp_supervisor_data: Path,
|
||||||
|
ha_ws_client: AsyncMock,
|
||||||
|
install_addon_example: Addon,
|
||||||
|
):
|
||||||
|
"""Test that an eligible add-on is auto-updated via websocket command."""
|
||||||
|
await coresys.core.set_state(CoreState.RUNNING)
|
||||||
|
|
||||||
|
# Set up the add-on as eligible for auto-update
|
||||||
|
install_addon_example.auto_update = True
|
||||||
|
install_addon_example.data_store[ATTR_VERSION_TIMESTAMP] = 0
|
||||||
|
with patch.object(
|
||||||
|
Addon, "version", new=PropertyMock(return_value=AwesomeVersion("1.0"))
|
||||||
|
):
|
||||||
|
assert install_addon_example.need_update is True
|
||||||
|
assert install_addon_example.auto_update_available is True
|
||||||
|
|
||||||
|
# Make sure all job events from installing the add-on are cleared
|
||||||
|
ha_ws_client.async_send_command.reset_mock()
|
||||||
|
|
||||||
|
# pylint: disable-next=protected-access
|
||||||
|
await tasks._update_addons()
|
||||||
|
|
||||||
|
ha_ws_client.async_send_command.assert_any_call(
|
||||||
|
{
|
||||||
|
"type": "hassio/update/addon",
|
||||||
|
"addon": install_addon_example.slug,
|
||||||
|
"backup": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user