From e40df25e300952718851170b17bb41ed17034916 Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 15:37:28 +0100 Subject: [PATCH 1/8] Start writing user documentation for Image finding. Just to show what to do if we don't have standardized image names any longer. Python and Shell (CLI) covered, opentofu is TBD. Signed-off-by: Kurt Garloff --- user-docs/usage-hints/find-image/find_img.py | 138 +++++++++++++++++++ user-docs/usage-hints/find-image/find_img.sh | 91 ++++++++++++ user-docs/usage-hints/find-image/index.md | 111 +++++++++++++++ 3 files changed, 340 insertions(+) create mode 100755 user-docs/usage-hints/find-image/find_img.py create mode 100755 user-docs/usage-hints/find-image/find_img.sh create mode 100644 user-docs/usage-hints/find-image/index.md diff --git a/user-docs/usage-hints/find-image/find_img.py b/user-docs/usage-hints/find-image/find_img.py new file mode 100755 index 0000000000..94e537912d --- /dev/null +++ b/user-docs/usage-hints/find-image/find_img.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# +# find-img.py +# +# Searches for an image with distribution and version +# +# (c) Kurt Garloff , 7/2025 +# SPDX-License-Identifier: MIT +"This module finds the a vanilla distribution image" + +import os +import sys +import openstack +# import logging + + +def warn(log, msg): + "warn output" + if log: + log.warn(msg) + else: + print(f"WARN: {msg}", file=sys.stderr) + + +def debug(log, msg): + "debug output" + if log: + log.debug(msg) + else: + print(f"DEBUG: {msg}", file=sys.stderr) + + +def img_sort_heuristic(images, distro, version, purpose): + """Sort list to prefer old names""" + # Do sorting magic (could be omitted) + newlist = [] + distro = distro.lower() + version = version.lower() + purpose = purpose.lower() + # 0th: Exact match old SCS naming scheme ("Ubuntu 24.04 Minimal") + for img in images: + newel = (img.id, img.name) + if img.name.lower() == f"{distro} {version} {purpose}": + newlist.append(newel) + elif img.name.lower() == f"{distro} {purpose} {version}": + newlist.append(newel) + # 1st: Exact match old SCS naming scheme ("Ubuntu 24.04") + for img in images: + newel = (img.id, img.name) + if img.name.lower() == f"{distro} {version}": + newlist.append(newel) + # 2nd: Fuzzy match old SCS naming scheme ("Ubuntu 24.04*") + for img in images: + newel = (img.id, img.name) + if img.name.lower().startswith(f"{distro} {version}") and newel not in newlist: + newlist.append(newel) + # 3rd: Even more fuzzy match old SCS naming scheme ("Ubuntu*24.04") + for img in images: + newel = (img.id, img.name) + if img.name.lower().startswith(f"{distro}") and img.name.lower().endswith(f"{version}") \ + and newel not in newlist: + newlist.append(newel) + # 4th: Rest + for img in images: + newel = (img.id, img.name) + if newel not in newlist: + newlist.append(newel) + return newlist + + +def find_image(conn, distro, version, purpose="generic", strict=False, log=None): + """Return a sorted list of ID,Name pairs that contain the wanted image. + Empty list indicates no image has been found. The list is sorted such + that (on SCS-compliant clouds), it will very likely contain the most + vanilla, most recent image as first element. + If strict is set, multiple matches are not allowed. + """ + ldistro = distro.lower() + # FIXME: The image.images() method only passes selected filters + images = [x for x in conn.image.images(os_distro=ldistro, os_version=version, + sort="name:desc,created_at:desc", visibility="public") + if x.properties.get("os_purpose") == purpose] + if len(images) == 0: + warn(log, f"No image found with os_distro={ldistro} os_version={version} os_purpose={purpose}") + # images = list(conn.image.images(os_distro=ldistro, os_version=version, + # sort="name:desc,created_at:desc")) + images = [x for x in conn.image.images(os_distro=ldistro, os_version=version, + sort="name:desc,created_at:desc") + if "os_purpose" not in x.properties] + if len(images) == 0: + warn(log, f"No image found with os_distro={ldistro} os_version={version} without os_purpose") + return [] + # Now comes sorting magic for best backwards compatibility + if len(images) > 1: + debug(log, f"Several {purpose} images found with os_distro={ldistro} os_version={version}") + if (strict): + return [] + return img_sort_heuristic(images, distro, version, purpose) + return [(img.id, img.name) for img in images] + + +def usage(): + "Usage hints (CLI)" + print("Usage: find-img.sh [-s] DISTRO VERSION [PURPOSE]", file=sys.stderr) + print("Returns all images matching, latest first, purpose defaulting to generic", file=sys.stderr) + print("[-s] sets strict mode where only one match is allowed.", file=sys.stderr) + print("You need to have OS_CLOUD set when running this", file=sys.stderr) + sys.exit(1) + + +def main(argv): + "Main entry for CLI" + if len(argv) < 3: + usage() + try: + conn = openstack.connect(cloud=os.environ["OS_CLOUD"]) + except openstack.exceptions.ConfigException: + print(f"No valid entry for cloud {os.environ['OS_CLOUD']}", file=sys.stderr) + usage() + except KeyError: + print("OS_CLOUD environment not configured", file=sys.stderr) + usage() + conn.authorize() + purpose = "generic" + strict = False + if argv[1] == "-s": + argv = argv[1:] + strict = True + if len(argv) > 3: + purpose = argv[3] + images = find_image(conn, argv[1], argv[2], purpose, strict) + for img in images: + print(f"{img[0]} {img[1]}") + return len(images) == 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/user-docs/usage-hints/find-image/find_img.sh b/user-docs/usage-hints/find-image/find_img.sh new file mode 100755 index 0000000000..43c8af50e8 --- /dev/null +++ b/user-docs/usage-hints/find-image/find_img.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# +# Find Image by properties +# +# (c) Kurt Garloff , 7/2025 +# SPDX-License-Identifier: MIT + +usage() +{ + echo "Usage: find-img distro version [purpose]" + echo "Returns all images matching, latest first, purpose defaults to generic" + echo "If some images have the wanted purpose, only those will be shown" +} + +get_images_raw() +{ + # global OS_RESP + DIST=$(echo "$1" | tr A-Z a-z) + VERS="$2" + #VERS=$(echo "$2" | tr A-Z a-z) + shift; shift + #echo "DEBUG: openstack image list --property os_distro=$DIST --property os_version=$VERS $@ -f value -c ID -c Name --sort created_at:desc" + OS_RESP=$(openstack image list --property os_distro="$DIST" --property os_version="$VERS" $@ -f value -c ID -c Name --sort name:desc,created_at:desc) +} + + +img_sort_heuristic() +{ + # Acts on global OS_RESP + # FIXME: We could do all sorts of advanced heuristics here, looking at the name etc. + # We only do one thing here: Sort the image that matches the old naming scheme first. + # distro version purpose + local NEW_RESP0=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 $2 $3\$") + # distro version purpose with extras appended + local NEW_RESP1=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 $2 $3" | grep -iv "^[0-9a-f\-]* $1 $2 $3\$") + # distro purpose version + local NEW_RESP2=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 $3 $2\$") + # distro purpose version with extras appended + local NEW_RESP3=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 $3 $2" | grep -iv "^[0-9a-f\-]* $1 $3 $2\$") + # distro version + local NEW_RESP4=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 $2\$") + # distro version with extras (but not purpose) + local NEW_RESP5=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 $2" | grep -iv "^[0-9a-f\-]* $1 $2\$" | grep -iv "^[0-9a-f\-]* $1 $2 $3") + # distro extra version (but extra != purpose) + local NEW_RESP6=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 .*$2\$" | grep -iv "^[0-9a-f\-]* $1 $3 $2\$" | grep -iv "$1 $2\$") + OS_RESP=$(echo -e "$NEW_RESP0\n$NEW_RESP1\n$NEW_RESP2\n$NEW_RESP3\n$NEW_RESP4\n$NEW_RESP5\n$NEW_RESP6" | sed '/^$/d') +} + +get_images() +{ + PURPOSE=${3:-generic} + get_images_raw "$1" "$2" --property os_purpose=$PURPOSE + if test -z "$OS_RESP"; then + echo "WARN: No image found with os_distro=$1 os_version=$2 os_purpose=$PURPOSE" 1>&2 + # We're screwed as we can not filter for the absence of os_purpose with CLI + # We could loop and do an image show and then flter out, but that's very slow + get_images_raw "$1" "$2" # --property os_purpose= + # FIXME: We need to filter out images with os_purpose property set + NEW_RESP="" + while read ID Name; do + PROPS=$(openstack image show $ID -f value -c properties) + if test $? != 0; then continue; fi + if echo "$PROPS" | grep os_purpose >/dev/null 2>&1; then continue; fi + NEW_RESP=$(echo -en "$NEW_RESP\n$ID $Name") + done < <(echo "$OS_RESP") + OS_RESP=$(echo "$NEW_RESP" | sed '/^$/d') + fi + NR_IMG=$(echo "$OS_RESP" | sed '/^$/d' | wc -l) + if test "$NR_IMG" = "0"; then echo "ERROR: No image found with os_distro=$1 os_version=$2" 1>&2; return 1 + elif test "$NR_IMG" = "1"; then return 0 + else + echo "DEBUG: Several $PURPOSE images matching os_distro=$1 os_version=$2" 1>&2; + if test -n "$STRICT"; then return 1; fi + img_sort_heuristic "$1" "$2" "$PURPOSE" + return 0 + fi +} + +if test -z "$OS_CLOUD" -a -z "$OS_AUTH_URL"; then + echo "You need to configure clouds.yaml/secure.yaml and set OS_CLOUD" 1>&2 + exit 2 +fi +if test -z "$1"; then + usage + exit 1 +fi + +get_images "$@" +RC=$? +echo "$OS_RESP" +(exit $RC) diff --git a/user-docs/usage-hints/find-image/index.md b/user-docs/usage-hints/find-image/index.md new file mode 100644 index 0000000000..d9d84b40b1 --- /dev/null +++ b/user-docs/usage-hints/find-image/index.md @@ -0,0 +1,111 @@ +--- +layout: post +title: 'Locating provider-managed images' +author: + - 'Kurt Garloff' +avatar: + - 'kgarloff.jpg' +--- + +## Purpose + +Many providers provide public images that they maintain for user convenience. +Maintenance means that they regularly update it to include the latest bug- and +security fixes. The exact policy is transparent from the image metadata as +specified in SCS standard [scs-0102](https://docs.scs.community/standards/iaas/scs-0102). +A few images have to be managed this way by the provider according to +[scs-0104](https://docs.scs.community/standards/iaas/scs-0104). +Previously (with [scs-0102-v1](https://docs.scs.community/standards/scs-0102-v1-image-metadata)) +the image could be referenced by a standard name to always get the current +image whereas a reference by UUID would result in an unchanged image (until +it is removed according to the provider's policy that is transparent from +the metadata). + +Some providers prefer to use different image names. We intend to allow this with +[scs-0102-v2](https://docs.scs.community/standards/scs-0102-v2-image-metadata). +This however means that identifying the most recent "Ubuntu 24.04" image on +an SCS-compatible IaaS cloud becomes a bit harder in a portable way. +This article describes how to do this. + +## The new `os_purpose` property + +While we suggest to rename or better to hide old images, there can still legitimately +be several variants of images, e.g. minimal variants or Kubernetes node images etc. +These must not be confused with the standard general purpose images. To avoid +confusion, we have introduce a new `os_purpose` (recommended in v1.1 of scs-0102 +and mandatory in v2) field, that can be set to `generic`, `minimal`, `k8snode`, +`gpu`, `network`, or `custom` in v2. +To now find the latest general purpose Ubuntu Noble Numbat 24.04 image, one can search the +image catalog for `os_distro=ubuntu`, `os_version=24.04`, and `os_purpose=generic`. +This is straightforward if all SCS clouds already comply to the new metadata standard +and only have one matching image. +It's a bit more complex in case we have to deal with a mixture of old and new ... + +## Identifying the right image using python (openstack-SDK) + +To find the Ubuntu 24.04 generic image, we would just do + +```python + images = [x for x in conn.image.images(os_distro=distro, os_version=version, + sort="name:desc,created_at:desc") + if x.properties.get("os_purpose") == purpose] +``` + +where `conn` is a connection to your OpenStack project and `distro`, `version` and +`purpose` have been set to the lowercase strings you are looking for. + +Three notes: + +- We use a list comprehension to filter for `os_purpose` because `os_purpose` + is not one of the hardcoded properties that the SDK knows unlike `os_distro` + and `os_version`. +- We can add additional filtering such as `visibility="public"` if we just want + to look for public images. +- We sort the list, so in case we have several matches, we want the images grouped + by image name and within the same name have the latest images first. This would + typically find the latest image both in the case where a provider renames old + images "Ubuntu 24.04" to "Ubuntu 24.04 timestamp" or fails to rename them. + (The latter would not be compliant with scs-0102.) + +It gets a bit harder when you want SCS clouds that comply to the old v1 standard +and do not yet have the `os_purpose` field set. Above call then returns an empty +list. We then would fall back to look for images that match `os_distro` and +`os_version`, but have no `os_purpose` property. + +```python + images = [x for x in conn.image.images(os_distro=distro, os_version=version, + sort="name:desc,created_at:desc") + if "os_purpose" not in x.properties] +``` + +We have to expect several matches here and need some heuristic to find the +right image, preferrably the one matching the old naming convention. + +Full code that does this is available in [find_img.py](find_img.py). +Feel free to copy, I deliberately put this under MIT license. + +## Identifying the image with OpenStack CLI + +Unlike with Python, we can pass the `os_purpose` field just like the other +properties. + +```bash + openstack image list --property os_distro="$DIST" --property os_version="$VERS" --property os_purpose="$PURP" -f value -c ID -c Name --sort name:desc,created_at:desc +``` + +where `OS_CLOUD` environment has been configured to access your cloud project and +`DIST`, `VERS` and `PURP` are set to the lowercased image properties you +are looking for. An additional filter `--public` parameter could be passed to only +list public images. See above python comment for the sorting rationale. + +Dealing with old SCS clouds (not yet implementing v2 of scs-0102) is harder +with shell code. The reason is that we can not pass a flag to `openstack +image list` that would tell it to restrict results to records without an +`os_purpose` property. So this requires looping over the images and filtering +out all images with `os_purpose` (but not matching our request). + +Full code that does this is available in [find_img.sh](find_img.sh). + +## Terraform / opentofu + +TBW From a47a6afc9c0513eaa90f0f7b72b33ec78c7b5f4c Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 15:48:51 +0100 Subject: [PATCH 2/8] Wording improvements Signed-off-by: Kurt Garloff --- user-docs/usage-hints/find-image/index.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/user-docs/usage-hints/find-image/index.md b/user-docs/usage-hints/find-image/index.md index d9d84b40b1..f7b36bbe29 100644 --- a/user-docs/usage-hints/find-image/index.md +++ b/user-docs/usage-hints/find-image/index.md @@ -32,9 +32,9 @@ This article describes how to do this. While we suggest to rename or better to hide old images, there can still legitimately be several variants of images, e.g. minimal variants or Kubernetes node images etc. These must not be confused with the standard general purpose images. To avoid -confusion, we have introduce a new `os_purpose` (recommended in v1.1 of scs-0102 +confusion, we have introduced a new `os_purpose` (recommended in v1.1 of scs-0102 and mandatory in v2) field, that can be set to `generic`, `minimal`, `k8snode`, -`gpu`, `network`, or `custom` in v2. +`gpu`, `network`, or `custom` according to scs-0102-v2. To now find the latest general purpose Ubuntu Noble Numbat 24.04 image, one can search the image catalog for `os_distro=ubuntu`, `os_version=24.04`, and `os_purpose=generic`. This is straightforward if all SCS clouds already comply to the new metadata standard @@ -63,7 +63,7 @@ Three notes: to look for public images. - We sort the list, so in case we have several matches, we want the images grouped by image name and within the same name have the latest images first. This would - typically find the latest image both in the case where a provider renames old + typically put the latest image first in the case where a provider renames old images "Ubuntu 24.04" to "Ubuntu 24.04 timestamp" or fails to rename them. (The latter would not be compliant with scs-0102.) @@ -102,7 +102,9 @@ Dealing with old SCS clouds (not yet implementing v2 of scs-0102) is harder with shell code. The reason is that we can not pass a flag to `openstack image list` that would tell it to restrict results to records without an `os_purpose` property. So this requires looping over the images and filtering -out all images with `os_purpose` (but not matching our request). +out all images with `os_purpose` (but not matching our request). We would +have to expect several matches now again and sort them by a heuristic, +somewhat similar (but not identical) to the python code. Full code that does this is available in [find_img.sh](find_img.sh). From 5508dcf4f2eee59730ad58e3763abf5595a30310 Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 15:56:56 +0100 Subject: [PATCH 3/8] Tiny code improvements. Signed-off-by: Kurt Garloff --- user-docs/usage-hints/find-image/.flake8 | 2 ++ user-docs/usage-hints/find-image/find_img.py | 14 ++++++++------ user-docs/usage-hints/find-image/find_img.sh | 16 ++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 user-docs/usage-hints/find-image/.flake8 diff --git a/user-docs/usage-hints/find-image/.flake8 b/user-docs/usage-hints/find-image/.flake8 new file mode 100644 index 0000000000..e44b810841 --- /dev/null +++ b/user-docs/usage-hints/find-image/.flake8 @@ -0,0 +1,2 @@ +[flake8] +ignore = E501 diff --git a/user-docs/usage-hints/find-image/find_img.py b/user-docs/usage-hints/find-image/find_img.py index 94e537912d..52fd03e3f4 100755 --- a/user-docs/usage-hints/find-image/find_img.py +++ b/user-docs/usage-hints/find-image/find_img.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 # -# find-img.py +# find_img.py # -# Searches for an image with distribution and version +# Searches for an image with distribution and version and purpose # # (c) Kurt Garloff , 7/2025 # SPDX-License-Identifier: MIT @@ -71,17 +71,19 @@ def img_sort_heuristic(images, distro, version, purpose): def find_image(conn, distro, version, purpose="generic", strict=False, log=None): """Return a sorted list of ID,Name pairs that contain the wanted image. Empty list indicates no image has been found. The list is sorted such - that (on SCS-compliant clouds), it will very likely contain the most - vanilla, most recent image as first element. + that (on SCS-compliant clouds), it will very likely contain the best + matching, most recent image as first element. If strict is set, multiple matches are not allowed. """ ldistro = distro.lower() # FIXME: The image.images() method only passes selected filters + purpose_out = purpose images = [x for x in conn.image.images(os_distro=ldistro, os_version=version, sort="name:desc,created_at:desc", visibility="public") if x.properties.get("os_purpose") == purpose] if len(images) == 0: warn(log, f"No image found with os_distro={ldistro} os_version={version} os_purpose={purpose}") + purpose_out = "" # images = list(conn.image.images(os_distro=ldistro, os_version=version, # sort="name:desc,created_at:desc")) images = [x for x in conn.image.images(os_distro=ldistro, os_version=version, @@ -92,8 +94,8 @@ def find_image(conn, distro, version, purpose="generic", strict=False, log=None) return [] # Now comes sorting magic for best backwards compatibility if len(images) > 1: - debug(log, f"Several {purpose} images found with os_distro={ldistro} os_version={version}") - if (strict): + debug(log, f"Several {purpose_out} images found with os_distro={ldistro} os_version={version}") + if strict: return [] return img_sort_heuristic(images, distro, version, purpose) return [(img.id, img.name) for img in images] diff --git a/user-docs/usage-hints/find-image/find_img.sh b/user-docs/usage-hints/find-image/find_img.sh index 43c8af50e8..fd379588e2 100755 --- a/user-docs/usage-hints/find-image/find_img.sh +++ b/user-docs/usage-hints/find-image/find_img.sh @@ -7,7 +7,7 @@ usage() { - echo "Usage: find-img distro version [purpose]" + echo "Usage: find-img [-s] distro version [purpose]" echo "Returns all images matching, latest first, purpose defaults to generic" echo "If some images have the wanted purpose, only those will be shown" } @@ -28,7 +28,7 @@ img_sort_heuristic() { # Acts on global OS_RESP # FIXME: We could do all sorts of advanced heuristics here, looking at the name etc. - # We only do one thing here: Sort the image that matches the old naming scheme first. + # We only do a few pattern matches here # distro version purpose local NEW_RESP0=$(echo "$OS_RESP" | grep -i "^[0-9a-f\-]* $1 $2 $3\$") # distro version purpose with extras appended @@ -48,10 +48,12 @@ img_sort_heuristic() get_images() { - PURPOSE=${3:-generic} + PURPOSE="${3:-generic}" + PURP="$PURPOSE" get_images_raw "$1" "$2" --property os_purpose=$PURPOSE if test -z "$OS_RESP"; then echo "WARN: No image found with os_distro=$1 os_version=$2 os_purpose=$PURPOSE" 1>&2 + PURP="" # We're screwed as we can not filter for the absence of os_purpose with CLI # We could loop and do an image show and then flter out, but that's very slow get_images_raw "$1" "$2" # --property os_purpose= @@ -69,7 +71,7 @@ get_images() if test "$NR_IMG" = "0"; then echo "ERROR: No image found with os_distro=$1 os_version=$2" 1>&2; return 1 elif test "$NR_IMG" = "1"; then return 0 else - echo "DEBUG: Several $PURPOSE images matching os_distro=$1 os_version=$2" 1>&2; + echo "DEBUG: Several $PURP images matching os_distro=$1 os_version=$2" 1>&2; if test -n "$STRICT"; then return 1; fi img_sort_heuristic "$1" "$2" "$PURPOSE" return 0 @@ -80,10 +82,8 @@ if test -z "$OS_CLOUD" -a -z "$OS_AUTH_URL"; then echo "You need to configure clouds.yaml/secure.yaml and set OS_CLOUD" 1>&2 exit 2 fi -if test -z "$1"; then - usage - exit 1 -fi +if test "$1" = "-s"; then STRICT=1; shift; fi +if test -z "$1"; then usage; exit 1; fi get_images "$@" RC=$? From 819538bcc4a9c33236593ecba27b5e5851dccf8b Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 16:07:17 +0100 Subject: [PATCH 4/8] Comment out link to not yet existing standard version. scs-0102-v2 is not there yet ... Signed-off-by: Kurt Garloff --- user-docs/usage-hints/find-image/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user-docs/usage-hints/find-image/index.md b/user-docs/usage-hints/find-image/index.md index f7b36bbe29..e543678b69 100644 --- a/user-docs/usage-hints/find-image/index.md +++ b/user-docs/usage-hints/find-image/index.md @@ -22,7 +22,7 @@ it is removed according to the provider's policy that is transparent from the metadata). Some providers prefer to use different image names. We intend to allow this with -[scs-0102-v2](https://docs.scs.community/standards/scs-0102-v2-image-metadata). +scs-0102-v2. This however means that identifying the most recent "Ubuntu 24.04" image on an SCS-compatible IaaS cloud becomes a bit harder in a portable way. This article describes how to do this. From b634819344c7e44d2e0114b105eabf55e8121f7b Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 16:20:11 +0100 Subject: [PATCH 5/8] Try to avoid matching double space in tables. This fixes the markdownlint rule. Signed-off-by: Kurt Garloff --- .markdownlint-cli2.jsonc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc index eb066754bf..a3753a7327 100644 --- a/.markdownlint-cli2.jsonc +++ b/.markdownlint-cli2.jsonc @@ -44,8 +44,8 @@ { "name": "double-spaces", "message": "Avoid double spaces", - "searchPattern": "/([^\\s>]) ([^\\s|])/g", - "replace": "$1 $2", + "searchPattern": "/^([^|].*)([^\\s>]) ([^\\s|])/g", + "replace": "$1 $2 $3", "skipCode": true } ] From 72d84519dc3668b5dced2d96dff0e71f4e76a53f Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 17:08:03 +0100 Subject: [PATCH 6/8] Add to sidebar. (1st attempt.) Signed-off-by: Kurt Garloff --- sidebarsUserDocs.js | 9 +++++++++ user-docs/usage-hints/index.md | 7 +++++++ 2 files changed, 16 insertions(+) create mode 100644 user-docs/usage-hints/index.md diff --git a/sidebarsUserDocs.js b/sidebarsUserDocs.js index c05de04316..c53be1834a 100644 --- a/sidebarsUserDocs.js +++ b/sidebarsUserDocs.js @@ -28,6 +28,15 @@ const sidebars = { ] } ] + }, + { + type: 'category', + label: 'Portability Hints', + link: { + type: 'doc', + id: 'usage-hints/index' + }, + items: ['usage-hints/find-image'] } ] } diff --git a/user-docs/usage-hints/index.md b/user-docs/usage-hints/index.md new file mode 100644 index 0000000000..5b7daa087b --- /dev/null +++ b/user-docs/usage-hints/index.md @@ -0,0 +1,7 @@ +--- +title: Overview +--- + +We collect and document best practices that allow developers +to benefit from the SCS standardization and create automation +that works across SCS clouds. From 2961b4fa4178986c00eff4a7fc0b0f5f7888c782 Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 17:12:27 +0100 Subject: [PATCH 7/8] Link index file explicitly. Signed-off-by: Kurt Garloff --- sidebarsUserDocs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sidebarsUserDocs.js b/sidebarsUserDocs.js index c53be1834a..527c226395 100644 --- a/sidebarsUserDocs.js +++ b/sidebarsUserDocs.js @@ -36,7 +36,7 @@ const sidebars = { type: 'doc', id: 'usage-hints/index' }, - items: ['usage-hints/find-image'] + items: ['usage-hints/find-image/index'] } ] } From 0a6d2f8868faf5efef06a1020e7974da972a3148 Mon Sep 17 00:00:00 2001 From: Kurt Garloff Date: Wed, 26 Nov 2025 18:54:06 +0100 Subject: [PATCH 8/8] Add link to diskless flavor article w/ sidebar link. Signed-off-by: Kurt Garloff --- sidebarsUserDocs.js | 5 +++- .../usage-hints/diskless-flavor/index.md | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 user-docs/usage-hints/diskless-flavor/index.md diff --git a/sidebarsUserDocs.js b/sidebarsUserDocs.js index 527c226395..db8ae61a89 100644 --- a/sidebarsUserDocs.js +++ b/sidebarsUserDocs.js @@ -36,7 +36,10 @@ const sidebars = { type: 'doc', id: 'usage-hints/index' }, - items: ['usage-hints/find-image/index'] + items: [ + 'usage-hints/find-image/index', + 'usage-hints/diskless-flavor/index' + ] } ] } diff --git a/user-docs/usage-hints/diskless-flavor/index.md b/user-docs/usage-hints/diskless-flavor/index.md new file mode 100644 index 0000000000..bad72771f0 --- /dev/null +++ b/user-docs/usage-hints/diskless-flavor/index.md @@ -0,0 +1,23 @@ +--- +layout: post +title: 'Preferring diskless flavors in SCS' +author: + - 'Kurt Garloff' +--- + +## Purpose + +Sovereign Cloud Stack (SCS) downgraded the formerly mandatory flavors with +root disks to recommended ones when the flavor naming standard version 3 +became effective in the fall 2023. For many users using flavors that comprise +a root disk is still the standard and at least when using CLI tooling, +it's also simpler. + +This article documents how the diskless flavors can be used with common +IaC tooling. + +## Link to blog article + +We covered this in a blog article before, for which we +[link here](https://scs.community/2023/08/21/diskless-flavors/) to our +old web site for now.