Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add named parameter to image.save to identify which repository name to use in the resulting tarball #2169

Merged
merged 1 commit into from Nov 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 18 additions & 2 deletions docker/models/images.py
Expand Up @@ -59,14 +59,20 @@ def history(self):
"""
return self.client.api.history(self.id)

def save(self, chunk_size=DEFAULT_DATA_CHUNK_SIZE):
def save(self, chunk_size=DEFAULT_DATA_CHUNK_SIZE, named=False):
"""
Get a tarball of an image. Similar to the ``docker save`` command.

Args:
chunk_size (int): The generator will return up to that much data
per iteration, but may return less. If ``None``, data will be
streamed as it is received. Default: 2 MB
named (str or bool): If ``False`` (default), the tarball will not
retain repository and tag information for this image. If set
to ``True``, the first tag in the :py:attr:`~tags` list will
be used to identify the image. Alternatively, any element of
the :py:attr:`~tags` list can be used as an argument to use
that specific tag as the saved identifier.

Returns:
(generator): A stream of raw archive data.
Expand All @@ -83,7 +89,17 @@ def save(self, chunk_size=DEFAULT_DATA_CHUNK_SIZE):
>>> f.write(chunk)
>>> f.close()
"""
return self.client.api.get_image(self.id, chunk_size)
img = self.id
if named:
img = self.tags[0] if self.tags else img
if isinstance(named, six.string_types):
if named not in self.tags:
raise InvalidArgument(
"{} is not a valid tag for this image".format(named)
)
img = named

return self.client.api.get_image(img, chunk_size)

def tag(self, repository, tag=None, **kwargs):
"""
Expand Down
27 changes: 27 additions & 0 deletions tests/integration/models_images_test.py
Expand Up @@ -5,6 +5,7 @@
import pytest

from .base import BaseIntegrationTest, BUSYBOX, TEST_API_VERSION
from ..helpers import random_name


class ImageCollectionTest(BaseIntegrationTest):
Expand Down Expand Up @@ -108,6 +109,32 @@ def test_save_and_load(self):
assert len(result) == 1
assert result[0].id == image.id

def test_save_and_load_repo_name(self):
client = docker.from_env(version=TEST_API_VERSION)
image = client.images.get(BUSYBOX)
additional_tag = random_name()
image.tag(additional_tag)
self.tmp_imgs.append(additional_tag)
image.reload()
with tempfile.TemporaryFile() as f:
stream = image.save(named='{}:latest'.format(additional_tag))
for chunk in stream:
f.write(chunk)

f.seek(0)
client.images.remove(additional_tag, force=True)
result = client.images.load(f.read())

assert len(result) == 1
assert result[0].id == image.id
assert '{}:latest'.format(additional_tag) in result[0].tags

def test_save_name_error(self):
client = docker.from_env(version=TEST_API_VERSION)
image = client.images.get(BUSYBOX)
with pytest.raises(docker.errors.InvalidArgument):
image.save(named='sakuya/izayoi')


class ImageTest(BaseIntegrationTest):

Expand Down