mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-27 11:06:32 +00:00
commit
803eb0f8c9
19
API.md
19
API.md
@ -40,13 +40,11 @@ The addons from `addons` are only installed one.
|
|||||||
"name": "xy bla",
|
"name": "xy bla",
|
||||||
"slug": "xy",
|
"slug": "xy",
|
||||||
"description": "description",
|
"description": "description",
|
||||||
"arch": ["armhf", "aarch64", "i386", "amd64"],
|
|
||||||
"repository": "12345678|null",
|
"repository": "12345678|null",
|
||||||
"version": "LAST_VERSION",
|
"version": "LAST_VERSION",
|
||||||
"installed": "INSTALL_VERSION",
|
"installed": "INSTALL_VERSION",
|
||||||
"detached": "bool",
|
"logo": "bool",
|
||||||
"build": "bool",
|
"state": "started|stopped",
|
||||||
"url": "null|url"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"addons_repositories": [
|
"addons_repositories": [
|
||||||
@ -55,10 +53,6 @@ The addons from `addons` are only installed one.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- GET `/supervisor/addons`
|
|
||||||
|
|
||||||
Get all available addons. Will be delete soon. Look to `/addons`
|
|
||||||
|
|
||||||
- POST `/supervisor/update`
|
- POST `/supervisor/update`
|
||||||
Optional:
|
Optional:
|
||||||
```json
|
```json
|
||||||
@ -299,7 +293,8 @@ Get all available addons
|
|||||||
"installed": "none|INSTALL_VERSION",
|
"installed": "none|INSTALL_VERSION",
|
||||||
"detached": "bool",
|
"detached": "bool",
|
||||||
"build": "bool",
|
"build": "bool",
|
||||||
"url": "null|url"
|
"url": "null|url",
|
||||||
|
"logo": "bool"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"repositories": [
|
"repositories": [
|
||||||
@ -332,10 +327,14 @@ Get all available addons
|
|||||||
"build": "bool",
|
"build": "bool",
|
||||||
"options": "{}",
|
"options": "{}",
|
||||||
"network": "{}|null",
|
"network": "{}|null",
|
||||||
"host_network": "bool"
|
"host_network": "bool",
|
||||||
|
"logo": "bool",
|
||||||
|
"webui": "null|http(s)://[HOST]:port/xy/zx"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- GET `/addons/{addon}/logo`
|
||||||
|
|
||||||
- POST `/addons/{addon}/options`
|
- POST `/addons/{addon}/options`
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ from ..const import (
|
|||||||
ATTR_URL, ATTR_ARCH, ATTR_LOCATON, ATTR_DEVICES, ATTR_ENVIRONMENT,
|
ATTR_URL, ATTR_ARCH, ATTR_LOCATON, ATTR_DEVICES, ATTR_ENVIRONMENT,
|
||||||
ATTR_HOST_NETWORK, ATTR_TMPFS, ATTR_PRIVILEGED, ATTR_STARTUP,
|
ATTR_HOST_NETWORK, ATTR_TMPFS, ATTR_PRIVILEGED, ATTR_STARTUP,
|
||||||
STATE_STARTED, STATE_STOPPED, STATE_NONE, ATTR_USER, ATTR_SYSTEM,
|
STATE_STARTED, STATE_STOPPED, STATE_NONE, ATTR_USER, ATTR_SYSTEM,
|
||||||
ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK)
|
ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI)
|
||||||
from .util import check_installed
|
from .util import check_installed
|
||||||
from ..dock.addon import DockerAddon
|
from ..dock.addon import DockerAddon
|
||||||
from ..tools import write_json_file, read_json_file
|
from ..tools import write_json_file, read_json_file
|
||||||
@ -27,6 +27,7 @@ from ..tools import write_json_file, read_json_file
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
RE_VOLUME = re.compile(MAP_VOLUME)
|
RE_VOLUME = re.compile(MAP_VOLUME)
|
||||||
|
RE_WEBUI = re.compile(r"^(.*\[HOST\]:)\[PORT:(\d+)\](.*)$")
|
||||||
|
|
||||||
|
|
||||||
class Addon(object):
|
class Addon(object):
|
||||||
@ -130,7 +131,8 @@ class Addon(object):
|
|||||||
@property
|
@property
|
||||||
def auto_update(self):
|
def auto_update(self):
|
||||||
"""Return if auto update is enable."""
|
"""Return if auto update is enable."""
|
||||||
return self.data.user[self._id][ATTR_AUTO_UPDATE]
|
if ATTR_AUTO_UPDATE in self.data.user.get(self._id, {}):
|
||||||
|
return self.data.user[self._id][ATTR_AUTO_UPDATE]
|
||||||
|
|
||||||
@auto_update.setter
|
@auto_update.setter
|
||||||
def auto_update(self, value):
|
def auto_update(self, value):
|
||||||
@ -196,6 +198,25 @@ class Addon(object):
|
|||||||
|
|
||||||
self.data.save()
|
self.data.save()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def webui(self):
|
||||||
|
"""Return URL to webui or None."""
|
||||||
|
if ATTR_WEBUI not in self._mesh:
|
||||||
|
return
|
||||||
|
|
||||||
|
webui = self._mesh[ATTR_WEBUI]
|
||||||
|
dock_port = RE_WEBUI.sub(r"\2", webui)
|
||||||
|
if self.ports is None:
|
||||||
|
real_port = dock_port
|
||||||
|
else:
|
||||||
|
real_port = self.ports.get("{}/tcp".format(dock_port), dock_port)
|
||||||
|
|
||||||
|
# for interface config or port lists
|
||||||
|
if isinstance(real_port, (tuple, list)):
|
||||||
|
real_port = real_port[-1]
|
||||||
|
|
||||||
|
return RE_WEBUI.sub(r"\g<1>{}\g<3>".format(real_port), webui)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def network_mode(self):
|
def network_mode(self):
|
||||||
"""Return network mode of addon."""
|
"""Return network mode of addon."""
|
||||||
@ -228,6 +249,11 @@ class Addon(object):
|
|||||||
"""Return url of addon."""
|
"""Return url of addon."""
|
||||||
return self._mesh.get(ATTR_URL)
|
return self._mesh.get(ATTR_URL)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def with_logo(self):
|
||||||
|
"""Return True if a logo exists."""
|
||||||
|
return self.path_logo.exists()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_arch(self):
|
def supported_arch(self):
|
||||||
"""Return list of supported arch."""
|
"""Return list of supported arch."""
|
||||||
@ -273,15 +299,20 @@ class Addon(object):
|
|||||||
return PurePath(self.config.path_extern_addons_data, self._id)
|
return PurePath(self.config.path_extern_addons_data, self._id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path_addon_options(self):
|
def path_options(self):
|
||||||
"""Return path to addons options."""
|
"""Return path to addons options."""
|
||||||
return Path(self.path_data, "options.json")
|
return Path(self.path_data, "options.json")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path_addon_location(self):
|
def path_location(self):
|
||||||
"""Return path to this addon."""
|
"""Return path to this addon."""
|
||||||
return Path(self._mesh[ATTR_LOCATON])
|
return Path(self._mesh[ATTR_LOCATON])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path_logo(self):
|
||||||
|
"""Return path to addon logo."""
|
||||||
|
return Path(self.path_location, 'logo.png')
|
||||||
|
|
||||||
def write_options(self):
|
def write_options(self):
|
||||||
"""Return True if addon options is written to data."""
|
"""Return True if addon options is written to data."""
|
||||||
schema = self.schema
|
schema = self.schema
|
||||||
@ -289,7 +320,7 @@ class Addon(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
schema(options)
|
schema(options)
|
||||||
return write_json_file(self.path_addon_options, options)
|
return write_json_file(self.path_options, options)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
_LOGGER.error("Addon %s have wrong options -> %s", self._id,
|
_LOGGER.error("Addon %s have wrong options -> %s", self._id,
|
||||||
humanize_error(options, ex))
|
humanize_error(options, ex))
|
||||||
|
@ -10,7 +10,7 @@ from ..const import (
|
|||||||
ARCH_AARCH64, ARCH_AMD64, ARCH_I386, ATTR_TMPFS, ATTR_PRIVILEGED,
|
ARCH_AARCH64, ARCH_AMD64, ARCH_I386, ATTR_TMPFS, ATTR_PRIVILEGED,
|
||||||
ATTR_USER, ATTR_STATE, ATTR_SYSTEM, STATE_STARTED, STATE_STOPPED,
|
ATTR_USER, ATTR_STATE, ATTR_SYSTEM, STATE_STARTED, STATE_STOPPED,
|
||||||
ATTR_LOCATON, ATTR_REPOSITORY, ATTR_TIMEOUT, ATTR_NETWORK,
|
ATTR_LOCATON, ATTR_REPOSITORY, ATTR_TIMEOUT, ATTR_NETWORK,
|
||||||
ATTR_AUTO_UPDATE)
|
ATTR_AUTO_UPDATE, ATTR_WEBUI)
|
||||||
from ..validate import NETWORK_PORT, DOCKER_PORTS
|
from ..validate import NETWORK_PORT, DOCKER_PORTS
|
||||||
|
|
||||||
|
|
||||||
@ -65,6 +65,8 @@ SCHEMA_ADDON_CONFIG = vol.Schema({
|
|||||||
vol.Required(ATTR_BOOT):
|
vol.Required(ATTR_BOOT):
|
||||||
vol.In([BOOT_AUTO, BOOT_MANUAL]),
|
vol.In([BOOT_AUTO, BOOT_MANUAL]),
|
||||||
vol.Optional(ATTR_PORTS): DOCKER_PORTS,
|
vol.Optional(ATTR_PORTS): DOCKER_PORTS,
|
||||||
|
vol.Optional(ATTR_WEBUI):
|
||||||
|
vol.Match(r"^(?:https?):\/\/\[HOST\]:\[PORT:\d+\].*$"),
|
||||||
vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(),
|
vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(),
|
||||||
vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")],
|
vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")],
|
||||||
vol.Optional(ATTR_TMPFS):
|
vol.Optional(ATTR_TMPFS):
|
||||||
|
@ -53,8 +53,6 @@ class RestAPI(object):
|
|||||||
|
|
||||||
self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping)
|
self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping)
|
||||||
self.webapp.router.add_get('/supervisor/info', api_supervisor.info)
|
self.webapp.router.add_get('/supervisor/info', api_supervisor.info)
|
||||||
self.webapp.router.add_get(
|
|
||||||
'/supervisor/addons', api_supervisor.available_addons)
|
|
||||||
self.webapp.router.add_post(
|
self.webapp.router.add_post(
|
||||||
'/supervisor/update', api_supervisor.update)
|
'/supervisor/update', api_supervisor.update)
|
||||||
self.webapp.router.add_post(
|
self.webapp.router.add_post(
|
||||||
@ -94,6 +92,7 @@ class RestAPI(object):
|
|||||||
self.webapp.router.add_post(
|
self.webapp.router.add_post(
|
||||||
'/addons/{addon}/options', api_addons.options)
|
'/addons/{addon}/options', api_addons.options)
|
||||||
self.webapp.router.add_get('/addons/{addon}/logs', api_addons.logs)
|
self.webapp.router.add_get('/addons/{addon}/logs', api_addons.logs)
|
||||||
|
self.webapp.router.add_get('/addons/{addon}/logo', api_addons.logo)
|
||||||
|
|
||||||
def register_security(self):
|
def register_security(self):
|
||||||
"""Register security function."""
|
"""Register security function."""
|
||||||
|
@ -11,7 +11,8 @@ from ..const import (
|
|||||||
ATTR_URL, ATTR_DESCRIPTON, ATTR_DETACHED, ATTR_NAME, ATTR_REPOSITORY,
|
ATTR_URL, ATTR_DESCRIPTON, ATTR_DETACHED, ATTR_NAME, ATTR_REPOSITORY,
|
||||||
ATTR_BUILD, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_HOST_NETWORK, ATTR_SLUG,
|
ATTR_BUILD, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_HOST_NETWORK, ATTR_SLUG,
|
||||||
ATTR_SOURCE, ATTR_REPOSITORIES, ATTR_ADDONS, ATTR_ARCH, ATTR_MAINTAINER,
|
ATTR_SOURCE, ATTR_REPOSITORIES, ATTR_ADDONS, ATTR_ARCH, ATTR_MAINTAINER,
|
||||||
ATTR_INSTALLED, BOOT_AUTO, BOOT_MANUAL)
|
ATTR_INSTALLED, ATTR_LOGO, ATTR_WEBUI, BOOT_AUTO, BOOT_MANUAL,
|
||||||
|
CONTENT_TYPE_PNG, CONTENT_TYPE_BINARY)
|
||||||
from ..validate import DOCKER_PORTS
|
from ..validate import DOCKER_PORTS
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -64,6 +65,7 @@ class APIAddons(object):
|
|||||||
ATTR_REPOSITORY: addon.repository,
|
ATTR_REPOSITORY: addon.repository,
|
||||||
ATTR_BUILD: addon.need_build,
|
ATTR_BUILD: addon.need_build,
|
||||||
ATTR_URL: addon.url,
|
ATTR_URL: addon.url,
|
||||||
|
ATTR_LOGO: addon.with_logo,
|
||||||
})
|
})
|
||||||
|
|
||||||
data_repositories = []
|
data_repositories = []
|
||||||
@ -82,9 +84,10 @@ class APIAddons(object):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def reload(self, request):
|
async def reload(self, request):
|
||||||
"""Reload all addons data."""
|
"""Reload all addons data."""
|
||||||
return self.addons.reload()
|
await asyncio.shield(self.addons.reload(), loop=self.loop)
|
||||||
|
return True
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def info(self, request):
|
async def info(self, request):
|
||||||
@ -106,6 +109,8 @@ class APIAddons(object):
|
|||||||
ATTR_BUILD: addon.need_build,
|
ATTR_BUILD: addon.need_build,
|
||||||
ATTR_NETWORK: addon.ports,
|
ATTR_NETWORK: addon.ports,
|
||||||
ATTR_HOST_NETWORK: addon.network_mode == 'host',
|
ATTR_HOST_NETWORK: addon.network_mode == 'host',
|
||||||
|
ATTR_LOGO: addon.with_logo,
|
||||||
|
ATTR_WEBUI: addon.webui,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
@ -182,8 +187,18 @@ class APIAddons(object):
|
|||||||
addon = self._extract_addon(request)
|
addon = self._extract_addon(request)
|
||||||
return await asyncio.shield(addon.restart(), loop=self.loop)
|
return await asyncio.shield(addon.restart(), loop=self.loop)
|
||||||
|
|
||||||
@api_process_raw
|
@api_process_raw(CONTENT_TYPE_BINARY)
|
||||||
def logs(self, request):
|
def logs(self, request):
|
||||||
"""Return logs from addon."""
|
"""Return logs from addon."""
|
||||||
addon = self._extract_addon(request)
|
addon = self._extract_addon(request)
|
||||||
return addon.logs()
|
return addon.logs()
|
||||||
|
|
||||||
|
@api_process_raw(CONTENT_TYPE_PNG)
|
||||||
|
async def logo(self, request):
|
||||||
|
"""Return logo from addon."""
|
||||||
|
addon = self._extract_addon(request, check_installed=False)
|
||||||
|
if not addon.with_logo:
|
||||||
|
raise RuntimeError("No image found!")
|
||||||
|
|
||||||
|
with addon.path_logo.open('rb') as png:
|
||||||
|
return png.read()
|
||||||
|
@ -6,7 +6,8 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from .util import api_process, api_process_raw, api_validate
|
from .util import api_process, api_process_raw, api_validate
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_DEVICES, ATTR_IMAGE, ATTR_CUSTOM)
|
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_DEVICES, ATTR_IMAGE, ATTR_CUSTOM,
|
||||||
|
CONTENT_TYPE_BINARY)
|
||||||
from ..validate import HASS_DEVICES
|
from ..validate import HASS_DEVICES
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -79,7 +80,7 @@ class APIHomeAssistant(object):
|
|||||||
return await asyncio.shield(
|
return await asyncio.shield(
|
||||||
self.homeassistant.restart(), loop=self.loop)
|
self.homeassistant.restart(), loop=self.loop)
|
||||||
|
|
||||||
@api_process_raw
|
@api_process_raw(CONTENT_TYPE_BINARY)
|
||||||
def logs(self, request):
|
def logs(self, request):
|
||||||
"""Return homeassistant docker logs.
|
"""Return homeassistant docker logs.
|
||||||
|
|
||||||
|
@ -63,9 +63,10 @@ class APISnapshots(object):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
def reload(self, request):
|
async def reload(self, request):
|
||||||
"""Reload snapshot list."""
|
"""Reload snapshot list."""
|
||||||
return asyncio.shield(self.snapshots.reload(), loop=self.loop)
|
await asyncio.shield(self.snapshots.reload(), loop=self.loop)
|
||||||
|
return True
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def info(self, request):
|
async def info(self, request):
|
||||||
|
@ -6,11 +6,10 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from .util import api_process, api_process_raw, api_validate
|
from .util import api_process, api_process_raw, api_validate
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_ADDONS, ATTR_VERSION, ATTR_LAST_VERSION, ATTR_BETA_CHANNEL,
|
ATTR_ADDONS, ATTR_VERSION, ATTR_LAST_VERSION, ATTR_BETA_CHANNEL, ATTR_ARCH,
|
||||||
HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_REPOSITORIES,
|
HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_LOGO, ATTR_REPOSITORY,
|
||||||
ATTR_REPOSITORY, ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED,
|
ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED, ATTR_TIMEZONE,
|
||||||
ATTR_DETACHED, ATTR_SOURCE, ATTR_MAINTAINER, ATTR_URL, ATTR_ARCH,
|
ATTR_STATE, CONTENT_TYPE_BINARY)
|
||||||
ATTR_BUILD, ATTR_TIMEZONE)
|
|
||||||
from ..tools import validate_timezone
|
from ..tools import validate_timezone
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -41,42 +40,6 @@ class APISupervisor(object):
|
|||||||
self.host_control = host_control
|
self.host_control = host_control
|
||||||
self.websession = websession
|
self.websession = websession
|
||||||
|
|
||||||
def _addons_list(self, only_installed=False):
|
|
||||||
"""Return a list of addons."""
|
|
||||||
data = []
|
|
||||||
for addon in self.addons.list_addons:
|
|
||||||
if only_installed and not addon.is_installed:
|
|
||||||
continue
|
|
||||||
|
|
||||||
data.append({
|
|
||||||
ATTR_NAME: addon.name,
|
|
||||||
ATTR_SLUG: addon.slug,
|
|
||||||
ATTR_DESCRIPTON: addon.description,
|
|
||||||
ATTR_VERSION: addon.last_version,
|
|
||||||
ATTR_INSTALLED: addon.version_installed,
|
|
||||||
ATTR_ARCH: addon.supported_arch,
|
|
||||||
ATTR_DETACHED: addon.is_detached,
|
|
||||||
ATTR_REPOSITORY: addon.repository,
|
|
||||||
ATTR_BUILD: addon.need_build,
|
|
||||||
ATTR_URL: addon.url,
|
|
||||||
})
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _repositories_list(self):
|
|
||||||
"""Return a list of addons repositories."""
|
|
||||||
data = []
|
|
||||||
for repository in self.addons.list_repositories:
|
|
||||||
data.append({
|
|
||||||
ATTR_SLUG: repository.slug,
|
|
||||||
ATTR_NAME: repository.name,
|
|
||||||
ATTR_SOURCE: repository.source,
|
|
||||||
ATTR_URL: repository.url,
|
|
||||||
ATTR_MAINTAINER: repository.maintainer,
|
|
||||||
})
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def ping(self, request):
|
async def ping(self, request):
|
||||||
"""Return ok for signal that the api is ready."""
|
"""Return ok for signal that the api is ready."""
|
||||||
@ -85,24 +48,30 @@ class APISupervisor(object):
|
|||||||
@api_process
|
@api_process
|
||||||
async def info(self, request):
|
async def info(self, request):
|
||||||
"""Return host information."""
|
"""Return host information."""
|
||||||
|
list_addons = []
|
||||||
|
for addon in self.addons.list_addons:
|
||||||
|
if addon.is_installed:
|
||||||
|
list_addons.append({
|
||||||
|
ATTR_NAME: addon.name,
|
||||||
|
ATTR_SLUG: addon.slug,
|
||||||
|
ATTR_DESCRIPTON: addon.description,
|
||||||
|
ATTR_STATE: await addon.state(),
|
||||||
|
ATTR_VERSION: addon.last_version,
|
||||||
|
ATTR_INSTALLED: addon.version_installed,
|
||||||
|
ATTR_REPOSITORY: addon.repository,
|
||||||
|
ATTR_LOGO: addon.with_logo,
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ATTR_VERSION: HASSIO_VERSION,
|
ATTR_VERSION: HASSIO_VERSION,
|
||||||
ATTR_LAST_VERSION: self.config.last_hassio,
|
ATTR_LAST_VERSION: self.config.last_hassio,
|
||||||
ATTR_BETA_CHANNEL: self.config.upstream_beta,
|
ATTR_BETA_CHANNEL: self.config.upstream_beta,
|
||||||
ATTR_ARCH: self.config.arch,
|
ATTR_ARCH: self.config.arch,
|
||||||
ATTR_TIMEZONE: self.config.timezone,
|
ATTR_TIMEZONE: self.config.timezone,
|
||||||
ATTR_ADDONS: self._addons_list(only_installed=True),
|
ATTR_ADDONS: list_addons,
|
||||||
ATTR_ADDONS_REPOSITORIES: self.config.addons_repositories,
|
ATTR_ADDONS_REPOSITORIES: self.config.addons_repositories,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api_process
|
|
||||||
async def available_addons(self, request):
|
|
||||||
"""Return information for all available addons."""
|
|
||||||
return {
|
|
||||||
ATTR_ADDONS: self._addons_list(),
|
|
||||||
ATTR_REPOSITORIES: self._repositories_list(),
|
|
||||||
}
|
|
||||||
|
|
||||||
@api_process
|
@api_process
|
||||||
async def options(self, request):
|
async def options(self, request):
|
||||||
"""Set supervisor options."""
|
"""Set supervisor options."""
|
||||||
@ -150,7 +119,7 @@ class APISupervisor(object):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@api_process_raw
|
@api_process_raw(CONTENT_TYPE_BINARY)
|
||||||
def logs(self, request):
|
def logs(self, request):
|
||||||
"""Return supervisor docker logs.
|
"""Return supervisor docker logs.
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ import voluptuous as vol
|
|||||||
from voluptuous.humanize import humanize_error
|
from voluptuous.humanize import humanize_error
|
||||||
|
|
||||||
from ..const import (
|
from ..const import (
|
||||||
JSON_RESULT, JSON_DATA, JSON_MESSAGE, RESULT_OK, RESULT_ERROR)
|
JSON_RESULT, JSON_DATA, JSON_MESSAGE, RESULT_OK, RESULT_ERROR,
|
||||||
|
CONTENT_TYPE_BINARY)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -65,18 +66,23 @@ def api_process_hostcontrol(method):
|
|||||||
return wrap_hostcontrol
|
return wrap_hostcontrol
|
||||||
|
|
||||||
|
|
||||||
def api_process_raw(method):
|
def api_process_raw(content):
|
||||||
"""Wrap function with raw output to rest api."""
|
"""Wrap content_type into function."""
|
||||||
async def wrap_api(api, *args, **kwargs):
|
def wrap_method(method):
|
||||||
"""Return api information."""
|
"""Wrap function with raw output to rest api."""
|
||||||
try:
|
async def wrap_api(api, *args, **kwargs):
|
||||||
message = await method(api, *args, **kwargs)
|
"""Return api information."""
|
||||||
except RuntimeError as err:
|
try:
|
||||||
message = str(err).encode()
|
msg_data = await method(api, *args, **kwargs)
|
||||||
|
msg_type = content
|
||||||
|
except RuntimeError as err:
|
||||||
|
msg_data = str(err).encode()
|
||||||
|
msg_type = CONTENT_TYPE_BINARY
|
||||||
|
|
||||||
return web.Response(body=message)
|
return web.Response(body=msg_data, content_type=msg_type)
|
||||||
|
|
||||||
return wrap_api
|
return wrap_api
|
||||||
|
return wrap_method
|
||||||
|
|
||||||
|
|
||||||
def api_return_error(message=None):
|
def api_return_error(message=None):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Const file for HassIO."""
|
"""Const file for HassIO."""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
HASSIO_VERSION = '0.45'
|
HASSIO_VERSION = '0.46'
|
||||||
|
|
||||||
URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/'
|
URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/'
|
||||||
'hassio/master/version.json')
|
'hassio/master/version.json')
|
||||||
@ -44,6 +44,9 @@ JSON_MESSAGE = 'message'
|
|||||||
RESULT_ERROR = 'error'
|
RESULT_ERROR = 'error'
|
||||||
RESULT_OK = 'ok'
|
RESULT_OK = 'ok'
|
||||||
|
|
||||||
|
CONTENT_TYPE_BINARY = 'application/octet-stream'
|
||||||
|
CONTENT_TYPE_PNG = 'image/png'
|
||||||
|
|
||||||
ATTR_DATE = 'date'
|
ATTR_DATE = 'date'
|
||||||
ATTR_ARCH = 'arch'
|
ATTR_ARCH = 'arch'
|
||||||
ATTR_HOSTNAME = 'hostname'
|
ATTR_HOSTNAME = 'hostname'
|
||||||
@ -63,12 +66,14 @@ ATTR_STARTUP = 'startup'
|
|||||||
ATTR_BOOT = 'boot'
|
ATTR_BOOT = 'boot'
|
||||||
ATTR_PORTS = 'ports'
|
ATTR_PORTS = 'ports'
|
||||||
ATTR_MAP = 'map'
|
ATTR_MAP = 'map'
|
||||||
|
ATTR_WEBUI = 'webui'
|
||||||
ATTR_OPTIONS = 'options'
|
ATTR_OPTIONS = 'options'
|
||||||
ATTR_INSTALLED = 'installed'
|
ATTR_INSTALLED = 'installed'
|
||||||
ATTR_DETACHED = 'detached'
|
ATTR_DETACHED = 'detached'
|
||||||
ATTR_STATE = 'state'
|
ATTR_STATE = 'state'
|
||||||
ATTR_SCHEMA = 'schema'
|
ATTR_SCHEMA = 'schema'
|
||||||
ATTR_IMAGE = 'image'
|
ATTR_IMAGE = 'image'
|
||||||
|
ATTR_LOGO = 'logo'
|
||||||
ATTR_ADDONS_REPOSITORIES = 'addons_repositories'
|
ATTR_ADDONS_REPOSITORIES = 'addons_repositories'
|
||||||
ATTR_REPOSITORY = 'repository'
|
ATTR_REPOSITORY = 'repository'
|
||||||
ATTR_REPOSITORIES = 'repositories'
|
ATTR_REPOSITORIES = 'repositories'
|
||||||
|
@ -144,7 +144,7 @@ class DockerAddon(DockerBase):
|
|||||||
try:
|
try:
|
||||||
# prepare temporary addon build folder
|
# prepare temporary addon build folder
|
||||||
try:
|
try:
|
||||||
source = self.addon.path_addon_location
|
source = self.addon.path_location
|
||||||
shutil.copytree(str(source), str(build_dir))
|
shutil.copytree(str(source), str(build_dir))
|
||||||
except shutil.Error as err:
|
except shutil.Error as err:
|
||||||
_LOGGER.error("Can't copy %s to temporary build folder -> %s",
|
_LOGGER.error("Can't copy %s to temporary build folder -> %s",
|
||||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit 35c4e1d5ae925119fcc7c2f3cf31c5f4d09c4124
|
Subproject commit 5cdba73bacdbdf8a9cb1b95f55b2fdd44ae49a78
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"hassio": "0.45",
|
"hassio": "0.46",
|
||||||
"homeassistant": "0.49",
|
"homeassistant": "0.49",
|
||||||
"resinos": "1.0",
|
"resinos": "1.0",
|
||||||
"resinhup": "0.2",
|
"resinhup": "0.2",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user