From 7a0c4c506038315417cee315ce2804bc9703d9c7 Mon Sep 17 00:00:00 2001 From: Mike Degatano Date: Sun, 16 Oct 2022 05:07:31 -0400 Subject: [PATCH] Unsupported check for journal gateway (#3950) --- supervisor/resolution/const.py | 1 + .../resolution/evaluations/systemd_journal.py | 35 +++++++++++++ .../test_evaluate_systemd_journal.py | 49 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 supervisor/resolution/evaluations/systemd_journal.py create mode 100644 tests/resolution/evaluation/test_evaluate_systemd_journal.py diff --git a/supervisor/resolution/const.py b/supervisor/resolution/const.py index 0578472ae..09ba3ad6a 100644 --- a/supervisor/resolution/const.py +++ b/supervisor/resolution/const.py @@ -50,6 +50,7 @@ class UnsupportedReason(str, Enum): SOURCE_MODS = "source_mods" SUPERVISOR_VERSION = "supervisor_version" SYSTEMD = "systemd" + SYSTEMD_JOURNAL = "systemd_journal" SYSTEMD_RESOLVED = "systemd_resolved" diff --git a/supervisor/resolution/evaluations/systemd_journal.py b/supervisor/resolution/evaluations/systemd_journal.py new file mode 100644 index 000000000..3c9a63917 --- /dev/null +++ b/supervisor/resolution/evaluations/systemd_journal.py @@ -0,0 +1,35 @@ +"""Evaluation class for systemd journal.""" + +from ...const import CoreState +from ...coresys import CoreSys +from ...host.const import HostFeature +from ..const import UnsupportedReason +from .base import EvaluateBase + + +def setup(coresys: CoreSys) -> EvaluateBase: + """Initialize evaluation-setup function.""" + return EvaluateSystemdJournal(coresys) + + +class EvaluateSystemdJournal(EvaluateBase): + """Evaluate systemd journal.""" + + @property + def reason(self) -> UnsupportedReason: + """Return a UnsupportedReason enum.""" + return UnsupportedReason.SYSTEMD_JOURNAL + + @property + def on_failure(self) -> str: + """Return a string that is printed when self.evaluate is True.""" + return "Systemd journal is not working correctly or inaccessible" + + @property + def states(self) -> list[CoreState]: + """Return a list of valid states when this evaluation can run.""" + return [CoreState.SETUP] + + async def evaluate(self) -> bool: + """Run evaluation, return true if system fails.""" + return HostFeature.JOURNAL not in self.sys_host.features diff --git a/tests/resolution/evaluation/test_evaluate_systemd_journal.py b/tests/resolution/evaluation/test_evaluate_systemd_journal.py new file mode 100644 index 000000000..7c1b53c47 --- /dev/null +++ b/tests/resolution/evaluation/test_evaluate_systemd_journal.py @@ -0,0 +1,49 @@ +"""Test evaluation base.""" +# pylint: disable=import-error,protected-access +from unittest.mock import MagicMock, patch + +from supervisor.const import CoreState +from supervisor.coresys import CoreSys +from supervisor.resolution.evaluations.systemd_journal import EvaluateSystemdJournal + + +async def test_evaluation(coresys: CoreSys, journald_gateway: MagicMock): + """Test evaluation.""" + systemd_journal = EvaluateSystemdJournal(coresys) + coresys.core.state = CoreState.SETUP + + assert systemd_journal.reason not in coresys.resolution.unsupported + + with patch("supervisor.host.logs.Path.is_socket", return_value=False): + await systemd_journal() + assert systemd_journal.reason in coresys.resolution.unsupported + + coresys.host.supported_features.cache_clear() # pylint: disable=no-member + + await systemd_journal() + assert systemd_journal.reason not in coresys.resolution.unsupported + + +async def test_did_run(coresys: CoreSys): + """Test that the evaluation ran as expected.""" + systemd_journal = EvaluateSystemdJournal(coresys) + should_run = systemd_journal.states + should_not_run = [state for state in CoreState if state not in should_run] + assert len(should_run) != 0 + assert len(should_not_run) != 0 + + with patch( + "supervisor.resolution.evaluations.systemd_journal.EvaluateSystemdJournal.evaluate", + return_value=None, + ) as evaluate: + for state in should_run: + coresys.core.state = state + await systemd_journal() + evaluate.assert_called_once() + evaluate.reset_mock() + + for state in should_not_run: + coresys.core.state = state + await systemd_journal() + evaluate.assert_not_called() + evaluate.reset_mock()