#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

echo "************ baremetalds assisted operator catalog publish command ************"

# Setup registry credentials
echo "## Setting up registry credentials."
mkdir -p "$HOME/.docker"
REGISTRY_TOKEN_FILE="$SECRETS_PATH/$REGISTRY_SECRET/$REGISTRY_SECRET_FILE"
cp "${REGISTRY_TOKEN_FILE}" "$HOME/.docker/config.json"

set -x

# Install tools
TOOLS_DIR=/tmp/bin
mkdir -p "${TOOLS_DIR}"
export PATH="${TOOLS_DIR}:${PATH}"

echo "## Install opm"
curl -L --retry 5 https://github.com/operator-framework/operator-registry/releases/download/v1.26.2/linux-amd64-opm -o "${TOOLS_DIR}/opm" && chmod +x "${TOOLS_DIR}/opm"
echo "   opm installed"

echo "## Install umoci"
curl -L --retry 5 https://github.com/opencontainers/umoci/releases/download/v0.4.7/umoci.amd64 -o "${TOOLS_DIR}/umoci" && chmod +x "${TOOLS_DIR}/umoci"
echo "   umoci installed"

echo "## Install python dependencies"
python3 -m pip install --user --upgrade pip
python3 -m pip install --user -r deploy/olm-catalog/requirements.txt
echo "   python dependencies installed"

BUNDLE_DESTINATION="${REGISTRY_HOST}/${REGISTRY_ORG}/${REGISTRY_BUNDLE_REPOSITORY_NAME}:${REGISTRY_BUNDLE_REPOSITORY_TAG}"
echo "## Generate and publish bundle to ${BUNDLE_DESTINATION}"

SRC_DIR="${PWD}"

tmp=$(mktemp -d)
cd "${tmp}"

# Build the bundle image from an empty base and set the required labels
# It does the same as https://github.com/openshift/assisted-service/blob/master/deploy/olm-catalog/bundle.Dockerfile
umoci init --layout bundle
umoci new --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.bundle.mediatype.v1=registry+v1' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.bundle.mediatype.v1=registry+v1' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.bundle.manifests.v1=manifests/' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.bundle.metadata.v1=metadata/' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.bundle.package.v1=assisted-service-operator' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.bundle.channels.v1=alpha,ocm-2.5' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.bundle.channel.default.v1=alpha' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.metrics.builder=operator-sdk-v1.10.0+git' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.metrics.mediatype.v1=metrics+v1' --image bundle:latest
umoci config --config.label 'operators.operatorframework.io.metrics.project_layout=go.kubebuilder.io/v3' --image bundle:latest
umoci config --config.label 'quay.expires-after=24w' --image bundle:latest # let quay expire the tag after 6 months from build time
umoci unpack --rootless --image bundle:latest bundle

# Update the manifests to points to the digest of the images it contains
python3 "${SRC_DIR}/deploy/olm-catalog/pin-latest.py"
cp -r "${SRC_DIR}/deploy/olm-catalog/manifests" bundle/rootfs/
cp -r "${SRC_DIR}/deploy/olm-catalog/metadata" bundle/rootfs/

# Publish the bundle
umoci repack --image bundle:latest bundle
skopeo copy oci:bundle:latest "docker://${BUNDLE_DESTINATION}"

# Publish the bundle tagged with its sha
# In quay, we cannot pull by digest when no tag is associated with it
BUNDLE_DIGEST=$(skopeo inspect oci:bundle:latest | jq -r '.Digest')
BUNDLE_DIGEST=${BUNDLE_DIGEST/*:/} # only keep the sha "sha256:ac45..." -> "ac45..."
BUNDLE_DESTINATION_DIGEST_TAG="${REGISTRY_HOST}/${REGISTRY_ORG}/${REGISTRY_BUNDLE_REPOSITORY_NAME}:${BUNDLE_DIGEST}"
skopeo copy oci:bundle:latest "docker://${BUNDLE_DESTINATION_DIGEST_TAG}"

CATALOG_DESTINATION="${REGISTRY_HOST}/${REGISTRY_ORG}/${REGISTRY_CATALOG_REPOSITORY_NAME}:${REGISTRY_CATALOG_REPOSITORY_TAG}"
echo "## Generate and publish catalog to ${CATALOG_DESTINATION}"

tmp=$(mktemp -d)
cd "${tmp}"

# Create the index database from the bundle we just published
opm index add \
    --bundles "${BUNDLE_DESTINATION_DIGEST_TAG}" \
    --out-dockerfile index.Dockerfile \
    --generate

# Add the index database to the opm base image, configure it, and publish it
# It does the same operation as in the Dockerfile generated by the opm index add... command above
skopeo copy "docker://${OPM_BASE_IMAGE}" oci:opm:latest
umoci unpack --rootless --image opm:latest bundle
mv database bundle/rootfs/
umoci repack --image opm:index bundle
umoci config --config.label 'operators.operatorframework.io.index.database.v1=/database/index.db' --image opm:index
umoci config --config.exposedports "50051" --image opm:index
umoci config --config.entrypoint "/bin/opm" --image opm:index
umoci config --config.cmd "registry" \
                    --config.cmd "serve" \
                    --config.cmd "--database" \
                    --config.cmd "/database/index.db" \
                    --image opm:index
skopeo copy oci:opm:index "docker://${CATALOG_DESTINATION}"
