Use dispatch instead of eventbus for supervisor events (#46986)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
f4db74fe73
commit
7d90cdea1e
5 changed files with 164 additions and 115 deletions
|
@ -33,7 +33,8 @@ X_HASS_IS_ADMIN = "X-Hass-Is-Admin"
|
|||
WS_TYPE = "type"
|
||||
WS_ID = "id"
|
||||
|
||||
WS_TYPE_EVENT = "supervisor/event"
|
||||
WS_TYPE_API = "supervisor/api"
|
||||
WS_TYPE_EVENT = "supervisor/event"
|
||||
WS_TYPE_SUBSCRIBE = "supervisor/subscribe"
|
||||
|
||||
EVENT_SUPERVISOR_EVENT = "supervisor_event"
|
||||
|
|
|
@ -7,6 +7,10 @@ from homeassistant.components import websocket_api
|
|||
from homeassistant.components.websocket_api.connection import ActiveConnection
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
async_dispatcher_connect,
|
||||
async_dispatcher_send,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
ATTR_DATA,
|
||||
|
@ -20,6 +24,7 @@ from .const import (
|
|||
WS_TYPE,
|
||||
WS_TYPE_API,
|
||||
WS_TYPE_EVENT,
|
||||
WS_TYPE_SUBSCRIBE,
|
||||
)
|
||||
from .handler import HassIO
|
||||
|
||||
|
@ -36,6 +41,26 @@ def async_load_websocket_api(hass: HomeAssistant):
|
|||
"""Set up the websocket API."""
|
||||
websocket_api.async_register_command(hass, websocket_supervisor_event)
|
||||
websocket_api.async_register_command(hass, websocket_supervisor_api)
|
||||
websocket_api.async_register_command(hass, websocket_subscribe)
|
||||
|
||||
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.async_response
|
||||
@websocket_api.websocket_command({vol.Required(WS_TYPE): WS_TYPE_SUBSCRIBE})
|
||||
async def websocket_subscribe(
|
||||
hass: HomeAssistant, connection: ActiveConnection, msg: dict
|
||||
):
|
||||
"""Subscribe to supervisor events."""
|
||||
|
||||
@callback
|
||||
def forward_messages(data):
|
||||
"""Forward events to websocket."""
|
||||
connection.send_message(websocket_api.event_message(msg[WS_ID], data))
|
||||
|
||||
connection.subscriptions[msg[WS_ID]] = async_dispatcher_connect(
|
||||
hass, EVENT_SUPERVISOR_EVENT, forward_messages
|
||||
)
|
||||
connection.send_message(websocket_api.result_message(msg[WS_ID]))
|
||||
|
||||
|
||||
@websocket_api.async_response
|
||||
|
@ -49,7 +74,7 @@ async def websocket_supervisor_event(
|
|||
hass: HomeAssistant, connection: ActiveConnection, msg: dict
|
||||
):
|
||||
"""Publish events from the Supervisor."""
|
||||
hass.bus.async_fire(EVENT_SUPERVISOR_EVENT, msg[ATTR_DATA])
|
||||
async_dispatcher_send(hass, EVENT_SUPERVISOR_EVENT, msg[ATTR_DATA])
|
||||
connection.send_result(msg[WS_ID])
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,48 @@
|
|||
"""Tests for Hass.io component."""
|
||||
import pytest
|
||||
|
||||
HASSIO_TOKEN = "123456"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_all(aioclient_mock):
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"supervisor": "222", "homeassistant": "0.110.0", "hassos": None},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
|
|
|
@ -2,73 +2,16 @@
|
|||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.auth.const import GROUP_ID_ADMIN
|
||||
from homeassistant.components import frontend
|
||||
from homeassistant.components.hassio import STORAGE_KEY
|
||||
from homeassistant.components.hassio.const import (
|
||||
ATTR_DATA,
|
||||
ATTR_ENDPOINT,
|
||||
ATTR_METHOD,
|
||||
EVENT_SUPERVISOR_EVENT,
|
||||
WS_ID,
|
||||
WS_TYPE,
|
||||
WS_TYPE_API,
|
||||
WS_TYPE_EVENT,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import async_capture_events
|
||||
from . import mock_all # noqa
|
||||
|
||||
MOCK_ENVIRON = {"HASSIO": "127.0.0.1", "HASSIO_TOKEN": "abcdefgh"}
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_all(aioclient_mock):
|
||||
"""Mock all setup requests."""
|
||||
aioclient_mock.post("http://127.0.0.1/homeassistant/options", json={"result": "ok"})
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={"result": "ok"})
|
||||
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {"supervisor": "222", "homeassistant": "0.110.0", "hassos": None},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/host/info",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"chassis": "vm",
|
||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||
"kernel": "4.19.0-6-amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/os/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/info",
|
||||
json={"result": "ok", "data": {"version_latest": "1.0.0"}},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
||||
)
|
||||
|
||||
|
||||
async def test_setup_api_ping(hass, aioclient_mock):
|
||||
"""Test setup with API ping."""
|
||||
with patch.dict(os.environ, MOCK_ENVIRON):
|
||||
|
@ -359,58 +302,3 @@ async def test_service_calls_core(hassio_env, hass, aioclient_mock):
|
|||
assert mock_check_config.called
|
||||
|
||||
assert aioclient_mock.call_count == 5
|
||||
|
||||
|
||||
async def test_websocket_supervisor_event(
|
||||
hassio_env, hass: HomeAssistant, hass_ws_client
|
||||
):
|
||||
"""Test Supervisor websocket event."""
|
||||
assert await async_setup_component(hass, "hassio", {})
|
||||
websocket_client = await hass_ws_client(hass)
|
||||
|
||||
test_event = async_capture_events(hass, EVENT_SUPERVISOR_EVENT)
|
||||
|
||||
await websocket_client.send_json(
|
||||
{WS_ID: 1, WS_TYPE: WS_TYPE_EVENT, ATTR_DATA: {"event": "test"}}
|
||||
)
|
||||
|
||||
assert await websocket_client.receive_json()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert test_event[0].data == {"event": "test"}
|
||||
|
||||
|
||||
async def test_websocket_supervisor_api(
|
||||
hassio_env, hass: HomeAssistant, hass_ws_client, aioclient_mock
|
||||
):
|
||||
"""Test Supervisor websocket api."""
|
||||
assert await async_setup_component(hass, "hassio", {})
|
||||
websocket_client = await hass_ws_client(hass)
|
||||
aioclient_mock.post(
|
||||
"http://127.0.0.1/snapshots/new/partial",
|
||||
json={"result": "ok", "data": {"slug": "sn_slug"}},
|
||||
)
|
||||
|
||||
await websocket_client.send_json(
|
||||
{
|
||||
WS_ID: 1,
|
||||
WS_TYPE: WS_TYPE_API,
|
||||
ATTR_ENDPOINT: "/snapshots/new/partial",
|
||||
ATTR_METHOD: "post",
|
||||
}
|
||||
)
|
||||
|
||||
msg = await websocket_client.receive_json()
|
||||
assert msg["result"]["slug"] == "sn_slug"
|
||||
|
||||
await websocket_client.send_json(
|
||||
{
|
||||
WS_ID: 2,
|
||||
WS_TYPE: WS_TYPE_API,
|
||||
ATTR_ENDPOINT: "/supervisor/info",
|
||||
ATTR_METHOD: "get",
|
||||
}
|
||||
)
|
||||
|
||||
msg = await websocket_client.receive_json()
|
||||
assert msg["result"]["version_latest"] == "1.0.0"
|
||||
|
|
90
tests/components/hassio/test_websocket_api.py
Normal file
90
tests/components/hassio/test_websocket_api.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
"""Test websocket API."""
|
||||
from homeassistant.components.hassio.const import (
|
||||
ATTR_DATA,
|
||||
ATTR_ENDPOINT,
|
||||
ATTR_METHOD,
|
||||
ATTR_WS_EVENT,
|
||||
EVENT_SUPERVISOR_EVENT,
|
||||
WS_ID,
|
||||
WS_TYPE,
|
||||
WS_TYPE_API,
|
||||
WS_TYPE_SUBSCRIBE,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import mock_all # noqa
|
||||
|
||||
from tests.common import async_mock_signal
|
||||
|
||||
|
||||
async def test_ws_subscription(hassio_env, hass: HomeAssistant, hass_ws_client):
|
||||
"""Test websocket subscription."""
|
||||
assert await async_setup_component(hass, "hassio", {})
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json({WS_ID: 5, WS_TYPE: WS_TYPE_SUBSCRIBE})
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
|
||||
calls = async_mock_signal(hass, EVENT_SUPERVISOR_EVENT)
|
||||
async_dispatcher_send(hass, EVENT_SUPERVISOR_EVENT, {"lorem": "ipsum"})
|
||||
|
||||
response = await client.receive_json()
|
||||
assert response["event"]["lorem"] == "ipsum"
|
||||
assert len(calls) == 1
|
||||
|
||||
await client.send_json(
|
||||
{
|
||||
WS_ID: 6,
|
||||
WS_TYPE: "supervisor/event",
|
||||
ATTR_DATA: {ATTR_WS_EVENT: "test", "lorem": "ipsum"},
|
||||
}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
assert len(calls) == 2
|
||||
|
||||
response = await client.receive_json()
|
||||
assert response["event"]["lorem"] == "ipsum"
|
||||
|
||||
# Unsubscribe
|
||||
await client.send_json({WS_ID: 7, WS_TYPE: "unsubscribe_events", "subscription": 5})
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
|
||||
|
||||
async def test_websocket_supervisor_api(
|
||||
hassio_env, hass: HomeAssistant, hass_ws_client, aioclient_mock
|
||||
):
|
||||
"""Test Supervisor websocket api."""
|
||||
assert await async_setup_component(hass, "hassio", {})
|
||||
websocket_client = await hass_ws_client(hass)
|
||||
aioclient_mock.post(
|
||||
"http://127.0.0.1/snapshots/new/partial",
|
||||
json={"result": "ok", "data": {"slug": "sn_slug"}},
|
||||
)
|
||||
|
||||
await websocket_client.send_json(
|
||||
{
|
||||
WS_ID: 1,
|
||||
WS_TYPE: WS_TYPE_API,
|
||||
ATTR_ENDPOINT: "/snapshots/new/partial",
|
||||
ATTR_METHOD: "post",
|
||||
}
|
||||
)
|
||||
|
||||
msg = await websocket_client.receive_json()
|
||||
assert msg["result"]["slug"] == "sn_slug"
|
||||
|
||||
await websocket_client.send_json(
|
||||
{
|
||||
WS_ID: 2,
|
||||
WS_TYPE: WS_TYPE_API,
|
||||
ATTR_ENDPOINT: "/supervisor/info",
|
||||
ATTR_METHOD: "get",
|
||||
}
|
||||
)
|
||||
|
||||
msg = await websocket_client.receive_json()
|
||||
assert msg["result"]["version_latest"] == "1.0.0"
|
Loading…
Add table
Reference in a new issue