Merge pull request #636 from home-assistant/dev

Release 124
This commit is contained in:
Pascal Vizeli 2018-08-09 01:03:47 +02:00 committed by GitHub
commit d87a85ceb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 67 additions and 45 deletions

1
API.md
View File

@ -482,6 +482,7 @@ Get all available addons.
"webui": "null|http(s)://[HOST]:port/xy/zx", "webui": "null|http(s)://[HOST]:port/xy/zx",
"gpio": "bool", "gpio": "bool",
"devicetree": "bool", "devicetree": "bool",
"docker_api": "bool",
"audio": "bool", "audio": "bool",
"audio_input": "null|0,0", "audio_input": "null|0,0",
"audio_output": "null|0,0", "audio_output": "null|0,0",

View File

@ -25,8 +25,8 @@ from ..const import (
ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT, ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT,
ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC,
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES, ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES,
ATTR_APPARMOR, ATTR_DEVICETREE, SECURITY_PROFILE, SECURITY_DISABLE, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, SECURITY_PROFILE,
SECURITY_DEFAULT) SECURITY_DISABLE, SECURITY_DEFAULT)
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..docker.addon import DockerAddon from ..docker.addon import DockerAddon
from ..utils.json import write_json_file, read_json_file from ..utils.json import write_json_file, read_json_file
@ -335,6 +335,11 @@ class Addon(CoreSysAttributes):
"""Return if the add-on don't support hass labels.""" """Return if the add-on don't support hass labels."""
return self._mesh.get(ATTR_LEGACY) return self._mesh.get(ATTR_LEGACY)
@property
def with_docker_api(self):
"""Return if the add-on need read-only docker API access."""
return self._mesh.get(ATTR_DOCKER_API)
@property @property
def access_hassio_api(self): def access_hassio_api(self):
"""Return True if the add-on access to hassio api.""" """Return True if the add-on access to hassio api."""

View File

@ -18,7 +18,7 @@ from ..const import (
ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH,
ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY,
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_SERVICES, ATTR_DISCOVERY, ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_SERVICES, ATTR_DISCOVERY,
ATTR_APPARMOR, ATTR_DEVICETREE) ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API)
from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_DEVICE from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_DEVICE
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -63,7 +63,8 @@ PRIVILEGED_ALL = [
"SYS_RAWIO", "SYS_RAWIO",
"IPC_LOCK", "IPC_LOCK",
"SYS_TIME", "SYS_TIME",
"SYS_NICE" "SYS_NICE",
"SYS_RESOURCE"
] ]
BASE_IMAGE = { BASE_IMAGE = {
@ -116,6 +117,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({
vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(), vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(),
vol.Optional(ATTR_STDIN, default=False): vol.Boolean(), vol.Optional(ATTR_STDIN, default=False): vol.Boolean(),
vol.Optional(ATTR_LEGACY, default=False): vol.Boolean(), vol.Optional(ATTR_LEGACY, default=False): vol.Boolean(),
vol.Optional(ATTR_DOCKER_API, default=False): vol.Boolean(),
vol.Optional(ATTR_SERVICES): [vol.Match(RE_SERVICE)], vol.Optional(ATTR_SERVICES): [vol.Match(RE_SERVICE)],
vol.Optional(ATTR_DISCOVERY): [vol.Match(RE_DISCOVERY)], vol.Optional(ATTR_DISCOVERY): [vol.Match(RE_DISCOVERY)],
vol.Required(ATTR_OPTIONS): dict, vol.Required(ATTR_OPTIONS): dict,

View File

@ -17,7 +17,7 @@ from ..const import (
ATTR_CHANGELOG, ATTR_HOST_IPC, ATTR_HOST_DBUS, ATTR_LONG_DESCRIPTION, ATTR_CHANGELOG, ATTR_HOST_IPC, ATTR_HOST_DBUS, ATTR_LONG_DESCRIPTION,
ATTR_CPU_PERCENT, ATTR_MEMORY_LIMIT, ATTR_MEMORY_USAGE, ATTR_NETWORK_TX, ATTR_CPU_PERCENT, ATTR_MEMORY_LIMIT, ATTR_MEMORY_USAGE, ATTR_NETWORK_TX,
ATTR_NETWORK_RX, ATTR_BLK_READ, ATTR_BLK_WRITE, ATTR_ICON, ATTR_SERVICES, ATTR_NETWORK_RX, ATTR_BLK_READ, ATTR_BLK_WRITE, ATTR_ICON, ATTR_SERVICES,
ATTR_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API,
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT) CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT)
from ..coresys import CoreSysAttributes from ..coresys import CoreSysAttributes
from ..validate import DOCKER_PORTS, ALSA_DEVICE from ..validate import DOCKER_PORTS, ALSA_DEVICE
@ -137,6 +137,7 @@ class APIAddons(CoreSysAttributes):
ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api, ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api,
ATTR_GPIO: addon.with_gpio, ATTR_GPIO: addon.with_gpio,
ATTR_DEVICETREE: addon.with_devicetree, ATTR_DEVICETREE: addon.with_devicetree,
ATTR_DOCKER_API: addon.with_docker_api,
ATTR_AUDIO: addon.with_audio, ATTR_AUDIO: addon.with_audio,
ATTR_AUDIO_INPUT: addon.audio_input, ATTR_AUDIO_INPUT: addon.audio_input,
ATTR_AUDIO_OUTPUT: addon.audio_output, ATTR_AUDIO_OUTPUT: addon.audio_output,

View File

@ -59,6 +59,8 @@ class APIProxy(CoreSysAttributes):
except HomeAssistantAuthError: except HomeAssistantAuthError:
_LOGGER.error("Authenticate error on API for request %s", path) _LOGGER.error("Authenticate error on API for request %s", path)
except HomeAssistantAPIError:
_LOGGER.error("Error on API for request %s", path)
except aiohttp.ClientError as err: except aiohttp.ClientError as err:
_LOGGER.error("Client error on API %s request %s", path, err) _LOGGER.error("Client error on API %s request %s", path, err)
except asyncio.TimeoutError: except asyncio.TimeoutError:
@ -148,11 +150,12 @@ class APIProxy(CoreSysAttributes):
self.sys_homeassistant.access_token = None self.sys_homeassistant.access_token = None
return await self._websocket_client() return await self._websocket_client()
_LOGGER.error( raise HomeAssistantAuthError()
"Failed authentication to Home-Assistant websocket: %s", data)
except (RuntimeError, HomeAssistantAPIError) as err: except (RuntimeError, ValueError) as err:
_LOGGER.error("Client error on websocket API %s.", err) _LOGGER.error("Client error on websocket API %s.", err)
except HomeAssistantAuthError as err:
_LOGGER.error("Failed authentication to HomeAssistant websocket")
raise HTTPBadGateway() raise HTTPBadGateway()

View File

@ -2,7 +2,7 @@
from pathlib import Path from pathlib import Path
from ipaddress import ip_network from ipaddress import ip_network
HASSIO_VERSION = '123' HASSIO_VERSION = '124'
URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons" URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons"
URL_HASSIO_VERSION = \ URL_HASSIO_VERSION = \
@ -178,6 +178,7 @@ ATTR_HASSOS_CLI = 'hassos_cli'
ATTR_VERSION_CLI = 'version_cli' ATTR_VERSION_CLI = 'version_cli'
ATTR_VERSION_CLI_LATEST = 'version_cli_latest' ATTR_VERSION_CLI_LATEST = 'version_cli_latest'
ATTR_REFRESH_TOKEN = 'refresh_token' ATTR_REFRESH_TOKEN = 'refresh_token'
ATTR_DOCKER_API = 'docker_api'
SERVICE_MQTT = 'mqtt' SERVICE_MQTT = 'mqtt'

View File

@ -1,6 +1,7 @@
"""Init file for HassIO addon docker object.""" """Init file for HassIO addon docker object."""
import logging import logging
import os import os
from pathlib import Path
import docker import docker
import requests import requests
@ -204,14 +205,14 @@ class DockerAddon(DockerInterface):
# GPIO support # GPIO support
if self.addon.with_gpio: if self.addon.with_gpio:
volumes.update({ for gpio_path in ("/sys/class/gpio", "/sys/devices/platform/soc"):
"/sys/class/gpio": { if not Path(gpio_path).exists():
'bind': "/sys/class/gpio", 'mode': 'rw' continue
}, volumes.update({
"/sys/devices/platform/soc": { gpio_path: {
'bind': "/sys/devices/platform/soc", 'mode': 'rw' 'bind': gpio_path, 'mode': 'rw'
}, },
}) })
# DeviceTree support # DeviceTree support
if self.addon.with_devicetree: if self.addon.with_devicetree:
@ -221,6 +222,14 @@ class DockerAddon(DockerInterface):
}, },
}) })
# Docker API support
if self.addon.with_docker_api:
volumes.update({
"/var/run/docker.sock": {
'bind': "/var/run/docker.sock", 'mode': 'ro'
},
})
# Host dbus system # Host dbus system
if self.addon.host_dbus: if self.addon.host_dbus:
volumes.update({ volumes.update({

View File

@ -1,7 +1,4 @@
"""Core Exceptions.""" """Core Exceptions."""
import asyncio
import aiohttp
class HassioError(Exception): class HassioError(Exception):
@ -26,14 +23,13 @@ class HomeAssistantUpdateError(HomeAssistantError):
pass pass
class HomeAssistantAuthError(HomeAssistantError): class HomeAssistantAPIError(HomeAssistantError):
"""Home Assistant Auth API exception.""" """Home Assistant API exception."""
pass pass
class HomeAssistantAPIError( class HomeAssistantAuthError(HomeAssistantAPIError):
HomeAssistantAuthError, asyncio.TimeoutError, aiohttp.ClientError): """Home Assistant Auth API exception."""
"""Home Assistant API exception."""
pass pass

View File

@ -355,7 +355,7 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
return return
with suppress(asyncio.TimeoutError, aiohttp.ClientError): with suppress(asyncio.TimeoutError, aiohttp.ClientError):
async with self.sys_websession_ssl.get( async with self.sys_websession_ssl.post(
f"{self.api_url}/auth/token", f"{self.api_url}/auth/token",
timeout=30, timeout=30,
data={ data={
@ -363,15 +363,14 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
"refresh_token": self.refresh_token "refresh_token": self.refresh_token
} }
) as resp: ) as resp:
if resp.status != 200: if resp.status == 200:
_LOGGER.error("Authenticate problem with HomeAssistant!") _LOGGER.info("Updated HomeAssistant API token")
raise HomeAssistantAuthError() tokens = await resp.json()
tokens = await resp.json() self.access_token = tokens['access_token']
self.access_token = tokens['access_token'] return
return
_LOGGER.error("Can't update HomeAssistant access token!") _LOGGER.error("Can't update HomeAssistant access token!")
raise HomeAssistantAPIError() raise HomeAssistantAuthError()
@asynccontextmanager @asynccontextmanager
async def make_request(self, method, path, json=None, content_type=None, async def make_request(self, method, path, json=None, content_type=None,
@ -394,15 +393,20 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
await self.ensure_access_token() await self.ensure_access_token()
headers[hdrs.AUTHORIZATION] = f'Bearer {self.access_token}' headers[hdrs.AUTHORIZATION] = f'Bearer {self.access_token}'
async with getattr(self.sys_websession_ssl, method)( try:
url, data=data, timeout=timeout, json=json, headers=headers async with getattr(self.sys_websession_ssl, method)(
) as resp: url, data=data, timeout=timeout, json=json,
# Access token expired headers=headers
if resp.status == 401 and self.refresh_token: ) as resp:
self.access_token = None # Access token expired
continue if resp.status == 401 and self.refresh_token:
yield resp self.access_token = None
return continue
yield resp
return
except (asyncio.TimeoutError, aiohttp.ClientError) as err:
_LOGGER.error("Error on call %s: %s", url, err)
break
raise HomeAssistantAPIError() raise HomeAssistantAPIError()

View File

@ -1,9 +1,9 @@
attr==0.3.1 attr==0.3.1
async_timeout==3.0.0 async_timeout==3.0.0
aiohttp==3.3.2 aiohttp==3.3.2
docker==3.4.0 docker==3.4.1
colorlog==3.1.2 colorlog==3.1.2
voluptuous==0.11.1 voluptuous==0.11.5
gitpython==2.1.10 gitpython==2.1.10
pytz==2018.4 pytz==2018.4
pyudev==0.21.0 pyudev==0.21.0

View File

@ -4,7 +4,7 @@ envlist = lint
[testenv] [testenv]
deps = deps =
flake8==3.5.0 flake8==3.5.0
pylint==2.0.0 pylint==2.1.1
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
[testenv:lint] [testenv:lint]