198 lines
5.5 KiB
Bash
198 lines
5.5 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# Nexus production host preflight before applying a release tarball.
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# bash deploy/preflight-release-host.sh \
|
||
|
|
# --tarball /tmp/nexus-release-20260708.tar.gz \
|
||
|
|
# --sha256 a4eb8f35f0b98d40c1ad83117bfc652e7686ffc7d55f6bf90fcfd433a2ad6701 \
|
||
|
|
# --deploy-path /opt/nexus
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
TARBALL=""
|
||
|
|
EXPECTED_SHA256=""
|
||
|
|
DEPLOY_PATH="${NEXUS_DEPLOY_PATH:-/opt/nexus}"
|
||
|
|
MIN_FREE_MB="${NEXUS_RELEASE_MIN_FREE_MB:-1024}"
|
||
|
|
|
||
|
|
info() { echo -e "\033[0;32m[INFO]\033[0m $*"; }
|
||
|
|
warn() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
||
|
|
error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
||
|
|
|
||
|
|
usage() {
|
||
|
|
sed -n '1,12p' "$0"
|
||
|
|
}
|
||
|
|
|
||
|
|
while [[ $# -gt 0 ]]; do
|
||
|
|
case "$1" in
|
||
|
|
--tarball)
|
||
|
|
TARBALL="${2:-}"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--sha256)
|
||
|
|
EXPECTED_SHA256="${2:-}"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--deploy-path)
|
||
|
|
DEPLOY_PATH="${2:-}"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
--min-free-mb)
|
||
|
|
MIN_FREE_MB="${2:-}"
|
||
|
|
shift 2
|
||
|
|
;;
|
||
|
|
-h|--help)
|
||
|
|
usage
|
||
|
|
exit 0
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
error "Unknown argument: $1"
|
||
|
|
usage
|
||
|
|
exit 2
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
done
|
||
|
|
|
||
|
|
check_cmd() {
|
||
|
|
local cmd="$1"
|
||
|
|
if command -v "$cmd" >/dev/null 2>&1; then
|
||
|
|
info "command OK: $cmd"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
error "missing command: $cmd"
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
|
||
|
|
docker_cmd() {
|
||
|
|
if docker "$@" 2>/dev/null; then return 0; fi
|
||
|
|
sudo docker "$@" 2>/dev/null
|
||
|
|
}
|
||
|
|
|
||
|
|
detect_runtime() {
|
||
|
|
if [[ -f "${DEPLOY_PATH}/docker/.env.prod" ]] && command -v docker >/dev/null 2>&1; then
|
||
|
|
echo docker
|
||
|
|
return
|
||
|
|
fi
|
||
|
|
if command -v supervisorctl >/dev/null 2>&1 && supervisorctl status nexus >/dev/null 2>&1; then
|
||
|
|
echo supervisor
|
||
|
|
return
|
||
|
|
fi
|
||
|
|
echo unknown
|
||
|
|
}
|
||
|
|
|
||
|
|
verify_tarball() {
|
||
|
|
if [[ -z "$TARBALL" ]]; then
|
||
|
|
warn "--tarball not provided; skipping tarball checksum/content checks"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
[[ -f "$TARBALL" ]] || {
|
||
|
|
error "tarball not found: $TARBALL"
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
info "tarball exists: $TARBALL"
|
||
|
|
if [[ -n "$EXPECTED_SHA256" ]]; then
|
||
|
|
local actual
|
||
|
|
actual="$(sha256sum "$TARBALL" | awk '{print $1}')"
|
||
|
|
if [[ "$actual" != "$EXPECTED_SHA256" ]]; then
|
||
|
|
error "SHA256 mismatch: expected=$EXPECTED_SHA256 actual=$actual"
|
||
|
|
return 1
|
||
|
|
fi
|
||
|
|
info "SHA256 OK: $actual"
|
||
|
|
else
|
||
|
|
warn "--sha256 not provided; checksum not verified"
|
||
|
|
fi
|
||
|
|
tar tzf "$TARBALL" nexus-release/server nexus-release/deploy nexus-release/web/app-v2 >/dev/null
|
||
|
|
info "tarball required paths OK"
|
||
|
|
}
|
||
|
|
|
||
|
|
check_deploy_path() {
|
||
|
|
if [[ -d "$DEPLOY_PATH" ]]; then
|
||
|
|
info "deploy path exists: $DEPLOY_PATH"
|
||
|
|
else
|
||
|
|
warn "deploy path does not exist yet: $DEPLOY_PATH"
|
||
|
|
fi
|
||
|
|
if [[ -f "${DEPLOY_PATH}/.env" ]]; then
|
||
|
|
info "runtime .env preserved path exists"
|
||
|
|
else
|
||
|
|
warn "${DEPLOY_PATH}/.env not found"
|
||
|
|
fi
|
||
|
|
if [[ -f "${DEPLOY_PATH}/docker/.env.prod" ]]; then
|
||
|
|
info "docker/.env.prod exists"
|
||
|
|
else
|
||
|
|
warn "${DEPLOY_PATH}/docker/.env.prod not found"
|
||
|
|
fi
|
||
|
|
if [[ -d "${DEPLOY_PATH}/web/data" ]]; then
|
||
|
|
info "web/data exists"
|
||
|
|
else
|
||
|
|
warn "${DEPLOY_PATH}/web/data not found"
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
check_disk_space() {
|
||
|
|
local target free_mb
|
||
|
|
target="$DEPLOY_PATH"
|
||
|
|
[[ -e "$target" ]] || target="$(dirname "$DEPLOY_PATH")"
|
||
|
|
free_mb="$(df -Pm "$target" | awk 'NR==2 {print $4}')"
|
||
|
|
if [[ -z "$free_mb" ]]; then
|
||
|
|
warn "unable to determine free disk space for $target"
|
||
|
|
return 0
|
||
|
|
fi
|
||
|
|
if (( free_mb < MIN_FREE_MB )); then
|
||
|
|
error "low disk space on $target: ${free_mb}MB < ${MIN_FREE_MB}MB"
|
||
|
|
return 1
|
||
|
|
fi
|
||
|
|
info "disk free OK: ${free_mb}MB >= ${MIN_FREE_MB}MB"
|
||
|
|
}
|
||
|
|
|
||
|
|
check_runtime() {
|
||
|
|
local runtime
|
||
|
|
runtime="$(detect_runtime)"
|
||
|
|
info "runtime detected: $runtime"
|
||
|
|
case "$runtime" in
|
||
|
|
docker)
|
||
|
|
docker_cmd ps --format '{{.Names}}' | grep -E 'nexus-prod-nexus|nexus-nexus-1' >/dev/null \
|
||
|
|
&& info "Nexus docker container found" \
|
||
|
|
|| warn "Nexus docker container not found by known name pattern"
|
||
|
|
;;
|
||
|
|
supervisor)
|
||
|
|
supervisorctl status nexus || true
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
warn "runtime unknown; apply script may require manual restart"
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
}
|
||
|
|
|
||
|
|
check_local_endpoint() {
|
||
|
|
local port health app app_v2
|
||
|
|
port="$(grep -E '^NEXUS_PUBLISH_PORT=' "${DEPLOY_PATH}/docker/.env.prod" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '\r" ' || true)"
|
||
|
|
port="${port:-8600}"
|
||
|
|
health="$(curl -s "http://127.0.0.1:${port}/health" 2>/dev/null || true)"
|
||
|
|
app="$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${port}/app/" 2>/dev/null || echo 000)"
|
||
|
|
app_v2="$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${port}/app-v2/" 2>/dev/null || echo 000)"
|
||
|
|
echo " current /health -> ${health:-<empty>}"
|
||
|
|
echo " current /app/ -> ${app}"
|
||
|
|
echo " current /app-v2/ -> ${app_v2}"
|
||
|
|
}
|
||
|
|
|
||
|
|
main() {
|
||
|
|
local failures=0
|
||
|
|
for cmd in tar sha256sum df awk grep sed curl; do
|
||
|
|
check_cmd "$cmd" || failures=$((failures + 1))
|
||
|
|
done
|
||
|
|
check_cmd rsync || failures=$((failures + 1))
|
||
|
|
|
||
|
|
verify_tarball || failures=$((failures + 1))
|
||
|
|
check_deploy_path
|
||
|
|
check_disk_space || failures=$((failures + 1))
|
||
|
|
check_runtime
|
||
|
|
check_local_endpoint
|
||
|
|
|
||
|
|
if (( failures > 0 )); then
|
||
|
|
error "preflight failed: ${failures} blocking issue(s)"
|
||
|
|
return 1
|
||
|
|
fi
|
||
|
|
info "preflight OK"
|
||
|
|
}
|
||
|
|
|
||
|
|
main "$@"
|