Attempt plugin update before failing job condition (#3796)

This commit is contained in:
Mike Degatano 2022-08-17 01:36:05 -04:00 committed by GitHub
parent 5fc9484f73
commit 2cd7f9d1b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 10 deletions

View File

@ -92,7 +92,7 @@ class Job(CoreSysAttributes):
# Handle condition
if self.conditions:
try:
self._check_conditions()
await self._check_conditions()
except JobConditionException as err:
error_msg = str(err)
if self.on_condition is None:
@ -150,7 +150,7 @@ class Job(CoreSysAttributes):
return wrapper
def _check_conditions(self):
async def _check_conditions(self):
"""Check conditions."""
used_conditions = set(self.conditions) - set(self.sys_jobs.ignore_conditions)
ignored_conditions = set(self.conditions) & set(self.sys_jobs.ignore_conditions)
@ -238,13 +238,22 @@ class Job(CoreSysAttributes):
f"'{self._method.__qualname__}' blocked from execution, supervisor needs to be updated first"
)
if JobCondition.PLUGINS_UPDATED in self.conditions and 0 < len(
[plugin for plugin in self.sys_plugins.all_plugins if plugin.need_update]
if JobCondition.PLUGINS_UPDATED in self.conditions and (
out_of_date := [
plugin for plugin in self.sys_plugins.all_plugins if plugin.need_update
]
):
raise JobConditionException(
f"'{self._method.__qualname__}' blocked from execution, plugin(s) {', '.join([plugin.slug for plugin in self.sys_plugins.all_plugins if plugin.need_update])} need to be updated first"
errors = await asyncio.gather(
*[plugin.update() for plugin in out_of_date], return_exceptions=True
)
if update_failures := [
out_of_date[i].slug for i in range(len(errors)) if errors[i] is not None
]:
raise JobConditionException(
f"'{self._method.__qualname__}' blocked from execution, was unable to update plugin(s) {', '.join(update_failures)} and all plugins must be up to date first"
)
async def _acquire_exection_limit(self) -> None:
"""Process exection limits."""
if self.limit not in (

View File

@ -11,7 +11,7 @@ from supervisor.const import AddonState, BusEvent
from supervisor.coresys import CoreSys
from supervisor.docker.const import ContainerState
from supervisor.docker.monitor import DockerContainerStateEvent
from supervisor.exceptions import AddonsJobError
from supervisor.exceptions import AddonsJobError, AudioUpdateError
from ..const import TEST_ADDON_SLUG
@ -287,6 +287,8 @@ async def test_install_update_fails_if_out_of_date(
with patch.object(
type(coresys.plugins.audio), "need_update", new=PropertyMock(return_value=True)
), patch.object(
type(coresys.plugins.audio), "update", side_effect=AudioUpdateError
):
with pytest.raises(AddonsJobError):
await coresys.addons.install(TEST_ADDON_SLUG)

View File

@ -4,7 +4,7 @@ from unittest.mock import PropertyMock, patch
import pytest
from supervisor.coresys import CoreSys
from supervisor.exceptions import HomeAssistantJobError
from supervisor.exceptions import AudioUpdateError, HomeAssistantJobError
async def test_update_fails_if_out_of_date(coresys: CoreSys):
@ -18,5 +18,9 @@ async def test_update_fails_if_out_of_date(coresys: CoreSys):
with patch.object(
type(coresys.plugins.audio), "need_update", new=PropertyMock(return_value=True)
), pytest.raises(HomeAssistantJobError):
), patch.object(
type(coresys.plugins.audio), "update", side_effect=AudioUpdateError
), pytest.raises(
HomeAssistantJobError
):
await coresys.homeassistant.core.update()

View File

@ -9,7 +9,12 @@ import time_machine
from supervisor.const import CoreState
from supervisor.coresys import CoreSys
from supervisor.exceptions import HassioError, JobException, PluginJobError
from supervisor.exceptions import (
AudioUpdateError,
HassioError,
JobException,
PluginJobError,
)
from supervisor.jobs.const import JobExecutionLimit
from supervisor.jobs.decorator import Job, JobCondition
from supervisor.resolution.const import UnhealthyReason
@ -448,8 +453,11 @@ async def test_plugins_updated(coresys: CoreSys):
with patch.object(
type(coresys.plugins.audio), "need_update", new=PropertyMock(return_value=True)
), patch.object(
type(coresys.plugins.audio), "update", side_effect=[AudioUpdateError, None]
):
assert not await test.execute()
assert await test.execute()
async def test_auto_update(coresys: CoreSys):