From 23278550beca21ebe2a0e47634d094c17ab97286 Mon Sep 17 00:00:00 2001 From: pvizeli Date: Fri, 7 Apr 2017 08:57:40 +0200 Subject: [PATCH 1/6] Updates for Release 0.5 --- hassio/__main__.py | 3 ++- hassio/api/__init__.py | 1 + hassio/api/host.py | 30 ++++++++++++++++-------------- hassio/api/supervisor.py | 5 +++++ hassio/api/util.py | 9 ++------- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/hassio/__main__.py b/hassio/__main__.py index 788ab64e2..01d82b714 100644 --- a/hassio/__main__.py +++ b/hassio/__main__.py @@ -23,7 +23,7 @@ if __name__ == "__main__": loop.run_until_complete(hassio.setup()) _LOGGER.info("Start Hassio task") - loop.create_task(hassio.start()) + loop.call_soon_threadsafe(asyncio.ensure_future, hassio.start(), loop) try: loop.add_signal_handler( @@ -32,4 +32,5 @@ if __name__ == "__main__": _LOGGER.warning("Could not bind to SIGTERM") loop.run_forever() + loop.close() _LOGGER.info("Close Hassio") diff --git a/hassio/api/__init__.py b/hassio/api/__init__.py index cde4ae8ef..1bd0d577a 100644 --- a/hassio/api/__init__.py +++ b/hassio/api/__init__.py @@ -44,6 +44,7 @@ class RestAPI(object): """Register supervisor function.""" api_supervisor = APISupervisor(self.config, self.loop, host_controll) + self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping) self.webapp.router.add_get('/supervisor/info', api_supervisor.info) self.webapp.router.add_get('/supervisor/update', api_supervisor.update) self.webapp.router.add_get( diff --git a/hassio/api/host.py b/hassio/api/host.py index 5fc0c0fa4..8dc3a2217 100644 --- a/hassio/api/host.py +++ b/hassio/api/host.py @@ -1,11 +1,13 @@ """Init file for HassIO host rest api.""" import logging -from .util import api_process_hostcontroll, json_loads +from .util import api_process_hostcontroll, api_process, json_loads from ..const import ATTR_VERSION _LOGGER = logging.getLogger(__name__) +UNKNOWN = 'unknown' + class APIHost(object): """Handle rest api for host functions.""" @@ -16,10 +18,20 @@ class APIHost(object): self.loop = loop self.host_controll = host_controll - @api_process_hostcontroll - def info(self, request): + @api_process + async def info(self, request): """Return host information.""" - return self.host_controll.info() + if not self.host_controll.active: + info = { + 'os': UNKNOWN, + 'version': UNKNOWN, + 'current': UNKNOWN, + 'level': 0, + 'hostname': UNKNOWN, + } + return info + + return await self.host_controll.info() @api_process_hostcontroll def reboot(self, request): @@ -31,16 +43,6 @@ class APIHost(object): """Poweroff host.""" return self.host_controll.shutdown() - @api_process_hostcontroll - def network_info(self, request): - """Edit network settings.""" - pass - - @api_process_hostcontroll - def network_update(self, request): - """Edit network settings.""" - pass - @api_process_hostcontroll async def update(self, request): """Update host OS.""" diff --git a/hassio/api/supervisor.py b/hassio/api/supervisor.py index 62925b1fe..7c57d12ed 100644 --- a/hassio/api/supervisor.py +++ b/hassio/api/supervisor.py @@ -16,6 +16,11 @@ class APISupervisor(object): self.loop = loop self.host_controll = host_controll + @api_process + async def ping(self, request): + """Return ok for signal that the api is ready.""" + return True + @api_process async def info(self, request): """Return host information.""" diff --git a/hassio/api/util.py b/hassio/api/util.py index c1225400b..f78da86e9 100644 --- a/hassio/api/util.py +++ b/hassio/api/util.py @@ -52,7 +52,7 @@ def api_process_hostcontroll(method): if isinstance(answer, dict): return api_return_ok(data=answer) elif answer is None: - return api_not_supported() + return api_return_error("Function is not supported") elif answer: return api_return_ok() return api_return_error() @@ -68,14 +68,9 @@ def api_return_error(message=None): }) -def api_return_ok(data=None): +def api_return_ok(data={}): """Return a API ok answer.""" return web.json_response({ JSON_RESULT: RESULT_OK, JSON_DATA: data, }) - - -def api_not_supported(): - """Return a api error with not supported.""" - return api_return_error("Function is not supported") From 61e133df6b82cc71aaec290715465888b1ea26a2 Mon Sep 17 00:00:00 2001 From: pvizeli Date: Fri, 7 Apr 2017 08:58:47 +0200 Subject: [PATCH 2/6] Pump version --- hassio/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hassio/const.py b/hassio/const.py index a531b3c68..e641ea88a 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -1,5 +1,5 @@ """Const file for HassIO.""" -HASSIO_VERSION = '0.4' +HASSIO_VERSION = '0.5' URL_HASSIO_VERSION = \ 'https://raw.githubusercontent.com/pvizeli/hassio/master/version.json' From 878eb4025862eb42d29f24666c1f4fb81d674f01 Mon Sep 17 00:00:00 2001 From: pvizeli Date: Fri, 7 Apr 2017 09:11:05 +0200 Subject: [PATCH 3/6] Fix lint --- hassio/api/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hassio/api/util.py b/hassio/api/util.py index f78da86e9..56dfb348a 100644 --- a/hassio/api/util.py +++ b/hassio/api/util.py @@ -68,7 +68,7 @@ def api_return_error(message=None): }) -def api_return_ok(data={}): +def api_return_ok(data=dict()): """Return a API ok answer.""" return web.json_response({ JSON_RESULT: RESULT_OK, From 1ad196424f775e001bc09fe3653a127fb686761e Mon Sep 17 00:00:00 2001 From: pvizeli Date: Fri, 7 Apr 2017 09:13:08 +0200 Subject: [PATCH 4/6] Fix lint v2 --- hassio/api/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hassio/api/util.py b/hassio/api/util.py index 56dfb348a..50bf94ef2 100644 --- a/hassio/api/util.py +++ b/hassio/api/util.py @@ -68,9 +68,9 @@ def api_return_error(message=None): }) -def api_return_ok(data=dict()): +def api_return_ok(data=None): """Return a API ok answer.""" return web.json_response({ JSON_RESULT: RESULT_OK, - JSON_DATA: data, + JSON_DATA: data or {}, }) From 9e95e8671edea1d98ed3964c79f0f699cbd77cfa Mon Sep 17 00:00:00 2001 From: pvizeli Date: Fri, 7 Apr 2017 11:07:23 +0200 Subject: [PATCH 5/6] Add options validation --- hassio/api/homeassistant.py | 10 ++++++++-- hassio/api/host.py | 10 ++++++++-- hassio/api/supervisor.py | 16 +++++++++++++--- hassio/api/util.py | 13 +++++++++++++ setup.py | 1 + 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/hassio/api/homeassistant.py b/hassio/api/homeassistant.py index f4ad3841f..cd55a2453 100644 --- a/hassio/api/homeassistant.py +++ b/hassio/api/homeassistant.py @@ -2,11 +2,17 @@ import asyncio import logging -from .util import api_process, json_loads +import voluptuous as vol + +from .util import api_process, api_validate from ..const import ATTR_VERSION, ATTR_CURRENT _LOGGER = logging.getLogger(__name__) +SCHEMA_VERSION = vol.Schema({ + vol.Optional(ATTR_VERSION): vol.Coerce(str), +}) + class APIHomeAssistant(object): """Handle rest api for homeassistant functions.""" @@ -30,7 +36,7 @@ class APIHomeAssistant(object): @api_process async def update(self, request): """Update host OS.""" - body = await request.json(loads=json_loads) + body = await api_validate(SCHEMA_VERSION, request) version = body.get(ATTR_VERSION, self.config.current_homeassistant) if self.dock_hass.in_progress: diff --git a/hassio/api/host.py b/hassio/api/host.py index 8dc3a2217..23f0fb453 100644 --- a/hassio/api/host.py +++ b/hassio/api/host.py @@ -1,13 +1,19 @@ """Init file for HassIO host rest api.""" import logging -from .util import api_process_hostcontroll, api_process, json_loads +import voluptuous as vol + +from .util import api_process_hostcontroll, api_process, api_validate from ..const import ATTR_VERSION _LOGGER = logging.getLogger(__name__) UNKNOWN = 'unknown' +SCHEMA_VERSION = vol.Schema({ + vol.Optional(ATTR_VERSION): vol.Coerce(str), +}) + class APIHost(object): """Handle rest api for host functions.""" @@ -46,7 +52,7 @@ class APIHost(object): @api_process_hostcontroll async def update(self, request): """Update host OS.""" - body = await request.json(loads=json_loads) + body = await api_validate(SCHEMA_VERSION, request) version = body.get(ATTR_VERSION) if version == self.host_controll.version: diff --git a/hassio/api/supervisor.py b/hassio/api/supervisor.py index 7c57d12ed..94de47920 100644 --- a/hassio/api/supervisor.py +++ b/hassio/api/supervisor.py @@ -1,11 +1,21 @@ """Init file for HassIO supervisor rest api.""" import logging -from .util import api_process, api_process_hostcontroll, json_loads +import voluptuous as vol + +from .util import api_process, api_process_hostcontroll, api_validate from ..const import ATTR_VERSION, ATTR_CURRENT, ATTR_BETA, HASSIO_VERSION _LOGGER = logging.getLogger(__name__) +SCHEMA_OPTIONS = vol.Schema({ + vol.Optional(ATTR_BETA): vol.Boolean(), +}) + +SCHEMA_VERSION = vol.Schema({ + vol.Optional(ATTR_VERSION): vol.Coerce(str), +}) + class APISupervisor(object): """Handle rest api for supervisor functions.""" @@ -35,7 +45,7 @@ class APISupervisor(object): @api_process async def options(self, request): """Set supervisor options.""" - body = await request.json(loads=json_loads) + body = await api_validate(SCHEMA_OPTIONS, request) if ATTR_BETA in body: self.config.upstream_beta = body[ATTR_BETA] @@ -45,7 +55,7 @@ class APISupervisor(object): @api_process_hostcontroll async def update(self, request): """Update host OS.""" - body = await request.json(loads=json_loads) + body = await api_validate(SCHEMA_VERSION, request) version = body.get(ATTR_VERSION, self.config.current_hassio) if version == HASSIO_VERSION: diff --git a/hassio/api/util.py b/hassio/api/util.py index 50bf94ef2..fd75d5ec2 100644 --- a/hassio/api/util.py +++ b/hassio/api/util.py @@ -4,6 +4,8 @@ import logging from aiohttp import web from aiohttp.web_exceptions import HTTPServiceUnavailable +import voluptuous as vol +from voluptuous.humanize import humanize_error from ..const import ( JSON_RESULT, JSON_DATA, JSON_MESSAGE, RESULT_OK, RESULT_ERROR) @@ -74,3 +76,14 @@ def api_return_ok(data=None): JSON_RESULT: RESULT_OK, JSON_DATA: data or {}, }) + + +async def api_validate(schema, request): + """Validate request data with schema.""" + data = await request.json(loads=json_loads) + try: + schema(data) + except vol.Invalid as ex: + raise RuntimeError(humanize_error(data, ex)) from None + + return data diff --git a/setup.py b/setup.py index 7927bbf33..31a39092c 100644 --- a/setup.py +++ b/setup.py @@ -36,5 +36,6 @@ setup( 'aiohttp', 'docker', 'colorlog', + 'voluptuous', ] ) From 8c191e8c985323f29ff6081b31cb4721f7841383 Mon Sep 17 00:00:00 2001 From: pvizeli Date: Fri, 7 Apr 2017 11:11:26 +0200 Subject: [PATCH 6/6] fix lint --- hassio/api/supervisor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hassio/api/supervisor.py b/hassio/api/supervisor.py index 94de47920..73ef6ae5b 100644 --- a/hassio/api/supervisor.py +++ b/hassio/api/supervisor.py @@ -9,6 +9,7 @@ from ..const import ATTR_VERSION, ATTR_CURRENT, ATTR_BETA, HASSIO_VERSION _LOGGER = logging.getLogger(__name__) SCHEMA_OPTIONS = vol.Schema({ + # pylint: disable=no-value-for-parameter vol.Optional(ATTR_BETA): vol.Boolean(), })