summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradw1n <adw1n@users.noreply.github.com>2018-09-03 05:54:12 +0200
committerJoffrey F <joffrey@docker.com>2018-11-28 11:27:04 -0800
commita74d546864b64ba03dce1e3407d3b0cd5badee9f (patch)
treef16e0972a72241f8e592fa5f230ebae0738b3637
parente1e4048753aafc96571752cf54d96df7b24156d3 (diff)
downloaddocker-py-a74d546864b64ba03dce1e3407d3b0cd5badee9f.tar.gz
Fix pulling images with `stream=True`
Pulling an image with option `stream=True` like this: ``` client.api.pull('docker.io/user/repo_name', tag='latest', stream=True) ``` without consuming the generator oftentimes results in premature drop of the connection. Docker daemon tries to send progress of pulling the image to the client, but it encounters an error (broken pipe) and therefore cancells the pull action: ``` Thread 1 "dockerd-dev" received signal SIGPIPE, Broken pipe. ERRO[2018-09-03T05:12:35.746497638+02:00] Not continuing with pull after error: context canceled ``` As described in issue #2116, even though client receives response with status code 200, image is not pulled. Closes #2116 Signed-off-by: Przemysław Adamek <adw1n@users.noreply.github.com>
-rw-r--r--docker/api/image.py3
-rw-r--r--docker/models/images.py1
-rw-r--r--tests/unit/models_containers_test.py3
-rw-r--r--tests/unit/models_images_test.py6
4 files changed, 9 insertions, 4 deletions
diff --git a/docker/api/image.py b/docker/api/image.py
index a9f801e..d3fed5c 100644
--- a/docker/api/image.py
+++ b/docker/api/image.py
@@ -334,7 +334,8 @@ class ImageApiMixin(object):
Args:
repository (str): The repository to pull
tag (str): The tag to pull
- stream (bool): Stream the output as a generator
+ stream (bool): Stream the output as a generator. Make sure to
+ consume the generator, otherwise pull might get cancelled.
auth_config (dict): Override the credentials that
:py:meth:`~docker.api.daemon.DaemonApiMixin.login` has set for
this request. ``auth_config`` should contain the ``username``
diff --git a/docker/models/images.py b/docker/models/images.py
index 4578c0b..f8b842a 100644
--- a/docker/models/images.py
+++ b/docker/models/images.py
@@ -425,6 +425,7 @@ class ImageCollection(Collection):
if not tag:
repository, tag = parse_repository_tag(repository)
+ kwargs['stream'] = False
self.client.api.pull(repository, tag=tag, **kwargs)
if tag:
return self.get('{0}{2}{1}'.format(
diff --git a/tests/unit/models_containers_test.py b/tests/unit/models_containers_test.py
index 22dd241..957035a 100644
--- a/tests/unit/models_containers_test.py
+++ b/tests/unit/models_containers_test.py
@@ -232,7 +232,8 @@ class ContainerCollectionTest(unittest.TestCase):
container = client.containers.run('alpine', 'sleep 300', detach=True)
assert container.id == FAKE_CONTAINER_ID
- client.api.pull.assert_called_with('alpine', platform=None, tag=None)
+ client.api.pull.assert_called_with('alpine', platform=None, tag=None,
+ stream=False)
def test_run_with_error(self):
client = make_fake_client()
diff --git a/tests/unit/models_images_test.py b/tests/unit/models_images_test.py
index 6783279..ef81a15 100644
--- a/tests/unit/models_images_test.py
+++ b/tests/unit/models_images_test.py
@@ -43,7 +43,8 @@ class ImageCollectionTest(unittest.TestCase):
def test_pull(self):
client = make_fake_client()
image = client.images.pull('test_image:latest')
- client.api.pull.assert_called_with('test_image', tag='latest')
+ client.api.pull.assert_called_with('test_image', tag='latest',
+ stream=False)
client.api.inspect_image.assert_called_with('test_image:latest')
assert isinstance(image, Image)
assert image.id == FAKE_IMAGE_ID
@@ -51,7 +52,8 @@ class ImageCollectionTest(unittest.TestCase):
def test_pull_multiple(self):
client = make_fake_client()
images = client.images.pull('test_image')
- client.api.pull.assert_called_with('test_image', tag=None)
+ client.api.pull.assert_called_with('test_image', tag=None,
+ stream=False)
client.api.images.assert_called_with(
all=False, name='test_image', filters=None
)