#!/usr/local/bin/bash
#/ Usage: ghe-restore-alambic-cluster
#/ Restore Alambic assets from an rsync snapshot of all assets to a GitHub cluster.
#/
#/ Note: This script typically isn't called directly. It's invoked by the
#/ ghe-restore command when restoring into a cluster.
set -e

# Bring in the backup configuration
. $( dirname "${BASH_SOURCE[0]}" )/ghe-backup-config

# Show usage and bail with no arguments
[ -z "$*" ] && print_usage

bm_start "$(basename $0)"

# Grab host arg
GHE_HOSTNAME="$1"

# Perform a host-check and establish GHE_REMOTE_XXX variables.
ghe_remote_version_required "$GHE_HOSTNAME"

# The snapshot to restore should be set by the ghe-restore command but this lets
# us run this script directly.
: ${GHE_RESTORE_SNAPSHOT:=current}

# Find the binary blobs to restore
storage_paths=$(cd $GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT/ && find storage -mindepth 4 -maxdepth 4 | cut -d / -f2-)

# No need to restore anything, early exit
if [ -z "$storage_paths" ]; then
  echo "Warning: Storage backup missing. Skipping ..."
  exit 0
fi

# Generate SSH config for forwarding
config=""

# Split host:port into parts
port=$(ssh_port_part "$GHE_HOSTNAME")
host=$(ssh_host_part "$GHE_HOSTNAME")

# Add user / -l option
user="${host%@*}"
[ "$user" = "$host" ] && user="admin"

hostnames=$(ghe-ssh "$GHE_HOSTNAME" ghe-config --get-regexp cluster.*.hostname | cut -d ' ' -f 2)
for hostname in $hostnames; do
  config="$config
Host $hostname
  ServerAliveInterval 60
  ProxyCommand ssh -q $GHE_EXTRA_SSH_OPTS -p $port $user@$host nc.openbsd %h %p"
done

config_file=$(mktemp -t cluster-backup-restore-XXXXXX)
echo "$config" > "$config_file"

opts="$GHE_EXTRA_SSH_OPTS -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o PasswordAuthentication=no"

cleanup() {
  for pid in $(jobs -p); do
    kill -KILL $pid > /dev/null 1>&2 || true
  done
  rm -rf $config_file ssh_routes_in ssh_routes_out ssh_finalize_out
}

trap 'cleanup' INT TERM EXIT

rm -rf ssh_routes_in ssh_routes_out ssh_finalize_out
mkfifo ssh_routes_in
mkfifo ssh_routes_out
mkfifo ssh_finalize_out

ghe-ssh "$GHE_HOSTNAME" github-env ./bin/storage-cluster-import-routes - < ssh_routes_out > ssh_routes_in &
ssh_routes_pid=$!
ghe-ssh "$GHE_HOSTNAME" github-env ./bin/storage-cluster-import-finalize - < ssh_finalize_out &
ssh_finalize_pid=$!

exec 4> ssh_routes_out
exec 5> ssh_finalize_out

for storage_path in $storage_paths; do
  oid=$(echo $storage_path | awk -F/ '{print $(NF)}')
  echo "$oid" >&4
  read routes < ssh_routes_in

  for route in $routes; do
    ghe-rsync -aHR --delete \
      -e "ssh -q $opts -p $port -F $config_file -l $user" \
      --rsync-path="sudo -u git rsync" \
      "$GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT/storage/./$storage_path" \
      "$route:$GHE_REMOTE_DATA_USER_DIR/storage" &
  done

  for pid in $(jobs -p); do
    if [ $pid = $ssh_routes_pid -o $pid = $ssh_finalize_pid ]; then
      continue
    fi
    wait $pid
    ret_code=$?
    if [ "$ret_code" != "0" ]; then
      echo "$pid exited $ret_code"
      exit $ret_code
    fi
  done

  echo "$oid $routes" >&5
done

exec 4>&-
exec 5>&-

# Ensure to flush these and close the pipes
cat ssh_routes_in > /dev/null &

wait $ssh_routes_pid > /dev/null 2>&1 || true
wait $ssh_finalize_pid > /dev/null 2>&1 || true

bm_end "$(basename $0)"
