Skip to content

Commit 38896fe

Browse files
committed
Add support to accept incomplete release files for S3 artifact upload
Signed-off-by: Tobias Wolf <wolf@b1-systems.de> On-behalf-of: SAP <tobias.wolf@sap.com>
1 parent 2d52501 commit 38896fe

File tree

11 files changed

+130
-56
lines changed

11 files changed

+130
-56
lines changed

.github/actions/setup/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Installs the given GardenLinux Python library
44
inputs:
55
version:
66
description: GardenLinux Python library version
7-
default: "0.10.13"
7+
default: "0.10.14"
88
python_version:
99
description: Python version to setup
1010
default: "3.13"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "gardenlinux"
3-
version = "0.10.13"
3+
version = "0.10.14"
44
description = "Contains tools to work with the features directory of gardenlinux, for example deducting dependencies from feature sets or validating cnames"
55
authors = ["Garden Linux Maintainers <contact@gardenlinux.io>"]
66
license = "Apache-2.0"

src/gardenlinux/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
GL_DEB_REPO_BASE_URL = "https://packages.gardenlinux.io/gardenlinux"
149149
GL_DISTRIBUTION_NAME = "Garden Linux"
150150
GL_HOME_URL = "https://gardenlinux.io"
151+
GL_PLATFORM_FRANKENSTEIN = "frankenstein"
151152
GL_RELEASE_ID = "gardenlinux"
152153
GL_REPOSITORY_URL = "https://github.com/gardenlinux/gardenlinux"
153154
GL_SUPPORT_URL = "https://github.com/gardenlinux/gardenlinux"

src/gardenlinux/features/cname.py

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
from configparser import UNNAMED_SECTION, ConfigParser
99
from os import PathLike, environ
1010
from pathlib import Path
11-
from typing import List, Optional, Self
11+
from typing import Any, Dict, List, Optional, Self
1212

1313
from ..constants import (
1414
ARCHS,
1515
GL_BUG_REPORT_URL,
1616
GL_DISTRIBUTION_NAME,
1717
GL_HOME_URL,
18+
GL_PLATFORM_FRANKENSTEIN,
1819
GL_RELEASE_ID,
1920
GL_SUPPORT_URL,
2021
)
@@ -59,14 +60,21 @@ def __init__(
5960
self._feature_flags_cached: Optional[List[str]] = None
6061
self._feature_platforms_cached: Optional[List[str]] = None
6162
self._feature_set_cached: Optional[str] = None
63+
self._features_cached: Optional[Dict[str, Any]] = None
64+
self._platform_cached: Optional[str] = None
6265
self._platform_variant_cached: Optional[str] = None
6366
self._flavor = ""
6467
self._version = None
6568

69+
self._flag_frankenstein = bool(environ.get("GL_ALLOW_FRANKENSTEIN", False))
70+
6671
self._flag_multiple_platforms = bool(
67-
environ.get("GL_ALLOW_FRANKENSTEIN", False)
72+
environ.get("GL_ALLOW_MULTIPLE_PLATFORMS", False)
6873
)
6974

75+
if self._flag_frankenstein:
76+
self._flag_multiple_platforms = True
77+
7078
commit_id_or_hash = None
7179

7280
if version is not None:
@@ -213,6 +221,20 @@ def flavor(self) -> str:
213221

214222
return self._flavor
215223

224+
@property
225+
def features(self) -> Dict[str, Any]:
226+
"""
227+
Returns the features for the cname parsed.
228+
229+
:return: (dict) Features of the cname
230+
:since: 0.10.14
231+
"""
232+
233+
if self._features_cached is None:
234+
self._features_cached = Parser().filter_as_dict(self.flavor)
235+
236+
return self._features_cached
237+
216238
@property
217239
def feature_set(self) -> str:
218240
"""
@@ -239,7 +261,7 @@ def feature_set_element(self) -> str:
239261
if self._feature_elements_cached is not None:
240262
return ",".join(self._feature_elements_cached)
241263

242-
return ",".join(Parser().filter_as_dict(self.flavor)["element"])
264+
return ",".join(self.features["element"])
243265

244266
@property
245267
def feature_set_flag(self) -> str:
@@ -253,7 +275,7 @@ def feature_set_flag(self) -> str:
253275
if self._feature_flags_cached is not None:
254276
return ",".join(self._feature_flags_cached)
255277

256-
return ",".join(Parser().filter_as_dict(self.flavor)["flag"])
278+
return ",".join(self.features["flag"])
257279

258280
@property
259281
def feature_set_platform(self) -> str:
@@ -265,7 +287,7 @@ def feature_set_platform(self) -> str:
265287
"""
266288

267289
if self._feature_platforms_cached is None:
268-
platforms = Parser().filter_as_dict(self.flavor)["platform"]
290+
platforms = self.features["platform"]
269291
else:
270292
platforms = self._feature_platforms_cached
271293

@@ -274,7 +296,7 @@ def feature_set_platform(self) -> str:
274296

275297
assert len(platforms) < 2
276298
"Only one platform is supported"
277-
return platforms[0]
299+
return platforms[0] # type: ignore[no-any-return]
278300

279301
@property
280302
def feature_set_list(self) -> List[str]:
@@ -293,19 +315,25 @@ def feature_set_list(self) -> List[str]:
293315
@property
294316
def platform(self) -> str:
295317
"""
296-
Returns the feature set of type "platform" for the cname parsed.
318+
Returns the platform for the cname parsed.
297319
298-
:return: (str) Feature set platforms
320+
:return: (str) Platform
299321
:since: 0.7.0
300322
"""
301323

302-
if self._feature_platforms_cached is None:
303-
platforms = Parser().filter_as_dict(self.flavor)["platform"]
304-
else:
324+
if self._platform_cached is not None:
325+
platforms = [self._platform_cached]
326+
elif self._feature_platforms_cached is not None:
305327
platforms = self._feature_platforms_cached
328+
else:
329+
platforms = self.features["platform"]
330+
331+
if self._flag_frankenstein and len(platforms) > 1:
332+
return GL_PLATFORM_FRANKENSTEIN
306333

307334
if not self._flag_multiple_platforms:
308335
assert len(platforms) < 2
336+
"Only one platform is supported"
309337

310338
return platforms[0]
311339

@@ -345,18 +373,8 @@ def release_metadata_string(self) -> str:
345373
:since: 1.0.0
346374
"""
347375

348-
features = Parser().filter_as_dict(self.flavor)
349-
350-
if not self._flag_multiple_platforms:
351-
assert len(features["platform"]) < 2
352-
"Only one platform is supported"
353-
354376
commit_hash = self.commit_hash
355377
commit_id = self.commit_id
356-
elements = ",".join(features["element"])
357-
flags = ",".join(features["flag"])
358-
platform = features["platform"][0]
359-
platforms = ",".join(features["platform"])
360378
platform_variant = self.platform_variant
361379
version = self.version
362380

@@ -387,10 +405,10 @@ def release_metadata_string(self) -> str:
387405
BUG_REPORT_URL="{GL_BUG_REPORT_URL}"
388406
GARDENLINUX_CNAME="{self.cname}"
389407
GARDENLINUX_FEATURES="{self.feature_set}"
390-
GARDENLINUX_FEATURES_PLATFORMS="{platforms}"
391-
GARDENLINUX_FEATURES_ELEMENTS="{elements}"
392-
GARDENLINUX_FEATURES_FLAGS="{flags}"
393-
GARDENLINUX_PLATFORM="{platform}"
408+
GARDENLINUX_FEATURES_PLATFORMS="{self.feature_set_platform}"
409+
GARDENLINUX_FEATURES_ELEMENTS="{self.feature_set_element}"
410+
GARDENLINUX_FEATURES_FLAGS="{self.feature_set_flag}"
411+
GARDENLINUX_PLATFORM="{self.platform}"
394412
GARDENLINUX_PLATFORM_VARIANT="{platform_variant}"
395413
GARDENLINUX_VERSION="{version}"
396414
GARDENLINUX_COMMIT_ID="{commit_id}"
@@ -456,6 +474,7 @@ def _copy_from_cname_object(self, cname_object: Self) -> None:
456474
self._feature_elements_cached = cname_object.feature_set_element.split(",")
457475
self._feature_flags_cached = cname_object.feature_set_flag.split(",")
458476
self._feature_platforms_cached = cname_object.feature_set_platform.split(",")
477+
self._platform_cached = cname_object.platform
459478
self._platform_variant_cached = cname_object.platform_variant
460479
self._version = cname_object.version
461480

@@ -477,6 +496,10 @@ def load_from_release_file(self, release_file: PathLike[str] | str) -> None:
477496
and self._commit_id != cname_object.commit_id
478497
)
479498
or (self._version is not None and self._version != cname_object.version)
499+
or (
500+
not self._flag_frankenstein
501+
and cname_object.platform not in cname_object.feature_set_platform
502+
)
480503
):
481504
raise RuntimeError(
482505
f"Release metadata file given is invalid: {release_file} failed consistency check - {self.cname} != {cname_object.cname}"
@@ -531,9 +554,7 @@ def new_from_release_file(release_file: PathLike[str] | str) -> "CName":
531554
"GARDENLINUX_CNAME",
532555
"GARDENLINUX_COMMIT_ID_LONG",
533556
"GARDENLINUX_FEATURES",
534-
"GARDENLINUX_FEATURES_ELEMENTS",
535-
"GARDENLINUX_FEATURES_FLAGS",
536-
"GARDENLINUX_FEATURES_PLATFORMS",
557+
"GARDENLINUX_PLATFORM",
537558
"GARDENLINUX_VERSION",
538559
):
539560
if not release_config.has_option(UNNAMED_SECTION, release_field):
@@ -559,23 +580,30 @@ def new_from_release_file(release_file: PathLike[str] | str) -> "CName":
559580
UNNAMED_SECTION, "GARDENLINUX_FEATURES"
560581
).strip("\"'")
561582

562-
cname_object._feature_elements_cached = (
563-
release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_ELEMENTS")
564-
.strip("\"'")
565-
.split(",")
566-
)
583+
if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_ELEMENTS"):
584+
cname_object._feature_elements_cached = (
585+
release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_ELEMENTS")
586+
.strip("\"'")
587+
.split(",")
588+
)
567589

568-
cname_object._feature_flags_cached = (
569-
release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_FLAGS")
570-
.strip("\"'")
571-
.split(",")
572-
)
590+
if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_FLAGS"):
591+
cname_object._feature_flags_cached = (
592+
release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_FLAGS")
593+
.strip("\"'")
594+
.split(",")
595+
)
573596

574-
cname_object._feature_platforms_cached = (
575-
release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_PLATFORMS")
576-
.strip("\"'")
577-
.split(",")
578-
)
597+
if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_PLATFORMS"):
598+
cname_object._feature_platforms_cached = (
599+
release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_PLATFORMS")
600+
.strip("\"'")
601+
.split(",")
602+
)
603+
604+
cname_object._platform_cached = release_config.get(
605+
UNNAMED_SECTION, "GARDENLINUX_PLATFORM"
606+
).strip("\"'")
579607

580608
if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_PLATFORM_VARIANT"):
581609
cname_object._platform_variant_cached = release_config.get(

src/gardenlinux/s3/s3_artifacts.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,26 @@ def upload_from_directory(
120120

121121
release_file = artifacts_dir.joinpath(f"{base_name}.release")
122122

123-
cname_object = CName.new_from_release_file(release_file)
123+
try:
124+
cname_object = CName.new_from_release_file(release_file)
125+
except RuntimeError:
126+
if not release_file.exists():
127+
raise RuntimeError(
128+
f"Release metadata file given is invalid: {release_file}"
129+
)
130+
131+
release_config = ConfigParser(allow_unnamed_section=True)
132+
release_config.read(release_file)
133+
134+
cname_object = CName(
135+
release_config.get(UNNAMED_SECTION, "GARDENLINUX_CNAME").strip("\"'"),
136+
commit_hash=release_config.get(
137+
UNNAMED_SECTION, "GARDENLINUX_COMMIT_ID_LONG"
138+
).strip("\"'"),
139+
version=release_config.get(
140+
UNNAMED_SECTION, "GARDENLINUX_VERSION"
141+
).strip("\"'"),
142+
)
124143

125144
if cname_object.version_and_commit_id is None:
126145
raise RuntimeError(
@@ -170,7 +189,7 @@ def upload_from_directory(
170189
commit_id_or_hash = cname_object.commit_id
171190

172191
metadata = {
173-
"platform": cname_object.feature_set_platform,
192+
"platform": cname_object.platform,
174193
"architecture": arch,
175194
"base_image": None,
176195
"build_committish": commit_id_or_hash,

test-data/gardenlinux

Submodule gardenlinux updated 627 files

tests/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
CONTAINER_NAME_ZOT_EXAMPLE = f"{REGISTRY}/{REPO_NAME}"
1515
GARDENLINUX_ROOT_DIR_EXAMPLE = f"{TEST_DATA_DIR}/gardenlinux/.build"
1616

17-
TEST_PLATFORMS = ["aws", "azure", "gcp", "openstack", "openstackbaremetal", "metal"]
17+
TEST_PLATFORMS = ["aws", "azure", "baremetal", "gcp", "openstack"]
1818
TEST_ARCHITECTURES = ["arm64", "amd64"]
1919
TEST_FEATURE_STRINGS_SHORT = ["gardener_prod"]
2020
TEST_FEATURE_SET = "_slim,base,container"

tests/features/test_parser.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@
8787
},
8888
),
8989
(
90-
"metal-khost_dev",
90+
"openstack-metal-khost_dev",
9191
{
92-
"platform": ["metal"],
92+
"platform": ["openstack"],
9393
"element": [
9494
"firewall",
9595
"log",
@@ -99,6 +99,7 @@
9999
"server",
100100
"chost",
101101
"khost",
102+
"metal"
102103
],
103104
"flag": ["_dev", "_fwcfg", "_legacy", "_selinux", "_slim"],
104105
},

tests/s3/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class S3Env:
2424

2525

2626
def make_cname(
27-
flavor: str = "container",
27+
flavor: str = "container_trustedboot_usi",
2828
arch: str = "amd64",
2929
version: str = "1234.1",
3030
commit: str = "abc123long",

tests/s3/constants.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# -*- coding: utf-8 -*-
22

33
RELEASE_DATA = """
4-
GARDENLINUX_CNAME="container-amd64-1234.1"
4+
GARDENLINUX_CNAME="container_trustedboot_usi-amd64-1234.1"
55
GARDENLINUX_VERSION=1234.1
66
GARDENLINUX_COMMIT_ID="abc123lo"
77
GARDENLINUX_COMMIT_ID_LONG="abc123long"
8+
GARDENLINUX_PLATFORM="container"
89
GARDENLINUX_FEATURES="_usi,_trustedboot"
910
GARDENLINUX_FEATURES_ELEMENTS=
1011
GARDENLINUX_FEATURES_FLAGS="_usi,_trustedboot"
@@ -25,13 +26,13 @@
2526
secureboot: true
2627
published_image_metadata: null
2728
s3_bucket: test-bucket
28-
s3_key: meta/singles/container-amd64-1234.1-abc123lo
29+
s3_key: meta/singles/container_trustedboot_usi-amd64-1234.1-abc123lo
2930
test_result: null
3031
version: '1234.1'
3132
paths:
32-
- name: container-amd64-1234.1-abc123lo.release
33+
- name: container_trustedboot_usi-amd64-1234.1-abc123lo.release
3334
s3_bucket_name: test-bucket
34-
s3_key: objects/container-amd64-1234.1-abc123lo/container-amd64-1234.1-abc123lo.release
35+
s3_key: objects/container_trustedboot_usi-amd64-1234.1-abc123lo/container_trustedboot_usi-amd64-1234.1-abc123lo.release
3536
suffix: .release
3637
md5sum: {md5sum}
3738
sha256sum: {sha256sum}

0 commit comments

Comments
 (0)