Kaydet (Commit) f95b9584 authored tarafından Joffrey F's avatar Joffrey F

Add support for experimental platform flag in build and pull

Signed-off-by: 's avatarJoffrey F <joffrey@docker.com>
üst bf5e7702
...@@ -19,7 +19,7 @@ class BuildApiMixin(object): ...@@ -19,7 +19,7 @@ class BuildApiMixin(object):
forcerm=False, dockerfile=None, container_limits=None, forcerm=False, dockerfile=None, container_limits=None,
decode=False, buildargs=None, gzip=False, shmsize=None, decode=False, buildargs=None, gzip=False, shmsize=None,
labels=None, cache_from=None, target=None, network_mode=None, labels=None, cache_from=None, target=None, network_mode=None,
squash=None, extra_hosts=None): squash=None, extra_hosts=None, platform=None):
""" """
Similar to the ``docker build`` command. Either ``path`` or ``fileobj`` Similar to the ``docker build`` command. Either ``path`` or ``fileobj``
needs to be set. ``path`` can be a local path (to a directory needs to be set. ``path`` can be a local path (to a directory
...@@ -103,6 +103,7 @@ class BuildApiMixin(object): ...@@ -103,6 +103,7 @@ class BuildApiMixin(object):
single layer. single layer.
extra_hosts (dict): Extra hosts to add to /etc/hosts in building extra_hosts (dict): Extra hosts to add to /etc/hosts in building
containers, as a mapping of hostname to IP address. containers, as a mapping of hostname to IP address.
platform (str): Platform in the format ``os[/arch[/variant]]``
Returns: Returns:
A generator for the build output. A generator for the build output.
...@@ -243,6 +244,13 @@ class BuildApiMixin(object): ...@@ -243,6 +244,13 @@ class BuildApiMixin(object):
extra_hosts = utils.format_extra_hosts(extra_hosts) extra_hosts = utils.format_extra_hosts(extra_hosts)
params.update({'extrahosts': extra_hosts}) params.update({'extrahosts': extra_hosts})
if platform is not None:
if utils.version_lt(self._version, '1.32'):
raise errors.InvalidVersion(
'platform was only introduced in API version 1.32'
)
params['platform'] = platform
if context is not None: if context is not None:
headers = {'Content-Type': 'application/tar'} headers = {'Content-Type': 'application/tar'}
if encoding: if encoding:
......
...@@ -323,7 +323,8 @@ class ImageApiMixin(object): ...@@ -323,7 +323,8 @@ 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, def pull(self, repository, tag=None, stream=False,
insecure_registry=False, auth_config=None, decode=False): insecure_registry=False, auth_config=None, decode=False,
platform=None):
""" """
Pulls an image. Similar to the ``docker pull`` command. Pulls an image. Similar to the ``docker pull`` command.
...@@ -336,6 +337,7 @@ class ImageApiMixin(object): ...@@ -336,6 +337,7 @@ class ImageApiMixin(object):
:py:meth:`~docker.api.daemon.DaemonApiMixin.login` has set for :py:meth:`~docker.api.daemon.DaemonApiMixin.login` has set for
this request. ``auth_config`` should contain the ``username`` this request. ``auth_config`` should contain the ``username``
and ``password`` keys to be valid. and ``password`` keys to be valid.
platform (str): Platform in the format ``os[/arch[/variant]]``
Returns: Returns:
(generator or str): The output (generator or str): The output
...@@ -376,7 +378,7 @@ class ImageApiMixin(object): ...@@ -376,7 +378,7 @@ class ImageApiMixin(object):
} }
headers = {} headers = {}
if utils.compare_version('1.5', self._version) >= 0: if utils.version_gte(self._version, '1.5'):
if auth_config is None: if auth_config is None:
header = auth.get_config_header(self, registry) header = auth.get_config_header(self, registry)
if header: if header:
...@@ -385,6 +387,13 @@ class ImageApiMixin(object): ...@@ -385,6 +387,13 @@ class ImageApiMixin(object):
log.debug('Sending supplied auth config') log.debug('Sending supplied auth config')
headers['X-Registry-Auth'] = auth.encode_header(auth_config) headers['X-Registry-Auth'] = auth.encode_header(auth_config)
if platform is not None:
if utils.version_lt(self._version, '1.32'):
raise errors.InvalidVersion(
'platform was only introduced in API version 1.32'
)
params['platform'] = platform
response = self._post( response = self._post(
self._url('/images/create'), params=params, headers=headers, self._url('/images/create'), params=params, headers=headers,
stream=stream, timeout=None stream=stream, timeout=None
......
...@@ -579,6 +579,8 @@ class ContainerCollection(Collection): ...@@ -579,6 +579,8 @@ class ContainerCollection(Collection):
inside the container. inside the container.
pids_limit (int): Tune a container's pids limit. Set ``-1`` for pids_limit (int): Tune a container's pids limit. Set ``-1`` for
unlimited. unlimited.
platform (str): Platform in the format ``os[/arch[/variant]]``.
Only used if the method needs to pull the requested image.
ports (dict): Ports to bind inside the container. ports (dict): Ports to bind inside the container.
The keys of the dictionary are the ports to bind inside the The keys of the dictionary are the ports to bind inside the
...@@ -700,7 +702,9 @@ class ContainerCollection(Collection): ...@@ -700,7 +702,9 @@ class ContainerCollection(Collection):
if isinstance(image, Image): if isinstance(image, Image):
image = image.id image = image.id
stream = kwargs.pop('stream', False) stream = kwargs.pop('stream', False)
detach = kwargs.pop("detach", False) detach = kwargs.pop('detach', False)
platform = kwargs.pop('platform', None)
if detach and remove: if detach and remove:
if version_gte(self.client.api._version, '1.25'): if version_gte(self.client.api._version, '1.25'):
kwargs["auto_remove"] = True kwargs["auto_remove"] = True
...@@ -718,7 +722,7 @@ class ContainerCollection(Collection): ...@@ -718,7 +722,7 @@ class ContainerCollection(Collection):
container = self.create(image=image, command=command, container = self.create(image=image, command=command,
detach=detach, **kwargs) detach=detach, **kwargs)
except ImageNotFound: except ImageNotFound:
self.client.images.pull(image) self.client.images.pull(image, platform=platform)
container = self.create(image=image, command=command, container = self.create(image=image, command=command,
detach=detach, **kwargs) detach=detach, **kwargs)
......
...@@ -157,6 +157,7 @@ class ImageCollection(Collection): ...@@ -157,6 +157,7 @@ class ImageCollection(Collection):
single layer. single layer.
extra_hosts (dict): Extra hosts to add to /etc/hosts in building extra_hosts (dict): Extra hosts to add to /etc/hosts in building
containers, as a mapping of hostname to IP address. containers, as a mapping of hostname to IP address.
platform (str): Platform in the format ``os[/arch[/variant]]``.
Returns: Returns:
(:py:class:`Image`): The built image. (:py:class:`Image`): The built image.
...@@ -265,6 +266,7 @@ class ImageCollection(Collection): ...@@ -265,6 +266,7 @@ class ImageCollection(Collection):
:py:meth:`~docker.client.DockerClient.login` has set for :py:meth:`~docker.client.DockerClient.login` has set for
this request. ``auth_config`` should contain the ``username`` this request. ``auth_config`` should contain the ``username``
and ``password`` keys to be valid. and ``password`` keys to be valid.
platform (str): Platform in the format ``os[/arch[/variant]]``
Returns: Returns:
(:py:class:`Image`): The image that has been pulled. (:py:class:`Image`): The image that has been pulled.
......
...@@ -377,3 +377,18 @@ class BuildTest(BaseAPIIntegrationTest): ...@@ -377,3 +377,18 @@ class BuildTest(BaseAPIIntegrationTest):
def test_build_gzip_custom_encoding(self): def test_build_gzip_custom_encoding(self):
with self.assertRaises(errors.DockerException): with self.assertRaises(errors.DockerException):
self.client.build(path='.', gzip=True, encoding='text/html') self.client.build(path='.', gzip=True, encoding='text/html')
@requires_api_version('1.32')
@requires_experimental(until=None)
def test_build_invalid_platform(self):
script = io.BytesIO('FROM busybox\n'.encode('ascii'))
with pytest.raises(errors.APIError) as excinfo:
stream = self.client.build(
fileobj=script, stream=True, platform='foobar'
)
for _ in stream:
pass
assert excinfo.value.status_code == 400
assert 'invalid platform' in excinfo.exconly()
...@@ -14,7 +14,7 @@ from six.moves import socketserver ...@@ -14,7 +14,7 @@ from six.moves import socketserver
import docker import docker
from ..helpers import requires_api_version from ..helpers import requires_api_version, requires_experimental
from .base import BaseAPIIntegrationTest, BUSYBOX from .base import BaseAPIIntegrationTest, BUSYBOX
...@@ -67,6 +67,15 @@ class PullImageTest(BaseAPIIntegrationTest): ...@@ -67,6 +67,15 @@ class PullImageTest(BaseAPIIntegrationTest):
img_info = self.client.inspect_image('hello-world') img_info = self.client.inspect_image('hello-world')
self.assertIn('Id', img_info) self.assertIn('Id', img_info)
@requires_api_version('1.32')
@requires_experimental(until=None)
def test_pull_invalid_platform(self):
with pytest.raises(docker.errors.APIError) as excinfo:
self.client.pull('hello-world', platform='foobar')
assert excinfo.value.status_code == 500
assert 'invalid platform' in excinfo.exconly()
class CommitTest(BaseAPIIntegrationTest): class CommitTest(BaseAPIIntegrationTest):
def test_commit(self): def test_commit(self):
......
...@@ -225,7 +225,7 @@ class ContainerCollectionTest(unittest.TestCase): ...@@ -225,7 +225,7 @@ class ContainerCollectionTest(unittest.TestCase):
container = client.containers.run('alpine', 'sleep 300', detach=True) container = client.containers.run('alpine', 'sleep 300', detach=True)
assert container.id == FAKE_CONTAINER_ID assert container.id == FAKE_CONTAINER_ID
client.api.pull.assert_called_with('alpine', tag=None) client.api.pull.assert_called_with('alpine', platform=None, tag=None)
def test_run_with_error(self): def test_run_with_error(self):
client = make_fake_client() client = make_fake_client()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment