#!/usr/bin/env bash
#/ Usage: ghe-backup-es-rsync
#/ Take an online, incremental snapshot of Elasticsearch indices.
#/
#/ Note: This command typically isn't called directly. It's invoked by
#/ ghe-backup when the rsync strategy is used.
set -e

# Bring in the backup configuration
# shellcheck source=share/github-backup-utils/ghe-backup-config
. "$( dirname "${BASH_SOURCE[0]}" )/ghe-backup-config"

bm_start "$(basename $0)"

# Set up remote host and root elastic backup directory based on config
host="$GHE_HOSTNAME"

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

# Verify rsync is available.
if ! rsync --version 1>/dev/null 2>&1; then
  echo "Error: rsync not found." 1>&2
  exit 1
fi

# Make sure root backup dir exists if this is the first run
mkdir -p "$GHE_SNAPSHOT_DIR/elasticsearch"

# Verify that the /data/elasticsearch directory exists.
if ! ghe-ssh "$host" -- "[ -d '$GHE_REMOTE_DATA_USER_DIR/elasticsearch' ]"; then
  ghe_verbose "* The '$GHE_REMOTE_DATA_USER_DIR/elasticsearch' directory doesn't exist."
  exit 0
fi

# If we have a previous increment, avoid transferring existing files via rsync's
# --link-dest support. This also decreases physical space usage considerably.
if [ -d "$GHE_DATA_DIR/current/elasticsearch" ]; then
  link_dest="--link-dest=../../current/elasticsearch"
fi

# Transfer ES indices from a GitHub instance to the current snapshot
# directory, using a previous snapshot to avoid transferring files that have
# already been transferred.
ghe_verbose "* Performing initial sync of ES indices ..."
ghe-rsync -avz \
  -e "ghe-ssh -p $(ssh_port_part "$host")" \
  --rsync-path="sudo -u elasticsearch rsync" \
  $link_dest \
  "$(ssh_host_part "$host"):$GHE_REMOTE_DATA_USER_DIR/elasticsearch/" \
  "$GHE_SNAPSHOT_DIR/elasticsearch" 1>&3

# Set up a trap to re-enable flushing on exit and remove temp file
cleanup () {
  ghe_verbose "* Enabling ES index flushing ..."
  echo '{"index":{"translog.disable_flush":false}}' |
  ghe-ssh "$host" -- curl -s -XPUT "localhost:9200/_settings" -d @- >/dev/null
}
trap 'cleanup' EXIT
trap 'exit $?' INT # ^C always terminate

# Disable ES flushing and force a flush right now
ghe_verbose "* Disabling ES index flushing ..."
echo '{"index":{"translog.disable_flush":true}}' |
ghe-ssh "$host" -- curl -s -XPUT  "localhost:9200/_settings" -d @- >/dev/null
ghe-ssh "$host" -- curl -s -XPOST "localhost:9200/_flush" >/dev/null

# Transfer all ES indices again
ghe_verbose "* Performing follow-up sync of ES indices ..."
ghe-rsync -avz \
  -e "ghe-ssh -p $(ssh_port_part "$host")" \
  --rsync-path="sudo -u elasticsearch rsync" \
  $link_dest \
  "$(ssh_host_part "$host"):$GHE_REMOTE_DATA_USER_DIR/elasticsearch/" \
  "$GHE_SNAPSHOT_DIR/elasticsearch" 1>&3

# "Backup" audit log migration sentinel file
if ghe-ssh "$host" -- "test -f $GHE_REMOTE_DATA_USER_DIR/common/es-scan-complete"; then
  touch $GHE_SNAPSHOT_DIR/es-scan-complete
fi

bm_end "$(basename $0)"
