diff --git a/API.md b/API.md index 75db52f13..93e5c7233 100644 --- a/API.md +++ b/API.md @@ -78,10 +78,10 @@ Get all available addons "repositories": [ { "slug": "12345678", - "name": "Repitory Name", + "name": "Repitory Name|unknown", "source": "URL_OF_REPOSITORY", - "url": "null|WEBSITE", - "maintainer": "null|BLA BLU " + "url": "WEBSITE|REPOSITORY", + "maintainer": "BLA BLU |unknown" } ] } diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index 57eb1942a..1ef79e685 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -260,12 +260,13 @@ class Addon(object): async def install(self, version=None): """Install a addon.""" if self.config.arch not in self.supported_arch: - raise RuntimeError("Addon {} not supported on {}".format( - self._id, self.config.arch)) + _LOGGER.error( + "Addon %s not supported on %s", self._id, self.config.arch) + return False if self.is_installed: - raise RuntimeError( - "Addon {} is already installed".format(self._id)) + _LOGGER.error("Addon %s is already installed", self._id) + return False if not self.path_data.is_dir(): _LOGGER.info( @@ -282,7 +283,8 @@ class Addon(object): async def uninstall(self): """Remove a addon.""" if not self.is_installed: - raise RuntimeError("Addon {} is not installed".format(self._id)) + _LOGGER.error("Addon %s is not installed", self._id) + return False if not await self.addon_docker.remove(): return False @@ -307,29 +309,33 @@ class Addon(object): async def start(self): """Set options and start addon.""" if not self.is_installed: - raise RuntimeError("Addon {} is not installed".format(self._id)) + _LOGGER.error("Addon %s is not installed", self._id) + return False if not self.write_addon_options(): - raise RuntimeError( - "Can't write options for addon {}".format(self._id)) + return False return await self.addon_docker.run() async def stop(self): """Stop addon.""" if not self.is_installed: - raise RuntimeError("Addon {} is not installed".format(self._id)) + _LOGGER.error("Addon %s is not installed", self._id) + return False return await self.addon_docker.stop() async def update(self, version=None): """Update addon.""" if not self.is_installed: - raise RuntimeError("Addon {} is not installed".format(self._id)) + _LOGGER.error("Addon %s is not installed", self._id) + return False version = version or self.last_version if version == self.version_installed: - raise RuntimeError("Version is already in use") + _LOGGER.warning( + "Addon %s is already installed in %s", self._id, version) + return True if not await self.addon_docker.update(version): return False @@ -340,17 +346,18 @@ class Addon(object): async def restart(self): """Restart addon.""" if not self.is_installed: - raise RuntimeError("Addon {} is not installed".format(self._id)) + _LOGGER.error("Addon %s is not installed", self._id) + return False if not self.write_addon_options(): - raise RuntimeError( - "Can't write options for addon {}".format(self._id)) + return False return await self.addon_docker.restart() async def logs(self): """Return addons log output.""" if not self.is_installed: - raise RuntimeError("Addon {} is not installed".format(self._id)) + _LOGGER.error("Addon %s is not installed", self._id) + return False return await self.addon_docker.logs() diff --git a/hassio/addons/repository.py b/hassio/addons/repository.py index 71abf6edf..73859c987 100644 --- a/hassio/addons/repository.py +++ b/hassio/addons/repository.py @@ -4,6 +4,8 @@ from .util import get_hash_from_repository from ..const import ( REPOSITORY_CORE, REPOSITORY_LOCAL, ATTR_NAME, ATTR_URL, ATTR_MAINTAINER) +UNKNOWN = 'unknown' + class Repository(object): """Repository in HassIO.""" @@ -37,17 +39,17 @@ class Repository(object): @property def name(self): """Return name of repository.""" - return self._mesh.get(ATTR_NAME, self.source) + return self._mesh.get(ATTR_NAME, UNKNOWN) @property def url(self): """Return url of repository.""" - return self._mesh.get(ATTR_URL) + return self._mesh.get(ATTR_URL, self.source) @property def maintainer(self): """Return url of repository.""" - return self._mesh.get(ATTR_MAINTAINER) + return self._mesh.get(ATTR_MAINTAINER, UNKNOWN) async def load(self): """Load addon repository.""" diff --git a/hassio/api/addons.py b/hassio/api/addons.py index ed12b98da..504a5f85b 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -30,18 +30,21 @@ class APIAddons(object): self.loop = loop self.addons = addons - def _extract_addon(self, request): + def _extract_addon(self, request, check_installed=True): """Return addon and if not exists trow a exception.""" addon = self.addons.get(request.match_info.get('addon')) if not addon: raise RuntimeError("Addon not exists") + if check_installed and not addon.is_installed: + raise RuntimeError("Addon is not installed") + return addon @api_process async def info(self, request): """Return addon information.""" - addon = self._extract_addon(request) + addon = self._extract_addon(request, check_installed=False) return { ATTR_NAME: addon.name, @@ -62,9 +65,6 @@ class APIAddons(object): """Store user options for addon.""" addon = self._extract_addon(request) - if not addon.is_installed: - raise RuntimeError("Addon {} is not installed!".format(addon.slug)) - addon_schema = SCHEMA_OPTIONS.extend({ vol.Optional(ATTR_OPTIONS): addon.schema, }) @@ -79,7 +79,7 @@ class APIAddons(object): return True @api_process - async def install(self, request): + async def install(self, request, check_installed=False): """Install addon.""" body = await api_validate(SCHEMA_VERSION, request) addon = self._extract_addon(request) diff --git a/hassio/dock/__init__.py b/hassio/dock/__init__.py index 17731c004..ba8c8b2f5 100644 --- a/hassio/dock/__init__.py +++ b/hassio/dock/__init__.py @@ -189,13 +189,13 @@ class DockerBase(object): except docker.errors.DockerException: return - _LOGGER.info("Stop %s docker application", self.image) - if container.status == 'running': + _LOGGER.info("Stop %s docker application", self.image) with suppress(docker.errors.DockerException): container.stop(timeout=15) with suppress(docker.errors.DockerException): + _LOGGER.info("Clean %s docker application", self.image) container.remove(force=True) async def remove(self):