Fix version conflict

This commit is contained in:
Pascal Vizeli 2018-04-09 23:41:00 +02:00
commit 0d4a5a7ffb
12 changed files with 182 additions and 167 deletions

2
API.md
View File

@ -427,6 +427,8 @@ Get all available addons.
"host_ipc": "bool", "host_ipc": "bool",
"host_dbus": "bool", "host_dbus": "bool",
"privileged": ["NET_ADMIN", "SYS_ADMIN"], "privileged": ["NET_ADMIN", "SYS_ADMIN"],
"seccomp": "disable|default|profile",
"apparmor": "disable|default|profile",
"devices": ["/dev/xy"], "devices": ["/dev/xy"],
"auto_uart": "bool", "auto_uart": "bool",
"icon": "bool", "icon": "bool",

View File

@ -23,7 +23,9 @@ from ..const import (
ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI, ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI,
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_SECCOMP, ATTR_APPARMOR, SECURITY_PROFILE, 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
@ -316,6 +318,24 @@ class Addon(CoreSysAttributes):
"""Return list of privilege.""" """Return list of privilege."""
return self._mesh.get(ATTR_PRIVILEGED) return self._mesh.get(ATTR_PRIVILEGED)
@property
def seccomp(self):
"""Return True if seccomp is enabled."""
if not self._mesh.get(ATTR_SECCOMP):
return SECURITY_DISABLE
elif self.path_seccomp.exists():
return SECURITY_PROFILE
return SECURITY_DEFAULT
@property
def apparmor(self):
"""Return True if seccomp is enabled."""
if not self._mesh.get(ATTR_APPARMOR):
return SECURITY_DISABLE
elif self.path_apparmor.exists():
return SECURITY_PROFILE
return SECURITY_DEFAULT
@property @property
def legacy(self): def legacy(self):
"""Return if the add-on don't support hass labels.""" """Return if the add-on don't support hass labels."""
@ -474,6 +494,16 @@ class Addon(CoreSysAttributes):
"""Return path to addon changelog.""" """Return path to addon changelog."""
return Path(self.path_location, 'CHANGELOG.md') return Path(self.path_location, 'CHANGELOG.md')
@property
def path_seccomp(self):
"""Return path to custom seccomp profile."""
return Path(self.path_location, 'seccomp.json')
@property
def path_apparmor(self):
"""Return path to custom AppArmor profile."""
return Path(self.path_location, 'apparmor')
def save_data(self): def save_data(self):
"""Save data of addon.""" """Save data of addon."""
self._addons.data.save_data() self._addons.data.save_data()

View File

@ -55,8 +55,8 @@ class AddonBuild(JsonConfig, CoreSysAttributes):
'io.hass.version': version, 'io.hass.version': version,
'io.hass.arch': self._arch, 'io.hass.arch': self._arch,
'io.hass.type': META_ADDON, 'io.hass.type': META_ADDON,
'io.hass.name': self.addon.name, 'io.hass.name': self._fix_label('name'),
'io.hass.description': self.addon.description, 'io.hass.description': self._fix_label('description'),
}, },
'buildargs': { 'buildargs': {
'BUILD_FROM': self.base_image, 'BUILD_FROM': self.base_image,
@ -70,3 +70,8 @@ class AddonBuild(JsonConfig, CoreSysAttributes):
args['labels']['io.hass.url'] = self.addon.url args['labels']['io.hass.url'] = self.addon.url
return args return args
def _fix_label(self, label_name):
"""Remove characters they are not supported."""
label = getattr(self.addon, label_name, "")
return label.replace("'", "")

View File

@ -17,7 +17,8 @@ from ..const import (
ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_HOST_IPC, ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_HOST_IPC,
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_SECCOMP, ATTR_APPARMOR)
from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -107,6 +108,8 @@ SCHEMA_ADDON_CONFIG = vol.Schema({
vol.Optional(ATTR_MAP, default=list): [vol.Match(RE_VOLUME)], vol.Optional(ATTR_MAP, default=list): [vol.Match(RE_VOLUME)],
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)}, vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
vol.Optional(ATTR_PRIVILEGED): [vol.In(PRIVILEGED_ALL)], vol.Optional(ATTR_PRIVILEGED): [vol.In(PRIVILEGED_ALL)],
vol.Optional(ATTR_SECCOMP, default=True): vol.Boolean(),
vol.Optional(ATTR_APPARMOR, default=True): vol.Boolean(),
vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(), vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(),
vol.Optional(ATTR_GPIO, default=False): vol.Boolean(), vol.Optional(ATTR_GPIO, default=False): vol.Boolean(),
vol.Optional(ATTR_HASSIO_API, default=False): vol.Boolean(), vol.Optional(ATTR_HASSIO_API, default=False): vol.Boolean(),

View File

@ -51,178 +51,163 @@ class RestAPI(CoreSysAttributes):
api_host = APIHost() api_host = APIHost()
api_host.coresys = self.coresys api_host.coresys = self.coresys
self.webapp.router.add_get('/host/info', api_host.info) self.webapp.add_routes([
self.webapp.router.add_get('/host/hardware', api_host.hardware) web.get('/host/info', api_host.info),
self.webapp.router.add_post('/host/reboot', api_host.reboot) web.get('/host/hardware', api_host.hardware),
self.webapp.router.add_post('/host/shutdown', api_host.shutdown) web.post('/host/reboot', api_host.reboot),
self.webapp.router.add_post('/host/update', api_host.update) web.post('/host/shutdown', api_host.shutdown),
self.webapp.router.add_post('/host/options', api_host.options) web.post('/host/update', api_host.update),
self.webapp.router.add_post('/host/reload', api_host.reload) web.post('/host/options', api_host.options),
web.post('/host/reload', api_host.reload),
])
def _register_network(self): def _register_network(self):
"""Register network function.""" """Register network function."""
api_net = APINetwork() api_net = APINetwork()
api_net.coresys = self.coresys api_net.coresys = self.coresys
self.webapp.router.add_get('/network/info', api_net.info) self.webapp.add_routes([
self.webapp.router.add_post('/network/options', api_net.options) web.get('/network/info', api_net.info),
web.post('/network/options', api_net.options),
])
def _register_supervisor(self): def _register_supervisor(self):
"""Register supervisor function.""" """Register supervisor function."""
api_supervisor = APISupervisor() api_supervisor = APISupervisor()
api_supervisor.coresys = self.coresys api_supervisor.coresys = self.coresys
self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping) self.webapp.add_routes([
self.webapp.router.add_get('/supervisor/info', api_supervisor.info) web.get('/supervisor/ping', api_supervisor.ping),
self.webapp.router.add_get('/supervisor/stats', api_supervisor.stats) web.get('/supervisor/info', api_supervisor.info),
self.webapp.router.add_post( web.get('/supervisor/stats', api_supervisor.stats),
'/supervisor/update', api_supervisor.update) web.get('/supervisor/logs', api_supervisor.logs),
self.webapp.router.add_post( web.post('/supervisor/update', api_supervisor.update),
'/supervisor/reload', api_supervisor.reload) web.post('/supervisor/reload', api_supervisor.reload),
self.webapp.router.add_post( web.post('/supervisor/options', api_supervisor.options),
'/supervisor/options', api_supervisor.options) ])
self.webapp.router.add_get('/supervisor/logs', api_supervisor.logs)
def _register_homeassistant(self): def _register_homeassistant(self):
"""Register homeassistant function.""" """Register homeassistant function."""
api_hass = APIHomeAssistant() api_hass = APIHomeAssistant()
api_hass.coresys = self.coresys api_hass.coresys = self.coresys
self.webapp.router.add_get('/homeassistant/info', api_hass.info) self.webapp.add_routes([
self.webapp.router.add_get('/homeassistant/logs', api_hass.logs) web.get('/homeassistant/info', api_hass.info),
self.webapp.router.add_get('/homeassistant/stats', api_hass.stats) web.get('/homeassistant/logs', api_hass.logs),
self.webapp.router.add_post('/homeassistant/options', api_hass.options) web.get('/homeassistant/stats', api_hass.stats),
self.webapp.router.add_post('/homeassistant/update', api_hass.update) web.post('/homeassistant/options', api_hass.options),
self.webapp.router.add_post('/homeassistant/restart', api_hass.restart) web.post('/homeassistant/update', api_hass.update),
self.webapp.router.add_post('/homeassistant/stop', api_hass.stop) web.post('/homeassistant/restart', api_hass.restart),
self.webapp.router.add_post('/homeassistant/start', api_hass.start) web.post('/homeassistant/stop', api_hass.stop),
self.webapp.router.add_post('/homeassistant/check', api_hass.check) web.post('/homeassistant/start', api_hass.start),
web.post('/homeassistant/check', api_hass.check),
])
def _register_proxy(self): def _register_proxy(self):
"""Register HomeAssistant API Proxy.""" """Register HomeAssistant API Proxy."""
api_proxy = APIProxy() api_proxy = APIProxy()
api_proxy.coresys = self.coresys api_proxy.coresys = self.coresys
self.webapp.router.add_get( self.webapp.add_routes([
'/homeassistant/api/websocket', api_proxy.websocket) web.get('/homeassistant/api/websocket', api_proxy.websocket),
self.webapp.router.add_get( web.get('/homeassistant/websocket', api_proxy.websocket),
'/homeassistant/websocket', api_proxy.websocket) web.get('/homeassistant/api/stream', api_proxy.stream),
self.webapp.router.add_get( web.post('/homeassistant/api/{path:.+}', api_proxy.api),
'/homeassistant/api/stream', api_proxy.stream) web.get('/homeassistant/api/{path:.+}', api_proxy.api),
self.webapp.router.add_post( web.get('/homeassistant/api/', api_proxy.api),
'/homeassistant/api/{path:.+}', api_proxy.api) ])
self.webapp.router.add_get(
'/homeassistant/api/{path:.+}', api_proxy.api)
self.webapp.router.add_get(
'/homeassistant/api/', api_proxy.api)
def _register_addons(self): def _register_addons(self):
"""Register homeassistant function.""" """Register homeassistant function."""
api_addons = APIAddons() api_addons = APIAddons()
api_addons.coresys = self.coresys api_addons.coresys = self.coresys
self.webapp.router.add_get('/addons', api_addons.list) self.webapp.add_routes([
self.webapp.router.add_post('/addons/reload', api_addons.reload) web.get('/addons', api_addons.list),
self.webapp.router.add_get('/addons/{addon}/info', api_addons.info) web.post('/addons/reload', api_addons.reload),
self.webapp.router.add_post( web.get('/addons/{addon}/info', api_addons.info),
'/addons/{addon}/install', api_addons.install) web.post('/addons/{addon}/install', api_addons.install),
self.webapp.router.add_post( web.post('/addons/{addon}/uninstall', api_addons.uninstall),
'/addons/{addon}/uninstall', api_addons.uninstall) web.post('/addons/{addon}/start', api_addons.start),
self.webapp.router.add_post('/addons/{addon}/start', api_addons.start) web.post('/addons/{addon}/stop', api_addons.stop),
self.webapp.router.add_post('/addons/{addon}/stop', api_addons.stop) web.post('/addons/{addon}/restart', api_addons.restart),
self.webapp.router.add_post( web.post('/addons/{addon}/update', api_addons.update),
'/addons/{addon}/restart', api_addons.restart) web.post('/addons/{addon}/options', api_addons.options),
self.webapp.router.add_post( web.post('/addons/{addon}/rebuild', api_addons.rebuild),
'/addons/{addon}/update', api_addons.update) web.get('/addons/{addon}/logs', api_addons.logs),
self.webapp.router.add_post( web.get('/addons/{addon}/icon', api_addons.icon),
'/addons/{addon}/options', api_addons.options) web.get('/addons/{addon}/logo', api_addons.logo),
self.webapp.router.add_post( web.get('/addons/{addon}/changelog', api_addons.changelog),
'/addons/{addon}/rebuild', api_addons.rebuild) web.post('/addons/{addon}/stdin', api_addons.stdin),
self.webapp.router.add_get('/addons/{addon}/logs', api_addons.logs) web.get('/addons/{addon}/stats', api_addons.stats),
self.webapp.router.add_get('/addons/{addon}/icon', api_addons.icon) ])
self.webapp.router.add_get('/addons/{addon}/logo', api_addons.logo)
self.webapp.router.add_get(
'/addons/{addon}/changelog', api_addons.changelog)
self.webapp.router.add_post('/addons/{addon}/stdin', api_addons.stdin)
self.webapp.router.add_get('/addons/{addon}/stats', api_addons.stats)
def _register_snapshots(self): def _register_snapshots(self):
"""Register snapshots function.""" """Register snapshots function."""
api_snapshots = APISnapshots() api_snapshots = APISnapshots()
api_snapshots.coresys = self.coresys api_snapshots.coresys = self.coresys
self.webapp.router.add_get('/snapshots', api_snapshots.list) self.webapp.add_routes([
self.webapp.router.add_post('/snapshots/reload', api_snapshots.reload) web.get('/snapshots', api_snapshots.list),
web.post('/snapshots/reload', api_snapshots.reload),
self.webapp.router.add_post( web.post('/snapshots/new/full', api_snapshots.snapshot_full),
'/snapshots/new/full', api_snapshots.snapshot_full) web.post('/snapshots/new/partial', api_snapshots.snapshot_partial),
self.webapp.router.add_post( web.post('/snapshots/new/upload', api_snapshots.upload),
'/snapshots/new/partial', api_snapshots.snapshot_partial) web.get('/snapshots/{snapshot}/info', api_snapshots.info),
self.webapp.router.add_post( web.post('/snapshots/{snapshot}/remove', api_snapshots.remove),
'/snapshots/new/upload', api_snapshots.upload) web.post('/snapshots/{snapshot}/restore/full',
api_snapshots.restore_full),
self.webapp.router.add_get( web.post('/snapshots/{snapshot}/restore/partial',
'/snapshots/{snapshot}/info', api_snapshots.info) api_snapshots.restore_partial),
self.webapp.router.add_post( web.get('/snapshots/{snapshot}/download', api_snapshots.download),
'/snapshots/{snapshot}/remove', api_snapshots.remove) ])
self.webapp.router.add_post(
'/snapshots/{snapshot}/restore/full', api_snapshots.restore_full)
self.webapp.router.add_post(
'/snapshots/{snapshot}/restore/partial',
api_snapshots.restore_partial)
self.webapp.router.add_get(
'/snapshots/{snapshot}/download',
api_snapshots.download)
def _register_services(self): def _register_services(self):
api_services = APIServices() api_services = APIServices()
api_services.coresys = self.coresys api_services.coresys = self.coresys
self.webapp.router.add_get('/services', api_services.list) self.webapp.add_routes([
web.get('/services', api_services.list),
self.webapp.router.add_get( web.get('/services/{service}', api_services.get_service),
'/services/{service}', api_services.get_service) web.post('/services/{service}', api_services.set_service),
self.webapp.router.add_post( web.delete('/services/{service}', api_services.del_service),
'/services/{service}', api_services.set_service) ])
self.webapp.router.add_delete(
'/services/{service}', api_services.del_service)
def _register_discovery(self): def _register_discovery(self):
api_discovery = APIDiscovery() api_discovery = APIDiscovery()
api_discovery.coresys = self.coresys api_discovery.coresys = self.coresys
self.webapp.router.add_get( self.webapp.add_routes([
'/services/discovery', api_discovery.list) web.get('/services/discovery', api_discovery.list),
self.webapp.router.add_get( web.get('/services/discovery/{uuid}', api_discovery.get_discovery),
'/services/discovery/{uuid}', api_discovery.get_discovery) web.delete('/services/discovery/{uuid}',
self.webapp.router.add_delete( api_discovery.del_discovery),
'/services/discovery/{uuid}', api_discovery.del_discovery) web.post('/services/discovery', api_discovery.set_discovery),
self.webapp.router.add_post( ])
'/services/discovery', api_discovery.set_discovery)
def _register_panel(self): def _register_panel(self):
"""Register panel for homeassistant.""" """Register panel for homeassistant."""
def create_panel_response(build_type): def create_response(build_type):
"""Create a function to generate a response.""" """Create a function to generate a response."""
path = Path(__file__).parent.joinpath( path = Path(__file__).parent.joinpath(
f"panel/{build_type}.html") f"panel/{build_type}.html")
return lambda request: web.FileResponse(path) return lambda request: web.FileResponse(path)
# This route is for backwards compatibility with HA < 0.58 # This route is for backwards compatibility with HA < 0.58
self.webapp.router.add_get( self.webapp.add_routes([
'/panel', create_panel_response('hassio-main-es5')) web.get('/panel', create_response('hassio-main-es5'))])
# This route is for backwards compatibility with HA 0.58 - 0.61 # This route is for backwards compatibility with HA 0.58 - 0.61
self.webapp.router.add_get( self.webapp.add_routes([
'/panel_es5', create_panel_response('hassio-main-es5')) web.get('/panel_es5', create_response('hassio-main-es5')),
self.webapp.router.add_get( web.get('/panel_latest', create_response('hassio-main-latest')),
'/panel_latest', create_panel_response('hassio-main-latest')) ])
# This route is for HA > 0.61 # This route is for HA > 0.61
self.webapp.router.add_get( self.webapp.add_routes([
'/app-es5/index.html', create_panel_response('index')) web.get('/app-es5/index.html', create_response('index')),
self.webapp.router.add_get( web.get('/app-es5/hassio-app.html', create_response('hassio-app')),
'/app-es5/hassio-app.html', create_panel_response('hassio-app')) ])
async def start(self): async def start(self):
"""Run rest api webserver.""" """Run rest api webserver."""

View File

@ -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_DISCOVERY, ATTR_SECCOMP, ATTR_APPARMOR,
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 from ..validate import DOCKER_PORTS
@ -123,6 +123,8 @@ class APIAddons(CoreSysAttributes):
ATTR_HOST_IPC: addon.host_ipc, ATTR_HOST_IPC: addon.host_ipc,
ATTR_HOST_DBUS: addon.host_dbus, ATTR_HOST_DBUS: addon.host_dbus,
ATTR_PRIVILEGED: addon.privileged, ATTR_PRIVILEGED: addon.privileged,
ATTR_SECCOMP: addon.seccomp,
ATTR_APPARMOR: addon.apparmor,
ATTR_DEVICES: self._pretty_devices(addon), ATTR_DEVICES: self._pretty_devices(addon),
ATTR_ICON: addon.with_icon, ATTR_ICON: addon.with_icon,
ATTR_LOGO: addon.with_logo, ATTR_LOGO: addon.with_logo,

View File

@ -2,7 +2,7 @@
from pathlib import Path from pathlib import Path
from ipaddress import ip_network from ipaddress import ip_network
HASSIO_VERSION = '0.99' HASSIO_VERSION = '1.0'
URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/' URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/'
'hassio/{}/version.json') 'hassio/{}/version.json')
@ -159,6 +159,8 @@ ATTR_DISCOVERY = 'discovery'
ATTR_PROTECTED = 'protected' ATTR_PROTECTED = 'protected'
ATTR_CRYPTO = 'crypto' ATTR_CRYPTO = 'crypto'
ATTR_BRANCH = 'branch' ATTR_BRANCH = 'branch'
ATTR_SECCOMP = 'seccomp'
ATTR_APPARMOR = 'apparmor'
SERVICE_MQTT = 'mqtt' SERVICE_MQTT = 'mqtt'
@ -202,3 +204,7 @@ SNAPSHOT_FULL = 'full'
SNAPSHOT_PARTIAL = 'partial' SNAPSHOT_PARTIAL = 'partial'
CRYPTO_AES128 = 'aes128' CRYPTO_AES128 = 'aes128'
SECURITY_PROFILE = 'profile'
SECURITY_DEFAULT = 'default'
SECURITY_DISABLE = 'disable'

View File

@ -9,7 +9,7 @@ from .interface import DockerInterface
from ..addons.build import AddonBuild from ..addons.build import AddonBuild
from ..const import ( from ..const import (
MAP_CONFIG, MAP_SSL, MAP_ADDONS, MAP_BACKUP, MAP_SHARE, ENV_TOKEN, MAP_CONFIG, MAP_SSL, MAP_ADDONS, MAP_BACKUP, MAP_SHARE, ENV_TOKEN,
ENV_TIME) ENV_TIME, SECURITY_PROFILE, SECURITY_DISABLE)
from ..utils import process_lock from ..utils import process_lock
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -121,14 +121,21 @@ class DockerAddon(DockerInterface):
@property @property
def security_opt(self): def security_opt(self):
"""Controlling security opt.""" """Controlling security opt."""
privileged = self.addon.privileged or [] security = []
# Disable AppArmor sinse it make troubles wit SYS_ADMIN # AppArmor
if 'SYS_ADMIN' in privileged: if self.addon.apparmor == SECURITY_DISABLE:
return [ security.append("apparmor:unconfined")
"apparmor:unconfined", elif self.addon.apparmor == SECURITY_PROFILE:
] security.append(f"apparmor={self.addon.slug}")
return None
# Seccomp
if self.addon.seccomp == SECURITY_DISABLE:
security.append("seccomp=unconfined")
elif self.addon.seccomp == SECURITY_PROFILE:
security.append(f"seccomp={self.addon.path_seccomp}")
return security or None
@property @property
def tmpfs(self): def tmpfs(self):

View File

@ -264,31 +264,6 @@ class DockerInterface(CoreSysAttributes):
except docker.errors.DockerException as err: except docker.errors.DockerException as err:
_LOGGER.warning("Can't grap logs from %s: %s", self.image, err) _LOGGER.warning("Can't grap logs from %s: %s", self.image, err)
@process_lock
def restart(self):
"""Restart docker container."""
return self._loop.run_in_executor(None, self._restart)
def _restart(self):
"""Restart docker container.
Need run inside executor.
"""
try:
container = self._docker.containers.get(self.name)
except docker.errors.DockerException:
return False
_LOGGER.info("Restart %s", self.image)
try:
container.restart(timeout=self.timeout)
except docker.errors.DockerException as err:
_LOGGER.warning("Can't restart %s: %s", self.image, err)
return False
return True
@process_lock @process_lock
def cleanup(self): def cleanup(self):
"""Check if old version exists and cleanup.""" """Check if old version exists and cleanup."""

View File

@ -216,17 +216,19 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
async def _start(self): async def _start(self):
"""Start HomeAssistant docker & wait.""" """Start HomeAssistant docker & wait."""
if await self.instance.run():
await self._block_till_run()
@process_lock
async def start(self):
"""Run HomeAssistant docker."""
if not await self.instance.run(): if not await self.instance.run():
return False return False
return await self._block_till_run() return await self._block_till_run()
@process_lock
def start(self):
"""Run HomeAssistant docker.
Return a coroutine.
"""
return self._start()
@process_lock
def stop(self): def stop(self):
"""Stop HomeAssistant docker. """Stop HomeAssistant docker.
@ -237,10 +239,8 @@ class HomeAssistant(JsonConfig, CoreSysAttributes):
@process_lock @process_lock
async def restart(self): async def restart(self):
"""Restart HomeAssistant docker.""" """Restart HomeAssistant docker."""
if not await self.instance.restart(): await self.instance.stop()
return False return await self._start()
return await self._block_till_run()
def logs(self): def logs(self):
"""Get HomeAssistant docker logs. """Get HomeAssistant docker logs.

View File

@ -40,9 +40,9 @@ setup(
], ],
include_package_data=True, include_package_data=True,
install_requires=[ install_requires=[
'async_timeout==2.0.0', 'async_timeout==2.0.1',
'aiohttp==3.0.9', 'aiohttp==3.1.2',
'docker==3.1.1', 'docker==3.2.0',
'colorlog==3.1.2', 'colorlog==3.1.2',
'voluptuous==0.11.1', 'voluptuous==0.11.1',
'gitpython==2.1.8', 'gitpython==2.1.8',

View File

@ -1,5 +1,5 @@
{ {
"hassio": "0.99", "hassio": "1.0",
"homeassistant": "0.67.0b0", "homeassistant": "0.67.0b0",
"resinos": "1.3", "resinos": "1.3",
"resinhup": "0.3", "resinhup": "0.3",