diff --git a/supervisor/addons/__init__.py b/supervisor/addons/__init__.py index 1acadd1a7..689dab9ac 100644 --- a/supervisor/addons/__init__.py +++ b/supervisor/addons/__init__.py @@ -15,11 +15,11 @@ from ..exceptions import ( DockerAPIError, DockerError, DockerNotFound, - DockerRequestError, HomeAssistantAPIError, HostAppArmorError, ) from ..store.addon import AddonStore +from ..utils import check_exception_chain from .addon import Addon from .data import AddonsData @@ -102,11 +102,13 @@ class AddonManager(CoreSysAttributes): for addon in tasks: try: await addon.start() - except DockerRequestError: - pass - except (AddonConfigurationError, DockerAPIError, DockerNotFound): - addon.boot = AddonBoot.MANUAL - addon.save_persist() + except AddonsError as err: + # Check if there is an system/user issue + if check_exception_chain( + err, (DockerAPIError, DockerNotFound, AddonConfigurationError) + ): + addon.boot = AddonBoot.MANUAL + addon.save_persist() except Exception as err: # pylint: disable=broad-except self.sys_capture_exception(err) else: diff --git a/supervisor/utils/__init__.py b/supervisor/utils/__init__.py index 41df7065a..ff1078100 100644 --- a/supervisor/utils/__init__.py +++ b/supervisor/utils/__init__.py @@ -5,7 +5,7 @@ from ipaddress import IPv4Address import logging import re import socket -from typing import Optional +from typing import Any, Optional _LOGGER: logging.Logger = logging.getLogger(__name__) @@ -107,3 +107,17 @@ def check_port(address: IPv4Address, port: int) -> bool: except OSError: pass return False + + +def check_exception_chain(err: Exception, object_type: Any) -> bool: + """Check if exception chain include sub exception. + + It's not full recursive because we need mostly only access to the latest. + """ + if issubclass(type(err), object_type): + return True + + if not err.__context__: + return False + + return check_exception_chain(err.__context__, object_type) diff --git a/tests/utils/test_exception_helper.py b/tests/utils/test_exception_helper.py new file mode 100644 index 000000000..6e5c14937 --- /dev/null +++ b/tests/utils/test_exception_helper.py @@ -0,0 +1,36 @@ +"""Test exception helpers.""" + +from supervisor.utils import check_exception_chain + + +def test_simple_chain_exception(): + """Test simple chain of excepiton.""" + + try: + raise ValueError() + except ValueError as err: + assert check_exception_chain(err, ValueError) + + +def test_simple_nested_chain_exception(): + """Test simple nested chain of excepiton.""" + + try: + try: + raise ValueError() + except ValueError as err: + raise KeyError() from err + except KeyError as err: + assert check_exception_chain(err, ValueError) + + +def test_list_nested_chain_exception(): + """Test list nested chain of excepiton.""" + + try: + try: + raise ValueError() + except ValueError as err: + raise KeyError() from err + except KeyError as err: + assert check_exception_chain(err, (ValueError, OSError))