Skip to content

Commit e658d11

Browse files
committed
Check the image is outdated and pop warning to pull the latest
1 parent 33c7a26 commit e658d11

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed

aiidalab_launch/__main__.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@
2121
from .core import LOGGER
2222
from .instance import AiidaLabInstance
2323
from .profile import DEFAULT_IMAGE, DEFAULT_PORT, Profile
24-
from .util import confirm_with_value, get_latest_version, spinner, webbrowser_available
24+
from .util import (
25+
confirm_with_value,
26+
get_latest_version,
27+
image_is_latest,
28+
spinner,
29+
webbrowser_available,
30+
)
2531
from .version import __version__
2632

2733
MSG_MOUNT_POINT_CONFLICT = """Warning: There is at least one other running
@@ -350,6 +356,13 @@ async def _async_start(
350356
# use local image
351357
msg = f"Using local image '{profile.image}'."
352358

359+
# check if local image is outdated and pull latest version if so
360+
if not image_is_latest(instance.client, profile.image):
361+
click.secho(
362+
"Warning! Local image is outdated, please run with --pull to update.",
363+
fg="yellow",
364+
)
365+
353366
if instance.image is None:
354367
raise click.ClickException(
355368
f"Unable to find image '{profile.image}'. "

aiidalab_launch/util.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,26 @@ def get_docker_env(container: docker.models.containers.Container, env_name: str)
225225
except KeyError:
226226
pass
227227
raise KeyError(env_name)
228+
229+
230+
def image_is_latest(docker_client, image: str):
231+
"""Check if the local image has the same digest as the image
232+
on remote registry.
233+
"""
234+
try:
235+
local_image = docker_client.images.get(image)
236+
except docker.errors.ImageNotFound:
237+
return False
238+
239+
try:
240+
remote_image = docker_client.images.get_registry_data(image)
241+
except docker.errors.APIError:
242+
return False
243+
244+
# There is no need to check creation date of the image, since the once
245+
# there is a new image with the same tag, the id will be different.
246+
# We can not use image id, see https://windsock.io/explaining-docker-image-ids/
247+
local_digest = local_image.attrs.get("RepoDigests")[0].split("@")[-1]
248+
remote_digest = remote_image.attrs.get("Descriptor", {}).get("digest")
249+
250+
return local_digest == remote_digest

tests/test_util.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from time import time
22

3+
import pytest
34
from packaging.version import parse
45

5-
from aiidalab_launch.util import get_latest_version
6+
from aiidalab_launch.util import get_latest_version, image_is_latest
67

78

89
def test_get_latest_version(mock_pypi_request):
@@ -13,3 +14,14 @@ def test_get_latest_version_timeout(mock_pypi_request_timeout):
1314
start = time()
1415
assert get_latest_version() is None
1516
assert (time() - start) < 0.5
17+
18+
19+
@pytest.mark.usefixtures("enable_docker_pull")
20+
def test_image_is_latest(docker_client):
21+
"""Test that the latest version is identified correctly."""
22+
# download the alpine image for testing
23+
image_name = "alpine:latest"
24+
docker_client.images.pull(image_name)
25+
26+
# check that the image is identified as latest
27+
assert image_is_latest(docker_client, image_name)

0 commit comments

Comments
 (0)