mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-08 01:36:29 +00:00
Add support for logo
This commit is contained in:
parent
8aec943a5c
commit
cd5a09938f
5
API.md
5
API.md
@ -332,10 +332,13 @@ Get all available addons
|
|||||||
"build": "bool",
|
"build": "bool",
|
||||||
"options": "{}",
|
"options": "{}",
|
||||||
"network": "{}|null",
|
"network": "{}|null",
|
||||||
"host_network": "bool"
|
"host_network": "bool",
|
||||||
|
"logo": "bool"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- 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_LOGO)
|
||||||
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
|
||||||
@ -228,6 +228,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 +278,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 +299,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))
|
||||||
|
@ -94,6 +94,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,7 @@ 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, BOOT_AUTO, BOOT_MANUAL, CONTENT_TYPE_PNG)
|
||||||
from ..validate import DOCKER_PORTS
|
from ..validate import DOCKER_PORTS
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -64,6 +64,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 = []
|
||||||
@ -187,3 +188,13 @@ class APIAddons(object):
|
|||||||
"""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)
|
||||||
|
def png(self, request):
|
||||||
|
"""Return logo from addon."""
|
||||||
|
addon = self._extract_addon(request)
|
||||||
|
if addon.with_logo:
|
||||||
|
raise RuntimeError("No image found!")
|
||||||
|
|
||||||
|
with addon.path_logo.open('rb') as png:
|
||||||
|
return png.read()
|
||||||
|
@ -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,21 @@ def api_process_hostcontrol(method):
|
|||||||
return wrap_hostcontrol
|
return wrap_hostcontrol
|
||||||
|
|
||||||
|
|
||||||
def api_process_raw(method):
|
def api_process_raw(content=CONTENT_TYPE_BINARY):
|
||||||
"""Wrap function with raw output to rest api."""
|
def api_raw(method):
|
||||||
async def wrap_api(api, *args, **kwargs):
|
"""Wrap function with raw output to rest api."""
|
||||||
"""Return api information."""
|
async def wrap_api(api, *args, **kwargs):
|
||||||
try:
|
"""Return api information."""
|
||||||
message = await method(api, *args, **kwargs)
|
try:
|
||||||
except RuntimeError as err:
|
message = await method(api, *args, **kwargs)
|
||||||
message = str(err).encode()
|
except RuntimeError as err:
|
||||||
|
message = str(err).encode()
|
||||||
|
content = CONTENT_TYPE_BINARY
|
||||||
|
|
||||||
return web.Response(body=message)
|
return web.Response(body=message, content_type=content)
|
||||||
|
|
||||||
return wrap_api
|
return wrap_api
|
||||||
|
return api_raw
|
||||||
|
|
||||||
|
|
||||||
def api_return_error(message=None):
|
def api_return_error(message=None):
|
||||||
|
@ -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'
|
||||||
@ -69,6 +72,7 @@ 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",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user