77import subprocess
88from typing import Optional
99
10+ # It is important that this list is sorted in descending length of the entries
11+ GL_MEDIA_TYPES = [
12+ "gcpimage.tar.gz.log" ,
13+ "firecracker.tar.gz" ,
14+ "gcpimage.tar.gz" ,
15+ "pxe.tar.gz.log" ,
16+ "manifest.log" ,
17+ "release.log" ,
18+ "pxe.tar.gz" ,
19+ "qcow2.log" ,
20+ "test-log" ,
21+ "manifest" ,
22+ "vmdk.log" ,
23+ "tar.log" ,
24+ "release" ,
25+ "vhd.log" ,
26+ "ova.log" ,
27+ "raw.log" ,
28+ "tar.gz" ,
29+ "qcow2" ,
30+ "tar" ,
31+ "iso" ,
32+ "oci" ,
33+ "vhd" ,
34+ "vmdk" ,
35+ "ova" ,
36+ "raw" ,
37+ ]
38+
39+
1040GL_MEDIA_TYPE_LOOKUP = {
1141 "tar" : "application/io.gardenlinux.image.archive.format.tar" ,
1242 "tar.gz" : "application/io.gardenlinux.image.archive.format.tar.gz" ,
2050 "vmdk" : "application/io.gardenlinux.image.format.vmdk" ,
2151 "ova" : "application/io.gardenlinux.image.format.ova" ,
2252 "raw" : "application/io.gardenlinux.image.archive.format.raw" ,
53+ "manifest.log" : "application/io.gardenlinux.log" ,
54+ "release.log" : "application/io.gardenlinux.log" ,
55+ "test-log" : "application/io.gardenlinux.test-log" ,
56+ "manifest" : "application/io.gardenlinux.manifest" ,
57+ "tar.log" : "application/io.gardenlinux.log" ,
58+ "release" : "application/io.gardenlinux.release" ,
59+ "raw.log" : "application/io.gardenlinux.log" ,
60+ "qcow2.log" : "application/io.gardenlinux.log" ,
61+ "pxe.tar.gz.log" : "application/io.gardenlinux.log" ,
62+ "gcpimage.tar.gz.log" : "application/io.gardenlinux.log" ,
63+ "vmdk.log" : "application/io.gardenlinux.log" ,
64+ "vhd.log" : "application/io.gardenlinux.log" ,
65+ "ova.log" : "application/io.gardenlinux.log" ,
2366}
2467
2568
@@ -88,53 +131,82 @@ def construct_layer_metadata(
88131 return {
89132 "file_name" : f"{ cname } -{ arch } -{ version } -{ commit } .{ filetype } " ,
90133 "media_type" : media_type ,
134+ "annotations" : {"io.gardenlinux.image.layer.architecture" : arch },
135+ }
136+
137+
138+ def construct_layer_metadata_from_filename (filename : str , arch : str ) -> dict :
139+ """
140+ :param str filename: filename of the blob
141+ :param str arch: the arch of the target image
142+ :return: dict of oci layer metadata for a given layer file
143+ """
144+ media_type = lookup_media_type_for_file (filename )
145+ return {
146+ "file_name" : filename ,
147+ "media_type" : media_type ,
148+ "annotations" : {"io.gardenlinux.image.layer.architecture" : arch },
91149 }
92150
93151
94- def get_oci_metadata (cname : str , version : str , gardenlinux_root : str ):
152+ def get_file_set_from_cname (cname : str , version : str , arch : str , gardenlinux_root : str ):
95153 """
96154 :param str cname: the target cname of the image
97- :param str version: the target version of the image
155+ :param str version: the version of the target image
156+ :param str arch: the arch of the target image
98157 :param str gardenlinux_root: path of garden linux src root
99- :return: list of dicts, where each dict represents a layer
158+ :return: set of file names for a given cname
100159 """
101- oci_layer_metadata_list = list ()
160+ file_set = set ()
102161 features_by_type = get_features_dict (cname , gardenlinux_root )
103162 commit_str = get_gardenlinux_commit (gardenlinux_root , 8 )
104163
105164 if commit_str == "local" :
106165 raise ValueError ("Using local commit. Refusing to upload to OCI Registry" )
107-
108- for arch in ["amd64" , "arm64" ]:
109- for platform in features_by_type ["platform" ]:
110- image_file_types = deduce_image_filetype (
111- f"{ gardenlinux_root } /features/{ platform } "
112- )
113- archive_file_types = deduce_archive_filetype (
114- f"{ gardenlinux_root } /features/{ platform } "
166+ for platform in features_by_type ["platform" ]:
167+ image_file_types = deduce_filetypes (f"{ gardenlinux_root } /features/{ platform } " )
168+ for ft in image_file_types :
169+ file_set .add (
170+ f"{ cname } -{ arch } -{ version } -{ commit_str } .{ ft } " ,
115171 )
116- # Allow multiple image scripts per feature
117- if not image_file_types :
118- image_file_types .append ("raw" )
119- if not archive_file_types :
120- image_file_types .append ("tar" )
121- for ft in archive_file_types :
122- cur_layer_metadata = construct_layer_metadata (
123- ft , cname , version , arch , commit_str
124- )
125- cur_layer_metadata ["annotations" ] = {
126- "io.gardenlinux.image.layer.architecture" : arch
127- }
128- oci_layer_metadata_list .append (cur_layer_metadata )
129- # Allow multiple convert scripts per feature
130- for ft in image_file_types :
131- cur_layer_metadata = construct_layer_metadata (
132- ft , cname , version , arch , commit_str
133- )
134- cur_layer_metadata ["annotations" ] = {
135- "io.gardenlinux.image.layer.architecture" : arch
136- }
137- oci_layer_metadata_list .append (cur_layer_metadata )
172+ return file_set
173+
174+
175+ def get_oci_metadata_from_fileset (fileset : set , arch : str ):
176+ """
177+ :param str arch: arch of the target image
178+ :param set fileset: a list of filenames (not paths) to set oci_metadata for
179+ :return: list of dicts, where each dict represents a layer
180+ """
181+ oci_layer_metadata_list = list ()
182+
183+ for file in fileset :
184+ oci_layer_metadata_list .append (
185+ construct_layer_metadata_from_filename (file , arch )
186+ )
187+
188+ return oci_layer_metadata_list
189+
190+
191+ def get_oci_metadata (cname : str , version : str , arch : str , gardenlinux_root : str ):
192+ """
193+ :param str cname: the target cname of the image
194+ :param str version: the target version of the image
195+ :param str arch: arch of the target image
196+ :param str gardenlinux_root: path of garden linux src root
197+ :return: list of dicts, where each dict represents a layer
198+ """
199+
200+ # This is the feature deduction approach (glcli oci push)
201+ file_set = get_file_set_from_cname (cname , version , arch , gardenlinux_root )
202+
203+ # This is the tarball extraction approach (glcli oci push-tarball)
204+ oci_layer_metadata_list = list ()
205+
206+ for file in file_set :
207+ oci_layer_metadata_list .append (
208+ construct_layer_metadata_from_filename (file , arch )
209+ )
138210
139211 return oci_layer_metadata_list
140212
@@ -148,7 +220,21 @@ def lookup_media_type_for_filetype(filetype: str) -> str:
148220 return GL_MEDIA_TYPE_LOOKUP [filetype ]
149221 else :
150222 raise ValueError (
151- f"No media type for { filetype } is defined. You may want to add the definition to parse_features_lib"
223+ f"media type for { filetype } is not defined. You may want to add the definition to parse_features_lib"
224+ )
225+
226+
227+ def lookup_media_type_for_file (filename : str ) -> str :
228+ """
229+ :param str filename: filename of the target layer
230+ :return: mediatype
231+ """
232+ for suffix in GL_MEDIA_TYPES :
233+ if filename .endswith (suffix ):
234+ return GL_MEDIA_TYPE_LOOKUP [suffix ]
235+ else :
236+ raise ValueError (
237+ f"media type for { filename } is not defined. You may want to add the definition to parse_features_lib"
152238 )
153239
154240
@@ -163,25 +249,40 @@ def deduce_feature_name(feature_dir: str):
163249 return parsed ["name" ]
164250
165251
166- def deduce_archive_filetype (feature_dir ):
252+ def deduce_archive_filetypes (feature_dir ):
253+ """
254+ :param str feature_dir: Directory of single Feature
255+ :return: str list of filetype for archive
256+ """
257+ return deduce_filetypes_from_string (feature_dir , "image" )
258+
259+
260+ def deduce_image_filetypes (feature_dir ):
167261 """
168262 :param str feature_dir: Directory of single Feature
169- :return: str of filetype for archive
263+ :return: str list of filetype for image
170264 """
171- return deduce_filetype_from_string (feature_dir , "image " )
265+ return deduce_filetypes_from_string (feature_dir , "convert " )
172266
173267
174- def deduce_image_filetype (feature_dir ):
268+ def deduce_filetypes (feature_dir ):
175269 """
176270 :param str feature_dir: Directory of single Feature
177- :return: str of filetype for image
271+ :return: str list of filetypes for the feature
178272 """
179- return deduce_filetype_from_string (feature_dir , "convert" )
273+ image_file_types = deduce_image_filetypes (feature_dir )
274+ archive_file_types = deduce_archive_filetypes (feature_dir )
275+ if not image_file_types :
276+ image_file_types .append ("raw" )
277+ if not archive_file_types :
278+ archive_file_types .append ("tar" )
279+ image_file_types .extend (archive_file_types )
280+ return image_file_types
180281
181282
182- def deduce_filetype_from_string (feature_dir : str , script_base_name : str ):
283+ def deduce_filetypes_from_string (feature_dir : str , script_base_name : str ):
183284 """
184- Garden Linux features can optionally have a image.<filetype> or convert.<filetype> script,
285+ Garden Linux features can optionally have an image.<filetype> or convert.<filetype> script,
185286 where the <filetype> indicates the target filetype.
186287
187288 image.<filetype> script converts the .tar to <filetype> archive.
@@ -229,7 +330,7 @@ def read_feature_files(feature_dir):
229330 )
230331 feature_graph .add_edge (node , ref , attr = attr )
231332 if not networkx .is_directed_acyclic_graph (feature_graph ):
232- raise ValueError ("Graph is not directed asyclic graph" )
333+ raise ValueError ("Graph is not directed acyclic graph" )
233334 return feature_graph
234335
235336
0 commit comments