#!/usr/bin/env bash
# Copyright 2023 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -euo pipefail

cd "$(dirname "$0")"

if ((BASH_VERSINFO[0] < 4)); then
    echo "At least bash version 4 is required to run this script"
    exit 1
fi

# Change the following configurations to adapt the resulting ignitions files.
declare -A CONFIGURATIONS=(
    ["crio"]="root env"
    ["crio_eventedpleg"]="root env eventedpleg"
    ["crio_canary"]="root env-canary"
    ["crio_drop_infra_ctr"]="root env drop-infra-ctr"
    ["crio_swap1g"]="root env swap-1G"
    ["crio_imagefs"]="root env imagefs"
    ["crio_splitfs"]="root env splitfs"
    ["crio_hugepages"]="root env hugepages"
    ["crio_userns"]="root env userns"
)

CONTAINER_RUNTIME=$(which podman 2>/dev/null || which nerdctl 2>/dev/null || which docker 2>/dev/null)

if [[ -z "$CONTAINER_RUNTIME" ]]; then
    echo "Neither podman, nerdctl nor docker found in \$PATH"
    exit 1
fi

readonly YQ_IMAGE=mikefarah/yq:4
readonly BUTANE_IMAGE=quay.io/coreos/butane:release
readonly BASE_PATH=base

# Helper function to run container commands
run_container() {
    local image=$1
    shift
    $CONTAINER_RUNTIME run --privileged -i --rm -v "$PWD":/w -w /w "$image" "$@"
}

# Merge multiple YAML files into one
merge() {
    local output=$1
    shift
    local files=("${@/#/$BASE_PATH/}")
    local files=("${files[@]/%/.yaml}")

    # shellcheck disable=SC2016
    run_container "$YQ_IMAGE" ea '. as $item ireduce ({}; . *+ $item)' "${files[@]}" >"$output.yaml"
}

# Generate ignition files from configurations
for name in "${!CONFIGURATIONS[@]}"; do
    echo "Building $name"

    read -ra templates <<<"${CONFIGURATIONS[$name]}"
    merge "$name" "${templates[@]}"
    run_container "$BUTANE_IMAGE" -ps -d "$BASE_PATH" <"$name.yaml" >"../$name.ign"
done

# Validate CRI-O commit references
extract_commit() {
    grep "$1" "$BASE_PATH/env.yaml" | grep -o '[0-9a-f]\{40\}'
}

CRIO_SCRIPT_COMMIT=$(extract_commit "CRIO_SCRIPT_COMMIT")
CRIO_SCRIPT_URL="https://raw.githubusercontent.com/cri-o/packaging/$CRIO_SCRIPT_COMMIT/get"
if ! curl -fs "$CRIO_SCRIPT_URL" -o /dev/null; then
    echo "Error: CRIO_SCRIPT_COMMIT in $BASE_PATH/env.yaml is wrong. The get script was not found at: $CRIO_SCRIPT_URL" >&2
    exit 1
fi

CRIO_COMMIT=$(extract_commit "CRIO_COMMIT")
CRIO_BIN_URL="https://storage.googleapis.com/cri-o/artifacts/cri-o.amd64.$CRIO_COMMIT.tar.gz"
if ! curl -fs "$CRIO_BIN_URL" -o /dev/null; then
    echo "Error: CRIO_COMMIT in $BASE_PATH/env.yaml is wrong. The cri-o binary was not found at: $CRIO_BIN_URL" >&2
    exit 1
fi
