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",
"gpio": "bool",
"devicetree": "bool",
"docker_api": "bool",
"audio": "bool",
"audio_input": "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_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC,
ATTR_HOST_DBUS, ATTR_AUTO_UART, ATTR_DISCOVERY, ATTR_SERVICES,
ATTR_APPARMOR, ATTR_DEVICETREE, SECURITY_PROFILE, SECURITY_DISABLE,
SECURITY_DEFAULT)
ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API, SECURITY_PROFILE,
SECURITY_DISABLE, SECURITY_DEFAULT)
from ..coresys import CoreSysAttributes
from ..docker.addon import DockerAddon
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 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
def access_hassio_api(self):
"""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_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY,
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
_LOGGER = logging.getLogger(__name__)
@ -63,7 +63,8 @@ PRIVILEGED_ALL = [
"SYS_RAWIO",
"IPC_LOCK",
"SYS_TIME",
"SYS_NICE"
"SYS_NICE",
"SYS_RESOURCE"
]
BASE_IMAGE = {
@ -116,6 +117,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({
vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(),
vol.Optional(ATTR_STDIN, 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_DISCOVERY): [vol.Match(RE_DISCOVERY)],
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_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_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE,
ATTR_DISCOVERY, ATTR_APPARMOR, ATTR_DEVICETREE, ATTR_DOCKER_API,
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY, CONTENT_TYPE_TEXT)
from ..coresys import CoreSysAttributes
from ..validate import DOCKER_PORTS, ALSA_DEVICE
@ -137,6 +137,7 @@ class APIAddons(CoreSysAttributes):
ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api,
ATTR_GPIO: addon.with_gpio,
ATTR_DEVICETREE: addon.with_devicetree,
ATTR_DOCKER_API: addon.with_docker_api,
ATTR_AUDIO: addon.with_audio,
ATTR_AUDIO_INPUT: addon.audio_input,
ATTR_AUDIO_OUTPUT: addon.audio_output,

View File

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

View File

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

View File

@ -1,6 +1,7 @@
"""Init file for HassIO addon docker object."""
import logging
import os
from pathlib import Path
import docker
import requests
@ -204,14 +205,14 @@ class DockerAddon(DockerInterface):
# GPIO support
if self.addon.with_gpio:
volumes.update({
"/sys/class/gpio": {
'bind': "/sys/class/gpio", 'mode': 'rw'
},
"/sys/devices/platform/soc": {
'bind': "/sys/devices/platform/soc", 'mode': 'rw'
},
})
for gpio_path in ("/sys/class/gpio", "/sys/devices/platform/soc"):
if not Path(gpio_path).exists():
continue
volumes.update({
gpio_path: {
'bind': gpio_path, 'mode': 'rw'
},
})
# DeviceTree support
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
if self.addon.host_dbus:
volumes.update({

View File

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

View File

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

View File

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

View File

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