Skip to content

Commit 042a0e5

Browse files
authored
Merge pull request #2186 from docker/adw1n-i2116
Fix pulling images with `stream=True`
2 parents e1e4048 + c53423f commit 042a0e5

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

docker/api/image.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,8 @@ def pull(self, repository, tag=None, stream=False, auth_config=None,
334334
Args:
335335
repository (str): The repository to pull
336336
tag (str): The tag to pull
337-
stream (bool): Stream the output as a generator
337+
stream (bool): Stream the output as a generator. Make sure to
338+
consume the generator, otherwise pull might get cancelled.
338339
auth_config (dict): Override the credentials that
339340
:py:meth:`~docker.api.daemon.DaemonApiMixin.login` has set for
340341
this request. ``auth_config`` should contain the ``username``

docker/models/images.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import itertools
22
import re
3+
import warnings
34

45
import six
56

@@ -425,7 +426,21 @@ def pull(self, repository, tag=None, **kwargs):
425426
if not tag:
426427
repository, tag = parse_repository_tag(repository)
427428

428-
self.client.api.pull(repository, tag=tag, **kwargs)
429+
if 'stream' in kwargs:
430+
warnings.warn(
431+
'`stream` is not a valid parameter for this method'
432+
' and will be overridden'
433+
)
434+
del kwargs['stream']
435+
436+
pull_log = self.client.api.pull(
437+
repository, tag=tag, stream=True, **kwargs
438+
)
439+
for _ in pull_log:
440+
# We don't do anything with the logs, but we need
441+
# to keep the connection alive and wait for the image
442+
# to be pulled.
443+
pass
429444
if tag:
430445
return self.get('{0}{2}{1}'.format(
431446
repository, tag, '@' if tag.startswith('sha256:') else ':'

tests/unit/models_containers_test.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@ def test_run_pull(self):
232232
container = client.containers.run('alpine', 'sleep 300', detach=True)
233233

234234
assert container.id == FAKE_CONTAINER_ID
235-
client.api.pull.assert_called_with('alpine', platform=None, tag=None)
235+
client.api.pull.assert_called_with(
236+
'alpine', platform=None, tag=None, stream=True
237+
)
236238

237239
def test_run_with_error(self):
238240
client = make_fake_client()

tests/unit/models_images_test.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import unittest
2+
import warnings
3+
14
from docker.constants import DEFAULT_DATA_CHUNK_SIZE
25
from docker.models.images import Image
3-
import unittest
46

57
from .fake_api import FAKE_IMAGE_ID
68
from .fake_api_client import make_fake_client
@@ -43,15 +45,19 @@ def test_load(self):
4345
def test_pull(self):
4446
client = make_fake_client()
4547
image = client.images.pull('test_image:latest')
46-
client.api.pull.assert_called_with('test_image', tag='latest')
48+
client.api.pull.assert_called_with(
49+
'test_image', tag='latest', stream=True
50+
)
4751
client.api.inspect_image.assert_called_with('test_image:latest')
4852
assert isinstance(image, Image)
4953
assert image.id == FAKE_IMAGE_ID
5054

5155
def test_pull_multiple(self):
5256
client = make_fake_client()
5357
images = client.images.pull('test_image')
54-
client.api.pull.assert_called_with('test_image', tag=None)
58+
client.api.pull.assert_called_with(
59+
'test_image', tag=None, stream=True
60+
)
5561
client.api.images.assert_called_with(
5662
all=False, name='test_image', filters=None
5763
)
@@ -61,6 +67,16 @@ def test_pull_multiple(self):
6167
assert isinstance(image, Image)
6268
assert image.id == FAKE_IMAGE_ID
6369

70+
def test_pull_with_stream_param(self):
71+
client = make_fake_client()
72+
with warnings.catch_warnings(record=True) as w:
73+
client.images.pull('test_image', stream=True)
74+
75+
assert len(w) == 1
76+
assert str(w[0].message).startswith(
77+
'`stream` is not a valid parameter'
78+
)
79+
6480
def test_push(self):
6581
client = make_fake_client()
6682
client.images.push('foobar', insecure_registry=True)

0 commit comments

Comments
 (0)