mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-12 19:56: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"
|
||||
BACKUP_START = "backup/start"
|
||||
BACKUP_END = "backup/end"
|
||||
HASSIO_UPDATE_ADDON = "hassio/update/addon"
|
||||
|
||||
|
||||
class WSEvent(StrEnum):
|
||||
|
@ -1,13 +1,11 @@
|
||||
"""A collection of tasks."""
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Awaitable
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
|
||||
from ..addons.const import ADDON_UPDATE_CONDITIONS
|
||||
from ..backups.const import LOCATION_CLOUD_BACKUP
|
||||
from ..const import AddonState
|
||||
from ..const import ATTR_TYPE, AddonState
|
||||
from ..coresys import CoreSysAttributes
|
||||
from ..exceptions import (
|
||||
AddonsError,
|
||||
@ -15,7 +13,7 @@ from ..exceptions import (
|
||||
HomeAssistantError,
|
||||
ObserverError,
|
||||
)
|
||||
from ..homeassistant.const import LANDINGPAGE
|
||||
from ..homeassistant.const import LANDINGPAGE, WSType
|
||||
from ..jobs.decorator import Job, JobCondition, JobExecutionLimit
|
||||
from ..plugins.const import PLUGIN_UPDATE_CONDITIONS
|
||||
from ..utils.dt import utcnow
|
||||
@ -106,7 +104,6 @@ class Tasks(CoreSysAttributes):
|
||||
)
|
||||
async def _update_addons(self):
|
||||
"""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:
|
||||
if not addon.is_installed or not addon.auto_update:
|
||||
continue
|
||||
@ -131,16 +128,21 @@ class Tasks(CoreSysAttributes):
|
||||
)
|
||||
continue
|
||||
|
||||
# Run Add-on update sequential
|
||||
# avoid issue on slow IO
|
||||
_LOGGER.info("Add-on auto update process %s", addon.slug)
|
||||
try:
|
||||
if start_task := await self.sys_addons.update(addon.slug, backup=True):
|
||||
start_tasks.append(start_task)
|
||||
except AddonsError:
|
||||
_LOGGER.error("Can't auto update Add-on %s", addon.slug)
|
||||
|
||||
await asyncio.gather(*start_tasks)
|
||||
# Call Home Assistant Core to update add-on to make sure that backups
|
||||
# get created through the Home Assistant Core API (categorized correctly).
|
||||
# Ultimately auto updates should be handled by Home Assistant Core itself
|
||||
# through a update entity feature.
|
||||
message = {
|
||||
ATTR_TYPE: WSType.HASSIO_UPDATE_ADDON,
|
||||
"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(
|
||||
name="tasks_update_supervisor",
|
||||
|
@ -8,7 +8,8 @@ from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, patch
|
||||
from awesomeversion import AwesomeVersion
|
||||
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.exceptions import HomeAssistantError
|
||||
from supervisor.homeassistant.api import HomeAssistantAPI
|
||||
@ -230,3 +231,37 @@ async def test_core_backup_cleanup(
|
||||
assert not coresys.backups.get("7fed74c8")
|
||||
assert new_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