mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 09:47:52 +00:00
Initial import for HassIO (#6935)
* Initial import for HassIO * Cleanup api code for views * First unittest for view * Add test for edit view * Finish unittest * fix addons test * cleanup service.yaml * Address first round with ping command * handle timeout dynamic * fix lint
This commit is contained in:
parent
74ac160355
commit
3e66df50c8
272
homeassistant/components/hassio.py
Normal file
272
homeassistant/components/hassio.py
Normal file
@ -0,0 +1,272 @@
|
||||
"""
|
||||
Exposes regular rest commands as services.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/hassio/
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
import aiohttp
|
||||
from aiohttp import web
|
||||
from aiohttp.web_exceptions import HTTPBadGateway
|
||||
import async_timeout
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
from homeassistant.components.http import HomeAssistantView
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
DOMAIN = 'hassio'
|
||||
DEPENDENCIES = ['http']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
LONG_TASK_TIMEOUT = 900
|
||||
DEFAULT_TIMEOUT = 10
|
||||
|
||||
SERVICE_HOST_SHUTDOWN = 'host_shutdown'
|
||||
SERVICE_HOST_REBOOT = 'host_reboot'
|
||||
|
||||
SERVICE_HOST_UPDATE = 'host_update'
|
||||
SERVICE_SUPERVISOR_UPDATE = 'supervisor_update'
|
||||
SERVICE_HOMEASSISTANT_UPDATE = 'homeassistant_update'
|
||||
|
||||
SERVICE_ADDON_INSTALL = 'addon_install'
|
||||
SERVICE_ADDON_UNINSTALL = 'addon_uninstall'
|
||||
SERVICE_ADDON_UPDATE = 'addon_update'
|
||||
SERVICE_ADDON_START = 'addon_start'
|
||||
SERVICE_ADDON_STOP = 'addon_stop'
|
||||
|
||||
ATTR_ADDON = 'addon'
|
||||
ATTR_VERSION = 'version'
|
||||
|
||||
|
||||
SCHEMA_SERVICE_UPDATE = vol.Schema({
|
||||
vol.Optional(ATTR_VERSION): cv.string,
|
||||
})
|
||||
|
||||
SCHEMA_SERVICE_ADDONS = vol.Schema({
|
||||
vol.Required(ATTR_ADDON): cv.slug,
|
||||
})
|
||||
|
||||
SCHEMA_SERVICE_ADDONS_VERSION = SCHEMA_SERVICE_ADDONS.extend({
|
||||
vol.Optional(ATTR_VERSION): cv.string,
|
||||
})
|
||||
|
||||
|
||||
SERVICE_MAP = {
|
||||
SERVICE_HOST_SHUTDOWN: None,
|
||||
SERVICE_HOST_REBOOT: None,
|
||||
SERVICE_HOST_UPDATE: SCHEMA_SERVICE_UPDATE,
|
||||
SERVICE_SUPERVISOR_UPDATE: SCHEMA_SERVICE_UPDATE,
|
||||
SERVICE_HOMEASSISTANT_UPDATE: SCHEMA_SERVICE_UPDATE,
|
||||
SERVICE_ADDON_INSTALL: SCHEMA_SERVICE_ADDONS_VERSION,
|
||||
SERVICE_ADDON_UNINSTALL: SCHEMA_SERVICE_ADDONS,
|
||||
SERVICE_ADDON_START: SCHEMA_SERVICE_ADDONS,
|
||||
SERVICE_ADDON_STOP: SCHEMA_SERVICE_ADDONS,
|
||||
SERVICE_ADDON_UPDATE: SCHEMA_SERVICE_ADDONS_VERSION,
|
||||
}
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_setup(hass, config):
|
||||
"""Setup the hassio component."""
|
||||
try:
|
||||
host = os.environ['HASSIO']
|
||||
except KeyError:
|
||||
_LOGGER.error("No HassIO supervisor detect!")
|
||||
return False
|
||||
|
||||
websession = async_get_clientsession(hass)
|
||||
hassio = HassIO(hass.loop, websession, host)
|
||||
|
||||
api_ok = yield from hassio.is_connected()
|
||||
if not api_ok:
|
||||
_LOGGER.error("Not connected with HassIO!")
|
||||
return False
|
||||
|
||||
# register base api views
|
||||
for base in ('host', 'homeassistant'):
|
||||
hass.http.register_view(HassIOBaseView(hassio, base))
|
||||
for base in ('supervisor', 'network'):
|
||||
hass.http.register_view(HassIOBaseEditView(hassio, base))
|
||||
|
||||
# register view for addons
|
||||
hass.http.register_view(HassIOAddonsView(hassio))
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_service_handler(service):
|
||||
"""Handle HassIO service calls."""
|
||||
addon = service.data.get(ATTR_ADDON)
|
||||
if ATTR_VERSION in service.data:
|
||||
version = {ATTR_VERSION: service.data[ATTR_VERSION]}
|
||||
else:
|
||||
version = None
|
||||
|
||||
# map to api call
|
||||
if service.service == SERVICE_HOST_UPDATE:
|
||||
yield from hassio.send_command(
|
||||
"/host/update", payload=version)
|
||||
elif service.service == SERVICE_HOST_REBOOT:
|
||||
yield from hassio.send_command("/host/reboot")
|
||||
elif service.service == SERVICE_HOST_SHUTDOWN:
|
||||
yield from hassio.send_command("/host/shutdown")
|
||||
elif service.service == SERVICE_SUPERVISOR_UPDATE:
|
||||
yield from hassio.send_command(
|
||||
"/supervisor/update", payload=version)
|
||||
elif service.service == SERVICE_HOMEASSISTANT_UPDATE:
|
||||
yield from hassio.send_command(
|
||||
"/homeassistant/update", payload=version,
|
||||
timeout=LONG_TASK_TIMEOUT)
|
||||
elif service.service == SERVICE_ADDON_INSTALL:
|
||||
yield from hassio.send_command(
|
||||
"/addons/{}/install".format(addon), payload=version,
|
||||
timeout=LONG_TASK_TIMEOUT)
|
||||
elif service.service == SERVICE_ADDON_UNINSTALL:
|
||||
yield from hassio.send_command(
|
||||
"/addons/{}/uninstall".format(addon))
|
||||
elif service.service == SERVICE_ADDON_START:
|
||||
yield from hassio.send_command("/addons/{}/start".format(addon))
|
||||
elif service.service == SERVICE_ADDON_STOP:
|
||||
yield from hassio.send_command("/addons/{}/stop".format(addon))
|
||||
elif service.service == SERVICE_ADDON_UPDATE:
|
||||
yield from hassio.send_command(
|
||||
"/addons/{}/update".format(addon), payload=version,
|
||||
timeout=LONG_TASK_TIMEOUT)
|
||||
|
||||
descriptions = yield from hass.loop.run_in_executor(
|
||||
None, load_yaml_config_file, os.path.join(
|
||||
os.path.dirname(__file__), 'services.yaml'))
|
||||
|
||||
for service, schema in SERVICE_MAP.items():
|
||||
hass.services.async_register(
|
||||
DOMAIN, service, async_service_handler,
|
||||
descriptions[DOMAIN][service], schema=schema)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class HassIO(object):
|
||||
"""Small API wrapper for HassIO."""
|
||||
|
||||
def __init__(self, loop, websession, ip):
|
||||
"""Initialze HassIO api."""
|
||||
self.loop = loop
|
||||
self.websession = websession
|
||||
self._ip = ip
|
||||
|
||||
def is_connected(self):
|
||||
"""Return True if it connected to HassIO supervisor.
|
||||
|
||||
Return a coroutine.
|
||||
"""
|
||||
return self.send_command("/supervisor/ping")
|
||||
|
||||
@asyncio.coroutine
|
||||
def send_command(self, cmd, payload=None, timeout=DEFAULT_TIMEOUT):
|
||||
"""Send request to API."""
|
||||
answer = yield from self.send_raw(cmd, payload=payload)
|
||||
if answer['result'] == 'ok':
|
||||
return answer['data'] if answer['data'] else True
|
||||
|
||||
_LOGGER.error("%s return error %s.", cmd, answer['message'])
|
||||
return False
|
||||
|
||||
@asyncio.coroutine
|
||||
def send_raw(self, cmd, payload=None, timeout=DEFAULT_TIMEOUT):
|
||||
"""Send raw request to API."""
|
||||
try:
|
||||
with async_timeout.timeout(timeout, loop=self.loop):
|
||||
request = yield from self.websession.get(
|
||||
"http://{}{}".format(self._ip, cmd),
|
||||
timeout=None, json=payload
|
||||
)
|
||||
|
||||
if request.status != 200:
|
||||
_LOGGER.error("%s return code %d.", cmd, request.status)
|
||||
return
|
||||
|
||||
return (yield from request.json())
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.error("Timeout on api request %s.", cmd)
|
||||
|
||||
except aiohttp.ClientError:
|
||||
_LOGGER.error("Client error on api request %s.", cmd)
|
||||
|
||||
|
||||
class HassIOBaseView(HomeAssistantView):
|
||||
"""HassIO view to handle base part."""
|
||||
|
||||
requires_auth = True
|
||||
|
||||
def __init__(self, hassio, base):
|
||||
"""Initialize a hassio base view."""
|
||||
self.hassio = hassio
|
||||
self._url_info = "/{}/info".format(base)
|
||||
|
||||
self.url = "/api/hassio/{}".format(base)
|
||||
self.name = "api:hassio:{}".format(base)
|
||||
|
||||
@asyncio.coroutine
|
||||
def get(self, request):
|
||||
"""Get base data."""
|
||||
data = yield from self.hassio.send_command(self._url_info)
|
||||
if not data:
|
||||
raise HTTPBadGateway()
|
||||
return web.json_response(data)
|
||||
|
||||
|
||||
class HassIOBaseEditView(HassIOBaseView):
|
||||
"""HassIO view to handle base with options support."""
|
||||
|
||||
def __init__(self, hassio, base):
|
||||
"""Initialize a hassio base edit view."""
|
||||
super().__init__(hassio, base)
|
||||
self._url_options = "/{}/options".format(base)
|
||||
|
||||
@asyncio.coroutine
|
||||
def post(self, request):
|
||||
"""Set options on host."""
|
||||
data = yield from request.json()
|
||||
|
||||
response = yield from self.hassio.send_raw(
|
||||
self._url_options, payload=data)
|
||||
if not response:
|
||||
raise HTTPBadGateway()
|
||||
return web.json_response(response)
|
||||
|
||||
|
||||
class HassIOAddonsView(HomeAssistantView):
|
||||
"""HassIO view to handle addons part."""
|
||||
|
||||
requires_auth = True
|
||||
url = "/api/hassio/addons/{addon}"
|
||||
name = "api:hassio:addons"
|
||||
|
||||
def __init__(self, hassio):
|
||||
"""Initialize a hassio addon view."""
|
||||
self.hassio = hassio
|
||||
|
||||
@asyncio.coroutine
|
||||
def get(self, request, addon):
|
||||
"""Get addon data."""
|
||||
data = yield from self.hassio.send_command(
|
||||
"/addons/{}/info".format(addon))
|
||||
if not data:
|
||||
raise HTTPBadGateway()
|
||||
return web.json_response(data)
|
||||
|
||||
@asyncio.coroutine
|
||||
def post(self, request, addon):
|
||||
"""Set options on host."""
|
||||
data = yield from request.json()
|
||||
|
||||
response = yield from self.hassio.send_raw(
|
||||
"/addons/{}/options".format(addon), payload=data)
|
||||
if not response:
|
||||
raise HTTPBadGateway()
|
||||
return web.json_response(response)
|
@ -316,3 +316,72 @@ ffmpeg:
|
||||
logger:
|
||||
set_level:
|
||||
description: Set log level for components.
|
||||
|
||||
hassio:
|
||||
host_reboot:
|
||||
description: Reboot host computer.
|
||||
|
||||
host_shutdown:
|
||||
description: Poweroff host computer.
|
||||
|
||||
host_update:
|
||||
description: Update host computer.
|
||||
fields:
|
||||
version:
|
||||
description: Optional or it will be use the latest version.
|
||||
example: '0.3'
|
||||
|
||||
supervisor_update:
|
||||
description: Update HassIO supervisor.
|
||||
fields:
|
||||
version:
|
||||
description: Optional or it will be use the latest version.
|
||||
example: '0.3'
|
||||
|
||||
homeassistant_update:
|
||||
description: Update HomeAssistant docker image.
|
||||
fields:
|
||||
version:
|
||||
description: Optional or it will be use the latest version.
|
||||
example: '0.40.1'
|
||||
|
||||
addon_install:
|
||||
description: Install a HassIO docker addon.
|
||||
fields:
|
||||
addon:
|
||||
description: Name of addon.
|
||||
example: 'smb_config'
|
||||
version:
|
||||
description: Optional or it will be use the latest version.
|
||||
example: '0.2'
|
||||
|
||||
addon_uninstall:
|
||||
description: Uninstall a HassIO docker addon.
|
||||
fields:
|
||||
addon:
|
||||
description: Name of addon.
|
||||
example: 'smb_config'
|
||||
|
||||
addon_update:
|
||||
description: Update a HassIO docker addon.
|
||||
fields:
|
||||
addon:
|
||||
description: Name of addon.
|
||||
example: 'smb_config'
|
||||
version:
|
||||
description: Optional or it will be use the latest version.
|
||||
example: '0.2'
|
||||
|
||||
addon_start:
|
||||
description: Start a HassIO docker addon.
|
||||
fields:
|
||||
addon:
|
||||
description: Name of addon.
|
||||
example: 'smb_config'
|
||||
|
||||
addon_stop:
|
||||
description: Stop a HassIO docker addon.
|
||||
fields:
|
||||
addon:
|
||||
description: Name of addon.
|
||||
example: 'smb_config'
|
||||
|
543
tests/components/test_hassio.py
Normal file
543
tests/components/test_hassio.py
Normal file
@ -0,0 +1,543 @@
|
||||
"""The tests for the hassio component."""
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
import aiohttp
|
||||
|
||||
import homeassistant.components.hassio as ho
|
||||
from homeassistant.setup import setup_component, async_setup_component
|
||||
|
||||
from tests.common import (
|
||||
get_test_home_assistant, assert_setup_component)
|
||||
|
||||
|
||||
class TestHassIOSetup(object):
|
||||
"""Test the hassio component."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
self.config = {
|
||||
ho.DOMAIN: {},
|
||||
}
|
||||
|
||||
os.environ['HASSIO'] = "127.0.0.1"
|
||||
|
||||
def teardown_method(self):
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_setup_component(self, aioclient_mock):
|
||||
"""Test setup component."""
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={
|
||||
'result': 'ok', 'data': {}
|
||||
})
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
def test_setup_component_test_service(self, aioclient_mock):
|
||||
"""Test setup component and check if service exits."""
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={
|
||||
'result': 'ok', 'data': {}
|
||||
})
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_HOST_REBOOT)
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_HOST_SHUTDOWN)
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_HOST_UPDATE)
|
||||
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_SUPERVISOR_UPDATE)
|
||||
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_INSTALL)
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_UNINSTALL)
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_UPDATE)
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_START)
|
||||
assert self.hass.services.has_service(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_STOP)
|
||||
|
||||
|
||||
class TestHassIOComponent(object):
|
||||
"""Test the HassIO component."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.config = {
|
||||
ho.DOMAIN: {},
|
||||
}
|
||||
|
||||
os.environ['HASSIO'] = "127.0.0.1"
|
||||
self.url = "http://127.0.0.1/{}"
|
||||
|
||||
self.error_msg = {
|
||||
'result': 'error',
|
||||
'message': 'Test error',
|
||||
}
|
||||
self.ok_msg = {
|
||||
'result': 'ok',
|
||||
'data': {},
|
||||
}
|
||||
|
||||
def teardown_method(self):
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_rest_command_timeout(self, aioclient_mock):
|
||||
"""Call a hassio with timeout."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("host/update"), exc=asyncio.TimeoutError())
|
||||
|
||||
self.hass.services.call(ho.DOMAIN, ho.SERVICE_HOST_UPDATE, {})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_aiohttp_error(self, aioclient_mock):
|
||||
"""Call a hassio with aiohttp exception."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("host/update"), exc=aiohttp.ClientError())
|
||||
|
||||
self.hass.services.call(ho.DOMAIN, ho.SERVICE_HOST_UPDATE, {})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_http_error(self, aioclient_mock):
|
||||
"""Call a hassio with status code 503."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("host/update"), status=503)
|
||||
|
||||
self.hass.services.call(ho.DOMAIN, ho.SERVICE_HOST_UPDATE, {})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_http_error_api(self, aioclient_mock):
|
||||
"""Call a hassio with status code 503."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("host/update"), json=self.error_msg)
|
||||
|
||||
self.hass.services.call(ho.DOMAIN, ho.SERVICE_HOST_UPDATE, {})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_http_host_reboot(self, aioclient_mock):
|
||||
"""Call a hassio for host reboot."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("host/reboot"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(ho.DOMAIN, ho.SERVICE_HOST_REBOOT, {})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_http_host_shutdown(self, aioclient_mock):
|
||||
"""Call a hassio for host shutdown."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("host/shutdown"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(ho.DOMAIN, ho.SERVICE_HOST_SHUTDOWN, {})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_http_host_update(self, aioclient_mock):
|
||||
"""Call a hassio for host update."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("host/update"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_HOST_UPDATE, {'version': '0.4'})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert aioclient_mock.mock_calls[-1][2]['version'] == '0.4'
|
||||
|
||||
def test_rest_command_http_supervisor_update(self, aioclient_mock):
|
||||
"""Call a hassio for supervisor update."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("supervisor/update"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_SUPERVISOR_UPDATE, {'version': '0.4'})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert aioclient_mock.mock_calls[-1][2]['version'] == '0.4'
|
||||
|
||||
def test_rest_command_http_homeassistant_update(self, aioclient_mock):
|
||||
"""Call a hassio for homeassistant update."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("homeassistant/update"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_HOMEASSISTANT_UPDATE, {'version': '0.4'})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert aioclient_mock.mock_calls[-1][2]['version'] == '0.4'
|
||||
|
||||
def test_rest_command_http_addon_install(self, aioclient_mock):
|
||||
"""Call a hassio for addon install."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("addons/smb_config/install"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_INSTALL, {
|
||||
'addon': 'smb_config',
|
||||
'version': '0.4'
|
||||
})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert aioclient_mock.mock_calls[-1][2]['version'] == '0.4'
|
||||
|
||||
def test_rest_command_http_addon_uninstall(self, aioclient_mock):
|
||||
"""Call a hassio for addon uninstall."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("addons/smb_config/uninstall"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_UNINSTALL, {
|
||||
'addon': 'smb_config'
|
||||
})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_http_addon_update(self, aioclient_mock):
|
||||
"""Call a hassio for addon update."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("addons/smb_config/update"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_UPDATE, {
|
||||
'addon': 'smb_config',
|
||||
'version': '0.4'
|
||||
})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert aioclient_mock.mock_calls[-1][2]['version'] == '0.4'
|
||||
|
||||
def test_rest_command_http_addon_start(self, aioclient_mock):
|
||||
"""Call a hassio for addon start."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("addons/smb_config/start"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_START, {
|
||||
'addon': 'smb_config',
|
||||
})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
def test_rest_command_http_addon_stop(self, aioclient_mock):
|
||||
"""Call a hassio for addon stop."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/ping", json=self.ok_msg)
|
||||
with assert_setup_component(0, ho.DOMAIN):
|
||||
setup_component(self.hass, ho.DOMAIN, self.config)
|
||||
|
||||
aioclient_mock.get(
|
||||
self.url.format("addons/smb_config/stop"), json=self.ok_msg)
|
||||
|
||||
self.hass.services.call(
|
||||
ho.DOMAIN, ho.SERVICE_ADDON_STOP, {
|
||||
'addon': 'smb_config'
|
||||
})
|
||||
self.hass.block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_async_hassio_host_view(aioclient_mock, hass, test_client):
|
||||
"""Test that it fetches the given url."""
|
||||
os.environ['HASSIO'] = "127.0.0.1"
|
||||
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={
|
||||
'result': 'ok', 'data': {}
|
||||
})
|
||||
result = yield from async_setup_component(hass, ho.DOMAIN, {ho.DOMAIN: {}})
|
||||
assert result, 'Failed to setup hasio'
|
||||
|
||||
client = yield from test_client(hass.http.app)
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/host/info', json={
|
||||
'result': 'ok',
|
||||
'data': {
|
||||
'os': 'resinos',
|
||||
'version': '0.3',
|
||||
'current': '0.4',
|
||||
'level': 16,
|
||||
'hostname': 'test',
|
||||
}
|
||||
})
|
||||
|
||||
resp = yield from client.get('/api/hassio/host')
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert resp.status == 200
|
||||
assert data['os'] == 'resinos'
|
||||
assert data['version'] == '0.3'
|
||||
assert data['current'] == '0.4'
|
||||
assert data['level'] == 16
|
||||
assert data['hostname'] == 'test'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_async_hassio_homeassistant_view(aioclient_mock, hass, test_client):
|
||||
"""Test that it fetches the given url."""
|
||||
os.environ['HASSIO'] = "127.0.0.1"
|
||||
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={
|
||||
'result': 'ok', 'data': {}
|
||||
})
|
||||
result = yield from async_setup_component(hass, ho.DOMAIN, {ho.DOMAIN: {}})
|
||||
assert result, 'Failed to setup hasio'
|
||||
|
||||
client = yield from test_client(hass.http.app)
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/homeassistant/info', json={
|
||||
'result': 'ok',
|
||||
'data': {
|
||||
'version': '0.41',
|
||||
'current': '0.41.1',
|
||||
}
|
||||
})
|
||||
|
||||
resp = yield from client.get('/api/hassio/homeassistant')
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert resp.status == 200
|
||||
assert data['version'] == '0.41'
|
||||
assert data['current'] == '0.41.1'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_async_hassio_supervisor_view(aioclient_mock, hass, test_client):
|
||||
"""Test that it fetches the given url."""
|
||||
os.environ['HASSIO'] = "127.0.0.1"
|
||||
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={
|
||||
'result': 'ok', 'data': {}
|
||||
})
|
||||
result = yield from async_setup_component(hass, ho.DOMAIN, {ho.DOMAIN: {}})
|
||||
assert result, 'Failed to setup hasio'
|
||||
|
||||
client = yield from test_client(hass.http.app)
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/supervisor/info', json={
|
||||
'result': 'ok',
|
||||
'data': {
|
||||
'version': '0.3',
|
||||
'current': '0.4',
|
||||
'beta': False,
|
||||
}
|
||||
})
|
||||
|
||||
resp = yield from client.get('/api/hassio/supervisor')
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert resp.status == 200
|
||||
assert data['version'] == '0.3'
|
||||
assert data['current'] == '0.4'
|
||||
assert not data['beta']
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/supervisor/options', json={
|
||||
'result': 'ok',
|
||||
'data': {},
|
||||
})
|
||||
|
||||
resp = yield from client.post('/api/hassio/supervisor', json={
|
||||
'beta': True,
|
||||
})
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 3
|
||||
assert resp.status == 200
|
||||
assert aioclient_mock.mock_calls[-1][2]['beta']
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_async_hassio_network_view(aioclient_mock, hass, test_client):
|
||||
"""Test that it fetches the given url."""
|
||||
os.environ['HASSIO'] = "127.0.0.1"
|
||||
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={
|
||||
'result': 'ok', 'data': {}
|
||||
})
|
||||
result = yield from async_setup_component(hass, ho.DOMAIN, {ho.DOMAIN: {}})
|
||||
assert result, 'Failed to setup hasio'
|
||||
|
||||
client = yield from test_client(hass.http.app)
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/network/info', json={
|
||||
'result': 'ok',
|
||||
'data': {
|
||||
'mode': 'dhcp',
|
||||
'ssid': 'my_wlan',
|
||||
'password': '123456',
|
||||
}
|
||||
})
|
||||
|
||||
resp = yield from client.get('/api/hassio/network')
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert resp.status == 200
|
||||
assert data['mode'] == 'dhcp'
|
||||
assert data['ssid'] == 'my_wlan'
|
||||
assert data['password'] == '123456'
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/network/options', json={
|
||||
'result': 'ok',
|
||||
'data': {},
|
||||
})
|
||||
|
||||
resp = yield from client.post('/api/hassio/network', json={
|
||||
'mode': 'dhcp',
|
||||
'ssid': 'my_wlan2',
|
||||
'password': '654321',
|
||||
})
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 3
|
||||
assert resp.status == 200
|
||||
assert aioclient_mock.mock_calls[-1][2]['ssid'] == 'my_wlan2'
|
||||
assert aioclient_mock.mock_calls[-1][2]['password'] == '654321'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_async_hassio_addon_view(aioclient_mock, hass, test_client):
|
||||
"""Test that it fetches the given url."""
|
||||
os.environ['HASSIO'] = "127.0.0.1"
|
||||
|
||||
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={
|
||||
'result': 'ok', 'data': {}
|
||||
})
|
||||
result = yield from async_setup_component(hass, ho.DOMAIN, {ho.DOMAIN: {}})
|
||||
assert result, 'Failed to setup hasio'
|
||||
|
||||
client = yield from test_client(hass.http.app)
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/addons/smb_config/info', json={
|
||||
'result': 'ok',
|
||||
'data': {
|
||||
'name': 'SMB Config',
|
||||
'state': 'running',
|
||||
'boot': 'auto',
|
||||
'options': {
|
||||
'bla': False,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
resp = yield from client.get('/api/hassio/addons/smb_config')
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 2
|
||||
assert resp.status == 200
|
||||
assert data['name'] == 'SMB Config'
|
||||
assert data['state'] == 'running'
|
||||
assert data['boot'] == 'auto'
|
||||
assert not data['options']['bla']
|
||||
|
||||
aioclient_mock.get('http://127.0.0.1/addons/smb_config/options', json={
|
||||
'result': 'ok',
|
||||
'data': {},
|
||||
})
|
||||
|
||||
resp = yield from client.post('/api/hassio/addons/smb_config', json={
|
||||
'boot': 'manual',
|
||||
'options': {
|
||||
'bla': True,
|
||||
}
|
||||
})
|
||||
data = yield from resp.json()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 3
|
||||
assert resp.status == 200
|
||||
assert aioclient_mock.mock_calls[-1][2]['boot'] == 'manual'
|
||||
assert aioclient_mock.mock_calls[-1][2]['options']['bla']
|
@ -75,8 +75,10 @@ class AiohttpClientMocker:
|
||||
@asyncio.coroutine
|
||||
# pylint: disable=unused-variable
|
||||
def match_request(self, method, url, *, data=None, auth=None, params=None,
|
||||
headers=None, allow_redirects=None):
|
||||
headers=None, allow_redirects=None, timeout=None,
|
||||
json=None):
|
||||
"""Match a request against pre-registered requests."""
|
||||
data = data or json
|
||||
for response in self._mocks:
|
||||
if response.match_request(method, url, params):
|
||||
self.mock_calls.append((method, url, data))
|
||||
|
Loading…
x
Reference in New Issue
Block a user