diff --git a/docker/api/image.py b/docker/api/image.py index 85109473b..3c101fd57 100644 --- a/docker/api/image.py +++ b/docker/api/image.py @@ -434,7 +434,7 @@ def pull(self, repository, tag=None, stream=False, auth_config=None, return self._result(response) def push(self, repository, tag=None, stream=False, auth_config=None, - decode=False): + decode=False, platform=None): """ Push an image or a repository to the registry. Similar to the ``docker push`` command. @@ -448,6 +448,7 @@ def push(self, repository, tag=None, stream=False, auth_config=None, ``username`` and ``password`` keys to be valid. decode (bool): Decode the JSON data from the server into dicts. Only applies with ``stream=True`` + platform (str): JSON-encoded OCI platform to select the platform-variant to push. If not provided, all available variants will attempt to be pushed. Returns: (generator or str): The output from the server. @@ -488,6 +489,13 @@ def push(self, repository, tag=None, stream=False, auth_config=None, log.debug('Sending supplied auth config') headers['X-Registry-Auth'] = auth.encode_header(auth_config) + if platform is not None: + if utils.version_lt(self._version, '1.46'): + raise errors.InvalidVersion( + 'platform was only introduced in API version 1.46' + ) + params['platform'] = platform + response = self._post_json( u, None, headers=headers, stream=stream, params=params ) diff --git a/tests/unit/api_image_test.py b/tests/unit/api_image_test.py index 148109d37..2e567293f 100644 --- a/tests/unit/api_image_test.py +++ b/tests/unit/api_image_test.py @@ -5,6 +5,7 @@ import docker from docker import auth +from ..helpers import requires_api_version from . import fake_api from .api_test import ( DEFAULT_TIMEOUT_SECONDS, @@ -271,6 +272,28 @@ def test_push_image_with_auth(self): timeout=DEFAULT_TIMEOUT_SECONDS ) + @requires_api_version('1.46') + def test_push_image_with_platform(self): + with mock.patch('docker.auth.resolve_authconfig', + fake_resolve_authconfig): + self.client.push( + fake_api.FAKE_IMAGE_NAME, + platform=fake_api.FAKE_PLATFORM + ) + + fake_request.assert_called_with( + 'POST', + f"{url_prefix}images/test_image/push", + params={ + 'tag': None, + 'platform': fake_api.FAKE_PLATFORM + }, + data='{}', + headers={'Content-Type': 'application/json'}, + stream=False, + timeout=DEFAULT_TIMEOUT_SECONDS + ) + def test_push_image_stream(self): with mock.patch('docker.auth.resolve_authconfig', fake_resolve_authconfig): diff --git a/tests/unit/fake_api.py b/tests/unit/fake_api.py index 03e53cc64..fd9936709 100644 --- a/tests/unit/fake_api.py +++ b/tests/unit/fake_api.py @@ -21,6 +21,7 @@ FAKE_SECRET_NAME = 'super_secret' FAKE_CONFIG_ID = 'sekvs771242jfdjnvfuds8232' FAKE_CONFIG_NAME = 'super_config' +FAKE_PLATFORM = "{'os': 'linux','architecture': 'arm','variant': 'v5'}" # Each method is prefixed with HTTP method (get, post...) # for clarity and readability