Coverage for src/gitlabracadabra/containers/manifest.py: 71%
38 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-10 17:02 +0100
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-10 17:02 +0100
1#
2# Copyright (C) 2019-2025 Mathieu Parent <math.parent@gmail.com>
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Lesser General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
17from __future__ import annotations
19from gitlabracadabra.containers.blob import Blob
20from gitlabracadabra.containers.const import (
21 DOCKER_MANIFEST_SCHEMA1,
22 DOCKER_MANIFEST_SCHEMA1_SIGNED,
23 DOCKER_MANIFEST_SCHEMA2,
24 DOCKER_MANIFEST_SCHEMA2_LIST,
25 OCI_IMAGE_INDEX,
26 OCI_IMAGE_MANIFEST,
27)
28from gitlabracadabra.containers.manifest_base import ManifestBase
31class Manifest(ManifestBase):
32 """Retrieve Manifest or Manifest list."""
34 def manifests(self) -> list[Manifest]:
35 """Get manifests of the manifest list.
37 Returns:
38 A list of manifests.
40 Raises:
41 ValueError: Unsupported manifest list type.
42 """
43 if self.mime_type in {DOCKER_MANIFEST_SCHEMA2_LIST, OCI_IMAGE_INDEX}: 43 ↛ 45line 43 didn't jump to line 45 because the condition on line 43 was always true
44 return self._manifests_v2()
45 msg = f"Unsupported manifest list type {self.mime_type}"
46 raise ValueError(msg)
48 def tag_list(self) -> list[str]:
49 """Get tags of the manifest.
51 Returns:
52 A list of tags (strings).
54 Raises:
55 ValueError: Expected list got something else.
56 """
57 response = self._registry.request(
58 "get",
59 f"/v2/{self.manifest_name}/tags/list",
60 scopes={self.scope()},
61 )
62 tags = response.json().get("tags")
63 if not isinstance(tags, list): 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true
64 msg = f"Expected list got {type(tags)}"
65 raise TypeError(msg)
66 return tags
68 def blobs(self) -> list[Blob]:
69 """Get blobs of the manifest.
71 Returns:
72 A list of blobs.
74 Raises:
75 ValueError: Unsupported media type.
76 """
77 if self.mime_type in {DOCKER_MANIFEST_SCHEMA2, OCI_IMAGE_MANIFEST}:
78 return [
79 Blob(
80 self.registry,
81 self.manifest_name,
82 layer_json["digest"],
83 size=layer_json["size"],
84 mime_type=layer_json["mediaType"],
85 )
86 for layer_json in self.json.get("layers")
87 ]
88 if self.mime_type in {DOCKER_MANIFEST_SCHEMA1, DOCKER_MANIFEST_SCHEMA1_SIGNED}: 88 ↛ 98line 88 didn't jump to line 98 because the condition on line 88 was always true
89 return [
90 Blob(
91 self.registry,
92 self.manifest_name,
93 fs_layer_json["blobSum"],
94 mime_type="application/octet-stream",
95 )
96 for fs_layer_json in self.json.get("fsLayers")
97 ]
98 msg = f"Unsupported media type: {self.mime_type}"
99 raise ValueError(msg)
101 def _manifests_v2(self) -> list[Manifest]:
102 json = dict(self.json)
103 if json["mediaType"] not in {DOCKER_MANIFEST_SCHEMA2_LIST, OCI_IMAGE_INDEX}: 103 ↛ 104line 103 didn't jump to line 104 because the condition on line 103 was never true
104 msg = "Unexpected manifest list type {}".format(json["mediaType"])
105 raise ValueError(msg)
106 if json["schemaVersion"] != 2: # noqa: PLR2004 106 ↛ 107line 106 didn't jump to line 107 because the condition on line 106 was never true
107 msg = "Unexpected manifest schema version {}".format(json["schemaVersion"])
108 raise ValueError(msg)
109 manifests = []
110 for manifest_json in json["manifests"]:
111 manifest = Manifest(
112 self.registry,
113 self.manifest_name,
114 digest=manifest_json["digest"],
115 size=manifest_json["size"],
116 mime_type=manifest_json["mediaType"],
117 tag=self.tag,
118 )
119 manifest.platform = manifest_json["platform"]
120 manifests.append(manifest)
121 return manifests