140 lines
5.9 KiB
Bash
Executable File
140 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# ds_install.sh SERVICE
|
|
#
|
|
# Handles the full install lifecycle on the remote server in a single SSH session.
|
|
# Called after the local dropshell has rsynced new template + config to a staging folder.
|
|
#
|
|
# Remote directory layout:
|
|
# services/SERVICE/config/ ← live service config
|
|
# services/SERVICE/template/ ← live template scripts
|
|
# services/SERVICE/_staging/config/ ← new config (rsynced by local)
|
|
# services/SERVICE/_staging/template/ ← new template (rsynced by local)
|
|
#
|
|
# Flow:
|
|
# 1. Run install-pre.sh from STAGING (new code + new config) → validate
|
|
# 2. Run uninstall.sh from LIVE (old code + old config) → stop old service
|
|
# 3. Swap staging → live (atomic replacement)
|
|
# 4. Run install.sh from LIVE (now the new version)
|
|
#
|
|
# If any step fails, the script exits immediately (set -e).
|
|
# If install-pre.sh fails, the old service is untouched.
|
|
|
|
# -- Determine paths --
|
|
SCRIPT_PATH="$(readlink -f "${BASH_SOURCE[0]}")"
|
|
AGENT_PATH="$(dirname "${SCRIPT_PATH}")"
|
|
DROPSHELL_DIR="$(dirname "${AGENT_PATH}")"
|
|
|
|
# Export for scripts that need them
|
|
export AGENT_PATH
|
|
export DROPSHELL_DIR
|
|
|
|
# -- Source common functions --
|
|
source "${AGENT_PATH}/common.sh"
|
|
|
|
# -- Validate arguments --
|
|
if [[ $# -lt 1 ]]; then
|
|
echo "Usage: ds_install.sh SERVICE [TEMP_DIR]" >&2
|
|
exit 1
|
|
fi
|
|
|
|
SERVICE="$1"
|
|
export SERVICE
|
|
export TEMP_DIR="${2:-}"
|
|
export DOCKER_CLI_HINTS=false
|
|
|
|
SERVICE_DIR="${DROPSHELL_DIR}/services/${SERVICE}"
|
|
LIVE_CONFIG="${SERVICE_DIR}/config"
|
|
LIVE_TEMPLATE="${SERVICE_DIR}/template"
|
|
STAGING_DIR="${SERVICE_DIR}/_staging"
|
|
STAGING_CONFIG="${STAGING_DIR}/config"
|
|
STAGING_TEMPLATE="${STAGING_DIR}/template"
|
|
|
|
# -- Validate staging exists --
|
|
[[ -d "${STAGING_CONFIG}" ]] || _die "Staging config not found at ${STAGING_CONFIG}"
|
|
[[ -d "${STAGING_TEMPLATE}" ]] || _die "Staging template not found at ${STAGING_TEMPLATE}"
|
|
[[ -f "${DROPSHELL_DIR}/server_info.env" ]] || _die "Missing server_info.env"
|
|
|
|
# -- Helper: source env for a given template/config pair --
|
|
load_env() {
|
|
local template_dir="$1"
|
|
local config_dir="$2"
|
|
|
|
# Find template_info.env
|
|
local tinfo="${template_dir}/template_info.env"
|
|
if [[ ! -f "${tinfo}" ]]; then
|
|
tinfo="${template_dir}/config/.template_info.env"
|
|
fi
|
|
[[ -f "${tinfo}" ]] || _die "Missing template_info.env in ${template_dir}"
|
|
|
|
# Must have service.env
|
|
[[ -f "${config_dir}/service.env" ]] || _die "Missing service.env in ${config_dir}"
|
|
|
|
# Source in order: server_info → template_info → service.env
|
|
set -a
|
|
source "${DROPSHELL_DIR}/server_info.env"
|
|
source "${tinfo}"
|
|
source "${config_dir}/service.env"
|
|
set +a
|
|
|
|
export CONFIG_PATH="${config_dir}"
|
|
export TEMPLATE_PATH="${template_dir}"
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
# STEP 1: Run install-pre.sh from STAGING (new code + new config)
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
if [[ -f "${STAGING_TEMPLATE}/install-pre.sh" ]]; then
|
|
echo "── Step 1: Running install-pre.sh (new version) ──"
|
|
load_env "${STAGING_TEMPLATE}" "${STAGING_CONFIG}"
|
|
cd "${STAGING_TEMPLATE}"
|
|
|
|
if ! bash ./install-pre.sh; then
|
|
echo "install-pre.sh failed — aborting install. Old service is untouched."
|
|
rm -rf "${STAGING_DIR}"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "── Step 1: No install-pre.sh — skipping ──"
|
|
fi
|
|
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
# STEP 2: Run uninstall.sh from LIVE (old code + old config)
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
if [[ -d "${LIVE_TEMPLATE}" ]] && [[ -f "${LIVE_TEMPLATE}/uninstall.sh" ]]; then
|
|
echo "── Step 2: Running uninstall.sh (old version) ──"
|
|
load_env "${LIVE_TEMPLATE}" "${LIVE_CONFIG}"
|
|
cd "${LIVE_TEMPLATE}"
|
|
|
|
# Uninstall is best-effort — don't abort if it fails
|
|
bash ./uninstall.sh || echo "Warning: uninstall.sh failed, continuing anyway"
|
|
else
|
|
echo "── Step 2: No existing service to uninstall ──"
|
|
fi
|
|
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
# STEP 3: Swap staging → live
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
echo "── Step 3: Swapping staging to live ──"
|
|
|
|
# Remove old live (if exists)
|
|
rm -rf "${LIVE_TEMPLATE}" "${LIVE_CONFIG}"
|
|
|
|
# Move staging into place
|
|
mkdir -p "${SERVICE_DIR}"
|
|
mv "${STAGING_CONFIG}" "${LIVE_CONFIG}"
|
|
mv "${STAGING_TEMPLATE}" "${LIVE_TEMPLATE}"
|
|
rm -rf "${STAGING_DIR}"
|
|
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
# STEP 4: Run install.sh from LIVE (now the new version)
|
|
# ═══════════════════════════════════════════════════════════════════
|
|
echo "── Step 4: Running install.sh (new version) ──"
|
|
load_env "${LIVE_TEMPLATE}" "${LIVE_CONFIG}"
|
|
cd "${LIVE_TEMPLATE}"
|
|
|
|
bash ./install.sh || _die "install.sh failed"
|
|
|
|
echo "── Install complete for ${SERVICE} ──"
|