#!/bin/bash
#
# Adapt containers build recipes for Orchid project.

# Strict mode
set -euo pipefail

INHERITED_LABELS_TO_KEEP=(
    # SLE
    "com.suse.bci" "com.suse.sle.base"
    # openSUSE
    "org.opensuse.bci" "org.opensuse.base"
)
TOPDIR="/usr/src/packages"
. /.build/build.data

# Helper functions
log() {
    echo "$@" >&2
}
check_required_environment_variables() {
    local required_environment_variable
    for required_environment_variable in "$@"; do
        if [[ -z ${!required_environment_variable:-} ]]; then
            log "Missing environment variable '$required_environment_variable'"
            return 1
        fi
    done
}

check_required_environment_variables BUILD_DIR BUILD_ROOT RECIPEFILE RELEASE

# Define initial set of values that we're interested in, to be replaced later
PACKAGE_NAME=""
DELIMITER="%"
DEFAULT_BUILD_FLAVOR=""
REVISION="$RELEASE"
BUILD_DATE="$(date --utc +%FT%T.%NZ)"
VARIABLES_TO_REPLACE=(
    BUILD_FLAVOR REVISION BUILD_DATE BASE_IMAGE_TAG BASE_IMAGE_DIGEST
)

# Parse input arguments to the script
while [[ $# -ne 0 ]]; do
    case "$1" in
        --package)
            shift
            PACKAGE_NAME="${1:?"Missing value for --package"}"
            ;;
        --default_build_flavor)
            shift
            DEFAULT_BUILD_FLAVOR="${1:?"Missing value for --default_build_flavor"}"
            ;;
        --delimiter)
            shift
            DELIMITER="${1:?"Missing value for --delimiter"}"
            ;;
        --outdir)
            log "Ignoring parameter: $1"
            shift
            ;;
        *)
            log "Invalid parameter: $1"
            exit 1
            ;;
    esac
    shift
done
# Ensure that build flavor contains hyphen as the 1st character when not empty
BUILD_FLAVOR="${BUILD_FLAVOR:-"$DEFAULT_BUILD_FLAVOR"}"
BUILD_FLAVOR="$(sed -E 's/-*(.+)/-\1/' <<<"$BUILD_FLAVOR")"
# Package name may contain build flavor, so we must replace the placeholder
PACKAGE_NAME="${PACKAGE_NAME//"${DELIMITER}BUILD_FLAVOR${DELIMITER}"/"$BUILD_FLAVOR"}"

# Obtain package version, if defined
# We are not going to use replace_using_package_version because it will not
# work well with some RPM packages that follow non-standard naming
if [[ -n $PACKAGE_NAME ]]; then
    # Obtain the raw version defined in the RPM package in the 'Version:' field
    RAW_VERSION="$(find /usr/src/packages/SOURCES/repos \
        \( -name "$PACKAGE_NAME.rpm" -o -name "$PACKAGE_NAME-*.rpm" \) \
        -exec rpm -q --qf '%{version}\n' {} \; -quit)"
    # Process the version so it can be used in a Docker tag
    VERSION="${RAW_VERSION//+/-build}" # the + symbol is not allowed
    VARIABLES_TO_REPLACE+=(RAW_VERSION VERSION)
    if [[ -n $RAW_VERSION && -n $VERSION ]]; then
        log "Detected version for $PACKAGE_NAME: $VERSION"
    else
        log "Could not detect version for RPM: $PACKAGE_NAME"
        exit 1
    fi
fi

# Special case for "-dev" flavored images:
# The base image will be BCI Base instead of BCI Micro
if [[ $BUILD_FLAVOR == "-dev" ]]; then
    # HACK: Avoiding 'FROM %BASE_IMAGE%' due to OBS dependency error:
    # "unresolvable: nothing provides container:%BASE_IMAGE%:latest"
    # To workaround, remove the micro base image and replace its occurrences
    # with "base" via sed substitutions
    log "Adapting Dockerfile for flavor: $BUILD_FLAVOR"
    sed -i \
        -e "/FROM bci\/bci-micro/d" \
        -e "s/--from=micro/--from=base/" \
        -e "s/FROM micro/FROM base/" \
        Dockerfile
fi

# Start docker
"$BUILD_DIR/startdockerd" \
    --root "$BUILD_ROOT" \
    --webserver "$TOPDIR/SOURCES/repos" \
    --webserver-upload "$TOPDIR/SOURCES/repos/UPLOAD"

# Load the base images into Docker, this is based on build-recipe-docker
# https://github.com/openSUSE/obs-build/blob/master/build-recipe-docker#L152-L170
# This will allow to get information about the base image
DOCKER_CMD="chroot $BUILD_ROOT docker"
LOCAL_BASE_IMAGE_TAG=$(grep "^\s*FROM" "$RECIPEFILE" | head -n 1 | cut -d" " -f2)
if [[ -z $LOCAL_BASE_IMAGE_TAG ]]; then
    log "Could not detect base image tag from $RECIPEFILE"
    exit 1
fi
for base_image_path in $(find containers -regextype egrep -regex "containers/.*\.(tgz|tar|tar\.xz|tar\.gz)$" -print); do
    echo "Loading base image ${base_image_path##*/}"
    if test -L "$base_image_path"; then
        # copy into build root
        cp -L "$base_image_path" "$base_image_path.lnk"
        mv "$base_image_path.lnk" "$base_image_path"
    fi
    # Inspect the content of the image to decide if this is a layered image
    # or a filesystem one. We need to know if we will "docker load" it or
    # "docker import" it.
    if tar -tf $base_image_path | grep -q "^manifest.json"; then
        $DOCKER_CMD load --input $TOPDIR/SOURCES/$base_image_path
    else
        echo "Layered base images not supported, FS-based base image required"
        exit 1
    fi
done

# Using Docker, obtain the rest of values that we are interested in
BASE_IMAGE_TAG="$($DOCKER_CMD inspect "$LOCAL_BASE_IMAGE_TAG" \
    --format='{{index .Config.Labels "org.opensuse.reference"}}')"
BASE_IMAGE_DIGEST="$($DOCKER_CMD inspect "$LOCAL_BASE_IMAGE_TAG" \
    --format='{{.Id}}')"
read -r -a LABELS <<<"$($DOCKER_CMD inspect "$LOCAL_BASE_IMAGE_TAG" \
    --format='{{ range $key, $val := .Config.Labels }}{{ $key }} {{ end }}')"

# Stop docker
"$BUILD_DIR/startdockerd" \
    --root "$BUILD_ROOT" \
    --kill

# Process labels
if [[ ${#LABELS[@]} -eq 0 ]]; then
    log "No labels were found in $LOCAL_BASE_IMAGE_TAG"
    exit 1
fi
OVERRIDDEN_LABELS=()
MATCHED_LABELS_TO_KEEP=false
for label in "${LABELS[@]}"; do
    LABEL_KEEP=false
    for inherited_label_to_keep in "${INHERITED_LABELS_TO_KEEP[@]}"; do
        [[ $label == "$inherited_label_to_keep."* ]] && LABEL_KEEP=true
    done
    if "$LABEL_KEEP"; then
        log "Keeping label $label"
        MATCHED_LABELS_TO_KEEP=true
    else
        log "Overriding label $label"
        OVERRIDDEN_LABELS+=("$label=\"\"")
    fi
done
# Ensure there was at least one inherited label to removed
if [[ ${#OVERRIDDEN_LABELS[@]} -eq 0 ]]; then
    log "No labels to override were detected"
    exit 1
fi
# Ensure there was at least one inherited label to keep
if ! "$MATCHED_LABELS_TO_KEEP"; then
    log "Expected inherited labels with these prefixes, but found none: \
${INHERITED_LABELS_TO_KEEP[@]}"
    exit 1
fi

log "Replacing metadata placeholders in $(basename "$RECIPEFILE")"
for value in "${VARIABLES_TO_REPLACE[@]}"; do
    log "Replacing $DELIMITER$value$DELIMITER: ${!value}"
    sed -i "s#$DELIMITER$value$DELIMITER#${!value}#" "$RECIPEFILE"
done
for label in "${OVERRIDDEN_LABELS[@]}"; do
    if ! grep -Eq "^LABEL ${label%%=*}=" "$RECIPEFILE"; then
        log "Adding label override: $label"
        echo "LABEL $label" >>"$RECIPEFILE"
    else
        log "Not adding label override (it was already overridden): $label"
    fi
done
