mirror of https://github.com/docker/docker-py.git
Merge 958049e01d into 6e6a273573
This commit is contained in:
commit
1a8f65bcdd
|
|
@ -3,6 +3,7 @@ import os
|
||||||
|
|
||||||
from .. import auth, errors, utils
|
from .. import auth, errors, utils
|
||||||
from ..constants import DEFAULT_DATA_CHUNK_SIZE
|
from ..constants import DEFAULT_DATA_CHUNK_SIZE
|
||||||
|
from ..types.image import Platform
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -434,7 +435,7 @@ class ImageApiMixin:
|
||||||
return self._result(response)
|
return self._result(response)
|
||||||
|
|
||||||
def push(self, repository, tag=None, stream=False, auth_config=None,
|
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 an image or a repository to the registry. Similar to the ``docker
|
||||||
push`` command.
|
push`` command.
|
||||||
|
|
@ -448,6 +449,7 @@ class ImageApiMixin:
|
||||||
``username`` and ``password`` keys to be valid.
|
``username`` and ``password`` keys to be valid.
|
||||||
decode (bool): Decode the JSON data from the server into dicts.
|
decode (bool): Decode the JSON data from the server into dicts.
|
||||||
Only applies with ``stream=True``
|
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:
|
Returns:
|
||||||
(generator or str): The output from the server.
|
(generator or str): The output from the server.
|
||||||
|
|
@ -488,6 +490,13 @@ class ImageApiMixin:
|
||||||
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.46'):
|
||||||
|
raise errors.InvalidVersion(
|
||||||
|
'platform was only introduced in API version 1.46'
|
||||||
|
)
|
||||||
|
params['platform'] = Platform
|
||||||
|
|
||||||
response = self._post_json(
|
response = self._post_json(
|
||||||
u, None, headers=headers, stream=stream, params=params
|
u, None, headers=headers, stream=stream, params=params
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
from .base import DictType
|
||||||
|
|
||||||
|
|
||||||
|
class Platform(DictType):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
architecture = kwargs.get('architecture', kwargs.get('Architecture'))
|
||||||
|
os = kwargs.get('os', kwargs.get('OS'))
|
||||||
|
|
||||||
|
if architecture is None and os is None:
|
||||||
|
raise ValueError("At least one of 'architecture' or 'os' must be provided")
|
||||||
|
|
||||||
|
|
||||||
|
super().__init__({
|
||||||
|
'Architecture': architecture,
|
||||||
|
'OS': os,
|
||||||
|
'OSVersion': kwargs.get('os_version', kwargs.get('OSVersion')),
|
||||||
|
'OSFeatures': kwargs.get('os_features', kwargs.get('OSFeatures')),
|
||||||
|
'Variant': kwargs.get('variant', kwargs.get('Variant'))
|
||||||
|
})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def architecture(self):
|
||||||
|
return self['Architecture']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def os(self):
|
||||||
|
return self['OS']
|
||||||
|
|
||||||
|
@architecture.setter
|
||||||
|
def architecture(self, value):
|
||||||
|
self['Architecture'] = value
|
||||||
|
|
||||||
|
@os.setter
|
||||||
|
def os(self, value):
|
||||||
|
self['OS'] = value
|
||||||
|
|
@ -5,6 +5,7 @@ import pytest
|
||||||
import docker
|
import docker
|
||||||
from docker import auth
|
from docker import auth
|
||||||
|
|
||||||
|
from ..helpers import requires_api_version
|
||||||
from . import fake_api
|
from . import fake_api
|
||||||
from .api_test import (
|
from .api_test import (
|
||||||
DEFAULT_TIMEOUT_SECONDS,
|
DEFAULT_TIMEOUT_SECONDS,
|
||||||
|
|
@ -271,6 +272,28 @@ class ImageTest(BaseAPIClientTest):
|
||||||
timeout=DEFAULT_TIMEOUT_SECONDS
|
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):
|
def test_push_image_stream(self):
|
||||||
with mock.patch('docker.auth.resolve_authconfig',
|
with mock.patch('docker.auth.resolve_authconfig',
|
||||||
fake_resolve_authconfig):
|
fake_resolve_authconfig):
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ FAKE_SECRET_ID = 'epdyrw4tsi03xy3deu8g8ly6o'
|
||||||
FAKE_SECRET_NAME = 'super_secret'
|
FAKE_SECRET_NAME = 'super_secret'
|
||||||
FAKE_CONFIG_ID = 'sekvs771242jfdjnvfuds8232'
|
FAKE_CONFIG_ID = 'sekvs771242jfdjnvfuds8232'
|
||||||
FAKE_CONFIG_NAME = 'super_config'
|
FAKE_CONFIG_NAME = 'super_config'
|
||||||
|
FAKE_PLATFORM = "{'os': 'linux','architecture': 'arm','variant': 'v5'}"
|
||||||
|
|
||||||
# Each method is prefixed with HTTP method (get, post...)
|
# Each method is prefixed with HTTP method (get, post...)
|
||||||
# for clarity and readability
|
# for clarity and readability
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue