2018-02-20 23:24:31 +00:00
|
|
|
"""The tests for the hassio component."""
|
2021-03-01 08:41:04 +00:00
|
|
|
from datetime import timedelta
|
2018-02-20 23:24:31 +00:00
|
|
|
import os
|
2021-01-01 21:31:56 +00:00
|
|
|
from unittest.mock import patch
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2021-03-01 08:41:04 +00:00
|
|
|
import pytest
|
|
|
|
|
2018-11-25 17:04:48 +00:00
|
|
|
from homeassistant.auth.const import GROUP_ID_ADMIN
|
2019-03-25 17:04:35 +00:00
|
|
|
from homeassistant.components import frontend
|
2021-03-01 08:41:04 +00:00
|
|
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
|
|
|
from homeassistant.components.hassio import ADDONS_COORDINATOR, DOMAIN, STORAGE_KEY
|
2022-04-04 15:34:06 +00:00
|
|
|
from homeassistant.components.hassio.handler import HassioAPIError
|
2021-03-01 08:41:04 +00:00
|
|
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
|
|
|
from homeassistant.helpers.device_registry import async_get
|
2019-12-08 15:33:22 +00:00
|
|
|
from homeassistant.setup import async_setup_component
|
2021-03-01 08:41:04 +00:00
|
|
|
from homeassistant.util import dt as dt_util
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2021-03-01 08:41:04 +00:00
|
|
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
2021-02-15 17:18:45 +00:00
|
|
|
|
2022-02-23 11:32:07 +00:00
|
|
|
MOCK_ENVIRON = {"HASSIO": "127.0.0.1", "HASSIO_TOKEN": "abcdefgh"}
|
2018-05-29 06:51:08 +00:00
|
|
|
|
|
|
|
|
2021-03-01 08:41:04 +00:00
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
def mock_all(aioclient_mock, request):
|
|
|
|
"""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",
|
2022-04-07 11:34:20 +00:00
|
|
|
"data": {
|
|
|
|
"supervisor": "222",
|
|
|
|
"homeassistant": "0.110.0",
|
|
|
|
"hassos": "1.2.3",
|
|
|
|
},
|
2021-03-01 08:41:04 +00:00
|
|
|
},
|
|
|
|
)
|
2021-05-31 12:06:11 +00:00
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/store",
|
|
|
|
json={
|
|
|
|
"result": "ok",
|
|
|
|
"data": {"addons": [], "repositories": []},
|
|
|
|
},
|
|
|
|
)
|
2021-03-01 08:41:04 +00:00
|
|
|
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",
|
2022-03-22 11:21:12 +00:00
|
|
|
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
2021-03-01 08:41:04 +00:00
|
|
|
)
|
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/os/info",
|
2021-12-01 20:41:31 +00:00
|
|
|
json={"result": "ok", "data": {"version_latest": "1.0.0", "version": "1.0.0"}},
|
2021-03-01 08:41:04 +00:00
|
|
|
)
|
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/supervisor/info",
|
|
|
|
json={
|
|
|
|
"result": "ok",
|
2022-03-22 11:21:12 +00:00
|
|
|
"data": {"version_latest": "1.0.0", "version": "1.0.0"},
|
2021-03-01 08:41:04 +00:00
|
|
|
"addons": [
|
|
|
|
{
|
|
|
|
"name": "test",
|
|
|
|
"slug": "test",
|
|
|
|
"installed": True,
|
|
|
|
"update_available": False,
|
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
2021-05-31 12:06:11 +00:00
|
|
|
"repository": "core",
|
2021-03-01 08:41:04 +00:00
|
|
|
"url": "https://github.com/home-assistant/addons/test",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "test2",
|
|
|
|
"slug": "test2",
|
|
|
|
"installed": True,
|
|
|
|
"update_available": False,
|
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
2021-05-31 12:06:11 +00:00
|
|
|
"repository": "core",
|
2021-03-01 08:41:04 +00:00
|
|
|
"url": "https://github.com",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
)
|
2021-10-22 10:23:21 +00:00
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/addons/test/stats",
|
|
|
|
json={
|
|
|
|
"result": "ok",
|
|
|
|
"data": {
|
|
|
|
"cpu_percent": 0.99,
|
|
|
|
"memory_usage": 182611968,
|
|
|
|
"memory_limit": 3977146368,
|
|
|
|
"memory_percent": 4.59,
|
|
|
|
"network_rx": 362570232,
|
|
|
|
"network_tx": 82374138,
|
|
|
|
"blk_read": 46010945536,
|
|
|
|
"blk_write": 15051526144,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/addons/test2/stats",
|
|
|
|
json={
|
|
|
|
"result": "ok",
|
|
|
|
"data": {
|
|
|
|
"cpu_percent": 0.8,
|
|
|
|
"memory_usage": 51941376,
|
|
|
|
"memory_limit": 3977146368,
|
|
|
|
"memory_percent": 1.31,
|
|
|
|
"network_rx": 31338284,
|
|
|
|
"network_tx": 15692900,
|
|
|
|
"blk_read": 740077568,
|
|
|
|
"blk_write": 6004736,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/addons/test3/stats",
|
|
|
|
json={
|
|
|
|
"result": "ok",
|
|
|
|
"data": {
|
|
|
|
"cpu_percent": 0.8,
|
|
|
|
"memory_usage": 51941376,
|
|
|
|
"memory_limit": 3977146368,
|
|
|
|
"memory_percent": 1.31,
|
|
|
|
"network_rx": 31338284,
|
|
|
|
"network_tx": 15692900,
|
|
|
|
"blk_read": 740077568,
|
|
|
|
"blk_write": 6004736,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
2022-03-22 11:21:12 +00:00
|
|
|
aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="")
|
2022-04-01 15:31:39 +00:00
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/addons/test/info",
|
|
|
|
json={"result": "ok", "data": {"auto_update": True}},
|
|
|
|
)
|
2022-03-22 11:21:12 +00:00
|
|
|
aioclient_mock.get("http://127.0.0.1/addons/test2/changelog", text="")
|
2022-04-01 15:31:39 +00:00
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/addons/test2/info",
|
|
|
|
json={"result": "ok", "data": {"auto_update": False}},
|
|
|
|
)
|
2021-03-01 08:41:04 +00:00
|
|
|
aioclient_mock.get(
|
|
|
|
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
|
|
|
|
)
|
2022-04-04 15:34:06 +00:00
|
|
|
aioclient_mock.post("http://127.0.0.1/refresh_updates", json={"result": "ok"})
|
2021-03-01 08:41:04 +00:00
|
|
|
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_setup_api_ping(hass, aioclient_mock):
|
2018-07-23 12:14:57 +00:00
|
|
|
"""Test setup with API ping."""
|
2018-05-29 06:51:08 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2020-01-01 23:13:43 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {})
|
2018-02-21 21:42:55 +00:00
|
|
|
assert result
|
|
|
|
|
2022-04-04 15:34:06 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2020-08-12 06:00:38 +00:00
|
|
|
assert hass.components.hassio.get_core_info()["version_latest"] == "1.0.0"
|
2022-02-23 11:32:07 +00:00
|
|
|
assert hass.components.hassio.is_hassio()
|
2018-02-21 21:42:55 +00:00
|
|
|
|
|
|
|
|
2019-03-25 17:04:35 +00:00
|
|
|
async def test_setup_api_panel(hass, aioclient_mock):
|
|
|
|
"""Test setup with API ping."""
|
2019-07-31 19:25:30 +00:00
|
|
|
assert await async_setup_component(hass, "frontend", {})
|
2019-03-25 17:04:35 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2019-07-31 19:25:30 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {})
|
2019-03-25 17:04:35 +00:00
|
|
|
assert result
|
|
|
|
|
|
|
|
panels = hass.data[frontend.DATA_PANELS]
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
assert panels.get("hassio").to_response() == {
|
|
|
|
"component_name": "custom",
|
2021-12-03 09:35:57 +00:00
|
|
|
"icon": None,
|
|
|
|
"title": None,
|
2019-07-31 19:25:30 +00:00
|
|
|
"url_path": "hassio",
|
|
|
|
"require_admin": True,
|
|
|
|
"config": {
|
|
|
|
"_panel_custom": {
|
|
|
|
"embed_iframe": True,
|
|
|
|
"js_url": "/api/hassio/app/entrypoint.js",
|
|
|
|
"name": "hassio-main",
|
|
|
|
"trust_external": False,
|
|
|
|
}
|
|
|
|
},
|
2019-03-25 17:04:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_setup_api_push_api_data(hass, aioclient_mock):
|
2018-02-21 21:42:55 +00:00
|
|
|
"""Test setup with API push."""
|
2018-05-29 06:51:08 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2020-01-01 23:13:43 +00:00
|
|
|
result = await async_setup_component(
|
2019-07-31 19:25:30 +00:00
|
|
|
hass, "hassio", {"http": {"server_port": 9999}, "hassio": {}}
|
|
|
|
)
|
2018-02-21 21:42:55 +00:00
|
|
|
assert result
|
|
|
|
|
2022-04-04 15:34:06 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2019-07-31 19:25:30 +00:00
|
|
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
|
|
|
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
|
|
|
assert aioclient_mock.mock_calls[1][2]["watchdog"]
|
2018-02-21 21:42:55 +00:00
|
|
|
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_setup_api_push_api_data_server_host(hass, aioclient_mock):
|
2018-02-21 21:42:55 +00:00
|
|
|
"""Test setup with API push with active server host."""
|
2018-05-29 06:51:08 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2020-01-01 23:13:43 +00:00
|
|
|
result = await async_setup_component(
|
2019-07-31 19:25:30 +00:00
|
|
|
hass,
|
|
|
|
"hassio",
|
|
|
|
{"http": {"server_port": 9999, "server_host": "127.0.0.1"}, "hassio": {}},
|
|
|
|
)
|
2018-02-21 21:42:55 +00:00
|
|
|
assert result
|
|
|
|
|
2022-04-04 15:34:06 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2019-07-31 19:25:30 +00:00
|
|
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
|
|
|
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
|
|
|
assert not aioclient_mock.mock_calls[1][2]["watchdog"]
|
2018-02-21 21:42:55 +00:00
|
|
|
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
async def test_setup_api_push_api_data_default(hass, aioclient_mock, hass_storage):
|
2018-02-21 21:42:55 +00:00
|
|
|
"""Test setup with API push default data."""
|
2018-12-02 15:32:53 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2019-07-31 19:25:30 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {"http": {}, "hassio": {}})
|
2018-07-23 12:14:57 +00:00
|
|
|
assert result
|
2018-02-21 21:42:55 +00:00
|
|
|
|
2022-04-04 15:34:06 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2019-07-31 19:25:30 +00:00
|
|
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
|
|
|
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
|
|
|
refresh_token = aioclient_mock.mock_calls[1][2]["refresh_token"]
|
2018-07-23 12:14:57 +00:00
|
|
|
hassio_user = await hass.auth.async_get_user(
|
2019-07-31 19:25:30 +00:00
|
|
|
hass_storage[STORAGE_KEY]["data"]["hassio_user"]
|
2018-07-23 12:14:57 +00:00
|
|
|
)
|
|
|
|
assert hassio_user is not None
|
|
|
|
assert hassio_user.system_generated
|
2018-11-25 17:04:48 +00:00
|
|
|
assert len(hassio_user.groups) == 1
|
|
|
|
assert hassio_user.groups[0].id == GROUP_ID_ADMIN
|
2021-06-14 16:01:18 +00:00
|
|
|
assert hassio_user.name == "Supervisor"
|
2018-08-14 19:14:12 +00:00
|
|
|
for token in hassio_user.refresh_tokens.values():
|
|
|
|
if token.token == refresh_token:
|
|
|
|
break
|
|
|
|
else:
|
2019-07-31 19:25:30 +00:00
|
|
|
assert False, "refresh token not found"
|
2018-07-23 12:14:57 +00:00
|
|
|
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
async def test_setup_adds_admin_group_to_user(hass, aioclient_mock, hass_storage):
|
2018-11-25 17:04:48 +00:00
|
|
|
"""Test setup with API push default data."""
|
|
|
|
# Create user without admin
|
2019-07-31 19:25:30 +00:00
|
|
|
user = await hass.auth.async_create_system_user("Hass.io")
|
2018-11-25 17:04:48 +00:00
|
|
|
assert not user.is_admin
|
|
|
|
await hass.auth.async_create_refresh_token(user)
|
|
|
|
|
|
|
|
hass_storage[STORAGE_KEY] = {
|
2019-07-31 19:25:30 +00:00
|
|
|
"data": {"hassio_user": user.id},
|
|
|
|
"key": STORAGE_KEY,
|
|
|
|
"version": 1,
|
2018-11-25 17:04:48 +00:00
|
|
|
}
|
|
|
|
|
2018-05-29 06:51:08 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2019-07-31 19:25:30 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {"http": {}, "hassio": {}})
|
2018-07-23 12:14:57 +00:00
|
|
|
assert result
|
|
|
|
|
2018-12-02 15:32:53 +00:00
|
|
|
assert user.is_admin
|
2018-07-23 12:14:57 +00:00
|
|
|
|
|
|
|
|
2021-06-14 16:01:18 +00:00
|
|
|
async def test_setup_migrate_user_name(hass, aioclient_mock, hass_storage):
|
|
|
|
"""Test setup with migrating the user name."""
|
|
|
|
# Create user with old name
|
|
|
|
user = await hass.auth.async_create_system_user("Hass.io")
|
|
|
|
await hass.auth.async_create_refresh_token(user)
|
|
|
|
|
|
|
|
hass_storage[STORAGE_KEY] = {
|
|
|
|
"data": {"hassio_user": user.id},
|
|
|
|
"key": STORAGE_KEY,
|
|
|
|
"version": 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
|
|
|
result = await async_setup_component(hass, "hassio", {"http": {}, "hassio": {}})
|
|
|
|
assert result
|
|
|
|
|
|
|
|
assert user.name == "Supervisor"
|
|
|
|
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
async def test_setup_api_existing_hassio_user(hass, aioclient_mock, hass_storage):
|
2018-07-23 12:14:57 +00:00
|
|
|
"""Test setup with API push default data."""
|
2019-07-31 19:25:30 +00:00
|
|
|
user = await hass.auth.async_create_system_user("Hass.io test")
|
2018-07-23 12:14:57 +00:00
|
|
|
token = await hass.auth.async_create_refresh_token(user)
|
2019-07-31 19:25:30 +00:00
|
|
|
hass_storage[STORAGE_KEY] = {"version": 1, "data": {"hassio_user": user.id}}
|
2018-12-02 15:32:53 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2019-07-31 19:25:30 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {"http": {}, "hassio": {}})
|
2018-02-21 21:42:55 +00:00
|
|
|
assert result
|
|
|
|
|
2022-04-04 15:34:06 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2019-07-31 19:25:30 +00:00
|
|
|
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
|
|
|
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
|
|
|
assert aioclient_mock.mock_calls[1][2]["refresh_token"] == token.token
|
2018-02-21 21:42:55 +00:00
|
|
|
|
|
|
|
|
2019-06-10 23:05:43 +00:00
|
|
|
async def test_setup_core_push_timezone(hass, aioclient_mock):
|
2018-02-21 21:42:55 +00:00
|
|
|
"""Test setup with API push default data."""
|
2019-07-31 19:25:30 +00:00
|
|
|
hass.config.time_zone = "testzone"
|
2019-06-10 23:05:43 +00:00
|
|
|
|
2018-05-29 06:51:08 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
2019-07-31 19:25:30 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {"hassio": {}})
|
2018-02-21 21:42:55 +00:00
|
|
|
assert result
|
|
|
|
|
2022-04-04 15:34:06 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2019-07-31 19:25:30 +00:00
|
|
|
assert aioclient_mock.mock_calls[2][2]["timezone"] == "testzone"
|
2018-02-21 21:42:55 +00:00
|
|
|
|
2020-10-29 21:34:06 +00:00
|
|
|
with patch("homeassistant.util.dt.set_default_time_zone"):
|
|
|
|
await hass.config.async_update(time_zone="America/New_York")
|
2019-06-10 23:05:43 +00:00
|
|
|
await hass.async_block_till_done()
|
2019-07-31 19:25:30 +00:00
|
|
|
assert aioclient_mock.mock_calls[-1][2]["timezone"] == "America/New_York"
|
2019-06-10 23:05:43 +00:00
|
|
|
|
2018-02-21 21:42:55 +00:00
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_setup_hassio_no_additional_data(hass, aioclient_mock):
|
2018-02-21 21:42:55 +00:00
|
|
|
"""Test setup with API push default data."""
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON), patch.dict(
|
|
|
|
os.environ, {"HASSIO_TOKEN": "123456"}
|
|
|
|
):
|
2020-01-01 23:13:43 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {"hassio": {}})
|
2018-02-21 21:42:55 +00:00
|
|
|
assert result
|
|
|
|
|
2022-04-04 15:34:06 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2019-07-31 19:25:30 +00:00
|
|
|
assert aioclient_mock.mock_calls[-1][3]["X-Hassio-Key"] == "123456"
|
2018-02-21 21:42:55 +00:00
|
|
|
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_fail_setup_without_environ_var(hass):
|
2018-02-20 23:24:31 +00:00
|
|
|
"""Fail setup if no environ variable set."""
|
|
|
|
with patch.dict(os.environ, {}, clear=True):
|
2020-01-01 23:13:43 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {})
|
2018-02-20 23:24:31 +00:00
|
|
|
assert not result
|
|
|
|
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_warn_when_cannot_connect(hass, caplog):
|
2019-03-26 22:24:28 +00:00
|
|
|
"""Fail warn when we cannot connect."""
|
2019-07-31 19:25:30 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON), patch(
|
2020-08-27 11:56:20 +00:00
|
|
|
"homeassistant.components.hassio.HassIO.is_connected",
|
|
|
|
return_value=None,
|
2019-07-31 19:25:30 +00:00
|
|
|
):
|
2020-01-01 23:13:43 +00:00
|
|
|
result = await async_setup_component(hass, "hassio", {})
|
2019-03-26 14:38:25 +00:00
|
|
|
assert result
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-02-23 11:32:07 +00:00
|
|
|
assert hass.components.hassio.is_hassio()
|
2021-09-29 07:46:05 +00:00
|
|
|
assert "Not connected with the supervisor / system too busy!" in caplog.text
|
2018-02-20 23:24:31 +00:00
|
|
|
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_service_register(hassio_env, hass):
|
2018-02-20 23:24:31 +00:00
|
|
|
"""Check if service will be setup."""
|
2020-01-01 23:13:43 +00:00
|
|
|
assert await async_setup_component(hass, "hassio", {})
|
2019-07-31 19:25:30 +00:00
|
|
|
assert hass.services.has_service("hassio", "addon_start")
|
|
|
|
assert hass.services.has_service("hassio", "addon_stop")
|
|
|
|
assert hass.services.has_service("hassio", "addon_restart")
|
2021-03-01 08:41:04 +00:00
|
|
|
assert hass.services.has_service("hassio", "addon_update")
|
2019-07-31 19:25:30 +00:00
|
|
|
assert hass.services.has_service("hassio", "addon_stdin")
|
|
|
|
assert hass.services.has_service("hassio", "host_shutdown")
|
|
|
|
assert hass.services.has_service("hassio", "host_reboot")
|
|
|
|
assert hass.services.has_service("hassio", "host_reboot")
|
2021-08-02 09:07:21 +00:00
|
|
|
assert hass.services.has_service("hassio", "backup_full")
|
|
|
|
assert hass.services.has_service("hassio", "backup_partial")
|
2019-07-31 19:25:30 +00:00
|
|
|
assert hass.services.has_service("hassio", "restore_full")
|
|
|
|
assert hass.services.has_service("hassio", "restore_partial")
|
2018-02-20 23:24:31 +00:00
|
|
|
|
|
|
|
|
2021-08-02 09:07:21 +00:00
|
|
|
async def test_service_calls(hassio_env, hass, aioclient_mock, caplog):
|
2018-02-20 23:24:31 +00:00
|
|
|
"""Call service and check the API calls behind that."""
|
2020-01-01 23:13:43 +00:00
|
|
|
assert await async_setup_component(hass, "hassio", {})
|
2019-07-31 19:25:30 +00:00
|
|
|
|
|
|
|
aioclient_mock.post("http://127.0.0.1/addons/test/start", json={"result": "ok"})
|
|
|
|
aioclient_mock.post("http://127.0.0.1/addons/test/stop", json={"result": "ok"})
|
|
|
|
aioclient_mock.post("http://127.0.0.1/addons/test/restart", json={"result": "ok"})
|
2021-03-01 08:41:04 +00:00
|
|
|
aioclient_mock.post("http://127.0.0.1/addons/test/update", json={"result": "ok"})
|
2019-07-31 19:25:30 +00:00
|
|
|
aioclient_mock.post("http://127.0.0.1/addons/test/stdin", json={"result": "ok"})
|
|
|
|
aioclient_mock.post("http://127.0.0.1/host/shutdown", json={"result": "ok"})
|
|
|
|
aioclient_mock.post("http://127.0.0.1/host/reboot", json={"result": "ok"})
|
2021-08-02 09:07:21 +00:00
|
|
|
aioclient_mock.post("http://127.0.0.1/backups/new/full", json={"result": "ok"})
|
|
|
|
aioclient_mock.post("http://127.0.0.1/backups/new/partial", json={"result": "ok"})
|
2018-02-20 23:24:31 +00:00
|
|
|
aioclient_mock.post(
|
2021-08-02 09:07:21 +00:00
|
|
|
"http://127.0.0.1/backups/test/restore/full", json={"result": "ok"}
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2018-02-20 23:24:31 +00:00
|
|
|
aioclient_mock.post(
|
2021-08-02 09:07:21 +00:00
|
|
|
"http://127.0.0.1/backups/test/restore/partial", json={"result": "ok"}
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.services.async_call("hassio", "addon_start", {"addon": "test"})
|
|
|
|
await hass.services.async_call("hassio", "addon_stop", {"addon": "test"})
|
|
|
|
await hass.services.async_call("hassio", "addon_restart", {"addon": "test"})
|
2021-03-01 08:41:04 +00:00
|
|
|
await hass.services.async_call("hassio", "addon_update", {"addon": "test"})
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.services.async_call(
|
2019-07-31 19:25:30 +00:00
|
|
|
"hassio", "addon_stdin", {"addon": "test", "input": "test"}
|
|
|
|
)
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-04-07 11:34:20 +00:00
|
|
|
assert aioclient_mock.call_count == 9
|
2019-07-31 19:25:30 +00:00
|
|
|
assert aioclient_mock.mock_calls[-1][2] == "test"
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.services.async_call("hassio", "host_shutdown", {})
|
|
|
|
await hass.services.async_call("hassio", "host_reboot", {})
|
|
|
|
await hass.async_block_till_done()
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-04-07 11:34:20 +00:00
|
|
|
assert aioclient_mock.call_count == 11
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2021-08-02 09:07:21 +00:00
|
|
|
await hass.services.async_call("hassio", "backup_full", {})
|
|
|
|
await hass.services.async_call(
|
|
|
|
"hassio",
|
|
|
|
"backup_partial",
|
2022-02-23 16:38:52 +00:00
|
|
|
{
|
|
|
|
"homeassistant": True,
|
|
|
|
"addons": ["test"],
|
|
|
|
"folders": ["ssl"],
|
|
|
|
"password": "123456",
|
|
|
|
},
|
2021-08-02 09:07:21 +00:00
|
|
|
)
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-04-07 11:34:20 +00:00
|
|
|
assert aioclient_mock.call_count == 13
|
2021-10-14 08:00:44 +00:00
|
|
|
assert aioclient_mock.mock_calls[-1][2] == {
|
2022-02-23 16:38:52 +00:00
|
|
|
"homeassistant": True,
|
2019-07-31 19:25:30 +00:00
|
|
|
"addons": ["test"],
|
|
|
|
"folders": ["ssl"],
|
|
|
|
"password": "123456",
|
|
|
|
}
|
|
|
|
|
2021-08-02 09:07:21 +00:00
|
|
|
await hass.services.async_call("hassio", "restore_full", {"slug": "test"})
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.services.async_call(
|
2019-07-31 19:25:30 +00:00
|
|
|
"hassio",
|
|
|
|
"restore_partial",
|
|
|
|
{
|
2021-08-02 09:07:21 +00:00
|
|
|
"slug": "test",
|
2019-07-31 19:25:30 +00:00
|
|
|
"homeassistant": False,
|
|
|
|
"addons": ["test"],
|
|
|
|
"folders": ["ssl"],
|
|
|
|
"password": "123456",
|
|
|
|
},
|
|
|
|
)
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.async_block_till_done()
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-04-07 11:34:20 +00:00
|
|
|
assert aioclient_mock.call_count == 15
|
2018-02-20 23:24:31 +00:00
|
|
|
assert aioclient_mock.mock_calls[-1][2] == {
|
2019-07-31 19:25:30 +00:00
|
|
|
"addons": ["test"],
|
|
|
|
"folders": ["ssl"],
|
|
|
|
"homeassistant": False,
|
|
|
|
"password": "123456",
|
2018-02-20 23:24:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
async def test_service_calls_core(hassio_env, hass, aioclient_mock):
|
2018-02-20 23:24:31 +00:00
|
|
|
"""Call core service and check the API calls behind that."""
|
2020-01-01 23:13:43 +00:00
|
|
|
assert await async_setup_component(hass, "hassio", {})
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
aioclient_mock.post("http://127.0.0.1/homeassistant/restart", json={"result": "ok"})
|
|
|
|
aioclient_mock.post("http://127.0.0.1/homeassistant/stop", json={"result": "ok"})
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.services.async_call("homeassistant", "stop")
|
|
|
|
await hass.async_block_till_done()
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-04-07 11:34:20 +00:00
|
|
|
assert aioclient_mock.call_count == 5
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.services.async_call("homeassistant", "check_config")
|
|
|
|
await hass.async_block_till_done()
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-04-07 11:34:20 +00:00
|
|
|
assert aioclient_mock.call_count == 5
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2019-03-18 23:58:48 +00:00
|
|
|
with patch(
|
2020-04-25 21:32:55 +00:00
|
|
|
"homeassistant.config.async_check_ha_config_file", return_value=None
|
2019-03-18 23:58:48 +00:00
|
|
|
) as mock_check_config:
|
2020-01-01 23:13:43 +00:00
|
|
|
await hass.services.async_call("homeassistant", "restart")
|
|
|
|
await hass.async_block_till_done()
|
2019-03-18 23:58:48 +00:00
|
|
|
assert mock_check_config.called
|
2018-02-20 23:24:31 +00:00
|
|
|
|
2022-04-07 11:34:20 +00:00
|
|
|
assert aioclient_mock.call_count == 6
|
2021-03-01 08:41:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_entry_load_and_unload(hass):
|
|
|
|
"""Test loading and unloading config entry."""
|
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON):
|
|
|
|
config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN)
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
assert SENSOR_DOMAIN in hass.config.components
|
|
|
|
assert BINARY_SENSOR_DOMAIN in hass.config.components
|
|
|
|
assert ADDONS_COORDINATOR in hass.data
|
|
|
|
|
2021-03-01 17:10:51 +00:00
|
|
|
assert await hass.config_entries.async_unload(config_entry.entry_id)
|
2021-03-01 08:41:04 +00:00
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert ADDONS_COORDINATOR not in hass.data
|
|
|
|
|
|
|
|
|
|
|
|
async def test_migration_off_hassio(hass):
|
|
|
|
"""Test that when a user moves instance off Hass.io, config entry gets cleaned up."""
|
|
|
|
config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN)
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert not await hass.config_entries.async_setup(config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert hass.config_entries.async_entries(DOMAIN) == []
|
|
|
|
|
|
|
|
|
|
|
|
async def test_device_registry_calls(hass):
|
|
|
|
"""Test device registry entries for hassio."""
|
|
|
|
dev_reg = async_get(hass)
|
|
|
|
supervisor_mock_data = {
|
2022-03-22 11:21:12 +00:00
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
2021-03-01 08:41:04 +00:00
|
|
|
"addons": [
|
|
|
|
{
|
|
|
|
"name": "test",
|
2021-10-26 17:58:17 +00:00
|
|
|
"state": "started",
|
2021-03-01 08:41:04 +00:00
|
|
|
"slug": "test",
|
|
|
|
"installed": True,
|
2022-03-22 11:21:12 +00:00
|
|
|
"icon": False,
|
2021-03-01 08:41:04 +00:00
|
|
|
"update_available": False,
|
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
|
|
|
"repository": "test",
|
|
|
|
"url": "https://github.com/home-assistant/addons/test",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "test2",
|
2021-10-26 17:58:17 +00:00
|
|
|
"state": "started",
|
2021-03-01 08:41:04 +00:00
|
|
|
"slug": "test2",
|
|
|
|
"installed": True,
|
2022-03-22 11:21:12 +00:00
|
|
|
"icon": False,
|
2021-03-01 08:41:04 +00:00
|
|
|
"update_available": False,
|
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
|
|
|
"url": "https://github.com",
|
|
|
|
},
|
2022-03-22 11:21:12 +00:00
|
|
|
],
|
2021-03-01 08:41:04 +00:00
|
|
|
}
|
|
|
|
os_mock_data = {
|
|
|
|
"board": "odroid-n2",
|
|
|
|
"boot": "A",
|
|
|
|
"update_available": False,
|
|
|
|
"version": "5.12",
|
|
|
|
"version_latest": "5.12",
|
|
|
|
}
|
|
|
|
|
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON), patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
|
|
|
return_value=supervisor_mock_data,
|
|
|
|
), patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.get_os_info",
|
|
|
|
return_value=os_mock_data,
|
|
|
|
):
|
|
|
|
config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN)
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
2022-03-22 11:21:12 +00:00
|
|
|
assert len(dev_reg.devices) == 5
|
2021-03-01 08:41:04 +00:00
|
|
|
|
|
|
|
supervisor_mock_data = {
|
2022-03-22 11:21:12 +00:00
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
2021-03-01 08:41:04 +00:00
|
|
|
"addons": [
|
|
|
|
{
|
|
|
|
"name": "test2",
|
2021-10-26 17:58:17 +00:00
|
|
|
"state": "started",
|
2021-03-01 08:41:04 +00:00
|
|
|
"slug": "test2",
|
|
|
|
"installed": True,
|
2022-03-22 11:21:12 +00:00
|
|
|
"icon": False,
|
2021-03-01 08:41:04 +00:00
|
|
|
"update_available": False,
|
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
|
|
|
"url": "https://github.com",
|
|
|
|
},
|
2022-03-22 11:21:12 +00:00
|
|
|
],
|
2021-03-01 08:41:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Test that when addon is removed, next update will remove the add-on and subsequent updates won't
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
|
|
|
return_value=supervisor_mock_data,
|
|
|
|
), patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.get_os_info",
|
|
|
|
return_value=os_mock_data,
|
|
|
|
):
|
|
|
|
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=1))
|
|
|
|
await hass.async_block_till_done()
|
2022-03-22 11:21:12 +00:00
|
|
|
assert len(dev_reg.devices) == 4
|
2021-03-01 08:41:04 +00:00
|
|
|
|
|
|
|
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=2))
|
|
|
|
await hass.async_block_till_done()
|
2022-03-22 11:21:12 +00:00
|
|
|
assert len(dev_reg.devices) == 4
|
2021-03-01 08:41:04 +00:00
|
|
|
|
|
|
|
supervisor_mock_data = {
|
2022-03-22 11:21:12 +00:00
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
2021-03-01 08:41:04 +00:00
|
|
|
"addons": [
|
|
|
|
{
|
|
|
|
"name": "test2",
|
|
|
|
"slug": "test2",
|
2021-10-26 17:58:17 +00:00
|
|
|
"state": "started",
|
2021-03-01 08:41:04 +00:00
|
|
|
"installed": True,
|
2022-03-22 11:21:12 +00:00
|
|
|
"icon": False,
|
2021-03-01 08:41:04 +00:00
|
|
|
"update_available": False,
|
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
|
|
|
"url": "https://github.com",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "test3",
|
|
|
|
"slug": "test3",
|
2021-10-26 17:58:17 +00:00
|
|
|
"state": "stopped",
|
2021-03-01 08:41:04 +00:00
|
|
|
"installed": True,
|
2022-03-22 11:21:12 +00:00
|
|
|
"icon": False,
|
2021-03-01 08:41:04 +00:00
|
|
|
"update_available": False,
|
|
|
|
"version": "1.0.0",
|
|
|
|
"version_latest": "1.0.0",
|
|
|
|
"url": "https://github.com",
|
|
|
|
},
|
2022-03-22 11:21:12 +00:00
|
|
|
],
|
2021-03-01 08:41:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Test that when addon is added, next update will reload the entry so we register
|
|
|
|
# a new device
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.get_supervisor_info",
|
|
|
|
return_value=supervisor_mock_data,
|
|
|
|
), patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.get_os_info",
|
|
|
|
return_value=os_mock_data,
|
2022-04-07 11:34:20 +00:00
|
|
|
), patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.get_info",
|
|
|
|
return_value={
|
|
|
|
"supervisor": "222",
|
|
|
|
"homeassistant": "0.110.0",
|
|
|
|
"hassos": None,
|
|
|
|
},
|
2021-03-01 08:41:04 +00:00
|
|
|
):
|
|
|
|
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=3))
|
|
|
|
await hass.async_block_till_done()
|
2022-04-07 11:34:20 +00:00
|
|
|
assert len(dev_reg.devices) == 4
|
2022-04-04 15:34:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def test_coordinator_updates(hass, caplog):
|
2022-04-15 16:31:02 +00:00
|
|
|
"""Test coordinator updates."""
|
|
|
|
await async_setup_component(hass, "homeassistant", {})
|
2022-04-04 15:34:06 +00:00
|
|
|
with patch.dict(os.environ, MOCK_ENVIRON), patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.refresh_updates"
|
|
|
|
) as refresh_updates_mock:
|
|
|
|
config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN)
|
|
|
|
config_entry.add_to_hass(hass)
|
|
|
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
assert refresh_updates_mock.call_count == 1
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.refresh_updates",
|
|
|
|
) as refresh_updates_mock:
|
2022-04-15 16:31:02 +00:00
|
|
|
async_fire_time_changed(hass, dt_util.now() + timedelta(minutes=20))
|
2022-04-04 15:34:06 +00:00
|
|
|
await hass.async_block_till_done()
|
2022-04-15 16:31:02 +00:00
|
|
|
assert refresh_updates_mock.call_count == 0
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.refresh_updates",
|
|
|
|
) as refresh_updates_mock:
|
|
|
|
await hass.services.async_call(
|
|
|
|
"homeassistant",
|
|
|
|
"update_entity",
|
|
|
|
{
|
|
|
|
"entity_id": [
|
|
|
|
"update.home_assistant_core_update",
|
|
|
|
"update.home_assistant_supervisor_update",
|
|
|
|
]
|
|
|
|
},
|
|
|
|
blocking=True,
|
|
|
|
)
|
2022-04-04 15:34:06 +00:00
|
|
|
assert refresh_updates_mock.call_count == 1
|
2022-04-15 16:31:02 +00:00
|
|
|
|
|
|
|
# There is a 10s cooldown on the debouncer
|
|
|
|
async_fire_time_changed(hass, dt_util.now() + timedelta(seconds=10))
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
"homeassistant.components.hassio.HassIO.refresh_updates",
|
|
|
|
side_effect=HassioAPIError("Unknown"),
|
|
|
|
) as refresh_updates_mock:
|
|
|
|
await hass.services.async_call(
|
|
|
|
"homeassistant",
|
|
|
|
"update_entity",
|
|
|
|
{
|
|
|
|
"entity_id": [
|
|
|
|
"update.home_assistant_core_update",
|
|
|
|
"update.home_assistant_supervisor_update",
|
|
|
|
]
|
|
|
|
},
|
|
|
|
blocking=True,
|
2022-04-04 15:34:06 +00:00
|
|
|
)
|
2022-04-15 16:31:02 +00:00
|
|
|
assert refresh_updates_mock.call_count == 1
|
|
|
|
assert "Error on Supervisor API: Unknown" in caplog.text
|