#!/usr/bin/env bash
set -eu

# More information is available in https://github.com/rancher/image-scanning/issues/199

# List of images that have multiple patch versions and that we must scan only
# the last patch version for each minor version available.
PATCH_VERSION_IMAGES=("rancher/rke2-runtime" "rancher/rke2-upgrade"
 "rancher/system-agent-installer-rke2" "rancher/system-agent-installer-k3s"
 "rancher/k3s-upgrade" "rancher/hardened-kubernetes")

# Function that iterates over a given image (arg $1) all the available versions
# and keeps only the last patch version for each minor version available. The
# remaining patch versions are considered deprecated and removed.
# Arg $2 is a temporary file that contains the list of images to be reviewed.
# Arg $3 is the image-scanning generated "images-sources.txt" file with all the
# images that will be scanned and that we must review the patch versions.
remove_deprecated_patch_versions() {
    image="${1}"
    tmp_file="${2}"
    rancher_images="${3}"

    # Given a list of images:
    # rancher/rke2-runtime:v1.22.9-rke2r1 rke2All,release/v2.6-head...
    # rancher/rke2-runtime:v1.22.9-rke2r2 rke2All...
    # rancher/rke2-runtime:v1.23.10-rke2r1 rke2All,release/v2.6-head...
    # Filters only the versions:
    # v1.22.9-rke2r1
    # v1.22.9-rke2r2
    # v1.23.10-rke2r1
    versions=$(grep "^${image}:" "${tmp_file}" | sed -E "s,^${image}:,,; s, .*,," | sort -u)

    # Now extract only the major and minor versions.
    # v1.22
    # v1.22
    # v1.23
    minor_versions=$(echo "${versions}" | sed -E "s/\.[[:digit:]]+-.*//" | sort -u)

    # For each minor version:
    for p in ${minor_versions}; do
        # Extract its corresponding patch versions, sort them (numerically and in
        # reverse order) and retrieves the last patch version.
        # Given:
        # v1.22.9-rke2r1
        # v1.22.9-rke2r2
        # Returns:
        # 9-rke2r2
        last_patch_version=$(echo "${versions}" | grep ${p} | awk -F"." '{ print $3 }' | sort -nr | head -n 1)

        # Similarly to the previous filter, now reverse the order and get all
        # deprecated patch versions (except the last patch version).
        # Given:
        # v1.22.9-rke2r1
        # v1.22.9-rke2r2
        # Returns:
        # 9-rke2r1
        deprecated_patch_versions=$(echo "${versions}" | grep ${p} | awk -F"." '{ print $3 }' | sort -nr | tail -n +2)

        echo "=> Last patch version found for ${p} release version"
        echo "${image}:${p}.${last_patch_version}"

        if [[ ! -z "${deprecated_patch_versions}" ]]; then
            # If there are deprecated versions, we remove them so they don't get scanned.
            echo "=> Deprecated patch versions removed"
            for d in ${deprecated_patch_versions}; do
                echo "${image}:${p}.${d}"

                # We must escape the slash for the sed command below to work.
                # From: rancher/rke2-runtime
                # To:   rancher\/rke2-runtime
                escaped_image=$(echo "${image}:${p}.${d}" | sed "s,/,\\\/,")
                sed -i'' -E "/${escaped_image}\s/d" "${rancher_images}"
            done
        else
            echo "=> No deprecated patch version to remove"
        fi
        echo ""
    done
}

# Arg $1 is the image-scanning generated "images-sources.txt" file with all the
# images that will be scanned and that we must review the patch versions.
for image in "${PATCH_VERSION_IMAGES[@]}"; do
    rancher_images="${1}"
    tmp_file=$(mktemp)

    echo "=> Looking for deprecated patch versions for image"
    echo "${image}"

    # We split the search first for non-Windows images and then for Windows
    # images only. This is needed, because non-Windows and Windows images can
    # have different last patch versions. If we search all of them together,
    # the search logic for the last patch version can get confused and
    # potentially remove valid Windows images.
    #
    # Example of non-Windows and Windows images with different patch versions:
    # rancher/rke2-runtime:v1.23.15-rke2r1-windows-amd64
    # rancher/rke2-runtime:v1.23.17-rke2r1
    #
    # The script, with the help of the sort binary, correctly handles RKE2 and
    # K3s release tags rke2rX and k3sX.
    if (grep -v windows "${rancher_images}" > "${tmp_file}"); then
        remove_deprecated_patch_versions "${image}" "${tmp_file}" "${rancher_images}"
    fi

    if (grep windows "${rancher_images}" > "${tmp_file}"); then
        remove_deprecated_patch_versions "${image}" "${tmp_file}" "${rancher_images}"
    fi
done

