mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-17 14:16:29 +00:00
Watchdog shouldn't rebuild addons (#3766)
* Watchdog shouldn't rebuild addons * pylint fix
This commit is contained in:
parent
5d6e2eeaac
commit
2b4f46f6b3
@ -914,23 +914,17 @@ class Addon(AddonModel):
|
|||||||
await asyncio.sleep(WATCHDOG_RETRY_SECONDS)
|
await asyncio.sleep(WATCHDOG_RETRY_SECONDS)
|
||||||
|
|
||||||
elif event.state == ContainerState.FAILED:
|
elif event.state == ContainerState.FAILED:
|
||||||
rebuild = False
|
# Ensure failed container is removed before attempting reanimation
|
||||||
|
with suppress(DockerError):
|
||||||
|
await self.instance.stop(remove_container=True)
|
||||||
|
|
||||||
while await self.instance.current_state() == event.state:
|
while await self.instance.current_state() == event.state:
|
||||||
if not self.in_progress:
|
if not self.in_progress:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Watchdog found addon %s failed, restarting...", self.name
|
"Watchdog found addon %s failed, restarting...", self.name
|
||||||
)
|
)
|
||||||
if not rebuild:
|
|
||||||
try:
|
|
||||||
await self.start()
|
|
||||||
except AddonsError as err:
|
|
||||||
self.sys_capture_exception(err)
|
|
||||||
rebuild = True
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await self.rebuild()
|
await self.start()
|
||||||
except AddonsError as err:
|
except AddonsError as err:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Watchdog reanimation of addon %s failed!", self.name
|
"Watchdog reanimation of addon %s failed!", self.name
|
||||||
|
@ -10,7 +10,6 @@ from supervisor.const import AddonState, BusEvent
|
|||||||
from supervisor.coresys import CoreSys
|
from supervisor.coresys import CoreSys
|
||||||
from supervisor.docker.const import ContainerState
|
from supervisor.docker.const import ContainerState
|
||||||
from supervisor.docker.monitor import DockerContainerStateEvent
|
from supervisor.docker.monitor import DockerContainerStateEvent
|
||||||
from supervisor.exceptions import AddonsError
|
|
||||||
|
|
||||||
from ..const import TEST_ADDON_SLUG
|
from ..const import TEST_ADDON_SLUG
|
||||||
|
|
||||||
@ -131,6 +130,10 @@ async def mock_current_state(state: ContainerState) -> ContainerState:
|
|||||||
return state
|
return state
|
||||||
|
|
||||||
|
|
||||||
|
async def mock_stop() -> None:
|
||||||
|
"""Mock for stop method."""
|
||||||
|
|
||||||
|
|
||||||
async def test_addon_watchdog(coresys: CoreSys, install_addon_ssh: Addon) -> None:
|
async def test_addon_watchdog(coresys: CoreSys, install_addon_ssh: Addon) -> None:
|
||||||
"""Test addon watchdog works correctly."""
|
"""Test addon watchdog works correctly."""
|
||||||
with patch.object(type(install_addon_ssh.instance), "attach"):
|
with patch.object(type(install_addon_ssh.instance), "attach"):
|
||||||
@ -159,18 +162,23 @@ async def test_addon_watchdog(coresys: CoreSys, install_addon_ssh: Addon) -> Non
|
|||||||
|
|
||||||
restart.reset_mock()
|
restart.reset_mock()
|
||||||
current_state.return_value = mock_current_state(ContainerState.FAILED)
|
current_state.return_value = mock_current_state(ContainerState.FAILED)
|
||||||
coresys.bus.fire_event(
|
|
||||||
BusEvent.DOCKER_CONTAINER_STATE_CHANGE,
|
with patch.object(
|
||||||
DockerContainerStateEvent(
|
type(install_addon_ssh.instance), "stop", return_value=mock_stop()
|
||||||
name=f"addon_{TEST_ADDON_SLUG}",
|
) as stop:
|
||||||
state=ContainerState.FAILED,
|
coresys.bus.fire_event(
|
||||||
id="abc123",
|
BusEvent.DOCKER_CONTAINER_STATE_CHANGE,
|
||||||
time=1,
|
DockerContainerStateEvent(
|
||||||
),
|
name=f"addon_{TEST_ADDON_SLUG}",
|
||||||
)
|
state=ContainerState.FAILED,
|
||||||
await asyncio.sleep(0)
|
id="abc123",
|
||||||
restart.assert_not_called()
|
time=1,
|
||||||
start.assert_called_once()
|
),
|
||||||
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
stop.assert_called_once_with(remove_container=True)
|
||||||
|
restart.assert_not_called()
|
||||||
|
start.assert_called_once()
|
||||||
|
|
||||||
start.reset_mock()
|
start.reset_mock()
|
||||||
# Do not process event if container state has changed since fired
|
# Do not process event if container state has changed since fired
|
||||||
@ -217,36 +225,6 @@ async def test_addon_watchdog(coresys: CoreSys, install_addon_ssh: Addon) -> Non
|
|||||||
start.assert_not_called()
|
start.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
async def test_addon_watchdog_rebuild_on_failure(
|
|
||||||
coresys: CoreSys, install_addon_ssh: Addon
|
|
||||||
) -> None:
|
|
||||||
"""Test addon watchdog rebuilds if start fails."""
|
|
||||||
with patch.object(type(install_addon_ssh.instance), "attach"):
|
|
||||||
await install_addon_ssh.load()
|
|
||||||
|
|
||||||
install_addon_ssh.watchdog = True
|
|
||||||
|
|
||||||
with patch.object(Addon, "start", side_effect=AddonsError()) as start, patch.object(
|
|
||||||
Addon, "rebuild"
|
|
||||||
) as rebuild, patch.object(
|
|
||||||
type(install_addon_ssh.instance),
|
|
||||||
"current_state",
|
|
||||||
return_value=mock_current_state(ContainerState.FAILED),
|
|
||||||
):
|
|
||||||
coresys.bus.fire_event(
|
|
||||||
BusEvent.DOCKER_CONTAINER_STATE_CHANGE,
|
|
||||||
DockerContainerStateEvent(
|
|
||||||
name=f"addon_{TEST_ADDON_SLUG}",
|
|
||||||
state=ContainerState.FAILED,
|
|
||||||
id="abc123",
|
|
||||||
time=1,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
await asyncio.sleep(0)
|
|
||||||
start.assert_called_once()
|
|
||||||
rebuild.assert_called_once()
|
|
||||||
|
|
||||||
|
|
||||||
async def test_listener_attached_on_install(coresys: CoreSys, repository):
|
async def test_listener_attached_on_install(coresys: CoreSys, repository):
|
||||||
"""Test events listener attached on addon install."""
|
"""Test events listener attached on addon install."""
|
||||||
container_collection = MagicMock()
|
container_collection = MagicMock()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user