|
5 | 5 |
|
6 | 6 | from ..api import APIClient
|
7 | 7 | from ..constants import DEFAULT_DATA_CHUNK_SIZE
|
8 |
| -from ..errors import BuildError, ImageLoadError |
| 8 | +from ..errors import BuildError, ImageLoadError, InvalidArgument |
9 | 9 | from ..utils import parse_repository_tag
|
10 | 10 | from ..utils.json_stream import json_stream
|
11 | 11 | from .resource import Collection, Model
|
@@ -105,6 +105,81 @@ def tag(self, repository, tag=None, **kwargs):
|
105 | 105 | return self.client.api.tag(self.id, repository, tag=tag, **kwargs)
|
106 | 106 |
|
107 | 107 |
|
| 108 | +class RegistryData(Model): |
| 109 | + """ |
| 110 | + Image metadata stored on the registry, including available platforms. |
| 111 | + """ |
| 112 | + def __init__(self, image_name, *args, **kwargs): |
| 113 | + super(RegistryData, self).__init__(*args, **kwargs) |
| 114 | + self.image_name = image_name |
| 115 | + |
| 116 | + @property |
| 117 | + def id(self): |
| 118 | + """ |
| 119 | + The ID of the object. |
| 120 | + """ |
| 121 | + return self.attrs['Descriptor']['digest'] |
| 122 | + |
| 123 | + @property |
| 124 | + def short_id(self): |
| 125 | + """ |
| 126 | + The ID of the image truncated to 10 characters, plus the ``sha256:`` |
| 127 | + prefix. |
| 128 | + """ |
| 129 | + return self.id[:17] |
| 130 | + |
| 131 | + def pull(self, platform=None): |
| 132 | + """ |
| 133 | + Pull the image digest. |
| 134 | +
|
| 135 | + Args: |
| 136 | + platform (str): The platform to pull the image for. |
| 137 | + Default: ``None`` |
| 138 | +
|
| 139 | + Returns: |
| 140 | + (:py:class:`Image`): A reference to the pulled image. |
| 141 | + """ |
| 142 | + repository, _ = parse_repository_tag(self.image_name) |
| 143 | + return self.collection.pull(repository, tag=self.id, platform=platform) |
| 144 | + |
| 145 | + def has_platform(self, platform): |
| 146 | + """ |
| 147 | + Check whether the given platform identifier is available for this |
| 148 | + digest. |
| 149 | +
|
| 150 | + Args: |
| 151 | + platform (str or dict): A string using the ``os[/arch[/variant]]`` |
| 152 | + format, or a platform dictionary. |
| 153 | +
|
| 154 | + Returns: |
| 155 | + (bool): ``True`` if the platform is recognized as available, |
| 156 | + ``False`` otherwise. |
| 157 | +
|
| 158 | + Raises: |
| 159 | + :py:class:`docker.errors.InvalidArgument` |
| 160 | + If the platform argument is not a valid descriptor. |
| 161 | + """ |
| 162 | + if platform and not isinstance(platform, dict): |
| 163 | + parts = platform.split('/') |
| 164 | + if len(parts) > 3 or len(parts) < 1: |
| 165 | + raise InvalidArgument( |
| 166 | + '"{0}" is not a valid platform descriptor'.format(platform) |
| 167 | + ) |
| 168 | + platform = {'os': parts[0]} |
| 169 | + if len(parts) > 2: |
| 170 | + platform['variant'] = parts[2] |
| 171 | + if len(parts) > 1: |
| 172 | + platform['architecture'] = parts[1] |
| 173 | + return normalize_platform( |
| 174 | + platform, self.client.version() |
| 175 | + ) in self.attrs['Platforms'] |
| 176 | + |
| 177 | + def reload(self): |
| 178 | + self.attrs = self.client.api.inspect_distribution(self.image_name) |
| 179 | + |
| 180 | + reload.__doc__ = Model.reload.__doc__ |
| 181 | + |
| 182 | + |
108 | 183 | class ImageCollection(Collection):
|
109 | 184 | model = Image
|
110 | 185 |
|
@@ -219,6 +294,26 @@ def get(self, name):
|
219 | 294 | """
|
220 | 295 | return self.prepare_model(self.client.api.inspect_image(name))
|
221 | 296 |
|
| 297 | + def get_registry_data(self, name): |
| 298 | + """ |
| 299 | + Gets the registry data for an image. |
| 300 | +
|
| 301 | + Args: |
| 302 | + name (str): The name of the image. |
| 303 | +
|
| 304 | + Returns: |
| 305 | + (:py:class:`RegistryData`): The data object. |
| 306 | + Raises: |
| 307 | + :py:class:`docker.errors.APIError` |
| 308 | + If the server returns an error. |
| 309 | + """ |
| 310 | + return RegistryData( |
| 311 | + image_name=name, |
| 312 | + attrs=self.client.api.inspect_distribution(name), |
| 313 | + client=self.client, |
| 314 | + collection=self, |
| 315 | + ) |
| 316 | + |
222 | 317 | def list(self, name=None, all=False, filters=None):
|
223 | 318 | """
|
224 | 319 | List images on the server.
|
@@ -336,3 +431,13 @@ def search(self, *args, **kwargs):
|
336 | 431 | def prune(self, filters=None):
|
337 | 432 | return self.client.api.prune_images(filters=filters)
|
338 | 433 | prune.__doc__ = APIClient.prune_images.__doc__
|
| 434 | + |
| 435 | + |
| 436 | +def normalize_platform(platform, engine_info): |
| 437 | + if platform is None: |
| 438 | + platform = {} |
| 439 | + if 'os' not in platform: |
| 440 | + platform['os'] = engine_info['Os'] |
| 441 | + if 'architecture' not in platform: |
| 442 | + platform['architecture'] = engine_info['Arch'] |
| 443 | + return platform |
0 commit comments