diff --git a/docker/models/images.py b/docker/models/images.py index 757a5a47..53bf24c5 100644 --- a/docker/models/images.py +++ b/docker/models/images.py @@ -6,7 +6,7 @@ import six from ..api import APIClient from ..constants import DEFAULT_DATA_CHUNK_SIZE -from ..errors import BuildError, ImageLoadError, InvalidArgument +from ..errors import BuildError, ImageLoadError, InvalidArgument, NotFound from ..utils import parse_repository_tag from ..utils.json_stream import json_stream from .resource import Collection, Model @@ -339,7 +339,7 @@ class ImageCollection(Collection): collection=self, ) - def list(self, name=None, all=False, filters=None): + def list(self, name=None, all=False, filters=None, ignore_removed=False): """ List images on the server. @@ -352,6 +352,10 @@ class ImageCollection(Collection): - ``dangling`` (bool) - `label` (str|list): format either ``"key"``, ``"key=value"`` or a list of such. + ignore_removed (bool): Ignore failures due to missing images + when attempting to inspect images from the original list. + Set to ``True`` if race conditions are likely. + Default: ``False`` Returns: (list of :py:class:`Image`): The images. @@ -361,7 +365,15 @@ class ImageCollection(Collection): If the server returns an error. """ resp = self.client.api.images(name=name, all=all, filters=filters) - return [self.get(r["Id"]) for r in resp] + images = [] + for r in resp: + try: + images.append(self.get(r['Id'])) + # a image may have been removed while iterating + except NotFound: + if not ignore_removed: + raise + return images def load(self, data): """ diff --git a/tests/unit/models_images_test.py b/tests/unit/models_images_test.py index fd894ab7..c7cb531d 100644 --- a/tests/unit/models_images_test.py +++ b/tests/unit/models_images_test.py @@ -1,9 +1,12 @@ import unittest import warnings +import pytest +import docker from docker.constants import DEFAULT_DATA_CHUNK_SIZE from docker.models.images import Image + from .fake_api import FAKE_IMAGE_ID from .fake_api_client import make_fake_client @@ -37,6 +40,18 @@ class ImageCollectionTest(unittest.TestCase): assert isinstance(images[0], Image) assert images[0].id == FAKE_IMAGE_ID + def test_list_ignore_removed(self): + def side_effect(*args, **kwargs): + raise docker.errors.NotFound('Image not found') + client = make_fake_client({ + 'inspect_image.side_effect': side_effect + }) + + with pytest.raises(docker.errors.NotFound): + client.images.list(all=True, ignore_removed=False) + + assert client.images.list(all=True, ignore_removed=True) == [] + def test_load(self): client = make_fake_client() client.images.load('byte stream')