diff options
Diffstat (limited to 'docker/api/image.py')
-rw-r--r-- | docker/api/image.py | 105 |
1 files changed, 69 insertions, 36 deletions
diff --git a/docker/api/image.py b/docker/api/image.py index 5f05d88..772d889 100644 --- a/docker/api/image.py +++ b/docker/api/image.py @@ -1,15 +1,13 @@ import logging import os -import six - from .. import auth, errors, utils from ..constants import DEFAULT_DATA_CHUNK_SIZE log = logging.getLogger(__name__) -class ImageApiMixin(object): +class ImageApiMixin: @utils.check_resource('image') def get_image(self, image, chunk_size=DEFAULT_DATA_CHUNK_SIZE): @@ -31,8 +29,8 @@ class ImageApiMixin(object): Example: - >>> image = cli.get_image("busybox:latest") - >>> f = open('/tmp/busybox-latest.tar', 'w') + >>> image = client.api.get_image("busybox:latest") + >>> f = open('/tmp/busybox-latest.tar', 'wb') >>> for chunk in image: >>> f.write(chunk) >>> f.close() @@ -70,7 +68,8 @@ class ImageApiMixin(object): filters (dict): Filters to be processed on the image list. Available filters: - ``dangling`` (bool) - - ``label`` (str): format either ``key`` or ``key=value`` + - `label` (str|list): format either ``"key"``, ``"key=value"`` + or a list of such. Returns: (dict or list): A list if ``quiet=True``, otherwise a dict. @@ -80,10 +79,18 @@ class ImageApiMixin(object): If the server returns an error. """ params = { - 'filter': name, 'only_ids': 1 if quiet else 0, 'all': 1 if all else 0, } + if name: + if utils.version_lt(self._version, '1.25'): + # only use "filter" on API 1.24 and under, as it is deprecated + params['filter'] = name + else: + if filters: + filters['reference'] = name + else: + filters = {'reference': name} if filters: params['filters'] = utils.convert_filters(filters) res = self._result(self._get(self._url("/images/json"), params=params), @@ -121,7 +128,7 @@ class ImageApiMixin(object): params = _import_image_params( repository, tag, image, - src=(src if isinstance(src, six.string_types) else None), + src=(src if isinstance(src, str) else None), changes=changes ) headers = {'Content-Type': 'application/tar'} @@ -130,7 +137,7 @@ class ImageApiMixin(object): return self._result( self._post(u, data=None, params=params) ) - elif isinstance(src, six.string_types): # from file path + elif isinstance(src, str): # from file path with open(src, 'rb') as f: return self._result( self._post( @@ -247,12 +254,15 @@ class ImageApiMixin(object): @utils.minimum_version('1.30') @utils.check_resource('image') - def inspect_distribution(self, image): + def inspect_distribution(self, image, auth_config=None): """ Get image digest and platform information by contacting the registry. Args: image (str): The image name to inspect + auth_config (dict): Override the credentials that are found in the + config for this request. ``auth_config`` should contain the + ``username`` and ``password`` keys to be valid. Returns: (dict): A dict containing distribution data @@ -261,9 +271,21 @@ class ImageApiMixin(object): :py:class:`docker.errors.APIError` If the server returns an error. """ + registry, _ = auth.resolve_repository_name(image) + + headers = {} + if auth_config is None: + header = auth.get_config_header(self, registry) + if header: + headers['X-Registry-Auth'] = header + else: + log.debug('Sending supplied auth config') + headers['X-Registry-Auth'] = auth.encode_header(auth_config) + + url = self._url("/distribution/{0}/json", image) return self._result( - self._get(self._url("/distribution/{0}/json", image)), True + self._get(url, headers=headers), True ) def load_image(self, data, quiet=None): @@ -327,21 +349,24 @@ class ImageApiMixin(object): return self._result(self._post(url, params=params), True) def pull(self, repository, tag=None, stream=False, auth_config=None, - decode=False, platform=None): + decode=False, platform=None, all_tags=False): """ Pulls an image. Similar to the ``docker pull`` command. Args: repository (str): The repository to pull - tag (str): The tag to pull - stream (bool): Stream the output as a generator - 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`` - and ``password`` keys to be valid. + tag (str): The tag to pull. If ``tag`` is ``None`` or empty, it + is set to ``latest``. + 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 are found in the + config for this request. ``auth_config`` should contain the + ``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): Platform in the format ``os[/arch[/variant]]`` + all_tags (bool): Pull all image tags, the ``tag`` parameter is + ignored. Returns: (generator or str): The output @@ -352,8 +377,8 @@ class ImageApiMixin(object): Example: - >>> for line in cli.pull('busybox', stream=True): - ... print(json.dumps(json.loads(line), indent=4)) + >>> for line in client.api.pull('busybox', stream=True, decode=True): + ... print(json.dumps(line, indent=4)) { "status": "Pulling image (latest) from busybox", "progressDetail": {}, @@ -366,8 +391,12 @@ class ImageApiMixin(object): } """ - if not tag: - repository, tag = utils.parse_repository_tag(repository) + repository, image_tag = utils.parse_repository_tag(repository) + tag = tag or image_tag or 'latest' + + if all_tags: + tag = None + registry, repo_name = auth.resolve_repository_name(repository) params = { @@ -413,10 +442,9 @@ class ImageApiMixin(object): repository (str): The repository to push to tag (str): An optional tag to push stream (bool): Stream the output as a blocking generator - 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`` - and ``password`` keys to be valid. + auth_config (dict): Override the credentials that are found in the + config for this request. ``auth_config`` should contain the + ``username`` and ``password`` keys to be valid. decode (bool): Decode the JSON data from the server into dicts. Only applies with ``stream=True`` @@ -428,12 +456,12 @@ class ImageApiMixin(object): If the server returns an error. Example: - >>> for line in cli.push('yourname/app', stream=True): - ... print line - {"status":"Pushing repository yourname/app (1 tags)"} - {"status":"Pushing","progressDetail":{},"id":"511136ea3c5a"} - {"status":"Image already pushed, skipping","progressDetail":{}, - "id":"511136ea3c5a"} + >>> for line in client.api.push('yourname/app', stream=True, decode=True): + ... print(line) + {'status': 'Pushing repository yourname/app (1 tags)'} + {'status': 'Pushing','progressDetail': {}, 'id': '511136ea3c5a'} + {'status': 'Image already pushed, skipping', 'progressDetail':{}, + 'id': '511136ea3c5a'} ... """ @@ -479,13 +507,14 @@ class ImageApiMixin(object): res = self._delete(self._url("/images/{0}", image), params=params) return self._result(res, True) - def search(self, term): + def search(self, term, limit=None): """ Search for images on Docker Hub. Similar to the ``docker search`` command. Args: term (str): A term to search for. + limit (int): The maximum number of results to return. Returns: (list of dicts): The response of the search. @@ -494,8 +523,12 @@ class ImageApiMixin(object): :py:class:`docker.errors.APIError` If the server returns an error. """ + params = {'term': term} + if limit is not None: + params['limit'] = limit + return self._result( - self._get(self._url("/images/search"), params={'term': term}), + self._get(self._url("/images/search"), params=params), True ) @@ -519,7 +552,7 @@ class ImageApiMixin(object): Example: - >>> client.tag('ubuntu', 'localhost:5000/ubuntu', 'latest', + >>> client.api.tag('ubuntu', 'localhost:5000/ubuntu', 'latest', force=True) """ params = { @@ -536,7 +569,7 @@ class ImageApiMixin(object): def is_file(src): try: return ( - isinstance(src, six.string_types) and + isinstance(src, str) and os.path.isfile(src) ) except TypeError: # a data string will make isfile() raise a TypeError |