diff --git a/supervisor/docker/homeassistant.py b/supervisor/docker/homeassistant.py index 56961f2c7..fcc3efcef 100644 --- a/supervisor/docker/homeassistant.py +++ b/supervisor/docker/homeassistant.py @@ -2,6 +2,7 @@ from collections.abc import Awaitable from ipaddress import IPv4Address import logging +import re from awesomeversion import AwesomeVersion, AwesomeVersionCompareException from docker.types import Mount @@ -28,6 +29,7 @@ from .interface import CommandReturn, DockerInterface _LOGGER: logging.Logger = logging.getLogger(__name__) _VERIFY_TRUST: AwesomeVersion = AwesomeVersion("2021.5.0") _HASS_DOCKER_NAME: str = "homeassistant" +ENV_S6_GRACETIME = re.compile(r"^S6_SERVICES_GRACETIME=([0-9]+)$") class DockerHomeAssistant(DockerInterface): @@ -53,10 +55,15 @@ class DockerHomeAssistant(DockerInterface): @property def timeout(self) -> int: """Return timeout for Docker actions.""" - # Synchronized with the homeassistant core container's S6_SERVICES_GRACETIME - # to avoid killing Home Assistant Core, see + # Use S6_SERVICES_GRACETIME to avoid killing Home Assistant Core, see # https://github.com/home-assistant/core/tree/dev/Dockerfile - return 240 + 20 + if self.meta_config and "Env" in self.meta_config: + for env in self.meta_config["Env"]: + if match := ENV_S6_GRACETIME.match(env): + return 20 + int(int(match.group(1)) / 1000) + + # Fallback - as of 2024.3, S6 SERVICES_GRACETIME was set to 24000 + return 260 @property def ip_address(self) -> IPv4Address: diff --git a/tests/docker/test_homeassistant.py b/tests/docker/test_homeassistant.py index 6565a5a37..97968369c 100644 --- a/tests/docker/test_homeassistant.py +++ b/tests/docker/test_homeassistant.py @@ -2,7 +2,7 @@ from ipaddress import IPv4Address from pathlib import Path -from unittest.mock import ANY, patch +from unittest.mock import ANY, MagicMock, patch from awesomeversion import AwesomeVersion from docker.types import Mount @@ -145,3 +145,32 @@ async def test_landingpage_start( ), ] assert "volumes" not in run.call_args.kwargs + + +async def test_timeout(coresys: CoreSys, container: MagicMock): + """Test timeout for set from S6_SERVICES_GRACETIME.""" + assert coresys.homeassistant.core.instance.timeout == 260 + + # Env missing, remain at default + await coresys.homeassistant.core.instance.attach(AwesomeVersion("2024.3.0")) + assert coresys.homeassistant.core.instance.timeout == 260 + + # Set a mock value for env in attrs, see that it changes + container.attrs["Config"] = { + "Env": [ + "SUPERVISOR=172.30.32.2", + "HASSIO=172.30.32.2", + "TZ=America/New_York", + "SUPERVISOR_TOKEN=abc123", + "HASSIO_TOKEN=abc123", + "PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "LANG=C.UTF-8", + "S6_BEHAVIOUR_IF_STAGE2_FAILS=2", + "S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0", + "S6_CMD_WAIT_FOR_SERVICES=1", + "S6_SERVICES_READYTIME=50", + "S6_SERVICES_GRACETIME=300000", + ] + } + await coresys.homeassistant.core.instance.attach(AwesomeVersion("2024.3.0")) + assert coresys.homeassistant.core.instance.timeout == 320