From df66102de004594dbaab4c5137b5df8280c32e3e Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 17 Sep 2017 14:42:35 +0200 Subject: [PATCH 1/8] Pump version to 0.64 --- hassio/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hassio/const.py b/hassio/const.py index ebf8eab7e..c53cfdbb3 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -2,7 +2,7 @@ from pathlib import Path from ipaddress import ip_network -HASSIO_VERSION = '0.63' +HASSIO_VERSION = '0.64' URL_HASSIO_VERSION = ('https://raw.githubusercontent.com/home-assistant/' 'hassio/{}/version.json') From b7820bc6a6f2e4b7911ffd5c020c3926a91b86f3 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 18 Sep 2017 22:05:11 +0200 Subject: [PATCH 2/8] Update resinos to 1.1 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 229b6a0bd..0781692d9 100644 --- a/version.json +++ b/version.json @@ -1,7 +1,7 @@ { "hassio": "0.63", "homeassistant": "0.53.1", - "resinos": "1.0", + "resinos": "1.1", "resinhup": "0.3", "generic": "0.3", "cluster": "0.1" From 1353d52bd1f4865033421d95a704661347df3449 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 19 Sep 2017 17:51:16 +0200 Subject: [PATCH 3/8] Reset json file to default on schema error (#193) --- hassio/tools.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hassio/tools.py b/hassio/tools.py index 53a06eb2a..0cd34e0e3 100644 --- a/hassio/tools.py +++ b/hassio/tools.py @@ -123,6 +123,8 @@ class JsonConfig(object): except vol.Invalid as ex: _LOGGER.error("Can't parse %s -> %s", self._file, humanize_error(self._data, ex)) + # reset data to default + self._data = self._schema({}) def save(self): """Store data to config file.""" From 3c04c714014444e62e85a667d74f4a7cdd265611 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 19 Sep 2017 18:06:34 +0200 Subject: [PATCH 4/8] Update build system to origin docker (#191) * Update build system to origin docker * Rename build env * fix lint p1 * fix bug & add more log info for snapshot/restore * fix exception * Log build info * revert last change * fix regex --- hassio/addons/addon.py | 4 +++ hassio/addons/build.py | 60 +++++++++++++++++++++++++++++++++++++++ hassio/addons/validate.py | 24 ++++++++++++++-- hassio/const.py | 3 ++ hassio/dock/addon.py | 55 +++++++++-------------------------- hassio/dock/util.py | 40 -------------------------- 6 files changed, 103 insertions(+), 83 deletions(-) create mode 100644 hassio/addons/build.py diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index 31f160cf9..ece50d989 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -566,11 +566,13 @@ class Addon(object): snapshot.add(self.path_data, arcname="data") try: + _LOGGER.info("Build snapshot for addon %s", self._id) await self.loop.run_in_executor(None, _create_tar) except tarfile.TarError as err: _LOGGER.error("Can't write tarfile %s -> %s", tar_file, err) return False + _LOGGER.info("Finish snapshot for addon %s", self._id) return True async def restore(self, tar_file): @@ -625,6 +627,7 @@ class Addon(object): shutil.copytree(str(Path(temp, "data")), str(self.path_data)) try: + _LOGGER.info("Restore data for addon %s", self._id) await self.loop.run_in_executor(None, _restore_data) except shutil.Error as err: _LOGGER.error("Can't restore origin data -> %s", err) @@ -634,4 +637,5 @@ class Addon(object): if data[ATTR_STATE] == STATE_STARTED: return await self.start() + _LOGGER.info("Finish restore for addon %s", self._id) return True diff --git a/hassio/addons/build.py b/hassio/addons/build.py new file mode 100644 index 000000000..c3231de74 --- /dev/null +++ b/hassio/addons/build.py @@ -0,0 +1,60 @@ +"""HassIO addons build environment.""" +from pathlib import Path + +from .validate import SCHEMA_BUILD_CONFIG +from ..const import ATTR_SQUASH, ATTR_BUILD_FROM, ATTR_ARGS, META_ADDON +from ..tools import JsonConfig + + +class AddonBuild(JsonConfig): + """Handle build options for addons.""" + + def __init__(self, config, addon): + """Initialize addon builder.""" + self.config = config + self.addon = addon + + super().__init__( + Path(addon.path_location, 'build.json'), SCHEMA_BUILD_CONFIG) + + def save(self): + """Ignore save function.""" + pass + + @property + def base_image(self): + """Base images for this addon.""" + return self._data[ATTR_BUILD_FROM][self.config.arch] + + @property + def squash(self): + """Return True or False if squash is active.""" + return self._data[ATTR_SQUASH] + + @property + def additional_args(self): + """Return additional docker build arguments.""" + return self._data[ATTR_ARGS] + + def get_docker_args(self, version): + """Create a dict with docker build arguments.""" + build_tag = "{}:{}".format(self.addon.image, version) + + return { + 'path': str(self.addon.path_location), + 'tag': build_tag, + 'pull': True, + 'forcerm': True, + 'squash': self.squash, + 'labels': { + 'io.hass.version': version, + 'io.hass.arch': self.config.arch, + 'io.hass.type': META_ADDON, + }, + 'buildargs': { + 'BUILD_FROM': self.base_image, + 'BUILD_VERSION': version, + 'BUILD_ARCH': self.config.arch, + **self.additional_args, + } + } diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index 86b61077b..62a5761ee 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -13,7 +13,8 @@ from ..const import ( ATTR_USER, ATTR_STATE, ATTR_SYSTEM, STATE_STARTED, STATE_STOPPED, ATTR_LOCATON, ATTR_REPOSITORY, ATTR_TIMEOUT, ATTR_NETWORK, ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, - ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API) + ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH, + ATTR_ARGS) from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL @@ -54,6 +55,13 @@ PRIVILEGED_ALL = [ "SYS_RAWIO" ] +BASE_IMAGE = { + ARCH_ARMHF: "homeassistant/armhf-base:latest", + ARCH_AARCH64: "homeassistant/aarch64-base:latest", + ARCH_I386: "homeassistant/i386-base:latest", + ARCH_AMD64: "homeassistant/amd64-base:latest", +} + def _simple_startup(value): """Simple startup schema.""" @@ -94,7 +102,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Any(SCHEMA_ELEMENT, {vol.Coerce(str): SCHEMA_ELEMENT}) ], vol.Schema({vol.Coerce(str): SCHEMA_ELEMENT})) }), False), - vol.Optional(ATTR_IMAGE): vol.Match(r"\w*/\w*"), + vol.Optional(ATTR_IMAGE): vol.Match(r"^[\-\w]*/[\-\w]*$"), vol.Optional(ATTR_TIMEOUT, default=10): vol.All(vol.Coerce(int), vol.Range(min=10, max=120)) }, extra=vol.ALLOW_EXTRA) @@ -108,6 +116,18 @@ SCHEMA_REPOSITORY_CONFIG = vol.Schema({ }, extra=vol.ALLOW_EXTRA) +# pylint: disable=no-value-for-parameter +SCHEMA_BUILD_CONFIG = vol.Schema({ + vol.Optional(ATTR_BUILD_FROM, default=BASE_IMAGE): vol.Schema({ + vol.In(ARCH_ALL): vol.Match(r"^[\-\w]*/[\-\w]*:[\-\w]*$"), + }), + vol.Optional(ATTR_SQUASH, default=False): vol.Boolean(), + vol.Optional(ATTR_ARGS, default={}): vol.Schema({ + vol.Coerce(str): vol.Coerce(str) + }), +}) + + # pylint: disable=no-value-for-parameter SCHEMA_ADDON_USER = vol.Schema({ vol.Required(ATTR_VERSION): vol.Coerce(str), diff --git a/hassio/const.py b/hassio/const.py index c53cfdbb3..cacc92832 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -55,6 +55,7 @@ ATTR_DATE = 'date' ATTR_ARCH = 'arch' ATTR_HOSTNAME = 'hostname' ATTR_TIMEZONE = 'timezone' +ATTR_ARGS = 'args' ATTR_OS = 'os' ATTR_TYPE = 'type' ATTR_SOURCE = 'source' @@ -117,6 +118,8 @@ ATTR_OUTPUT = 'output' ATTR_DISK = 'disk' ATTR_SERIAL = 'serial' ATTR_SECURITY = 'security' +ATTR_BUILD_FROM = 'build_from' +ATTR_SQUASH = 'squash' ATTR_ADDONS_CUSTOM_LIST = 'addons_custom_list' STARTUP_INITIALIZE = 'initialize' diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 3d8a9e341..938f3a673 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -1,15 +1,14 @@ """Init file for HassIO addon docker object.""" import logging -from pathlib import Path -import shutil import docker import requests from .interface import DockerInterface -from .util import dockerfile_template, docker_process +from .util import docker_process +from ..addons.build import AddonBuild from ..const import ( - META_ADDON, MAP_CONFIG, MAP_SSL, MAP_ADDONS, MAP_BACKUP, MAP_SHARE) + MAP_CONFIG, MAP_SSL, MAP_ADDONS, MAP_BACKUP, MAP_SHARE) _LOGGER = logging.getLogger(__name__) @@ -191,47 +190,21 @@ class DockerAddon(DockerInterface): Need run inside executor. """ - build_dir = Path(self.config.path_tmp, self.addon.slug) + build_env = AddonBuild(self.config, self.addon) + + _LOGGER.info("Start build %s:%s", self.image, tag) try: - # prepare temporary addon build folder - try: - source = self.addon.path_location - shutil.copytree(str(source), str(build_dir)) - except shutil.Error as err: - _LOGGER.error("Can't copy %s to temporary build folder -> %s", - source, err) - return False + image = self.docker.images.build(**build_env.get_docker_args(tag)) - # prepare Dockerfile - try: - dockerfile_template( - Path(build_dir, 'Dockerfile'), self.config.arch, - tag, META_ADDON) - except OSError as err: - _LOGGER.error("Can't prepare dockerfile -> %s", err) + image.tag(self.image, tag='latest') + self.process_metadata(image.attrs, force=True) - # run docker build - try: - build_tag = "{}:{}".format(self.image, tag) + except (docker.errors.DockerException) as err: + _LOGGER.error("Can't build %s:%s -> %s", self.image, tag, err) + return False - _LOGGER.info("Start build %s on %s", build_tag, build_dir) - image = self.docker.images.build( - path=str(build_dir), tag=build_tag, pull=True, - forcerm=True - ) - - image.tag(self.image, tag='latest') - self.process_metadata(image.attrs, force=True) - - except (docker.errors.DockerException, TypeError) as err: - _LOGGER.error("Can't build %s -> %s", build_tag, err) - return False - - _LOGGER.info("Build %s done", build_tag) - return True - - finally: - shutil.rmtree(str(build_dir), ignore_errors=True) + _LOGGER.info("Build %s:%s done", self.image, tag) + return True @docker_process def export_image(self, path): diff --git a/hassio/dock/util.py b/hassio/dock/util.py index 1f7ccf48f..d63c6cea5 100644 --- a/hassio/dock/util.py +++ b/hassio/dock/util.py @@ -1,48 +1,8 @@ """HassIO docker utilitys.""" import logging -import re - -from ..const import ARCH_AARCH64, ARCH_ARMHF, ARCH_I386, ARCH_AMD64 _LOGGER = logging.getLogger(__name__) -HASSIO_BASE_IMAGE = { - ARCH_ARMHF: "homeassistant/armhf-base:latest", - ARCH_AARCH64: "homeassistant/aarch64-base:latest", - ARCH_I386: "homeassistant/i386-base:latest", - ARCH_AMD64: "homeassistant/amd64-base:latest", -} - -TMPL_IMAGE = re.compile(r"%%BASE_IMAGE%%") - - -def dockerfile_template(dockerfile, arch, version, meta_type): - """Prepare a Hass.IO dockerfile.""" - buff = [] - hassio_image = HASSIO_BASE_IMAGE[arch] - custom_image = re.compile(r"^#{}:FROM".format(arch)) - - # read docker - with dockerfile.open('r') as dock_input: - for line in dock_input: - line = TMPL_IMAGE.sub(hassio_image, line) - line = custom_image.sub("FROM", line) - buff.append(line) - - # add metadata - buff.append(create_metadata(version, arch, meta_type)) - - # write docker - with dockerfile.open('w') as dock_output: - dock_output.writelines(buff) - - -def create_metadata(version, arch, meta_type): - """Generate docker label layer for hassio.""" - return ('LABEL io.hass.version="{}" ' - 'io.hass.arch="{}" ' - 'io.hass.type="{}"').format(version, arch, meta_type) - # pylint: disable=protected-access def docker_process(method): From a7e65613d6be112668178346a8f8f1788ac926eb Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 19 Sep 2017 20:43:44 +0200 Subject: [PATCH 5/8] Update validate.py (#196) --- hassio/addons/validate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index 62a5761ee..018d1f904 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -102,7 +102,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Any(SCHEMA_ELEMENT, {vol.Coerce(str): SCHEMA_ELEMENT}) ], vol.Schema({vol.Coerce(str): SCHEMA_ELEMENT})) }), False), - vol.Optional(ATTR_IMAGE): vol.Match(r"^[\-\w]*/[\-\w]*$"), + vol.Optional(ATTR_IMAGE): vol.Match(r"^[\-\w{}]+/[\-\w{}]+$"), vol.Optional(ATTR_TIMEOUT, default=10): vol.All(vol.Coerce(int), vol.Range(min=10, max=120)) }, extra=vol.ALLOW_EXTRA) @@ -119,7 +119,7 @@ SCHEMA_REPOSITORY_CONFIG = vol.Schema({ # pylint: disable=no-value-for-parameter SCHEMA_BUILD_CONFIG = vol.Schema({ vol.Optional(ATTR_BUILD_FROM, default=BASE_IMAGE): vol.Schema({ - vol.In(ARCH_ALL): vol.Match(r"^[\-\w]*/[\-\w]*:[\-\w]*$"), + vol.In(ARCH_ALL): vol.Match(r"^[\-\w{}]+/[\-\w{}]+:[\-\w{}]+$"), }), vol.Optional(ATTR_SQUASH, default=False): vol.Boolean(), vol.Optional(ATTR_ARGS, default={}): vol.Schema({ From 8bb43daf91953f7b18f181be7e86d52fb692af9c Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 19 Sep 2017 21:52:18 +0200 Subject: [PATCH 6/8] Remove support for custom configs / configs for other hass.io versions (#197) * Remove support for custom configs * not need since supervisor is autoupdate --- hassio/addons/validate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index 018d1f904..56cf47b53 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -105,7 +105,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Optional(ATTR_IMAGE): vol.Match(r"^[\-\w{}]+/[\-\w{}]+$"), vol.Optional(ATTR_TIMEOUT, default=10): vol.All(vol.Coerce(int), vol.Range(min=10, max=120)) -}, extra=vol.ALLOW_EXTRA) +}) # pylint: disable=no-value-for-parameter @@ -113,7 +113,7 @@ SCHEMA_REPOSITORY_CONFIG = vol.Schema({ vol.Required(ATTR_NAME): vol.Coerce(str), vol.Optional(ATTR_URL): vol.Url(), vol.Optional(ATTR_MAINTAINER): vol.Coerce(str), -}, extra=vol.ALLOW_EXTRA) +}) # pylint: disable=no-value-for-parameter From 44b247f3978222583583600b6d139432b375573a Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 19 Sep 2017 22:06:48 +0200 Subject: [PATCH 7/8] Update hass.io to 0.64 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 0781692d9..369eeda93 100644 --- a/version.json +++ b/version.json @@ -1,5 +1,5 @@ { - "hassio": "0.63", + "hassio": "0.64", "homeassistant": "0.53.1", "resinos": "1.1", "resinhup": "0.3", From cb881cba282869817b87169346bed99eedb23f56 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sat, 23 Sep 2017 12:02:49 +0200 Subject: [PATCH 8/8] Update Home-Assistant to 0.54 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 369eeda93..4ac78d041 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "hassio": "0.64", - "homeassistant": "0.53.1", + "homeassistant": "0.54", "resinos": "1.1", "resinhup": "0.3", "generic": "0.3",