mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-19 07:06:30 +00:00
Events when unhealthy/unsupported changes (#3951)
* Events when unhealthy/unsupported changes * called_once_with to called_once
This commit is contained in:
parent
bde5c938a7
commit
5d2b5bada7
@ -32,6 +32,8 @@ class WSEvent(str, Enum):
|
||||
"""Websocket events."""
|
||||
|
||||
ADDON = "addon"
|
||||
HEALTH_CHANGED = "health_changed"
|
||||
ISSUE_CHANGED = "issue_changed"
|
||||
ISSUE_REMOVED = "issue_removed"
|
||||
SUPERVISOR_UPDATE = "supervisor_update"
|
||||
SUPPORTED_CHANGED = "supported_changed"
|
||||
|
@ -3,7 +3,13 @@ from uuid import UUID, uuid4
|
||||
|
||||
import attr
|
||||
|
||||
from .const import ContextType, IssueType, SuggestionType
|
||||
from .const import (
|
||||
ContextType,
|
||||
IssueType,
|
||||
SuggestionType,
|
||||
UnhealthyReason,
|
||||
UnsupportedReason,
|
||||
)
|
||||
|
||||
|
||||
@attr.s(frozen=True, slots=True)
|
||||
@ -24,3 +30,19 @@ class Suggestion:
|
||||
context: ContextType = attr.ib()
|
||||
reference: str | None = attr.ib(default=None)
|
||||
uuid: UUID = attr.ib(factory=lambda: uuid4().hex, eq=False, init=False)
|
||||
|
||||
|
||||
@attr.s(frozen=True, slots=True)
|
||||
class HealthChanged:
|
||||
"""Describe change in system health."""
|
||||
|
||||
healthy: bool = attr.ib()
|
||||
unhealthy_reasons: list[UnhealthyReason] | None = attr.ib(default=None)
|
||||
|
||||
|
||||
@attr.s(frozen=True, slots=True)
|
||||
class SupportedChanged:
|
||||
"""Describe change in system supported."""
|
||||
|
||||
supported: bool = attr.ib()
|
||||
unsupported_reasons: list[UnsupportedReason] | None = attr.ib(default=None)
|
||||
|
@ -18,7 +18,7 @@ from .const import (
|
||||
UnhealthyReason,
|
||||
UnsupportedReason,
|
||||
)
|
||||
from .data import Issue, Suggestion
|
||||
from .data import HealthChanged, Issue, Suggestion, SupportedChanged
|
||||
from .evaluate import ResolutionEvaluation
|
||||
from .fixup import ResolutionFixup
|
||||
from .notify import ResolutionNotify
|
||||
@ -125,6 +125,10 @@ class ResolutionManager(FileConfiguration, CoreSysAttributes):
|
||||
"""Add a reason for unsupported."""
|
||||
if reason not in self._unsupported:
|
||||
self._unsupported.append(reason)
|
||||
self.sys_homeassistant.websocket.supervisor_event(
|
||||
WSEvent.SUPPORTED_CHANGED,
|
||||
attr.asdict(SupportedChanged(False, self.unsupported)),
|
||||
)
|
||||
|
||||
@property
|
||||
def unhealthy(self) -> list[UnhealthyReason]:
|
||||
@ -136,6 +140,10 @@ class ResolutionManager(FileConfiguration, CoreSysAttributes):
|
||||
"""Add a reason for unsupported."""
|
||||
if reason not in self._unhealthy:
|
||||
self._unhealthy.append(reason)
|
||||
self.sys_homeassistant.websocket.supervisor_event(
|
||||
WSEvent.HEALTH_CHANGED,
|
||||
attr.asdict(HealthChanged(False, self.unhealthy)),
|
||||
)
|
||||
|
||||
def get_suggestion(self, uuid: str) -> Suggestion:
|
||||
"""Return suggestion with uuid."""
|
||||
@ -228,6 +236,12 @@ class ResolutionManager(FileConfiguration, CoreSysAttributes):
|
||||
if reason not in self._unsupported:
|
||||
raise ResolutionError(f"The reason {reason} is not active", _LOGGER.warning)
|
||||
self._unsupported.remove(reason)
|
||||
self.sys_homeassistant.websocket.supervisor_event(
|
||||
WSEvent.SUPPORTED_CHANGED,
|
||||
attr.asdict(
|
||||
SupportedChanged(self.sys_core.supported, self.unsupported or None)
|
||||
),
|
||||
)
|
||||
|
||||
def suggestions_for_issue(self, issue: Issue) -> set[Suggestion]:
|
||||
"""Get suggestions that fix an issue."""
|
||||
|
@ -240,7 +240,7 @@ async def test_host_connectivity_disabled(coresys: CoreSys):
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.host.network.connectivity is True
|
||||
await asyncio.sleep(0)
|
||||
client.async_send_command.assert_called_once_with(
|
||||
client.async_send_command.assert_called_with(
|
||||
{
|
||||
"type": WSType.SUPERVISOR_EVENT,
|
||||
"data": {
|
||||
|
@ -261,3 +261,106 @@ async def test_resolution_apply_suggestion_multiple_copies(coresys: CoreSys):
|
||||
assert remove_store_1 in coresys.resolution.suggestions
|
||||
assert remove_store_2 not in coresys.resolution.suggestions
|
||||
assert remove_store_3 in coresys.resolution.suggestions
|
||||
|
||||
|
||||
async def test_events_on_unsupported_changed(coresys: CoreSys):
|
||||
"""Test events fired when unsupported changes."""
|
||||
with patch.object(
|
||||
type(coresys.homeassistant.websocket), "async_send_message"
|
||||
) as send_message:
|
||||
# Marking system as unsupported tells HA
|
||||
assert coresys.resolution.unsupported == []
|
||||
coresys.resolution.unsupported = UnsupportedReason.CONNECTIVITY_CHECK
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unsupported == [UnsupportedReason.CONNECTIVITY_CHECK]
|
||||
send_message.assert_called_once_with(
|
||||
_supervisor_event_message(
|
||||
"supported_changed",
|
||||
{"supported": False, "unsupported_reasons": ["connectivity_check"]},
|
||||
)
|
||||
)
|
||||
|
||||
# Adding the same reason again does nothing
|
||||
send_message.reset_mock()
|
||||
coresys.resolution.unsupported = UnsupportedReason.CONNECTIVITY_CHECK
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unsupported == [UnsupportedReason.CONNECTIVITY_CHECK]
|
||||
send_message.assert_not_called()
|
||||
|
||||
# Adding and removing additional reasons tells HA unsupported reasons changed
|
||||
coresys.resolution.unsupported = UnsupportedReason.JOB_CONDITIONS
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unsupported == [
|
||||
UnsupportedReason.CONNECTIVITY_CHECK,
|
||||
UnsupportedReason.JOB_CONDITIONS,
|
||||
]
|
||||
send_message.assert_called_once_with(
|
||||
_supervisor_event_message(
|
||||
"supported_changed",
|
||||
{
|
||||
"supported": False,
|
||||
"unsupported_reasons": ["connectivity_check", "job_conditions"],
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
send_message.reset_mock()
|
||||
coresys.resolution.dismiss_unsupported(UnsupportedReason.CONNECTIVITY_CHECK)
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unsupported == [UnsupportedReason.JOB_CONDITIONS]
|
||||
send_message.assert_called_once_with(
|
||||
_supervisor_event_message(
|
||||
"supported_changed",
|
||||
{"supported": False, "unsupported_reasons": ["job_conditions"]},
|
||||
)
|
||||
)
|
||||
|
||||
# Dismissing all unsupported reasons tells HA its supported again
|
||||
send_message.reset_mock()
|
||||
coresys.resolution.dismiss_unsupported(UnsupportedReason.JOB_CONDITIONS)
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unsupported == []
|
||||
send_message.assert_called_once_with(
|
||||
_supervisor_event_message(
|
||||
"supported_changed", {"supported": True, "unsupported_reasons": None}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def test_events_on_unhealthy_changed(coresys: CoreSys):
|
||||
"""Test events fired when unhealthy changes."""
|
||||
with patch.object(
|
||||
type(coresys.homeassistant.websocket), "async_send_message"
|
||||
) as send_message:
|
||||
# Marking system as unhealthy tells HA
|
||||
assert coresys.resolution.unhealthy == []
|
||||
coresys.resolution.unhealthy = UnhealthyReason.DOCKER
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unhealthy == [UnhealthyReason.DOCKER]
|
||||
send_message.assert_called_once_with(
|
||||
_supervisor_event_message(
|
||||
"health_changed",
|
||||
{"healthy": False, "unhealthy_reasons": ["docker"]},
|
||||
)
|
||||
)
|
||||
|
||||
# Adding the same reason again does nothing
|
||||
send_message.reset_mock()
|
||||
coresys.resolution.unhealthy = UnhealthyReason.DOCKER
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unhealthy == [UnhealthyReason.DOCKER]
|
||||
send_message.assert_not_called()
|
||||
|
||||
# Adding an additional reason tells HA unhealthy reasons changed
|
||||
coresys.resolution.unhealthy = UnhealthyReason.UNTRUSTED
|
||||
await asyncio.sleep(0)
|
||||
assert coresys.resolution.unhealthy == [
|
||||
UnhealthyReason.DOCKER,
|
||||
UnhealthyReason.UNTRUSTED,
|
||||
]
|
||||
send_message.assert_called_once_with(
|
||||
_supervisor_event_message(
|
||||
"health_changed",
|
||||
{"healthy": False, "unhealthy_reasons": ["docker", "untrusted"]},
|
||||
)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user