#!/bin/bash

set -e
set -o pipefail

BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
PROFILE="flux-test"
PROFILE_DIR="$BASEDIR/profiles/$PROFILE"
KNOWN_HOSTS="$PROFILE_DIR/.known_hosts"
CONFIG_REPO="$PROFILE_DIR/config"
SSH_PRIVATE_KEY="$HOME/.minikube/machines/$PROFILE/id_rsa"

#############################################################################
# Setup
#############################################################################

# Clear profile temp dir and reset minikube profile
rm -rf "$PROFILE_DIR"
mkdir -p "$PROFILE_DIR"
minikube delete --profile "$PROFILE" || true
minikube start --profile "$PROFILE" --keep-context
MINIKUBE_IP=$(minikube --profile "$PROFILE" ip)

# Copy the latest Flux image into the minikube VM
docker save "docker.io/fluxcd/flux:latest" | (eval $(minikube --profile "$PROFILE" docker-env) && docker load)

# Create a central git repo inside the minikube VM and get the host key for ssh access
minikube --profile "$PROFILE" ssh -- git init --bare /home/docker/flux.git
ssh-keyscan $MINIKUBE_IP > "$KNOWN_HOSTS"

# Deploy Flux in kube-system namespace, supplying it with the SSH keys it needs to access & authenticate the config repo
kubectl --context "$PROFILE" -n kube-system create secret generic flux-git-deploy --from-file=identity="$SSH_PRIVATE_KEY"
kubectl --context "$PROFILE" -n kube-system create configmap ssh-known-hosts --from-file=known_hosts="$KNOWN_HOSTS"
sed -e "s/MINIKUBE_IP/$MINIKUBE_IP/" "$BASEDIR/flux-deploy-all.yaml" | kubectl --context "$PROFILE" -n kube-system apply -f-

# Create a git repo in the local filesystem configured with the central git repo in minikube as origin
git init "$CONFIG_REPO"
git -C "$CONFIG_REPO" remote add origin ssh://docker@$MINIKUBE_IP/home/docker/flux.git
export GIT_SSH_COMMAND="ssh -i $SSH_PRIVATE_KEY -o UserKnownHostsFile=$KNOWN_HOSTS"

#############################################################################
# Test Helpers
#############################################################################

fail() {
    echo
    echo "*** FAILED ***"
    echo
    exit 1
}

success() {
    echo
    echo "*** SUCCESS ***"
    echo
    exit 0
}

wait_for_sync() {
    echo -n "Waiting for sync"
    HEAD_REV=$(git -C "$CONFIG_REPO" rev-list -n 1 HEAD)
    for i in $(seq 1 $1); do
        git -C "$CONFIG_REPO" fetch --tags > /dev/null 2>&1
        FLUX_SYNC_REV=$(git -C "$CONFIG_REPO" rev-list -n 1 flux-sync 2>/dev/null || true)
        if [ "$FLUX_SYNC_REV" = "$HEAD_REV" ]; then
            echo
            return
        fi
        sleep 1
        echo -n .
    done
    fail
}

wait_for_upstream_commits() {
    echo -n "Waiting for $2 upstream commits"
    for i in $(seq 1 $1); do
        git -C "$CONFIG_REPO" fetch --tags > /dev/null 2>&1
        if [ "$(git -C "$CONFIG_REPO" rev-list --count HEAD..flux-sync)" -eq "2" ]; then
            echo
            return
        fi
        sleep 1
        echo -n .
    done
    fail
}

workloads() {
    curl -s "http://$MINIKUBE_IP:30080/api/flux/v6/services?namespace=$1"
}

workload_container() {
    jq --raw-output ".[]|select(.ID==\"$1\")|.Containers[]|select(.Name==\"$2\")|.Current.ID"
}

assert_workload_container() {
    if [ "$(workloads $1|workload_container $2 $3)" != "$4" ]; then
        fail
    fi
}

#############################################################################
# Tests
#############################################################################

# Add the helloworld deployment to the config repo and push to the central config repo in minikube
cp "$BASEDIR/helloworld-deployment.yaml" "$CONFIG_REPO"
git -C "$CONFIG_REPO" add helloworld-deployment.yaml
git -C "$CONFIG_REPO" commit -m 'Deploy helloworld'
git -C "$CONFIG_REPO" push -u origin master

# Wait two minutes for flux-sync tag to point to local HEAD
wait_for_sync 120

# Examine workloads via Flux API an assert container versions are correct
assert_workload_container default default:deployment/helloworld helloworld quay.io/weaveworks/helloworld:master-a000001
assert_workload_container default default:deployment/helloworld sidecar quay.io/weaveworks/sidecar:master-a000001

# Now enable automation
fluxctl --url http://$(minikube -p flux-test ip):30080/api/flux automate --workload=default:deployment/helloworld

# Wait two minutes for two (automation and release) commits to appear
wait_for_upstream_commits 120 2

# Examine workload via Flux API an assert container versions are updated
assert_workload_container default default:deployment/helloworld helloworld quay.io/weaveworks/helloworld:master-9a16ff945b9e
assert_workload_container default default:deployment/helloworld sidecar quay.io/weaveworks/sidecar:master-a000002

success
