Merge ~twom/launchpad:oci-layer-tar-sizes into launchpad:master

Proposed by Tom Wardill
Status: Merged
Approved by: Tom Wardill
Approved revision: a8ad1da5d41b5288f0d635bbc670a7f3d6746f1b
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~twom/launchpad:oci-layer-tar-sizes
Merge into: launchpad:master
Diff against target: 122 lines (+20/-14)
2 files modified
lib/lp/oci/model/ociregistryclient.py (+12/-4)
lib/lp/oci/tests/test_ociregistryclient.py (+8/-10)
Reviewer Review Type Date Requested Status
Thiago F. Pappacena (community) Approve
Review via email: mp+391926@code.launchpad.net

Commit message

Use layer tar sizes in registry upload

Description of the change

The registry requires the size of the layer.tar, not the size of the .gzipped version that we have in the librarian.

To post a comment you must log in.
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/oci/model/ociregistryclient.py b/lib/lp/oci/model/ociregistryclient.py
2index 0176a89..7561267 100644
3--- a/lib/lp/oci/model/ociregistryclient.py
4+++ b/lib/lp/oci/model/ociregistryclient.py
5@@ -148,12 +148,13 @@ class OCIRegistryClient:
6 continue
7 fileobj = un_zipped.extractfile(tarinfo)
8 cls._upload(digest, push_rule, fileobj, http_client)
9+ return tarinfo.size
10 finally:
11 lfa.close()
12
13 @classmethod
14 def _build_registry_manifest(cls, digests, config, config_json,
15- config_sha, preloaded_data):
16+ config_sha, preloaded_data, layer_sizes):
17 """Create an image manifest for the uploading image.
18
19 This involves nearly everything as digests and lengths are required.
20@@ -163,6 +164,7 @@ class OCIRegistryClient:
21 :param config: The contents of the manifest config file as a dict.
22 :param config_json: The config file as a JSON string.
23 :param config_sha: The sha256sum of the config JSON string.
24+ :param layer_sizes: Dict of layer digests and their size in bytes.
25 """
26 # Create the initial manifest data with empty layer information
27 manifest = {
28@@ -181,7 +183,10 @@ class OCIRegistryClient:
29 manifest["layers"].append({
30 "mediaType":
31 "application/vnd.docker.image.rootfs.diff.tar.gzip",
32- "size": preloaded_data[layer].content.filesize,
33+ # This should be the size of the `layer.tar` that we extracted
34+ # from the OCI image at build time. It is not the size of the
35+ # gzipped version that we have in the librarian.
36+ "size": layer_sizes[layer],
37 "digest": layer})
38 return manifest
39
40@@ -238,12 +243,14 @@ class OCIRegistryClient:
41 file_data = preloaded_data[section["Config"]]
42 config = file_data["config_file"]
43 # Upload the layers involved
44+ layer_sizes = {}
45 for diff_id in config["rootfs"]["diff_ids"]:
46- cls._upload_layer(
47+ layer_size = cls._upload_layer(
48 diff_id,
49 push_rule,
50 file_data[diff_id],
51 http_client)
52+ layer_sizes[diff_id] = layer_size
53 # The config file is required in different forms, so we can
54 # calculate the sha, work these out and upload
55 config_json = json.dumps(config).encode("UTF-8")
56@@ -258,7 +265,8 @@ class OCIRegistryClient:
57 # and associated configs
58 registry_manifest = cls._build_registry_manifest(
59 digests, config, config_json, config_sha,
60- preloaded_data[section["Config"]])
61+ preloaded_data[section["Config"]],
62+ layer_sizes)
63
64 # Upload the registry manifest
65 try:
66diff --git a/lib/lp/oci/tests/test_ociregistryclient.py b/lib/lp/oci/tests/test_ociregistryclient.py
67index 7459a43..3c5aa8c 100644
68--- a/lib/lp/oci/tests/test_ociregistryclient.py
69+++ b/lib/lp/oci/tests/test_ociregistryclient.py
70@@ -148,7 +148,8 @@ class TestOCIRegistryClient(OCIConfigHelperMixin, SpyProxyCallsMixin,
71 self.useFixture(MockPatch(
72 "lp.oci.model.ociregistryclient.OCIRegistryClient._upload"))
73 self.useFixture(MockPatch(
74- "lp.oci.model.ociregistryclient.OCIRegistryClient._upload_layer"))
75+ "lp.oci.model.ociregistryclient.OCIRegistryClient._upload_layer",
76+ return_value=999))
77
78 push_rule = self.build.recipe.push_rules[0]
79 responses.add("GET", "%s/v2/" % push_rule.registry_url, status=200)
80@@ -169,14 +170,12 @@ class TestOCIRegistryClient(OCIConfigHelperMixin, SpyProxyCallsMixin,
81 "mediaType": Equals(
82 "application/vnd.docker.image.rootfs.diff.tar.gzip"),
83 "digest": Equals("diff_id_1"),
84- "size": Equals(
85- self.layer_files[0].library_file.content.filesize)}),
86+ "size": Equals(999)}),
87 MatchesDict({
88 "mediaType": Equals(
89 "application/vnd.docker.image.rootfs.diff.tar.gzip"),
90 "digest": Equals("diff_id_2"),
91- "size": Equals(
92- self.layer_files[1].library_file.content.filesize)})
93+ "size": Equals(999)})
94 ]),
95 "schemaVersion": Equals(2),
96 "config": MatchesDict({
97@@ -295,21 +294,20 @@ class TestOCIRegistryClient(OCIConfigHelperMixin, SpyProxyCallsMixin,
98 self.config,
99 json.dumps(self.config),
100 "config-sha",
101- preloaded_data["config_file_1.json"])
102+ preloaded_data["config_file_1.json"],
103+ {"diff_id_1": 999, "diff_id_2": 9001})
104 self.assertThat(manifest, MatchesDict({
105 "layers": MatchesListwise([
106 MatchesDict({
107 "mediaType": Equals(
108 "application/vnd.docker.image.rootfs.diff.tar.gzip"),
109 "digest": Equals("diff_id_1"),
110- "size": Equals(
111- self.layer_files[0].library_file.content.filesize)}),
112+ "size": Equals(999)}),
113 MatchesDict({
114 "mediaType": Equals(
115 "application/vnd.docker.image.rootfs.diff.tar.gzip"),
116 "digest": Equals("diff_id_2"),
117- "size": Equals(
118- self.layer_files[1].library_file.content.filesize)})
119+ "size": Equals(9001)})
120 ]),
121 "schemaVersion": Equals(2),
122 "config": MatchesDict({

Subscribers

People subscribed via source and target branches

to status/vote changes: