#!/bin/bash
set -euo pipefail
alias oc=${OC:-oc}

repo_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/.."

source "$repo_dir/hack/lib/init.sh"
source "$repo_dir/hack/testing-olm/utils"
source "$repo_dir/hack/testing-olm/assertions"

ELASTICSEARCH_OP_REPO=${ELASTICSEARCH_OP_REPO:-${repo_dir}/../elasticsearch-operator}

ADMIN_USER=${ADMIN_USER:-kubeadmin}
ADMIN_PSWD=${ADMIN_USER:-admin123}
REMOTE_REGISTRY=${REMOTE_REGISTRY:-false}
LOGGING_NS=${LOGGING_NS:-"openshift-logging"}

UBI_IMAGE=${UBI_IMAGE:-registry.ci.openshift.org/ocp/4.0:base}

function image_is_ubi() {
    # dockerfile is arg $1
    grep -q "^FROM $UBI_IMAGE" $1
}

function image_needs_private_repo() {
    # dockerfile is arg $1
    image_is_ubi $1 || \
        grep -q "^FROM registry.ci.openshift.org/openshift/origin-v4.0:base" $1
}

CI_REGISTRY=${CI_REGISTRY:-registry.ci.openshift.org}
CI_CLUSTER_NAME=${CI_CLUSTER_NAME:-api-ci-openshift-org:443}

function get_context_for_cluster() {
    set +o pipefail > /dev/null
    oc config get-contexts | awk -F'[* ]+' -v clname="$1" '$3 == clname {print $2; exit}'
    set -o pipefail > /dev/null
}

# get credentials needed to authenticate to $CI_REGISTRY
# requires `oc` and requires user to have recently `oc login` to the $CI_CLUSTER_NAME cluster
# NOTE: cluster name != cluster hostname!!
function login_to_ci_registry() {
    local savekc=""
    local savectx=$( oc config current-context )
    local cictx=$( get_context_for_cluster $CI_CLUSTER_NAME )
    rc=0
    if [ -z "$cictx" ] ; then
        # try again without KUBECONFIG
        savekc=${KUBECONFIG:-}
        unset KUBECONFIG
        savectx=$( oc config current-context )
        cictx=$( get_context_for_cluster $CI_CLUSTER_NAME )
    fi
    if [ -z "$cictx" ] ; then
        echo ERROR: login_to_ci_registry: you must oc login to the server for cluster $CI_CLUSTER_NAME
        echo oc config get-contexts does not list cluster $CI_CLUSTER_NAME
        rc=1
    else
        oc config use-context "$cictx"
        local username=$( oc whoami )
        local token=$( oc whoami -t 2> /dev/null || : )
        if [ -z "$token" -o -z "$username" ] ; then
            echo ERROR: no username or token for context "$cictx"
            echo your credentials may have expired
            echo please oc login to the server for cluster $CI_CLUSTER_NAME
            rc=1
        else
            docker login -u "$username" -p "$token" $CI_REGISTRY
        fi
    fi
    if [ -n "$savectx" ] ; then
        oc config use-context "$savectx"
    fi
    if [ -n "$savekc" ] ; then
        export KUBECONFIG=$savekc
    fi
    return $rc
}

function pull_ubi_if_needed() {
    if ! docker images --format "{{.Repository}}:{{.Tag}}" | grep -q "^${UBI_IMAGE}\$" ; then
        login_to_ci_registry
        docker pull $UBI_IMAGE
    fi
}

# to build using internal/private yum repos, specify
# INTERNAL_REPO_DIR=/path/to/dir/
# where /path/to/dir/ contains the yum .repo files, and
# any private key pem files needed - this dir will be
# mounted into the builder as /etc/yum.repos.d/
INTERNAL_REPO_DIR=${INTERNAL_REPO_DIR:-}
function get_private_repo_dir() {
    GOPATH=${GOPATH:-}
    if [ -z "${INTERNAL_REPO_DIR:-}" ] ; then
        pushd $1 > /dev/null
        if [ ! -d repos ] ; then
            mkdir repos
            if [ -f $GOPATH/src/github.com/openshift/shared-secrets/mirror/ops-mirror.pem ] ; then
                cp $GOPATH/src/github.com/openshift/shared-secrets/mirror/ops-mirror.pem repos
            else
                if [ ! -d shared-secrets ] ; then
                    git clone -q git@github.com:openshift/shared-secrets.git
                fi
                cp shared-secrets/mirror/ops-mirror.pem repos
            fi
            local releasedir=${GOPATH}/src/github.com/openshift/release
            if [ -d $releasedir ] ; then
                pushd $releasedir > /dev/null
                git pull -q
                popd > /dev/null
            else
                if [ ! -d release ] ; then
                    git clone -q https://github.com/openshift/release
                fi
                releasedir=release
            fi
            local repofile
            for repofile in \
                $releasedir/core-services/release-controller/_repos/ocp-${VERSION}-default.repo \
                $releasedir/core-services/release-controller/_repos/ocp-4.3-default.repo \
                $releasedir/core-services/release-controller/_repos/ocp-4.2-default.repo \
                $releasedir/core-services/release-controller/_repos/ocp-4.1-default.repo ; do
                if [ -f $repofile ] ; then
                    cp $repofile repos
                    break
                fi
            done
            touch repos/redhat.repo
            chmod 0444 repos/redhat.repo
            sed -i -e 's,^sslclientkey.*$,sslclientkey = /etc/yum.repos.d/ops-mirror.pem,' \
                   -e 's,^sslclientcert.*$,sslclientcert = /etc/yum.repos.d/ops-mirror.pem,' repos/*.repo
        fi
        INTERNAL_REPO_DIR=$( pwd )/repos
        popd > /dev/null
    elif [ ! -f $INTERNAL_REPO_DIR/ops-mirror.pem ] || [ ! -f $INTERNAL_REPO_DIR/ocp-4.1-default.repo -a ! -f $INTERNAL_REPO_DIR/ocp-4.0-default.repo ] ; then
        echo ERROR: $INTERNAL_REPO_DIR missing one of ops-mirror.pem or ocp-4.1-default.repo and ocp-4.0-default.repo
        exit 1
    fi
    echo $INTERNAL_REPO_DIR
}

function login_to_registry() {
    local savectx=$( oc config current-context )
    local token=""
    local username=""
    if [ -n "${PUSH_USER:-}" -a -n "${PUSH_PASSWORD:-}" ] ; then
        username=$PUSH_USER
        if [ "$username" = "kube:admin" ] ; then
            username=kubeadmin
        fi
        oc login -u "$username" -p "$PUSH_PASSWORD" > /dev/null
        token=$( oc whoami -t 2> /dev/null || : )
        oc config use-context "$savectx"
    else
        # see if current context has a token
        token=$( oc whoami -t 2> /dev/null || : )
        if [ -n "$token" ] ; then
            username=$( oc whoami )
        else
            # get the first user with a token
            token=$( oc config view -o go-template='{{ range .users }}{{ if .user.token }}{{ print .user.token }}{{ end }}{{ end }}' )
            if [ -n "$token" ] ; then
                username=$( oc config view -o go-template='{{ range .users }}{{ if .user.token }}{{ print .name }}{{ end }}{{ end }}' )
                # username is in form username/cluster - strip off the cluster part
                username=$( echo "$username" | sed 's,/.*$,,' )
            fi
        fi
        if [ -z "$token" ] ; then
            echo ERROR: could not determine token to use to login to "$1"
            echo please do `oc login -u username -p password` to create a context with a token
            echo OR
            echo set \$PUSH_USER and \$PUSH_PASSWORD and run this script again
            return 1
        fi
        if [ "$username" = "kube:admin" ] ; then
            username=kubeadmin
        fi
    fi
    docker login -u "$username" -p "$token" "$1" > /dev/null
}

function push_image() {
    skopeo copy --dest-tls-verify=false docker-daemon:"$1" docker://"$2"
}

# debug_print [max_count [interval]]
# Example usage in hack/testing/test-*.sh
#    debug_print &
#    TEST_NAMESPACE=${NAMESPACE} go test ./test/e2e/ \
#      -root=$(pwd) \
#      -kubeconfig=${KUBECONFIG} \
#      -globalMan ${global_manifest} \
#      -namespacedMan ${manifest} \
#      -parallel=1 \
#      -singleNamespace | tee -a $ARTIFACT_DIR/test.log
#
function debug_print() {
  local filename=$(basename "$0")
  local max=${1:-120}
  local interval=${2:-10}
  while [ $max -gt 0 ];
  do
    clo=$( oc -n ${LOGGING_NS} get pods -l name=cluster-logging-operator -o jsonpath='{.items[0].metadata.name}' )
    if [ -n "$clo" ]; then
        date >> $ARTIFACT_DIR/$filename.clo.log || :
        oc -n ${LOGGING_NS} logs $clo >> $ARTIFACT_DIR/$filename.clo.log || :
        echo "-------------------------------------------------" >> $ARTIFACT_DIR/$filename.clo.log || :
        date >> $ARTIFACT_DIR/$filename.clo.images || :
        oc -n ${LOGGING_NS} exec $clo -- env | egrep _IMAGE >> $ARTIFACT_DIR/$filename.clo.images || :
        echo "-------------------------------------------------" >> $ARTIFACT_DIR/$filename.clo.images || :
    else
        date >> $ARTIFACT_DIR/$filename.noclo.log || :
        oc -n ${LOGGING_NS} get deployments >> $ARTIFACT_DIR/$filename.noclo.log || :
        echo "-------------------------------------------------" >> $ARTIFACT_DIR/$filename.noclo.log || :
    fi
    date >> $ARTIFACT_DIR/$filename.events.log || :
    oc -n ${LOGGING_NS} get events >> $ARTIFACT_DIR/$filename.events.log || :
    echo "-------------------------------------------------" >> $ARTIFACT_DIR/$filename.events.log || :
    date >> $ARTIFACT_DIR/$filename.all.log || :
    oc -n ${LOGGING_NS} get all >> $ARTIFACT_DIR/$filename.all.log || :
    echo "-------------------------------------------------" >> $ARTIFACT_DIR/$filename.all.log || :
    sleep $interval
    max=$( expr $max - 1 ) || :
  done
}

if [ $REMOTE_REGISTRY = false ] ; then
    : # skip
else
    registry_namespace=openshift-image-registry
    registry_svc=image-registry
    registry_host=$registry_svc.$registry_namespace.svc
    if ! oc get namespace $registry_namespace ; then
        registry_namespace=default
        registry_svc=docker-registry
        # use ip instead
        registry_host=$(oc get svc $registry_svc -n $registry_namespace -o jsonpath={.spec.clusterIP})
    fi

    registry_port=$(oc get svc $registry_svc -n $registry_namespace -o jsonpath={.spec.ports[0].port})
    if [ $registry_namespace = openshift-image-registry ] ; then
        # takes pod name in 4.0
        port_fwd_obj=$( oc get pods -n $registry_namespace | awk '/^image-registry-/ {print $1}' )
    else
        # takes service in 3.11
        port_fwd_obj="service/$registry_svc"
    fi
fi
