Skip to content

templates: add almalinux-kitten-10 #3084

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 287 additions & 0 deletions hack/update-template-almalinux-kitten.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
#!/usr/bin/env bash

# SPDX-FileCopyrightText: Copyright The Lima Authors
# SPDX-License-Identifier: Apache-2.0

set -eu -o pipefail

# Functions in this script assume error handling with 'set -e'.
# To ensure 'set -e' works correctly:
# - Use 'set +e' before assignments and '$(set -e; <function>)' to capture output without exiting on errors.
# - Avoid calling functions directly in conditions to prevent disabling 'set -e'.
# - Use 'shopt -s inherit_errexit' (Bash 4.4+) to avoid repeated 'set -e' in all '$(...)'.
shopt -s inherit_errexit || error_exit "inherit_errexit not supported. Please use bash 4.4 or later."

function almalinux_print_help() {
cat <<HELP
$(basename "${BASH_SOURCE[0]}"): Update the AlmaLinux Kitten image location in the specified templates

Usage:
$(basename "${BASH_SOURCE[0]}") [--version-major <major version>] <template.yaml>...

Description:
This script updates the AlmaLinux Kitten image location in the specified templates.
If the image location in the template contains a minor version and release date in the URL,
the script replaces it with the latest available minor version and date.

Image location basename format:

AlmaLinux-Kitten-GenericCloud-<major version>-[latest|<date>.<release>].<arch>.qcow2

Published AlmaLinux Kitten image information is fetched from the following URLs:

https://kitten.repo.almalinux.org/<major version>-kitten/cloud/<arch>/images/

To parsing html, this script requires 'htmlq' or 'pup' command.
The downloaded files will be cached in the Lima cache directory.

Examples:
Update the AlmaLinux Kitten image location in templates/**.yaml:
$ $(basename "${BASH_SOURCE[0]}") templates/**.yaml

Update the AlmaLinux Kitten image location in ~/.lima/almalinux-kitten/lima.yaml:
$ $(basename "${BASH_SOURCE[0]}") ~/.lima/almalinux-kitten/lima.yaml
$ limactl factory-reset almalinux-kitten

Update the AlmaLinux Kitten image location to major version 10 in ~/.lima/almalinux-kitten/lima.yaml:
$ $(basename "${BASH_SOURCE[0]}") --version-major 10 ~/.lima/almalinux-kitten/lima.yaml
$ limactl factory-reset almalinux-kitten

Flags:
--version-major <version> Use the specified version. The version must be 10 or later.
-h, --help Print this help message
HELP
}

# print the URL spec for the given location
function almalinux_url_spec_from_location() {
local location=$1 jq_filter url_spec
jq_filter='capture(
"^https://kitten\\.repo\\.almalinux\\.org/(?<path_version>\\d+)-kitten/cloud/(?<path_arch>[^/]+)/images/" +
"AlmaLinux-Kitten-(?<target_vendor>.*)-(?<major_version>\\d+)-" +
"(latest|(?<date>\\d{8}(\\\\d+)?))\\.(?<release>\\d+)\\.(?<arch>[^.]+).(?<file_extension>.*)$"
;"x")
'
url_spec=$(jq -e -r "${jq_filter}" <<<"\"${location}\"")

jq -e '.path_arch == .arch' <<<"${url_spec}" >/dev/null ||
error_exit "Validation failed: .path_arch != .arch: ${location}"
echo "${url_spec}"
}

readonly almalinux_jq_filter_directory='"https://kitten.repo.almalinux.org/\(.path_version)-kitten/cloud/\(.path_arch)/images/"'
readonly almalinux_jq_filter_filename='"AlmaLinux-Kitten-\(.target_vendor)-\(.major_version)-\(if .date then .date + ".0" else "latest" end).\(.arch).\(.file_extension)"'

# print the location for the given URL spec
function almalinux_location_from_url_spec() {
local -r url_spec=$1
jq -e -r "${almalinux_jq_filter_directory} + ${almalinux_jq_filter_filename}" <<<"${url_spec}" ||
error_exit "Failed to get the location for ${url_spec}"
}

function almalinux_image_directory_from_url_spec() {
local -r url_spec=$1
jq -e -r "${almalinux_jq_filter_directory}" <<<"${url_spec}" ||
error_exit "Failed to get the image directory for ${url_spec}"
}

function almalinux_image_filename_from_url_spec() {
local -r url_spec=$1
jq -e -r "${almalinux_jq_filter_filename}" <<<"${url_spec}" ||
error_exit "Failed to get the image filename for ${url_spec}"
}

#
function almalinux_latest_image_entry_for_url_spec() {
local url_spec=$1 arch major_version_url_spec major_version_image_directory downloaded_page links_in_page latest_minor_version_info
arch=$(jq -r '.arch' <<<"${url_spec}")
# to detect minor version updates, we need to get the major version URL
major_version_url_spec=$(jq -e -r '.path_version = .major_version' <<<"${url_spec}")
major_version_image_directory=$(almalinux_image_directory_from_url_spec "${major_version_url_spec}")
downloaded_page=$(download_to_cache "${major_version_image_directory}")
if command -v htmlq >/dev/null; then
links_in_page=$(htmlq 'pre a' --attribute href <"${downloaded_page}")
elif command -v pup >/dev/null; then
links_in_page=$(pup 'pre a attr{href}' <"${downloaded_page}")
else
error_exit "Please install 'htmlq' or 'pup' to list images from ${major_version_image_directory}"
fi
latest_minor_version_info=$(jq -e -Rrs --argjson spec "${url_spec}" '
[
split("\n").[] |
capture(
"^AlmaLinux-Kitten-\($spec.target_vendor)-" +
"(?<major_minor_version>\($spec.major_version))-" +
"(?<date>\\d{8})\\.(?<release>\\d)+\\.\($spec.arch)\\.\($spec.file_extension)$"
;"x"
) |
.version_number_array = ([.major_minor_version | scan("\\d+") | tonumber])
] | sort_by(.version_number_array, .date_and_ci_job_id) | last
' <<<"${links_in_page}")
[[ -n ${latest_minor_version_info} ]] || return
local newer_url_spec location directory checksum_location downloaded_sha256sum filename digest
# prefer the major_minor_version in the path
newer_url_spec=$(jq -e -r ". + ${latest_minor_version_info} | .path_version = .major_minor_version" <<<"${url_spec}")
location=$(almalinux_location_from_url_spec "${newer_url_spec}")
directory=$(almalinux_image_directory_from_url_spec "${newer_url_spec}")
checksum_location="${directory}CHECKSUM"
downloaded_sha256sum=$(download_to_cache "${checksum_location}")
filename=$(almalinux_image_filename_from_url_spec "${newer_url_spec}")
digest=$(awk "/${filename}/{print \"sha256:\"\$1}" "${downloaded_sha256sum}")
[[ -n ${digest} ]] || error_exit "Failed to get the SHA256 digest for ${filename}"
json_vars location arch digest
}

function almalinux_cache_key_for_image_kernel() {
local location=$1 url_spec
url_spec=$(almalinux_url_spec_from_location "${location}")
jq -r '["almalinux-kitten", .major_minor_version // .major_version, .target_vendor,
if .date then "timestamped" else "latest" end,
.arch, .file_extension] | join(":")' <<<"${url_spec}"
}

function almalinux_image_entry_for_image_kernel() {
local location=$1 kernel_is_not_supported=$2 overriding=${3:-"{}"} url_spec image_entry=''
[[ ${kernel_is_not_supported} == "null" ]] || echo "Updating kernel information is not supported on AlmaLinux Kitten" >&2
url_spec=$(almalinux_url_spec_from_location "${location}" | jq -r ". + ${overriding}")
if jq -e '.date' <<<"${url_spec}" >/dev/null; then
image_entry=$(almalinux_latest_image_entry_for_url_spec "${url_spec}")
else
image_entry=$(
# shellcheck disable=SC2030
location=$(almalinux_location_from_url_spec "${url_spec}")
location=$(validate_url_without_redirect "${location}")
arch=$(jq -r '.path_arch' <<<"${url_spec}")
json_vars location arch
)
fi
# shellcheck disable=SC2031
if [[ -z ${image_entry} ]]; then
error_exit "Failed to get the ${url_spec} image location for ${location}"
elif jq -e ".location == \"${location}\"" <<<"${image_entry}" >/dev/null; then
echo "Image location is up-to-date: ${location}" >&2
else
echo "${image_entry}"
fi
}

# check if the script is executed or sourced
# shellcheck disable=SC1091
if [[ ${BASH_SOURCE[0]} == "${0}" ]]; then
scriptdir=$(dirname "${BASH_SOURCE[0]}")
# shellcheck source=./cache-common-inc.sh
. "${scriptdir}/cache-common-inc.sh"

if ! command -v htmlq >/dev/null && ! command -v pup >/dev/null; then
error_exit "Please install 'htmlq' or 'pup' to list images from https://kitten.repo.almalinux.org/<version>-kitten/cloud/<arch>/images/"
fi
# shellcheck source=/dev/null # avoid shellcheck hangs on source looping
. "${scriptdir}/update-template.sh"
else
# this script is sourced
if ! command -v htmlq >/dev/null && ! command -v pup >/dev/null; then
echo "Please install 'htmlq' or 'pup' to list images from https://kitten.repo.almalinux.org/<version>-kitten/cloud/<arch>/images/" >&2
elif [[ -v SUPPORTED_DISTRIBUTIONS ]]; then
SUPPORTED_DISTRIBUTIONS+=("almalinux-kitten")
else
declare -a SUPPORTED_DISTRIBUTIONS=("almalinux-kitten")
fi
return 0
fi

declare -a templates=()
declare overriding="{}"
while [[ $# -gt 0 ]]; do
case "$1" in
-h | --help)
almalinux_print_help
exit 0
;;
-d | --debug) set -x ;;
--version-major)
if [[ -n $2 && $2 != -* ]]; then
overriding=$(
major_version="${2%%.*}"
[[ ${major_version} -ge 10 ]] || error_exit "AlmaLinux Kitten major version must be 8 or later"
# shellcheck disable=2034
path_version="${major_version}"
json_vars path_version major_version <<<"${overriding}"
)
shift
else
error_exit "--version-major requires a value"
fi
;;
--version-major=*)
overriding=$(
major_version="${1#*=}"
major_version="${major_version%%.*}"
[[ ${major_version} -ge 10 ]] || error_exit "AlmaLinux Kitten major version must be 8 or later"
# shellcheck disable=2034
path_version="${major_version}"
json_vars path_version major_version <<<"${overriding}"
)
;;
*.yaml) templates+=("$1") ;;
*)
error_exit "Unknown argument: $1"
;;
esac
shift
[[ -z ${overriding} ]] && overriding="{}"
done

if [[ ${#templates[@]} -eq 0 ]]; then
almalinux_print_help
exit 0
fi

declare -A image_entry_cache=()

for template in "${templates[@]}"; do
echo "Processing ${template}"
# 1. extract location by parsing template using arch
yq_filter="
.images[] | [.location, .kernel.location, .kernel.cmdline] | @tsv
"
parsed=$(yq eval "${yq_filter}" "${template}")

# 3. get the image location
arr=()
while IFS= read -r line; do arr+=("${line}"); done <<<"${parsed}"
locations=("${arr[@]}")
for ((index = 0; index < ${#locations[@]}; index++)); do
[[ ${locations[index]} != "null" ]] || continue
set -e
IFS=$'\t' read -r location kernel_location kernel_cmdline <<<"${locations[index]}"
set +e # Disable 'set -e' to avoid exiting on error for the next assignment.
cache_key=$(
set -e # Enable 'set -e' for the next command.
almalinux_cache_key_for_image_kernel "${location}" "${kernel_location}"
) # Check exit status separately to prevent disabling 'set -e' by using the function call in the condition.
# shellcheck disable=2181
[[ $? -eq 0 ]] || continue
image_entry=$(
set -e # Enable 'set -e' for the next command.
if [[ -v image_entry_cache[${cache_key}] ]]; then
echo "${image_entry_cache[${cache_key}]}"
else
almalinux_image_entry_for_image_kernel "${location}" "${kernel_location}" "${overriding}"
fi
) # Check exit status separately to prevent disabling 'set -e' by using the function call in the condition.
# shellcheck disable=2181
[[ $? -eq 0 ]] || continue
set -e
image_entry_cache[${cache_key}]="${image_entry}"
if [[ -n ${image_entry} ]]; then
[[ ${kernel_cmdline} != "null" ]] &&
jq -e 'has("kernel")' <<<"${image_entry}" >/dev/null &&
image_entry=$(jq ".kernel.cmdline = \"${kernel_cmdline}\"" <<<"${image_entry}")
echo "${image_entry}" | jq
limactl edit --log-level error --set "
.images[${index}] = ${image_entry}|
(.images[${index}] | ..) style = \"double\"
" "${template}"
fi
done
done
2 changes: 2 additions & 0 deletions hack/update-template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ if [[ ${BASH_SOURCE[0]} == "${0}" ]]; then
. "${scriptdir}/update-template-centos-stream.sh"
# shellcheck source=./update-template-almalinux.sh
. "${scriptdir}/update-template-almalinux.sh"
# shellcheck source=./update-template-almalinux-kitten.sh
. "${scriptdir}/update-template-almalinux-kitten.sh"
# shellcheck source=./update-template-rocky.sh
. "${scriptdir}/update-template-rocky.sh"
# shellcheck source=./update-template-alpine.sh
Expand Down
1 change: 1 addition & 0 deletions templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Default: [`default`](./default.yaml) (⭐Ubuntu, with containerd/nerdctl)
Distro:
- [`almalinux-8`](./almalinux-8.yaml): AlmaLinux 8
- [`almalinux-9`](./almalinux-9.yaml), `almalinux.yaml`: AlmaLinux 9
- [`almalinux-kitten-10`](./almalinux-kitten-10.yaml), `almalinux-kitten.yaml`: AlmaLinux Kitten 10
- [`alpine`](./alpine.yaml): ☆Alpine Linux
- [`alpine-iso`](./alpine-iso.yaml): ☆Alpine Linux (ISO9660 image). Compatible with the `alpine` template used in Lima prior to v1.0.
- [`archlinux`](./archlinux.yaml): ☆Arch Linux
Expand Down
25 changes: 25 additions & 0 deletions templates/almalinux-kitten-10.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This template requires Lima v0.11.1 or later.

images:
- location: "https://kitten.repo.almalinux.org/10-kitten/cloud/x86_64/images/AlmaLinux-Kitten-GenericCloud-10-20241227.0.x86_64.qcow2"
arch: "x86_64"
digest: "sha256:cb06a7fd9829c7fdb318963703dea3822e509af0d93e786225d79be7200bdbeb"
- location: "https://kitten.repo.almalinux.org/10-kitten/cloud/aarch64/images/AlmaLinux-Kitten-GenericCloud-10-20241227.0.aarch64.qcow2"
arch: "aarch64"
digest: "sha256:31838872e87f7d264cfd865ef288e5a4b7f31ba88ab84984ac5d4491a1c1a9e8"
- location: "https://kitten.repo.almalinux.org/10-kitten/cloud/s390x/images/AlmaLinux-Kitten-GenericCloud-10-20241227.0.s390x.qcow2"
arch: "s390x"
digest: "sha256:b4174bd71f59346bc35c32b3743d13e0a06458f203cc3736580cc9f8d28f6725"
# Fallback to the latest release image.
# Hint: run `limactl prune` to invalidate the cache
- location: "https://kitten.repo.almalinux.org/10-kitten/cloud/x86_64/images/AlmaLinux-Kitten-GenericCloud-10-latest.x86_64.qcow2"
arch: "x86_64"
- location: "https://kitten.repo.almalinux.org/10-kitten/cloud/aarch64/images/AlmaLinux-Kitten-GenericCloud-10-latest.aarch64.qcow2"
arch: "aarch64"
- location: "https://kitten.repo.almalinux.org/10-kitten/cloud/s390x/images/AlmaLinux-Kitten-GenericCloud-10-latest.s390x.qcow2"
arch: "s390x"
mountTypesUnsupported: ["9p"]
mounts:
- location: "~"
- location: "/tmp/lima"
writable: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs CPUType for Intel?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, I was hoping for it to be fixed.

1 change: 1 addition & 0 deletions templates/almalinux-kitten.yaml
Loading