mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-27 02:56:31 +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",
|
"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",
|
||||||
|
@ -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."""
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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({
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user