From b228695907efa589519a99a506d86f002c71ca89 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 21 Feb 2018 22:42:55 +0100 Subject: [PATCH] Hassio cleanup part2 (#12588) * Update handler.py * Update handler.py * Update __init__.py * Update handler.py * Update handler.py * Update __init__.py * Update tests --- homeassistant/components/hassio/__init__.py | 11 +- homeassistant/components/hassio/handler.py | 37 ++++ tests/components/hassio/__init__.py | 1 + tests/components/hassio/conftest.py | 12 +- tests/components/hassio/test_handler.py | 183 +++++++------------- tests/components/hassio/test_init.py | 145 ++++++++++++++++ 6 files changed, 260 insertions(+), 129 deletions(-) diff --git a/homeassistant/components/hassio/__init__.py b/homeassistant/components/hassio/__init__.py index 9b229bd7a85..540659273b3 100644 --- a/homeassistant/components/hassio/__init__.py +++ b/homeassistant/components/hassio/__init__.py @@ -126,8 +126,8 @@ def is_hassio(hass): @asyncio.coroutine def async_check_config(hass): """Check configuration over Hass.io API.""" - result = yield from hass.data[DOMAIN].send_command( - '/homeassistant/check', timeout=300) + hassio = hass.data[DOMAIN] + result = yield from hassio.check_homeassistant_config() if not result: return "Hass.io config check API error" @@ -197,8 +197,7 @@ def async_setup(hass, config): """Update last available Home Assistant version.""" data = yield from hassio.get_homeassistant_info() if data: - hass.data[DATA_HOMEASSISTANT_VERSION] = \ - data['data']['last_version'] + hass.data[DATA_HOMEASSISTANT_VERSION] = data['last_version'] hass.helpers.event.async_track_point_in_utc_time( update_homeassistant_version, utcnow() + HASSIO_UPDATE_INTERVAL) @@ -210,7 +209,7 @@ def async_setup(hass, config): def async_handle_core_service(call): """Service handler for handling core services.""" if call.service == SERVICE_HOMEASSISTANT_STOP: - yield from hassio.send_command('/homeassistant/stop') + yield from hassio.stop_homeassistant() return error = yield from async_check_config(hass) @@ -222,7 +221,7 @@ def async_setup(hass, config): return if call.service == SERVICE_HOMEASSISTANT_RESTART: - yield from hassio.send_command('/homeassistant/restart') + yield from hassio.restart_homeassistant() # Mock core services for service in (SERVICE_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_RESTART, diff --git a/homeassistant/components/hassio/handler.py b/homeassistant/components/hassio/handler.py index 125622f063c..a954aaccbd4 100644 --- a/homeassistant/components/hassio/handler.py +++ b/homeassistant/components/hassio/handler.py @@ -32,6 +32,19 @@ def _api_bool(funct): return _wrapper +def _api_data(funct): + """Return a api data.""" + @asyncio.coroutine + def _wrapper(*argv, **kwargs): + """Wrap function.""" + data = yield from funct(*argv, **kwargs) + if data and data['result'] == "ok": + return data['data'] + return None + + return _wrapper + + class HassIO(object): """Small API wrapper for Hass.io.""" @@ -49,6 +62,7 @@ class HassIO(object): """ return self.send_command("/supervisor/ping", method="get") + @_api_data def get_homeassistant_info(self): """Return data for Home Assistant. @@ -56,6 +70,29 @@ class HassIO(object): """ return self.send_command("/homeassistant/info", method="get") + @_api_bool + def restart_homeassistant(self): + """Restart Home-Assistant container. + + This method return a coroutine. + """ + return self.send_command("/homeassistant/restart") + + @_api_bool + def stop_homeassistant(self): + """Stop Home-Assistant container. + + This method return a coroutine. + """ + return self.send_command("/homeassistant/stop") + + def check_homeassistant_config(self): + """Check Home-Assistant config with Hass.io API. + + This method return a coroutine. + """ + return self.send_command("/homeassistant/check", timeout=300) + @_api_bool def update_hass_api(self, http_config): """Update Home Assistant API data on Hass.io. diff --git a/tests/components/hassio/__init__.py b/tests/components/hassio/__init__.py index 34fd4ad23e5..6fcd9d2229f 100644 --- a/tests/components/hassio/__init__.py +++ b/tests/components/hassio/__init__.py @@ -1,3 +1,4 @@ """Tests for Hassio component.""" API_PASSWORD = 'pass1234' +HASSIO_TOKEN = '123456' diff --git a/tests/components/hassio/conftest.py b/tests/components/hassio/conftest.py index 852ec1aaa15..56d6cbe666e 100644 --- a/tests/components/hassio/conftest.py +++ b/tests/components/hassio/conftest.py @@ -5,9 +5,10 @@ from unittest.mock import patch, Mock import pytest from homeassistant.setup import async_setup_component +from homeassistant.components.hassio.handler import HassIO from tests.common import mock_coro -from . import API_PASSWORD +from . import API_PASSWORD, HASSIO_TOKEN @pytest.fixture @@ -38,3 +39,12 @@ def hassio_client(hassio_env, hass, test_client): } })) yield hass.loop.run_until_complete(test_client(hass.http.app)) + + +@pytest.fixture +def hassio_handler(hass, aioclient_mock): + """Create mock hassio handler.""" + websession = hass.helpers.aiohttp_client.async_get_clientsession() + + with patch.dict(os.environ, {'HASSIO_TOKEN': HASSIO_TOKEN}): + yield HassIO(hass.loop, websession, "127.0.0.1") diff --git a/tests/components/hassio/test_handler.py b/tests/components/hassio/test_handler.py index 39cfa689c59..78745489a78 100644 --- a/tests/components/hassio/test_handler.py +++ b/tests/components/hassio/test_handler.py @@ -1,151 +1,90 @@ """The tests for the hassio component.""" import asyncio -import os -from unittest.mock import patch -from homeassistant.setup import async_setup_component +import aiohttp @asyncio.coroutine -def test_setup_api_ping(hass, aioclient_mock): +def test_api_ping(hassio_handler, aioclient_mock): """Test setup with API ping.""" aioclient_mock.get( "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) - aioclient_mock.get( - "http://127.0.0.1/homeassistant/info", json={ - 'result': 'ok', 'data': {'last_version': '10.0'}}) - with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): - result = yield from async_setup_component(hass, 'hassio', {}) - assert result - - assert aioclient_mock.call_count == 2 - assert hass.components.hassio.get_homeassistant_version() == "10.0" - assert hass.components.hassio.is_hassio() + assert (yield from hassio_handler.is_connected()) + assert aioclient_mock.call_count == 1 @asyncio.coroutine -def test_setup_api_push_api_data(hass, aioclient_mock): - """Test setup with API push.""" +def test_api_ping_error(hassio_handler, aioclient_mock): + """Test setup with API ping error.""" aioclient_mock.get( - "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) + "http://127.0.0.1/supervisor/ping", json={'result': 'error'}) + + assert not (yield from hassio_handler.is_connected()) + assert aioclient_mock.call_count == 1 + + +@asyncio.coroutine +def test_api_ping_exeption(hassio_handler, aioclient_mock): + """Test setup with API ping exception.""" + aioclient_mock.get( + "http://127.0.0.1/supervisor/ping", exc=aiohttp.ClientError()) + + assert not (yield from hassio_handler.is_connected()) + assert aioclient_mock.call_count == 1 + + +@asyncio.coroutine +def test_api_homeassistant_info(hassio_handler, aioclient_mock): + """Test setup with API homeassistant info.""" aioclient_mock.get( "http://127.0.0.1/homeassistant/info", json={ 'result': 'ok', 'data': {'last_version': '10.0'}}) + + data = yield from hassio_handler.get_homeassistant_info() + assert aioclient_mock.call_count == 1 + assert data['last_version'] == "10.0" + + +@asyncio.coroutine +def test_api_homeassistant_info_error(hassio_handler, aioclient_mock): + """Test setup with API homeassistant info error.""" + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={ + 'result': 'error', 'message': None}) + + data = yield from hassio_handler.get_homeassistant_info() + assert aioclient_mock.call_count == 1 + assert data is None + + +@asyncio.coroutine +def test_api_homeassistant_stop(hassio_handler, aioclient_mock): + """Test setup with API HomeAssistant stop.""" aioclient_mock.post( - "http://127.0.0.1/homeassistant/options", json={'result': 'ok'}) + "http://127.0.0.1/homeassistant/stop", json={'result': 'ok'}) - with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): - result = yield from async_setup_component(hass, 'hassio', { - 'http': { - 'api_password': "123456", - 'server_port': 9999 - }, - 'hassio': {} - }) - assert result - - assert aioclient_mock.call_count == 3 - assert not aioclient_mock.mock_calls[1][2]['ssl'] - assert aioclient_mock.mock_calls[1][2]['password'] == "123456" - assert aioclient_mock.mock_calls[1][2]['port'] == 9999 - assert aioclient_mock.mock_calls[1][2]['watchdog'] + assert (yield from hassio_handler.stop_homeassistant()) + assert aioclient_mock.call_count == 1 @asyncio.coroutine -def test_setup_api_push_api_data_server_host(hass, aioclient_mock): - """Test setup with API push with active server host.""" - aioclient_mock.get( - "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) - aioclient_mock.get( - "http://127.0.0.1/homeassistant/info", json={ - 'result': 'ok', 'data': {'last_version': '10.0'}}) +def test_api_homeassistant_restart(hassio_handler, aioclient_mock): + """Test setup with API HomeAssistant restart.""" aioclient_mock.post( - "http://127.0.0.1/homeassistant/options", json={'result': 'ok'}) + "http://127.0.0.1/homeassistant/restart", json={'result': 'ok'}) - with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): - result = yield from async_setup_component(hass, 'hassio', { - 'http': { - 'api_password': "123456", - 'server_port': 9999, - 'server_host': "127.0.0.1" - }, - 'hassio': {} - }) - assert result - - assert aioclient_mock.call_count == 3 - assert not aioclient_mock.mock_calls[1][2]['ssl'] - assert aioclient_mock.mock_calls[1][2]['password'] == "123456" - assert aioclient_mock.mock_calls[1][2]['port'] == 9999 - assert not aioclient_mock.mock_calls[1][2]['watchdog'] + assert (yield from hassio_handler.restart_homeassistant()) + assert aioclient_mock.call_count == 1 @asyncio.coroutine -def test_setup_api_push_api_data_default(hass, aioclient_mock): - """Test setup with API push default data.""" - aioclient_mock.get( - "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) - aioclient_mock.get( - "http://127.0.0.1/homeassistant/info", json={ - 'result': 'ok', 'data': {'last_version': '10.0'}}) +def test_api_homeassistant_config(hassio_handler, aioclient_mock): + """Test setup with API HomeAssistant restart.""" aioclient_mock.post( - "http://127.0.0.1/homeassistant/options", json={'result': 'ok'}) + "http://127.0.0.1/homeassistant/check", json={ + 'result': 'ok', 'data': {'test': 'bla'}}) - with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): - result = yield from async_setup_component(hass, 'hassio', { - 'http': {}, - 'hassio': {} - }) - assert result - - assert aioclient_mock.call_count == 3 - assert not aioclient_mock.mock_calls[1][2]['ssl'] - assert aioclient_mock.mock_calls[1][2]['password'] is None - assert aioclient_mock.mock_calls[1][2]['port'] == 8123 - - -@asyncio.coroutine -def test_setup_core_push_timezone(hass, aioclient_mock): - """Test setup with API push default data.""" - aioclient_mock.get( - "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) - aioclient_mock.get( - "http://127.0.0.1/homeassistant/info", json={ - 'result': 'ok', 'data': {'last_version': '10.0'}}) - aioclient_mock.post( - "http://127.0.0.1/supervisor/options", json={'result': 'ok'}) - - with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): - result = yield from async_setup_component(hass, 'hassio', { - 'hassio': {}, - 'homeassistant': { - 'time_zone': 'testzone', - }, - }) - assert result - - assert aioclient_mock.call_count == 3 - assert aioclient_mock.mock_calls[1][2]['timezone'] == "testzone" - - -@asyncio.coroutine -def test_setup_hassio_no_additional_data(hass, aioclient_mock): - """Test setup with API push default data.""" - aioclient_mock.get( - "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) - aioclient_mock.get( - "http://127.0.0.1/homeassistant/info", json={ - 'result': 'ok', 'data': {'last_version': '10.0'}}) - aioclient_mock.get( - "http://127.0.0.1/homeassistant/info", json={'result': 'ok'}) - - with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}), \ - patch.dict(os.environ, {'HASSIO_TOKEN': "123456"}): - result = yield from async_setup_component(hass, 'hassio', { - 'hassio': {}, - }) - assert result - - assert aioclient_mock.call_count == 2 - assert aioclient_mock.mock_calls[-1][3]['X-HASSIO-KEY'] == "123456" + data = yield from hassio_handler.check_homeassistant_config() + assert data['data']['test'] == 'bla' + assert aioclient_mock.call_count == 1 diff --git a/tests/components/hassio/test_init.py b/tests/components/hassio/test_init.py index 313623bc40d..e17419e7fd5 100644 --- a/tests/components/hassio/test_init.py +++ b/tests/components/hassio/test_init.py @@ -9,6 +9,151 @@ from homeassistant.components.hassio import async_check_config from tests.common import mock_coro +@asyncio.coroutine +def test_setup_api_ping(hass, aioclient_mock): + """Test setup with API ping.""" + aioclient_mock.get( + "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={ + 'result': 'ok', 'data': {'last_version': '10.0'}}) + + with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): + result = yield from async_setup_component(hass, 'hassio', {}) + assert result + + assert aioclient_mock.call_count == 2 + assert hass.components.hassio.get_homeassistant_version() == "10.0" + assert hass.components.hassio.is_hassio() + + +@asyncio.coroutine +def test_setup_api_push_api_data(hass, aioclient_mock): + """Test setup with API push.""" + aioclient_mock.get( + "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={ + 'result': 'ok', 'data': {'last_version': '10.0'}}) + aioclient_mock.post( + "http://127.0.0.1/homeassistant/options", json={'result': 'ok'}) + + with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): + result = yield from async_setup_component(hass, 'hassio', { + 'http': { + 'api_password': "123456", + 'server_port': 9999 + }, + 'hassio': {} + }) + assert result + + assert aioclient_mock.call_count == 3 + assert not aioclient_mock.mock_calls[1][2]['ssl'] + assert aioclient_mock.mock_calls[1][2]['password'] == "123456" + assert aioclient_mock.mock_calls[1][2]['port'] == 9999 + assert aioclient_mock.mock_calls[1][2]['watchdog'] + + +@asyncio.coroutine +def test_setup_api_push_api_data_server_host(hass, aioclient_mock): + """Test setup with API push with active server host.""" + aioclient_mock.get( + "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={ + 'result': 'ok', 'data': {'last_version': '10.0'}}) + aioclient_mock.post( + "http://127.0.0.1/homeassistant/options", json={'result': 'ok'}) + + with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): + result = yield from async_setup_component(hass, 'hassio', { + 'http': { + 'api_password': "123456", + 'server_port': 9999, + 'server_host': "127.0.0.1" + }, + 'hassio': {} + }) + assert result + + assert aioclient_mock.call_count == 3 + assert not aioclient_mock.mock_calls[1][2]['ssl'] + assert aioclient_mock.mock_calls[1][2]['password'] == "123456" + assert aioclient_mock.mock_calls[1][2]['port'] == 9999 + assert not aioclient_mock.mock_calls[1][2]['watchdog'] + + +@asyncio.coroutine +def test_setup_api_push_api_data_default(hass, aioclient_mock): + """Test setup with API push default data.""" + aioclient_mock.get( + "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={ + 'result': 'ok', 'data': {'last_version': '10.0'}}) + aioclient_mock.post( + "http://127.0.0.1/homeassistant/options", json={'result': 'ok'}) + + with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): + result = yield from async_setup_component(hass, 'hassio', { + 'http': {}, + 'hassio': {} + }) + assert result + + assert aioclient_mock.call_count == 3 + assert not aioclient_mock.mock_calls[1][2]['ssl'] + assert aioclient_mock.mock_calls[1][2]['password'] is None + assert aioclient_mock.mock_calls[1][2]['port'] == 8123 + + +@asyncio.coroutine +def test_setup_core_push_timezone(hass, aioclient_mock): + """Test setup with API push default data.""" + aioclient_mock.get( + "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={ + 'result': 'ok', 'data': {'last_version': '10.0'}}) + aioclient_mock.post( + "http://127.0.0.1/supervisor/options", json={'result': 'ok'}) + + with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}): + result = yield from async_setup_component(hass, 'hassio', { + 'hassio': {}, + 'homeassistant': { + 'time_zone': 'testzone', + }, + }) + assert result + + assert aioclient_mock.call_count == 3 + assert aioclient_mock.mock_calls[1][2]['timezone'] == "testzone" + + +@asyncio.coroutine +def test_setup_hassio_no_additional_data(hass, aioclient_mock): + """Test setup with API push default data.""" + aioclient_mock.get( + "http://127.0.0.1/supervisor/ping", json={'result': 'ok'}) + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={ + 'result': 'ok', 'data': {'last_version': '10.0'}}) + aioclient_mock.get( + "http://127.0.0.1/homeassistant/info", json={'result': 'ok'}) + + with patch.dict(os.environ, {'HASSIO': "127.0.0.1"}), \ + patch.dict(os.environ, {'HASSIO_TOKEN': "123456"}): + result = yield from async_setup_component(hass, 'hassio', { + 'hassio': {}, + }) + assert result + + assert aioclient_mock.call_count == 2 + assert aioclient_mock.mock_calls[-1][3]['X-HASSIO-KEY'] == "123456" + + @asyncio.coroutine def test_fail_setup_without_environ_var(hass): """Fail setup if no environ variable set."""