#!/usr/bin/env bash
set -euo pipefail

if [[ ${EUID} -ne 0 ]]; then
  printf '%s\n' "activate-release must run as root" >&2
  exit 1
fi
exec 9>/run/lock/harbor-release.lock
if ! flock -n 9; then
	printf '%s\n' "another release or rollback is in progress" >&2
	exit 1
fi

archive=${1:-}
checksum=${2:-}
if [[ -z "$archive" || -z "$checksum" || ! -f "$archive" ]]; then
  printf '%s\n' "usage: activate-release.sh <archive> <sha256>" >&2
  exit 1
fi
if [[ "$archive" != /opt/harbor/incoming/* ]]; then
  printf '%s\n' "archive must be under /opt/harbor/incoming" >&2
  exit 1
fi

actual=$(sha256sum "$archive" | cut -d' ' -f1)
if [[ "$actual" != "$checksum" ]]; then
  printf '%s\n' "release checksum mismatch" >&2
  exit 1
fi

release_id=$(basename "$archive" .tar.gz)
if [[ ! "$release_id" =~ ^harbor-[0-9]{8}T[0-9]{6}Z-[a-zA-Z0-9._-]+$ ]]; then
  printf '%s\n' "invalid release archive name" >&2
  exit 1
fi
release_dir=/opt/harbor/releases/$release_id
if [[ ! -d "$release_dir" ]]; then
	tmp_release=$(mktemp -d "/opt/harbor/releases/.${release_id}.XXXXXX")
	trap 'rm -rf "${tmp_release:-}"' EXIT
	chown harbor:harbor "$tmp_release"
	runuser -u harbor -- tar --no-same-owner --no-same-permissions -xzf "$archive" -C "$tmp_release"
	runuser -u harbor -- sh -c 'cd "$1" && sha256sum -c manifest.sha256' sh "$tmp_release"
	mv "$tmp_release" "$release_dir"
	trap - EXIT
fi
test -x "$release_dir/bin/gateway"
test -x "$release_dir/bin/worker"
test -x "$release_dir/bin/seeder"
test -x "$release_dir/bin/migrate"
test -f "$release_dir/web/index.html"
test -f "$release_dir/scripts/threads-profile/scrape.mjs"
chown -R root:harbor "$release_dir"
find "$release_dir" -type d -exec chmod 0755 {} +
find "$release_dir" -type f -exec chmod 0644 {} +
chmod 0755 "$release_dir/bin/gateway" "$release_dir/bin/worker" "$release_dir/bin/seeder" "$release_dir/bin/migrate"

active=blue
if [[ -f /etc/harbor/active-slot ]]; then
  active=$(cat /etc/harbor/active-slot)
fi
if [[ "$active" == blue ]]; then
  inactive=green
  inactive_port=8889
else
  inactive=blue
  inactive_port=8888
fi

if systemctl is-active --quiet "harbor-gateway@$inactive.service"; then
  connections=$(ss -Htn state established "( sport = :$inactive_port )" | wc -l)
  if (( connections > 0 )); then
    printf '%s\n' "inactive slot still has $connections established connection(s); retry later" >&2
    exit 1
  fi
  systemctl stop "harbor-gateway@$inactive.service"
fi
systemctl stop "harbor-worker@$inactive.service" 2>/dev/null || true

set -a
source /etc/harbor/harbor.env
set +a
printf '%s\n' "running forward migrations"
runuser -u harbor -- "$release_dir/bin/migrate" -path "$release_dir/migrations" -database "$MONGO_URL" up
if [[ ! -f /etc/harbor/admin-seeded ]]; then
	/opt/harbor/deploy/remote/seed-admin.sh "$release_dir/bin/seeder"
fi

ln -sfn "$release_dir" "/opt/harbor/slots/$inactive"
chown -h harbor:harbor "/opt/harbor/slots/$inactive"
systemctl start "harbor-gateway@$inactive.service"
for _ in $(seq 1 60); do
  if curl -fsS "http://127.0.0.1:$inactive_port/api/v1/health" >/dev/null; then
    break
  fi
  sleep 1
done
if ! curl -fsS "http://127.0.0.1:$inactive_port/api/v1/health" >/dev/null; then
  journalctl -u "harbor-gateway@$inactive.service" -n 80 --no-pager >&2
  systemctl stop "harbor-gateway@$inactive.service"
  exit 1
fi

systemctl start "harbor-worker@$inactive.service"
sleep 3
if ! systemctl is-active --quiet "harbor-worker@$inactive.service"; then
	journalctl -u "harbor-worker@$inactive.service" -n 80 --no-pager >&2
	systemctl stop "harbor-gateway@$inactive.service"
	exit 1
fi

if [[ -L /opt/harbor/current ]]; then
  readlink -f /opt/harbor/current > /etc/harbor/previous-release
  printf '%s\n' "$active" > /etc/harbor/previous-slot
fi
ln -sfn "$release_dir" /opt/harbor/current.new
mv -Tf /opt/harbor/current.new /opt/harbor/current
printf 'server 127.0.0.1:%s;\n' "$inactive_port" > /etc/nginx/harbor-active-server.conf.new
mv -f /etc/nginx/harbor-active-server.conf.new /etc/nginx/harbor-active-server.conf
nginx -t
systemctl reload nginx
printf '%s\n' "$inactive" > /etc/harbor/active-slot
systemctl enable "harbor-gateway@$inactive.service" "harbor-worker@$inactive.service" >/dev/null
systemctl disable "harbor-gateway@$active.service" "harbor-worker@$active.service" >/dev/null 2>&1 || true
systemctl stop --no-block "harbor-worker@$active.service" 2>/dev/null || true

curl -fsS http://127.0.0.1/health >/dev/null
rm -f "$archive"
printf '%s\n' "activated $release_id on $inactive ($inactive_port)"
