diff --git a/README.md b/README.md index c09248d..8395581 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,41 @@ -# elemental-channels -A repository to maintain and publish Elemental image channels +# Elemental Channels + +[Elemental Channels](https://elemental.docs.rancher.com/next/channels) can be used to publish a list of container images to be used by the [Elemental Operator](https://elemental.docs.rancher.com). + +This repository automates and facilitates the creation of the officially distributed Elemental channels. + +## Goals for this repository + +1. Be the single source of truth for all channel .json files that need to be published by the Elemental team +1. Automatically refresh the channels watching container registries (Daily) +1. (Optional) Publish images on GitHub, for development or testing + +## Repository Watches config + +The [config.yaml](./config.yaml) can be updated using the following structure: + +```yaml +watches: + # A flavor for the Base OS being watched. Can be "" for unflavored images. + # This will be used as a prefix to distinguish same versions of different flavors. + - flavor: "my-flavor" + # The resulting .json filename on the ./channels directory + fileName: "sle-micro-5-5-my-flavor" + # The OS human readable name + displayName: "SLE Micro 5.5 My Flavor" + # The repository containing the "os" type images + osRepo: registry.suse.com/suse/sle-micro/my-flavor-5.5 + # The repository containing the "iso" type images. + # If this is not applicable, use "N/A" + isoRepo: registry.suse.com/suse/sle-micro-iso/my-flavor-5.5 + # How many images to limit per (minor) version. + limit: 3 +``` + +## Usage + +It is possible, at any moment, to run the `.refresh_channels.sh` script and integrate the changes, if any. +A GitHub [workflow](.github/workflows/refresh-channels.yaml) does it automatically every night, and optionally it can be triggered at any time. + +Manually crated `.json` files can be directly created and maintained in the `./channels` directory, for example to maintain a channel containing arbitrary images, for development or testing. +When this is the case, be mindful of not creating collision with the automated [config.yaml](./config.yaml), otherwise files with the same name will be overwritten. diff --git a/channels/sle-micro-5-5-kvm.json b/channels/sle-micro-5-5-kvm.json index b6015dd..98d6420 100644 --- a/channels/sle-micro-5-5-kvm.json +++ b/channels/sle-micro-5-5-kvm.json @@ -14,26 +14,26 @@ }, { "metadata": { - "name": "kvm-v2.0.2-2.2.20-os" + "name": "kvm-v2.0.2-2.2.85-os" }, "spec": { - "version": "v2.0.2-2.2.20", + "version": "v2.0.2-2.2.85", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/kvm-5.5:2.0.2-2.2.20", + "upgradeImage": "registry.suse.com/suse/sle-micro/kvm-5.5:2.0.2-2.2.85", "displayName": "SLE Micro KVM 5.5 OS" } } }, { "metadata": { - "name": "kvm-v2.0.2-2.2.85-os" + "name": "kvm-v2.0.2-2.2.20-os" }, "spec": { - "version": "v2.0.2-2.2.85", + "version": "v2.0.2-2.2.20", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/kvm-5.5:2.0.2-2.2.85", + "upgradeImage": "registry.suse.com/suse/sle-micro/kvm-5.5:2.0.2-2.2.20", "displayName": "SLE Micro KVM 5.5 OS" } } diff --git a/channels/sle-micro-5-5-rt.json b/channels/sle-micro-5-5-rt.json index a1acec7..c5b3767 100644 --- a/channels/sle-micro-5-5-rt.json +++ b/channels/sle-micro-5-5-rt.json @@ -14,26 +14,26 @@ }, { "metadata": { - "name": "rt-v2.0.2-3.2.23-os" + "name": "rt-v2.0.2-3.2.86-os" }, "spec": { - "version": "v2.0.2-3.2.23", + "version": "v2.0.2-3.2.86", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/rt-5.5:2.0.2-3.2.23", + "upgradeImage": "registry.suse.com/suse/sle-micro/rt-5.5:2.0.2-3.2.86", "displayName": "SLE Micro RT 5.5 OS" } } }, { "metadata": { - "name": "rt-v2.0.2-3.2.86-os" + "name": "rt-v2.0.2-3.2.23-os" }, "spec": { - "version": "v2.0.2-3.2.86", + "version": "v2.0.2-3.2.23", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/rt-5.5:2.0.2-3.2.86", + "upgradeImage": "registry.suse.com/suse/sle-micro/rt-5.5:2.0.2-3.2.23", "displayName": "SLE Micro RT 5.5 OS" } } diff --git a/channels/sle-micro-5-5.json b/channels/sle-micro-5-5.json index a233357..8b4c9c2 100644 --- a/channels/sle-micro-5-5.json +++ b/channels/sle-micro-5-5.json @@ -1,56 +1,4 @@ [ - { - "metadata": { - "name": "v2.0.2-4.2.102-os" - }, - "spec": { - "version": "v2.0.2-4.2.102", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.102", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.105-os" - }, - "spec": { - "version": "v2.0.2-4.2.105", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.105", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.107-os" - }, - "spec": { - "version": "v2.0.2-4.2.107", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.107", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.109-os" - }, - "spec": { - "version": "v2.0.2-4.2.109", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.109", - "displayName": "SLE Micro 5.5 OS" - } - } - }, { "metadata": { "name": "v2.0.2-4.2.111-os" @@ -66,195 +14,39 @@ }, { "metadata": { - "name": "v2.0.2-4.2.20-os" - }, - "spec": { - "version": "v2.0.2-4.2.20", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.20", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.70-os" - }, - "spec": { - "version": "v2.0.2-4.2.70", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.70", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.85-os" - }, - "spec": { - "version": "v2.0.2-4.2.85", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.85", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.87-os" - }, - "spec": { - "version": "v2.0.2-4.2.87", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.87", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.89-os" - }, - "spec": { - "version": "v2.0.2-4.2.89", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.89", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.91-os" - }, - "spec": { - "version": "v2.0.2-4.2.91", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.91", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.93-os" - }, - "spec": { - "version": "v2.0.2-4.2.93", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.93", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.94-os" - }, - "spec": { - "version": "v2.0.2-4.2.94", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.94", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.96-os" - }, - "spec": { - "version": "v2.0.2-4.2.96", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.96", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.97-os" - }, - "spec": { - "version": "v2.0.2-4.2.97", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.97", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.2-4.2.99-os" - }, - "spec": { - "version": "v2.0.2-4.2.99", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.99", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.4-5.5.15-os" - }, - "spec": { - "version": "v2.0.4-5.5.15", - "type": "container", - "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.4-5.5.15", - "displayName": "SLE Micro 5.5 OS" - } - } - }, - { - "metadata": { - "name": "v2.0.4-5.5.18-os" + "name": "v2.0.2-4.2.109-os" }, "spec": { - "version": "v2.0.4-5.5.18", + "version": "v2.0.2-4.2.109", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.4-5.5.18", + "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.109", "displayName": "SLE Micro 5.5 OS" } } }, { "metadata": { - "name": "v2.0.4-5.5.2-os" + "name": "v2.0.2-4.2.107-os" }, "spec": { - "version": "v2.0.4-5.5.2", + "version": "v2.0.2-4.2.107", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.4-5.5.2", + "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.2-4.2.107", "displayName": "SLE Micro 5.5 OS" } } }, { "metadata": { - "name": "v2.0.4-5.5.24-os" + "name": "v2.0.4-5.5.30-os" }, "spec": { - "version": "v2.0.4-5.5.24", + "version": "v2.0.4-5.5.30", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.4-5.5.24", + "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.4-5.5.30", "displayName": "SLE Micro 5.5 OS" } } @@ -274,13 +66,13 @@ }, { "metadata": { - "name": "v2.0.4-5.5.30-os" + "name": "v2.0.4-5.5.24-os" }, "spec": { - "version": "v2.0.4-5.5.30", + "version": "v2.0.4-5.5.24", "type": "container", "metadata": { - "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.4-5.5.30", + "upgradeImage": "registry.suse.com/suse/sle-micro/5.5:2.0.4-5.5.24", "displayName": "SLE Micro 5.5 OS" } } @@ -300,26 +92,26 @@ }, { "metadata": { - "name": "v2.0.2-4.2.27-iso" + "name": "v2.0.2-4.2.97-iso" }, "spec": { - "version": "v2.0.2-4.2.27", + "version": "v2.0.2-4.2.97", "type": "iso", "metadata": { - "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.2-4.2.27", + "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.2-4.2.97", "displayName": "SLE Micro 5.5 ISO" } } }, { "metadata": { - "name": "v2.0.2-4.2.97-iso" + "name": "v2.0.2-4.2.27-iso" }, "spec": { - "version": "v2.0.2-4.2.97", + "version": "v2.0.2-4.2.27", "type": "iso", "metadata": { - "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.2-4.2.97", + "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.2-4.2.27", "displayName": "SLE Micro 5.5 ISO" } } @@ -339,26 +131,26 @@ }, { "metadata": { - "name": "v2.0.4-5.5.3-iso" + "name": "v2.0.4-5.5.6-iso" }, "spec": { - "version": "v2.0.4-5.5.3", + "version": "v2.0.4-5.5.6", "type": "iso", "metadata": { - "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.4-5.5.3", + "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.4-5.5.6", "displayName": "SLE Micro 5.5 ISO" } } }, { "metadata": { - "name": "v2.0.4-5.5.6-iso" + "name": "v2.0.4-5.5.3-iso" }, "spec": { - "version": "v2.0.4-5.5.6", + "version": "v2.0.4-5.5.3", "type": "iso", "metadata": { - "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.4-5.5.6", + "uri": "registry.suse.com/suse/sle-micro-iso/5.5:2.0.4-5.5.3", "displayName": "SLE Micro 5.5 ISO" } } diff --git a/config.yaml b/config.yaml index 1b49a5d..1b95c6f 100644 --- a/config.yaml +++ b/config.yaml @@ -4,14 +4,17 @@ watches: displayName: "SLE Micro 5.5" osRepo: registry.suse.com/suse/sle-micro/5.5 isoRepo: registry.suse.com/suse/sle-micro-iso/5.5 + limit: 3 - flavor: "kvm" fileName: "sle-micro-5-5-kvm" displayName: "SLE Micro KVM 5.5" osRepo: registry.suse.com/suse/sle-micro/kvm-5.5 isoRepo: "N/A" + limit: 3 - flavor: "rt" fileName: "sle-micro-5-5-rt" displayName: "SLE Micro RT 5.5" osRepo: registry.suse.com/suse/sle-micro/rt-5.5 isoRepo: "N/A" + limit: 3 diff --git a/refresh_channels.sh b/refresh_channels.sh index c20766f..4edcbc2 100755 --- a/refresh_channels.sh +++ b/refresh_channels.sh @@ -31,7 +31,7 @@ function append_os_entry() { "type": "container", "metadata": { "upgradeImage": "$image_uri", - "displayName": "$display_name" + "displayName": "$display_name OS" } } }, @@ -55,13 +55,85 @@ function append_iso_entry() { "type": "iso", "metadata": { "uri": "$image_uri", - "displayName": "$display_name" + "displayName": "$display_name ISO" } } }, EOF } +# Processes the intermediate image list sorting by creation date +function process_intermediate_list() { + local version=$1 + local file=$2 + local type=$3 + local limit=$4 + shift 4 + + local IFS=$'\n' + local sorted_list=($(echo "$@" | jq -nc '[inputs]' | jq '. |= sort_by(.created) | reverse' | jq -c '.[]')) + + echo "Limiting $limit entries for version $version:" + + for ((i = 0; i < ${#sorted_list[@]} && i < $limit; i++)); do + local entry="${sorted_list[$i]}" + + echo -e "- $(( i + 1 )): $entry" + + local image_uri=$(echo "$entry" | jq '.uri' | sed 's/"//g') + local version=$(echo "$entry" | jq '.version' | sed 's/"//g') + local managed_os_version_name=$(echo "$entry" | jq '.managedOSVersionName' | sed 's/"//g') + local display_name=$(echo "$entry" | jq '.displayName' | sed 's/"//g') + + if [[ "$type" == "os" ]]; then + append_os_entry "$file" "$managed_os_version_name" "$version" "$image_uri" "$display_name" + elif [[ "$type" == "iso" ]]; then + append_iso_entry "$file" "$managed_os_version_name" "$version" "$image_uri" "$display_name" + fi + done +} + +# Processes an entire repository and creates a list of all images +function process_repo() { + local repo=$1 + local repo_type=$2 + local file=$3 + local limit=$4 + local flavor=$5 + local display_name=$6 + + local intermediate_list=() + local tags=($(skopeo list-tags docker://$repo | jq '.Tags[]' | grep -v '.att\|.sig\|latest' | sed 's/"//g')) + + echo "Processing repository: $repo" + + for tag in "${tags[@]}"; do + # Version (non-build) tag (ex '1.2.3') + if [[ $tag =~ ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$ ]]; then + # If the intermediate_list is not empty, + # it means we are done processing the previously met version tag. + if [[ -n $intermediate_list ]]; then + process_intermediate_list "$processing_version" "$file" "$repo_type" $limit "${intermediate_list[@]}" + local intermediate_list=() + fi + local processing_version="$tag" + continue + fi + local image_uri="$repo:$tag" + local image_creation_date=($(skopeo inspect docker://$image_uri | jq '.Created' | sed 's/"//g')) + local managed_os_version_name=$(format_managed_os_version_name "$flavor" "$tag" "$repo_type") + # Append entry to intermediate list + local intermediate_entry="{\"uri\":\"$image_uri\",\"created\":\"$image_creation_date\",\"version\":\"$tag\",\"managedOSVersionName\":\"$managed_os_version_name\",\"displayName\":\"$display_name\"}" + echo "Intermediate: $intermediate_entry" + local intermediate_list=("${intermediate_list[@]}" "$intermediate_entry") + done + # Process the intermediate_list again for the last remaining version + if [[ -n $intermediate_list ]]; then + process_intermediate_list "$processing_version" "$file" "$repo_type" $limit "${intermediate_list[@]}" + fi +} + +# The list of repositories to watch watches=$(yq e -o=j -I=0 '.watches[]' config.yaml) # Loop through all watches @@ -72,6 +144,7 @@ while IFS=\= read watch; do display_name=$(echo "$watch" | yq e '.displayName') os_repo=$(echo "$watch" | yq e '.osRepo') iso_repo=$(echo "$watch" | yq e '.isoRepo') + limit=$(echo "$watch" | yq e '.limit') # Start writing the channel file by opening a JSON array file="channels/$file_name.json" @@ -79,27 +152,11 @@ while IFS=\= read watch; do echo "[" > $file # Process OS container tags - os_tags=($(skopeo list-tags docker://$os_repo | jq '.Tags[]' | grep -v '.att\|.sig\|latest' | sed 's/"//g')) - for tag in "${os_tags[@]}"; do - # Omit version (non-build) tags - if [[ $tag =~ ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$ ]]; then - continue - fi - managed_os_version_name=$(format_managed_os_version_name "$flavor" "$tag" "os") - append_os_entry "$file" "$managed_os_version_name" "$tag" "$os_repo:$tag" "$display_name OS" - done + process_repo "$os_repo" "os" "$file" "$limit" "$flavor" "$display_name" # Process ISO container tags (if applicable) if [ "$iso_repo" != "N/A" ]; then - iso_tags=($(skopeo list-tags docker://$iso_repo | jq '.Tags[]' | grep -v '.att\|.sig\|latest' | sed 's/"//g')) - for tag in "${iso_tags[@]}"; do - # Omit version (non-build) tags - if [[ $tag =~ ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$ ]]; then - continue - fi - managed_os_version_name=$(format_managed_os_version_name "$flavor" "$tag" "iso") - append_iso_entry "$file" "$managed_os_version_name" "$tag" "$iso_repo:$tag" "$display_name ISO" - done + process_repo "$iso_repo" "iso" "$file" "$limit" "$flavor" "$display_name" fi # Delete trailing ',' from array. (technically last written char on the file)