From 5369a6c873c753d84c140019f54ed8b2d2eadec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20B=C3=BCchse?= Date: Thu, 10 Sep 2026 22:06:57 +0200 Subject: [PATCH 1/2] Add testcases for scs-0104-v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit well, at least the required testcases Signed-off-by: Matthias Büchse --- Tests/iaas/openstack_test.py | 9 ++- .../standard_images.py | 78 ++++++++++++++++++- Tests/scs-compatible-iaas.yaml | 25 +++++- 3 files changed, 107 insertions(+), 5 deletions(-) diff --git a/Tests/iaas/openstack_test.py b/Tests/iaas/openstack_test.py index dd5cef2ef..4a2882226 100755 --- a/Tests/iaas/openstack_test.py +++ b/Tests/iaas/openstack_test.py @@ -33,7 +33,9 @@ from scs_0103_standard_flavors.standard_flavors import \ SCS_0103_CANONICAL_NAMES, compute_flavor_lookup, compute_scs_0103_flavor from scs_0104_standard_images.standard_images import \ - SCS_0104_IMAGE_SPECS, compute_scs_0104_source, compute_scs_0104_image + SCS_0104_IMAGE_SPECS, compute_scs_0104_source, compute_scs_0104_image, \ + compute_image_lookup_ex, compute_scs_0104_source_ex, compute_scs_0104_source_capi, \ + compute_scs_0104_image_ubuntu_latest from scs_0114_volume_types.volume_types import \ compute_volume_type_lookup, compute_scs_0114_syntax_check, compute_scs_0114_aspect_type from scs_0115_security_groups.security_groups import \ @@ -106,17 +108,22 @@ def make_container(cloud): lambda c, cn=canonical_name: compute_scs_0103_flavor(c.flavor_lookup, compute_flavor_spec(cn)) ) # scs_0104_standard_images + c.add_function('image_lookup_ex', lambda c: compute_image_lookup_ex(c.images)) + c.add_function('scs_0104_source_capi', lambda c: compute_scs_0104_source_capi(c.image_lookup)) c.add_function('scs_0104_source_capi_1', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['ubuntu-capi-image-1'])) c.add_function('scs_0104_source_capi_2', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['ubuntu-capi-image-2'])) + c.add_function('scs_0104_source_ubuntu', lambda c: compute_scs_0104_source_ex(c.image_lookup_ex, 'ubuntu')) c.add_function('scs_0104_source_ubuntu_2404', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['Ubuntu 24.04'])) c.add_function('scs_0104_source_ubuntu_2204', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['Ubuntu 22.04'])) c.add_function('scs_0104_source_ubuntu_2004', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['Ubuntu 20.04'])) + c.add_function('scs_0104_source_debian', lambda c: compute_scs_0104_source_ex(c.image_lookup_ex, 'debian')) c.add_function('scs_0104_source_debian_13', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['Debian 13'])) c.add_function('scs_0104_source_debian_12', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['Debian 12'])) c.add_function('scs_0104_source_debian_11', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['Debian 11'])) c.add_function('scs_0104_source_debian_10', lambda c: compute_scs_0104_source(c.image_lookup, SCS_0104_IMAGE_SPECS['Debian 10'])) c.add_function('scs_0104_image_capi_1', lambda c: compute_scs_0104_image(c.image_lookup, SCS_0104_IMAGE_SPECS['ubuntu-capi-image-1'])) c.add_function('scs_0104_image_capi_2', lambda c: compute_scs_0104_image(c.image_lookup, SCS_0104_IMAGE_SPECS['ubuntu-capi-image-2'])) + c.add_function('scs_0104_image_ubuntu_latest', lambda c: compute_scs_0104_image_ubuntu_latest(c.image_lookup_ex)) c.add_function('scs_0104_image_ubuntu_2404', lambda c: compute_scs_0104_image(c.image_lookup, SCS_0104_IMAGE_SPECS['Ubuntu 24.04'])) c.add_function('scs_0104_image_ubuntu_2204', lambda c: compute_scs_0104_image(c.image_lookup, SCS_0104_IMAGE_SPECS['Ubuntu 22.04'])) c.add_function('scs_0104_image_ubuntu_2004', lambda c: compute_scs_0104_image(c.image_lookup, SCS_0104_IMAGE_SPECS['Ubuntu 20.04'])) diff --git a/Tests/iaas/scs_0104_standard_images/standard_images.py b/Tests/iaas/scs_0104_standard_images/standard_images.py index 277724526..84f257249 100644 --- a/Tests/iaas/scs_0104_standard_images/standard_images.py +++ b/Tests/iaas/scs_0104_standard_images/standard_images.py @@ -1,3 +1,5 @@ +from collections import defaultdict +from datetime import date import logging import re @@ -53,6 +55,18 @@ """) SCS_0104_IMAGE_SPECS = {key: {'name': key, **val} for key, val in _specs.items()} +IMAGE_SOURCES = { + 'debian': ['https://cloud.debian.org/images/cloud/', 'https://cdimage.debian.org/cdimage/cloud/'], + 'ubuntu': ['https://cloud-images.ubuntu.com/'], +} +CAPI_RE = re.compile(r"ubuntu-capi-image( |-)v[0-9]\\.[0-9]+(\\.[0-9]+)?") +CAPI_SOURCES = [ + 'https://nbg1.your-objectstorage.com/osism/openstack-k8s-capi-images/', + 'https://swift.services.a.regiocloud.tech/swift/v1/AUTH_b182637428444b9aa302bb8d5a5a418c/openstack-k8s-capi-images/', +] +CAPI_PURPOSE = 'k8snode' +CAPI_DESC = 'https://github.com/osism/k8s-capi-images' + def _lookup_images(image_lookup, image_spec): name_scheme = image_spec.get('name_scheme') @@ -65,6 +79,18 @@ def _lookup_images(image_lookup, image_spec): return [img] +def compute_image_lookup_ex(images): + """Compute image lookup via os_distro, for all images with os_purpose=generic""" + lookup = defaultdict(list) + for img in images: + if not img.os_distro: + continue + if img.properties.get('os_purpose', '') != 'generic': + continue + lookup[img.os_distro].append(img) + return lookup + + def compute_scs_0104_source(image_lookup, image_spec): """ This test ensures that every image matching `image_spec` has the correct `image_source`. @@ -72,10 +98,13 @@ def compute_scs_0104_source(image_lookup, image_spec): For an impression of what these specs look like, refer to `SCS_0104_IMAGE_SPECS`. """ matches = _lookup_images(image_lookup, image_spec) + return _check_image_source(matches, image_spec['source']) + + +def _check_image_source(matches, sources): errors = 0 for image in matches: img_source = image.properties.get('image_source', '') - sources = image_spec['source'] if not isinstance(sources, (tuple, list)): sources = [sources] if not any(img_source.startswith(src) for src in sources): @@ -84,6 +113,32 @@ def compute_scs_0104_source(image_lookup, image_spec): return not errors +def compute_scs_0104_source_ex(image_lookup_ex, os_distro): + matches = image_lookup_ex.get(os_distro, ()) + logger.debug(f"matches for {os_distro!r}: {', '.join([match.name for match in matches]) or 'none'}") + return _check_image_source(matches, IMAGE_SOURCES[os_distro]) + + +def compute_scs_0104_source_capi( + image_lookup, rex=CAPI_RE, sources=CAPI_SOURCES, purpose=CAPI_PURPOSE, desc=CAPI_DESC, +): + matches = [img for name, img in image_lookup.items() if rex.match(name)] + logger.debug(f"matches for CAPI: {', '.join([match.name for match in matches]) or '(none)'}") + errors = 0 + if not _check_image_source(matches, sources): + errors += 1 + for img in matches: + actual = img.properties.get('os_purpose', '(not set)') + if actual != purpose: + errors += 1 + logger.error(f"Image {img.name!r} should have os_purpose {purpose!r}, has {actual!r}") + actual = img.properties.get('image_description', '(not set)') + if actual != desc: + errors += 1 + logger.error(f"Image {img.name!r} should have image_description {desc!r}, has {actual!r}") + return not errors + + def compute_scs_0104_image(image_lookup, image_spec): """ This test ensures that a certain image is present, as specified by `image_spec`. @@ -95,3 +150,24 @@ def compute_scs_0104_image(image_lookup, image_spec): logger.error(f"Missing image '{image_spec['name']}'") return False return True + + +def compute_scs_0104_image_ubuntu_latest(image_lookup_ex, os_distro='ubuntu'): + """ + This test ensures that current Ubuntu LTS is present. + """ + today = date.today() + acceptable_year = today.year - today.year % 1 + acceptable = [f'{acceptable_year % 100:2d}.04'] + if date.year == acceptable_year and today.month <= 4: + acceptable.append(f'{acceptable_year % 100 - 2}.04') + matches = [ + image + for image in image_lookup_ex.get(os_distro, ()) + if image.os_version in acceptable + ] + logger.debug(f"matches for current {os_distro!r} LTS: {', '.join([match.name for match in matches]) or '(none)'}") + if not matches: + logger.error(f"Missing generic {os_distro} image with os_version in {acceptable!r}") + return False + return True diff --git a/Tests/scs-compatible-iaas.yaml b/Tests/scs-compatible-iaas.yaml index 42f68be0d..a759b1d6a 100644 --- a/Tests/scs-compatible-iaas.yaml +++ b/Tests/scs-compatible-iaas.yaml @@ -185,12 +185,18 @@ scripts: - id: scs-0103-flavor-16v-128 description: Check presence of flavor `SCS-16V-128`. url: https://docs.scs.community/standards/scs-0103-w1-standard-flavors-implementation#automated-tests + - id: scs-0104-source-capi + description: CAPI images adhere to canonical image source, os_purpose and image_description. + url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests - id: scs-0104-source-capi-1 description: CAPI images adhere to canonical image source. url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests - id: scs-0104-source-capi-2 description: CAPI images adhere to canonical image source. url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests + - id: scs-0104-source-ubuntu + description: Ubuntu images adhere to canonical image source. + url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests - id: scs-0104-source-ubuntu-2404 description: Ubuntu 24.04 images adhere to canonical image source. url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests @@ -200,6 +206,9 @@ scripts: - id: scs-0104-source-ubuntu-2004 description: Ubuntu 20.04 images adhere to canonical image source. url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests + - id: scs-0104-source-debian + description: Debian images adhere to canonical image source. + url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests - id: scs-0104-source-debian-13 description: Debian 13 images adhere to canonical image source. url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests @@ -215,6 +224,9 @@ scripts: - id: scs-0104-image-capi-1 description: CAPI image is present (naming scheme v1). url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests + - id: scs-0104-image-ubuntu-latest + description: Current Ubuntu LTS image is present. + url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests - id: scs-0104-image-ubuntu-2404 description: Ubuntu 24.04 image is present (by name). url: https://docs.scs.community/standards/scs-0104-w1-standard-images-implementation#automated-tests @@ -458,6 +470,15 @@ modules: recommended: - scs-0104-image-capi-2 - scs-0104-image-debian-12 + - id: scs-0104-v2 + name: Standard images + url: https://docs.scs.community/standards/scs-0104-v2-standard-images + targets: + main: + - scs-0104-source-capi + - scs-0104-source-ubuntu + - scs-0104-source-debian + - scs-0104-image-ubuntu-latest - id: scs-0114-v1 name: Volume Types url: https://docs.scs.community/standards/scs-0114-v1-volume-type-standard @@ -580,9 +601,7 @@ versions: - scs-0101-v1 - scs-0102-v2 # instead of scs-0102-v1 - scs-0103-v1 - - ref: scs-0104-v1-2 - parameters: - image_spec: https://raw.githubusercontent.com/SovereignCloudStack/standards/main/Tests/iaas/scs-0104-v1-images-v5.yaml + - scs-0104-v2 # instead of scs-0104-v1 - scs-0114-v1 - scs-0115-v1 - scs-0116-v1 From f21819b40f796627952928fafe2a7695fc1544dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20B=C3=BCchse?= Date: Fri, 11 Sep 2026 09:30:52 +0200 Subject: [PATCH 2/2] Fix regular expression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the double backslash was copied from the json above, but when we parse the regex directly (without json), one backslash is what we want Signed-off-by: Matthias Büchse --- Tests/iaas/scs_0104_standard_images/standard_images.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/iaas/scs_0104_standard_images/standard_images.py b/Tests/iaas/scs_0104_standard_images/standard_images.py index 84f257249..5f50aa881 100644 --- a/Tests/iaas/scs_0104_standard_images/standard_images.py +++ b/Tests/iaas/scs_0104_standard_images/standard_images.py @@ -59,7 +59,7 @@ 'debian': ['https://cloud.debian.org/images/cloud/', 'https://cdimage.debian.org/cdimage/cloud/'], 'ubuntu': ['https://cloud-images.ubuntu.com/'], } -CAPI_RE = re.compile(r"ubuntu-capi-image( |-)v[0-9]\\.[0-9]+(\\.[0-9]+)?") +CAPI_RE = re.compile(r"ubuntu-capi-image( |-)v[0-9]\.[0-9]+(\.[0-9]+)?") CAPI_SOURCES = [ 'https://nbg1.your-objectstorage.com/osism/openstack-k8s-capi-images/', 'https://swift.services.a.regiocloud.tech/swift/v1/AUTH_b182637428444b9aa302bb8d5a5a418c/openstack-k8s-capi-images/',