|
19 | 19 | from extension.models import ExtensionSource |
20 | 20 | from harbor import ContainerManager, DockerCtx |
21 | 21 | from harbor.exceptions import ContainerNotFound |
| 22 | +from aiodocker.exceptions import DockerError |
22 | 23 | from manifest import ManifestManager |
23 | 24 | from manifest.models import ExtensionVersion |
24 | 25 | from settings import ExtensionSettings, SettingsV2 |
@@ -177,6 +178,16 @@ def _prepare_docker_auth(self) -> Optional[str]: |
177 | 178 | docker_auth = f"{self.source.auth.username}:{self.source.auth.password}" |
178 | 179 | return base64.b64encode(docker_auth.encode("utf-8")).decode("utf-8") |
179 | 180 |
|
| 181 | + async def _image_is_available_locally(self) -> bool: |
| 182 | + """Check if the Docker image is available locally.""" |
| 183 | + try: |
| 184 | + image_ref = f"{self.source.docker}:{self.tag}" + (f"@{self.digest}" if self.digest else "") |
| 185 | + async with DockerCtx() as client: |
| 186 | + await client.images.inspect(image_ref) |
| 187 | + return True |
| 188 | + except DockerError: |
| 189 | + return False |
| 190 | + |
180 | 191 | async def _pull_docker_image(self, docker_auth: Optional[str]) -> AsyncGenerator[bytes, None]: |
181 | 192 | """Pull Docker image and yield progress updates.""" |
182 | 193 | tag = f"{self.source.docker}:{self.tag}" + (f"@{self.digest}" if self.digest else "") |
@@ -214,12 +225,14 @@ async def install(self, clear_remaining_tags: bool = True, atomic: bool = False) |
214 | 225 | # In case of some external installs kraken shouldn't try to install it again so we remove from settings |
215 | 226 | if atomic: |
216 | 227 | should_raise = False |
217 | | - if not running_ext or self.unique_entry != running_ext.unique_entry: |
218 | | - should_raise = True |
219 | | - await self.uninstall() |
220 | | - |
221 | | - if running_ext: |
222 | | - await running_ext.enable() |
| 228 | + if await self._image_is_available_locally(): |
| 229 | + logger.info(f"Pull failed but image {self.identifier}:{self.tag} is already available locally") |
| 230 | + else: |
| 231 | + if not running_ext or self.unique_entry != running_ext.unique_entry: |
| 232 | + should_raise = True |
| 233 | + await self.uninstall() |
| 234 | + if running_ext: |
| 235 | + await running_ext.enable() |
223 | 236 |
|
224 | 237 | if should_raise: |
225 | 238 | raise ExtensionPullFailed(f"Failed to pull extension {self.identifier}:{self.tag}") from error |
|
0 commit comments