mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-25 18:16:32 +00:00
commit
d87a85ceb5
1
API.md
1
API.md
@ -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",
|
||||
|
@ -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."""
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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({
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user