Skip to content

Commit 9de4dae

Browse files
committed
Add support to parse and return the GardenLinux "cname"
Relates: gardenlinux/gardenlinux#2830 Signed-off-by: Tobias Wolf <[email protected]>
1 parent 1bcdff0 commit 9de4dae

File tree

4 files changed

+189
-96
lines changed

4 files changed

+189
-96
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ boto3 = "*"
2626
black = "^24.8.0"
2727

2828
[tool.poetry.scripts]
29+
gl-cname = "src.python_gardenlinux_lib.cname:main"
2930
flavors-parse = "src.python_gardenlinux_lib.flavors.parse_flavors:main"
3031

3132
[tool.pytest.ini_options]
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python3
2+
3+
from .features import parse_features
4+
5+
from functools import reduce
6+
from os.path import basename, dirname
7+
8+
import argparse
9+
import re
10+
11+
def main():
12+
parser = argparse.ArgumentParser()
13+
14+
parser.add_argument("--feature-dir", default="features")
15+
parser.add_argument("--arch", dest="arch")
16+
parser.add_argument("--version", dest="version")
17+
parser.add_argument("cname")
18+
19+
args = parser.parse_args()
20+
21+
re_match = re.match("([a-zA-Z0-9]+(-[a-zA-Z0-9\\_\\-]*?)?)(-([a-z0-9]+)(-([a-z0-9.]+)-([a-z0-9]+))*)?$", args.cname)
22+
assert re_match, f"not a valid cname {args.cname}"
23+
24+
if re_match.lastindex == 1:
25+
cname_base, arch = re_match[1].split("-", 1)
26+
commit_id = None
27+
version = None
28+
else:
29+
arch = re_match[4]
30+
cname_base = re_match[1]
31+
commit_id = re_match[7]
32+
version = re_match[6]
33+
34+
if args.arch is not None:
35+
arch = args.arch
36+
37+
if args.version is not None:
38+
re_match = re.match("([a-z0-9.]+)(-([a-z0-9]+))?$", args.cname)
39+
assert re_match, f"not a valid version {args.version}"
40+
41+
commit_id = re_match[3]
42+
version = re_match[1]
43+
44+
gardenlinux_root = dirname(args.feature_dir)
45+
feature_dir_name = basename(args.feature_dir)
46+
47+
if gardenlinux_root == "":
48+
gardenlinux_root = "."
49+
50+
args = parser.parse_args()
51+
graph = parse_features.get_features_graph(cname_base, gardenlinux_root, feature_dir_name)
52+
sorted_features = parse_features.sort_nodes(graph)
53+
54+
minimal_feature_set = get_minimal_feature_set(graph)
55+
sorted_minimal_features = parse_features.sort_set(minimal_feature_set, sorted_features)
56+
cname_base = get_cname_base(sorted_minimal_features)
57+
58+
cname = f"{cname_base}-{arch}"
59+
if commit_id is not None: cname += f"-{version}-{commit_id}"
60+
61+
print(cname)
62+
63+
def get_cname_base(sorted_features):
64+
return reduce(lambda a, b : a + ("-" if not b.startswith("_") else "") + b, sorted_features)
65+
66+
def get_minimal_feature_set(graph):
67+
return set([node for (node, degree) in graph.in_degree() if degree == 0])
68+
69+
if __name__ == "__main__":
70+
main()
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env python3
2+
3+
# It is important that this list is sorted in descending length of the entries
4+
GL_MEDIA_TYPES = [
5+
"gcpimage.tar.gz.log",
6+
"firecracker.tar.gz",
7+
"platform.test.log",
8+
"platform.test.xml",
9+
"gcpimage.tar.gz",
10+
"chroot.test.log",
11+
"chroot.test.xml",
12+
"pxe.tar.gz.log",
13+
"root.squashfs",
14+
"manifest.log",
15+
"release.log",
16+
"pxe.tar.gz",
17+
"qcow2.log",
18+
"test-log",
19+
"boot.efi",
20+
"manifest",
21+
"vmdk.log",
22+
"tar.log",
23+
"uki.log",
24+
"vmlinuz",
25+
"release",
26+
"vhd.log",
27+
"ova.log",
28+
"raw.log",
29+
"oci.log",
30+
"initrd",
31+
"tar.gz",
32+
"qcow2",
33+
"tar",
34+
"iso",
35+
"oci",
36+
"vhd",
37+
"vmdk",
38+
"ova",
39+
"uki",
40+
"raw",
41+
]
42+
43+
GL_MEDIA_TYPE_LOOKUP = {
44+
"tar": "application/io.gardenlinux.image.archive.format.tar",
45+
"tar.gz": "application/io.gardenlinux.image.archive.format.tar.gz",
46+
"pxe.tar.gz": "application/io.gardenlinux.image.archive.format.pxe.tar.gz",
47+
"iso": "application/io.gardenlinux.image.archive.format.iso",
48+
"oci": "application/io.gardenlinux.image.archive.format.oci",
49+
"firecracker.tar.gz": "application/io.gardenlinux.image.archive.format.firecracker.tar.gz",
50+
"qcow2": "application/io.gardenlinux.image.format.qcow2",
51+
"vhd": "application/io.gardenlinux.image.format.vhd",
52+
"gcpimage.tar.gz": "application/io.gardenlinux.image.format.gcpimage.tar.gz",
53+
"vmdk": "application/io.gardenlinux.image.format.vmdk",
54+
"ova": "application/io.gardenlinux.image.format.ova",
55+
"uki": "application/io.gardenlinux.uki",
56+
"uki.log": "application/io.gardenlinux.log",
57+
"raw": "application/io.gardenlinux.image.archive.format.raw",
58+
"manifest.log": "application/io.gardenlinux.log",
59+
"release.log": "application/io.gardenlinux.log",
60+
"test-log": "application/io.gardenlinux.test-log",
61+
"manifest": "application/io.gardenlinux.manifest",
62+
"tar.log": "application/io.gardenlinux.log",
63+
"release": "application/io.gardenlinux.release",
64+
"raw.log": "application/io.gardenlinux.log",
65+
"qcow2.log": "application/io.gardenlinux.log",
66+
"pxe.tar.gz.log": "application/io.gardenlinux.log",
67+
"gcpimage.tar.gz.log": "application/io.gardenlinux.log",
68+
"vmdk.log": "application/io.gardenlinux.log",
69+
"vhd.log": "application/io.gardenlinux.log",
70+
"ova.log": "application/io.gardenlinux.log",
71+
"vmlinuz": "application/io.gardenlinux.kernel",
72+
"initrd": "application/io.gardenlinux.initrd",
73+
"root.squashfs": "application/io.gardenlinux.squashfs",
74+
"boot.efi": "application/io.gardenlinux.efi",
75+
"platform.test.log": "application/io.gardenlinux.io.platform.test.log",
76+
"platform.test.xml": "application/io.gardenlinux.io.platform.test.xml",
77+
"chroot.test.log": "application/io.gardenlinux.io.chroot.test.log",
78+
"chroot.test.xml": "application/io.gardenlinux.io.chroot.test.xml",
79+
"oci.log": "application/io.gardenlinux.log",
80+
}

src/python_gardenlinux_lib/features/parse_features.py

Lines changed: 38 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from ..constants import GL_MEDIA_TYPE_LOOKUP, GL_MEDIA_TYPES
2+
13
from glob import glob
2-
from git.objects import commit
34
import yaml
45
import networkx
56
import os
@@ -9,86 +10,6 @@
910

1011
from pygments.filter import apply_filters
1112

12-
# It is important that this list is sorted in descending length of the entries
13-
GL_MEDIA_TYPES = [
14-
"gcpimage.tar.gz.log",
15-
"firecracker.tar.gz",
16-
"platform.test.log",
17-
"platform.test.xml",
18-
"gcpimage.tar.gz",
19-
"chroot.test.log",
20-
"chroot.test.xml",
21-
"pxe.tar.gz.log",
22-
"root.squashfs",
23-
"manifest.log",
24-
"release.log",
25-
"pxe.tar.gz",
26-
"qcow2.log",
27-
"test-log",
28-
"boot.efi",
29-
"manifest",
30-
"vmdk.log",
31-
"tar.log",
32-
"uki.log",
33-
"vmlinuz",
34-
"release",
35-
"vhd.log",
36-
"ova.log",
37-
"raw.log",
38-
"oci.log",
39-
"initrd",
40-
"tar.gz",
41-
"qcow2",
42-
"tar",
43-
"iso",
44-
"oci",
45-
"vhd",
46-
"vmdk",
47-
"ova",
48-
"uki",
49-
"raw",
50-
]
51-
52-
53-
GL_MEDIA_TYPE_LOOKUP = {
54-
"tar": "application/io.gardenlinux.image.archive.format.tar",
55-
"tar.gz": "application/io.gardenlinux.image.archive.format.tar.gz",
56-
"pxe.tar.gz": "application/io.gardenlinux.image.archive.format.pxe.tar.gz",
57-
"iso": "application/io.gardenlinux.image.archive.format.iso",
58-
"oci": "application/io.gardenlinux.image.archive.format.oci",
59-
"firecracker.tar.gz": "application/io.gardenlinux.image.archive.format.firecracker.tar.gz",
60-
"qcow2": "application/io.gardenlinux.image.format.qcow2",
61-
"vhd": "application/io.gardenlinux.image.format.vhd",
62-
"gcpimage.tar.gz": "application/io.gardenlinux.image.format.gcpimage.tar.gz",
63-
"vmdk": "application/io.gardenlinux.image.format.vmdk",
64-
"ova": "application/io.gardenlinux.image.format.ova",
65-
"uki": "application/io.gardenlinux.uki",
66-
"uki.log": "application/io.gardenlinux.log",
67-
"raw": "application/io.gardenlinux.image.archive.format.raw",
68-
"manifest.log": "application/io.gardenlinux.log",
69-
"release.log": "application/io.gardenlinux.log",
70-
"test-log": "application/io.gardenlinux.test-log",
71-
"manifest": "application/io.gardenlinux.manifest",
72-
"tar.log": "application/io.gardenlinux.log",
73-
"release": "application/io.gardenlinux.release",
74-
"raw.log": "application/io.gardenlinux.log",
75-
"qcow2.log": "application/io.gardenlinux.log",
76-
"pxe.tar.gz.log": "application/io.gardenlinux.log",
77-
"gcpimage.tar.gz.log": "application/io.gardenlinux.log",
78-
"vmdk.log": "application/io.gardenlinux.log",
79-
"vhd.log": "application/io.gardenlinux.log",
80-
"ova.log": "application/io.gardenlinux.log",
81-
"vmlinuz": "application/io.gardenlinux.kernel",
82-
"initrd": "application/io.gardenlinux.initrd",
83-
"root.squashfs": "application/io.gardenlinux.squashfs",
84-
"boot.efi": "application/io.gardenlinux.efi",
85-
"platform.test.log": "application/io.gardenlinux.io.platform.test.log",
86-
"platform.test.xml": "application/io.gardenlinux.io.platform.test.xml",
87-
"chroot.test.log": "application/io.gardenlinux.io.chroot.test.log",
88-
"chroot.test.xml": "application/io.gardenlinux.io.chroot.test.xml",
89-
"oci.log": "application/io.gardenlinux.log",
90-
}
91-
9213

9314
def get_gardenlinux_commit(gardenlinux_root: str, limit: Optional[int] = None) -> str:
9415
"""
@@ -118,54 +39,75 @@ def get_gardenlinux_commit(gardenlinux_root: str, limit: Optional[int] = None) -
11839
return commit_str
11940

12041

121-
def get_features_dict(cname: str, gardenlinux_root: str) -> dict:
42+
def get_features_dict(
43+
cname: str, gardenlinux_root: str, feature_dir_name: str = "features"
44+
) -> dict:
12245
"""
12346
:param str cname: the target cname to get the feature dict for
12447
:param str gardenlinux_root: path of garden linux src root
12548
:return: dict with list of features for a given cname, split into platform, element and flag
12649
12750
"""
128-
feature_base_dir = f"{gardenlinux_root}/features"
129-
input_features = __reverse_cname_base(cname)
130-
feature_graph = read_feature_files(feature_base_dir)
131-
graph = filter_graph(feature_graph, input_features)
51+
52+
graph = get_features_graph(cname, gardenlinux_root, feature_dir_name)
13253
features = __reverse_sort_nodes(graph)
13354
features_by_type = dict()
55+
13456
for type in ["platform", "element", "flag"]:
13557
features_by_type[type] = [
13658
feature
13759
for feature in features
13860
if __get_node_type(graph.nodes[feature]) == type
13961
]
140-
return features_by_type
14162

63+
return features_by_type
14264

143-
def get_features_list(cname: str, gardenlinux_root: str) -> list:
65+
def get_features_graph(
66+
cname: str, gardenlinux_root: str, feature_dir_name: str = "features"
67+
) -> networkx.graph:
14468
"""
14569
:param str cname: the target cname to get the feature dict for
14670
:param str gardenlinux_root: path of garden linux src root
14771
:return: list of features for a given cname
14872
14973
"""
150-
feature_base_dir = f"{gardenlinux_root}/features"
74+
75+
feature_base_dir = f"{gardenlinux_root}/{feature_dir_name}"
15176
input_features = __reverse_cname_base(cname)
15277
feature_graph = read_feature_files(feature_base_dir)
15378
graph = filter_graph(feature_graph, input_features)
79+
80+
return graph
81+
82+
83+
def get_features_list(
84+
cname: str, gardenlinux_root: str, feature_dir_name: str = "features"
85+
) -> list:
86+
"""
87+
:param str cname: the target cname to get the feature dict for
88+
:param str gardenlinux_root: path of garden linux src root
89+
:return: list of features for a given cname
90+
91+
"""
92+
93+
graph = get_features_graph(cname, gardenlinux_root, feature_dir_name)
15494
features = __reverse_sort_nodes(graph)
95+
15596
return features
15697

15798

158-
def get_features(cname: str, gardenlinux_root: str) -> str:
99+
def get_features(
100+
cname: str, gardenlinux_root: str, feature_dir_name: str = "features"
101+
) -> str:
159102
"""
160103
:param str cname: the target cname to get the feature set for
161104
:param str gardenlinux_root: path of garden linux src root
162105
:return: a comma separated string with the expanded feature set for the cname
163106
"""
164-
feature_base_dir = f"{gardenlinux_root}/features"
165-
input_features = __reverse_cname_base(cname)
166-
feature_graph = read_feature_files(feature_base_dir)
167-
graph = filter_graph(feature_graph, input_features)
107+
108+
graph = get_features_graph(cname, gardenlinux_root, feature_dir_name)
168109
features = __reverse_sort_nodes(graph)
110+
169111
return ",".join(features)
170112

171113

@@ -458,7 +400,7 @@ def __sort_key(graph, node):
458400
return f"{prefix}-{node}"
459401

460402

461-
def __sort_nodes(graph):
403+
def sort_nodes(graph):
462404
def key_function(node):
463405
return __sort_key(graph, node)
464406

@@ -473,7 +415,7 @@ def __reverse_cname_base(cname):
473415
def __reverse_sort_nodes(graph):
474416
reverse_graph = graph.reverse()
475417
assert networkx.is_directed_acyclic_graph(reverse_graph)
476-
return __sort_nodes(reverse_graph)
418+
return sort_nodes(reverse_graph)
477419

478420

479421
def __get_node_type(node):

0 commit comments

Comments
 (0)