Set image default tag on pull

Signed-off-by: aiordache <anca.iordache@docker.com>
This commit is contained in:
aiordache 2020-09-15 18:42:19 +02:00
parent ed46fb0143
commit cec152db5f
7 changed files with 45 additions and 23 deletions

View File

@ -343,7 +343,7 @@ class ImageApiMixin(object):
return self._result(self._post(url, params=params), True) return self._result(self._post(url, params=params), True)
def pull(self, repository, tag=None, stream=False, auth_config=None, def pull(self, repository, tag=None, stream=False, auth_config=None,
decode=False, platform=None): decode=False, platform=None, all_tags=False):
""" """
Pulls an image. Similar to the ``docker pull`` command. Pulls an image. Similar to the ``docker pull`` command.
@ -358,6 +358,7 @@ class ImageApiMixin(object):
decode (bool): Decode the JSON data from the server into dicts. decode (bool): Decode the JSON data from the server into dicts.
Only applies with ``stream=True`` Only applies with ``stream=True``
platform (str): Platform in the format ``os[/arch[/variant]]`` platform (str): Platform in the format ``os[/arch[/variant]]``
all_tags (bool): Pull all image tags.
Returns: Returns:
(generator or str): The output (generator or str): The output
@ -382,8 +383,12 @@ class ImageApiMixin(object):
} }
""" """
if not tag: repository, image_tag = utils.parse_repository_tag(repository)
repository, tag = utils.parse_repository_tag(repository) tag = tag or image_tag or 'latest'
if all_tags:
tag = None
registry, repo_name = auth.resolve_repository_name(repository) registry, repo_name = auth.resolve_repository_name(repository)
params = { params = {

View File

@ -395,12 +395,12 @@ class ImageCollection(Collection):
return [self.get(i) for i in images] return [self.get(i) for i in images]
def pull(self, repository, tag=None, **kwargs): def pull(self, repository, tag=None, all_tags=False, **kwargs):
""" """
Pull an image of the given name and return it. Similar to the Pull an image of the given name and return it. Similar to the
``docker pull`` command. ``docker pull`` command.
If no tag is specified, all tags from that repository will be If ``all_tags`` is set, the ``tag`` parameter is ignored and all image
pulled. tags will be pulled.
If you want to get the raw pull output, use the If you want to get the raw pull output, use the
:py:meth:`~docker.api.image.ImageApiMixin.pull` method in the :py:meth:`~docker.api.image.ImageApiMixin.pull` method in the
@ -413,10 +413,11 @@ class ImageCollection(Collection):
config for this request. ``auth_config`` should contain the config for this request. ``auth_config`` should contain the
``username`` and ``password`` keys to be valid. ``username`` and ``password`` keys to be valid.
platform (str): Platform in the format ``os[/arch[/variant]]`` platform (str): Platform in the format ``os[/arch[/variant]]``
all_tags (bool): Pull all image tags
Returns: Returns:
(:py:class:`Image` or list): The image that has been pulled. (:py:class:`Image` or list): The image that has been pulled.
If no ``tag`` was specified, the method will return a list If ``tag`` is None, the method will return a list
of :py:class:`Image` objects belonging to this repository. of :py:class:`Image` objects belonging to this repository.
Raises: Raises:
@ -426,13 +427,13 @@ class ImageCollection(Collection):
Example: Example:
>>> # Pull the image tagged `latest` in the busybox repo >>> # Pull the image tagged `latest` in the busybox repo
>>> image = client.images.pull('busybox:latest') >>> image = client.images.pull('busybox')
>>> # Pull all tags in the busybox repo >>> # Pull all tags in the busybox repo
>>> images = client.images.pull('busybox') >>> images = client.images.pull('busybox', all_tags=True)
""" """
if not tag: repository, image_tag = parse_repository_tag(repository)
repository, tag = parse_repository_tag(repository) tag = tag or image_tag or 'latest'
if 'stream' in kwargs: if 'stream' in kwargs:
warnings.warn( warnings.warn(
@ -442,14 +443,14 @@ class ImageCollection(Collection):
del kwargs['stream'] del kwargs['stream']
pull_log = self.client.api.pull( pull_log = self.client.api.pull(
repository, tag=tag, stream=True, **kwargs repository, tag=tag, stream=True, all_tags=all_tags, **kwargs
) )
for _ in pull_log: for _ in pull_log:
# We don't do anything with the logs, but we need # We don't do anything with the logs, but we need
# to keep the connection alive and wait for the image # to keep the connection alive and wait for the image
# to be pulled. # to be pulled.
pass pass
if tag: if not all_tags:
return self.get('{0}{2}{1}'.format( return self.get('{0}{2}{1}'.format(
repository, tag, '@' if tag.startswith('sha256:') else ':' repository, tag, '@' if tag.startswith('sha256:') else ':'
)) ))

View File

@ -42,7 +42,7 @@ class PullImageTest(BaseAPIIntegrationTest):
self.client.remove_image('hello-world') self.client.remove_image('hello-world')
except docker.errors.APIError: except docker.errors.APIError:
pass pass
res = self.client.pull('hello-world', tag='latest') res = self.client.pull('hello-world')
self.tmp_imgs.append('hello-world') self.tmp_imgs.append('hello-world')
assert type(res) == six.text_type assert type(res) == six.text_type
assert len(self.client.images('hello-world')) >= 1 assert len(self.client.images('hello-world')) >= 1
@ -55,7 +55,7 @@ class PullImageTest(BaseAPIIntegrationTest):
except docker.errors.APIError: except docker.errors.APIError:
pass pass
stream = self.client.pull( stream = self.client.pull(
'hello-world', tag='latest', stream=True, decode=True) 'hello-world', stream=True, decode=True)
self.tmp_imgs.append('hello-world') self.tmp_imgs.append('hello-world')
for chunk in stream: for chunk in stream:
assert isinstance(chunk, dict) assert isinstance(chunk, dict)

View File

@ -86,7 +86,7 @@ class ImageCollectionTest(BaseIntegrationTest):
def test_pull_multiple(self): def test_pull_multiple(self):
client = docker.from_env(version=TEST_API_VERSION) client = docker.from_env(version=TEST_API_VERSION)
images = client.images.pull('hello-world') images = client.images.pull('hello-world', all_tags=True)
assert len(images) >= 1 assert len(images) >= 1
assert any([ assert any([
'hello-world:latest' in img.attrs['RepoTags'] for img in images 'hello-world:latest' in img.attrs['RepoTags'] for img in images

View File

@ -67,7 +67,7 @@ class ImageTest(BaseAPIClientTest):
args = fake_request.call_args args = fake_request.call_args
assert args[0][1] == url_prefix + 'images/create' assert args[0][1] == url_prefix + 'images/create'
assert args[1]['params'] == { assert args[1]['params'] == {
'tag': None, 'fromImage': 'joffrey/test001' 'tag': 'latest', 'fromImage': 'joffrey/test001'
} }
assert not args[1]['stream'] assert not args[1]['stream']
@ -77,7 +77,7 @@ class ImageTest(BaseAPIClientTest):
args = fake_request.call_args args = fake_request.call_args
assert args[0][1] == url_prefix + 'images/create' assert args[0][1] == url_prefix + 'images/create'
assert args[1]['params'] == { assert args[1]['params'] == {
'tag': None, 'fromImage': 'joffrey/test001' 'tag': 'latest', 'fromImage': 'joffrey/test001'
} }
assert args[1]['stream'] assert args[1]['stream']

View File

@ -233,7 +233,7 @@ class ContainerCollectionTest(unittest.TestCase):
assert container.id == FAKE_CONTAINER_ID assert container.id == FAKE_CONTAINER_ID
client.api.pull.assert_called_with( client.api.pull.assert_called_with(
'alpine', platform=None, tag=None, stream=True 'alpine', platform=None, tag='latest', all_tags=False, stream=True
) )
def test_run_with_error(self): def test_run_with_error(self):

View File

@ -44,9 +44,25 @@ class ImageCollectionTest(unittest.TestCase):
def test_pull(self): def test_pull(self):
client = make_fake_client() client = make_fake_client()
image = client.images.pull('test_image:latest') image = client.images.pull('test_image:test')
client.api.pull.assert_called_with( client.api.pull.assert_called_with(
'test_image', tag='latest', stream=True 'test_image', tag='test', all_tags=False, stream=True
)
client.api.inspect_image.assert_called_with('test_image:test')
assert isinstance(image, Image)
assert image.id == FAKE_IMAGE_ID
def test_pull_tag_precedence(self):
client = make_fake_client()
image = client.images.pull('test_image:latest', tag='test')
client.api.pull.assert_called_with(
'test_image', tag='test', all_tags=False, stream=True
)
client.api.inspect_image.assert_called_with('test_image:test')
image = client.images.pull('test_image')
client.api.pull.assert_called_with(
'test_image', tag='latest', all_tags=False, stream=True
) )
client.api.inspect_image.assert_called_with('test_image:latest') client.api.inspect_image.assert_called_with('test_image:latest')
assert isinstance(image, Image) assert isinstance(image, Image)
@ -54,9 +70,9 @@ class ImageCollectionTest(unittest.TestCase):
def test_pull_multiple(self): def test_pull_multiple(self):
client = make_fake_client() client = make_fake_client()
images = client.images.pull('test_image') images = client.images.pull('test_image', all_tags=True)
client.api.pull.assert_called_with( client.api.pull.assert_called_with(
'test_image', tag=None, stream=True 'test_image', tag='latest', all_tags=True, stream=True
) )
client.api.images.assert_called_with( client.api.images.assert_called_with(
all=False, name='test_image', filters=None all=False, name='test_image', filters=None