diff --git a/.gitignore b/.gitignore index 74453f62e..d2ef118c0 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,4 @@ ENV/ .vscode/* !.vscode/cSpell.json !.vscode/tasks.json +!.vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..0e3f62e4f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Supervisor remote debug", + "type": "python", + "request": "attach", + "port": 33333, + "host": "172.30.32.2", + "pathMappings": [ + { + "localRoot": "${workspaceFolder}", + "remoteRoot": "/usr/src/supervisor" + } + ] + } + ] +} diff --git a/requirements.txt b/requirements.txt index 5371558a1..ad37cb910 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,8 +6,8 @@ colorlog==4.1.0 cpe==1.2.1 cryptography==2.9 docker==4.2.0 -gitpython==3.1.0 -jinja2==2.11.1 +gitpython==3.1.1 +jinja2==2.11.2 packaging==20.3 ptvsd==4.3.2 pulsectl==20.2.4 diff --git a/supervisor/const.py b/supervisor/const.py index ef7fca2d2..802f36ae8 100644 --- a/supervisor/const.py +++ b/supervisor/const.py @@ -3,7 +3,7 @@ from enum import Enum from ipaddress import ip_network from pathlib import Path -SUPERVISOR_VERSION = "217" +SUPERVISOR_VERSION = "218" URL_HASSIO_ADDONS = "https://github.com/home-assistant/hassio-addons" diff --git a/supervisor/core.py b/supervisor/core.py index a2f22cfd6..f891b7d5a 100644 --- a/supervisor/core.py +++ b/supervisor/core.py @@ -34,6 +34,9 @@ class Core(CoreSysAttributes): """Setup supervisor orchestration.""" self.state = CoreStates.STARTUP + # load last available data + await self.sys_updater.load() + # Load DBus await self.sys_dbus.load() @@ -61,9 +64,6 @@ class Core(CoreSysAttributes): # rest api views await self.sys_api.load() - # load last available data - await self.sys_updater.load() - # load last available data await self.sys_snapshots.load() diff --git a/supervisor/docker/interface.py b/supervisor/docker/interface.py index 8a6819d74..72c277262 100644 --- a/supervisor/docker/interface.py +++ b/supervisor/docker/interface.py @@ -444,7 +444,7 @@ class DockerInterface(CoreSysAttributes): _LOGGER.debug("No version found for %s", self.image) raise DockerAPIError() else: - _LOGGER.debug("Found HA versions: %s", available_version) + _LOGGER.debug("Found %s versions: %s", self.image, available_version) # Sort version and return latest version available_version.sort(key=key, reverse=True) diff --git a/supervisor/docker/supervisor.py b/supervisor/docker/supervisor.py index d7c9f5f04..d1f110c6e 100644 --- a/supervisor/docker/supervisor.py +++ b/supervisor/docker/supervisor.py @@ -77,3 +77,30 @@ class DockerSupervisor(DockerInterface, CoreSysAttributes): except docker.errors.DockerException as err: _LOGGER.error("Can't retag supervisor version: %s", err) raise DockerAPIError() from None + + def update_start_tag(self, image: str, version: str) -> Awaitable[None]: + """Update start tag to new version.""" + return self.sys_run_in_executor(self._update_start_tag, image, version) + + def _update_start_tag(self, image: str, version: str) -> None: + """Update start tag to new version. + + Need run inside executor. + """ + try: + docker_container = self.sys_docker.containers.get(self.name) + docker_image = self.sys_docker.images.get(f"{image}:{version}") + + # Find start tag + for tag in docker_container.image.tags: + start_image = tag.partition(":")[0] + start_tag = tag.partition(":")[2] or "latest" + + # If version tag + if start_tag != "latest": + continue + docker_image.tag(start_image, start_tag) + + except docker.errors.DockerException as err: + _LOGGER.error("Can't fix start tag: %s", err) + raise DockerAPIError() from None diff --git a/supervisor/supervisor.py b/supervisor/supervisor.py index 02a9667ac..ced606e5c 100644 --- a/supervisor/supervisor.py +++ b/supervisor/supervisor.py @@ -116,7 +116,10 @@ class Supervisor(CoreSysAttributes): _LOGGER.info("Update Supervisor to version %s", version) try: await self.instance.install( - version, image=self.sys_updater.image_supervisor, latest=True + version, image=self.sys_updater.image_supervisor + ) + await self.instance.update_start_tag( + self.sys_updater.image_supervisor, version ) except DockerAPIError: _LOGGER.error("Update of Supervisor fails!") diff --git a/supervisor/updater.py b/supervisor/updater.py index 81f8aa109..0904dc164 100644 --- a/supervisor/updater.py +++ b/supervisor/updater.py @@ -87,55 +87,49 @@ class Updater(JsonConfig, CoreSysAttributes): @property def image_homeassistant(self) -> Optional[str]: """Return latest version of Home Assistant.""" - return ( - self._data[ATTR_IMAGE] - .get(ATTR_HOMEASSISTANT, "") - .format(machine=self.sys_machine) + if ATTR_HOMEASSISTANT not in self._data[ATTR_IMAGE]: + return None + return self._data[ATTR_IMAGE][ATTR_HOMEASSISTANT].format( + machine=self.sys_machine ) @property def image_supervisor(self) -> Optional[str]: """Return latest version of Supervisor.""" - return ( - self._data[ATTR_IMAGE] - .get(ATTR_SUPERVISOR, "") - .format(arch=self.sys_arch.supervisor) + if ATTR_SUPERVISOR not in self._data[ATTR_IMAGE]: + return None + return self._data[ATTR_IMAGE][ATTR_SUPERVISOR].format( + arch=self.sys_arch.supervisor ) @property def image_cli(self) -> Optional[str]: """Return latest version of CLI.""" - return ( - self._data[ATTR_IMAGE] - .get(ATTR_CLI, "") - .format(arch=self.sys_arch.supervisor) - ) + if ATTR_CLI not in self._data[ATTR_IMAGE]: + return None + return self._data[ATTR_IMAGE][ATTR_CLI].format(arch=self.sys_arch.supervisor) @property def image_dns(self) -> Optional[str]: """Return latest version of DNS.""" - return ( - self._data[ATTR_IMAGE] - .get(ATTR_DNS, "") - .format(arch=self.sys_arch.supervisor) - ) + if ATTR_DNS not in self._data[ATTR_IMAGE]: + return None + return self._data[ATTR_IMAGE][ATTR_DNS].format(arch=self.sys_arch.supervisor) @property def image_audio(self) -> Optional[str]: """Return latest version of Audio.""" - return ( - self._data[ATTR_IMAGE] - .get(ATTR_AUDIO, "") - .format(arch=self.sys_arch.supervisor) - ) + if ATTR_AUDIO not in self._data[ATTR_IMAGE]: + return None + return self._data[ATTR_IMAGE][ATTR_AUDIO].format(arch=self.sys_arch.supervisor) @property def image_multicast(self) -> Optional[str]: """Return latest version of Multicast.""" - return ( - self._data[ATTR_IMAGE] - .get(ATTR_MULTICAST, "") - .format(arch=self.sys_arch.supervisor) + if ATTR_MULTICAST not in self._data[ATTR_IMAGE]: + return None + return self._data[ATTR_IMAGE][ATTR_MULTICAST].format( + arch=self.sys_arch.supervisor ) @property