tools: add ppf-deploy

Validates syntax, rsyncs code, copies compose files, fixes ownership,
restarts containers. Supports --no-restart and per-host targeting.
This commit is contained in:
Username
2026-02-17 22:50:34 +01:00
parent 9b7ca20728
commit 7f59cae05c

167
tools/ppf-deploy Executable file
View File

@@ -0,0 +1,167 @@
#!/bin/bash
# ppf-deploy -- deploy PPF code to nodes
#
# Usage:
# ppf-deploy [--no-restart] [targets...]
#
# Targets:
# all odin + all workers (default)
# workers cassius, edge, sentinel
# master odin
# <hostname> specific host(s)
set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck disable=SC1091
. "$SCRIPT_DIR/lib/ppf-common.sh"
# ---------------------------------------------------------------------------
# Usage
# ---------------------------------------------------------------------------
usage() {
cat <<EOF
Usage: ppf-deploy [--no-restart] [targets...]
Deploy PPF code to nodes.
Targets:
all odin + all workers (default)
workers cassius, edge, sentinel
master odin
<hostname> specific host(s)
Options:
--no-restart sync files only, skip container restart
--help show this help
--version show version
Steps:
1. Validate Python syntax locally
2. Rsync *.py + servers.txt to targets
3. Copy compose file per role
4. Fix ownership (podman:podman)
5. Restart containers (unless --no-restart)
6. Show container status
EOF
exit 0
}
# ---------------------------------------------------------------------------
# Parse args
# ---------------------------------------------------------------------------
DO_RESTART=1
TARGETS=""
while [ $# -gt 0 ]; do
case "$1" in
--help|-h) usage ;;
--version|-V) echo "ppf-deploy $PPF_TOOLS_VERSION"; exit 0 ;;
--no-restart) DO_RESTART=0 ;;
-*) die "Unknown option: $1" ;;
*) TARGETS="${TARGETS:+$TARGETS }$1" ;;
esac
shift
done
TARGETS="${TARGETS:-all}"
HOSTS=$(resolve_targets $TARGETS)
[ -z "$HOSTS" ] && die "No valid targets"
section "Deploy targets"
log_info "$HOSTS"
# ---------------------------------------------------------------------------
# Step 1: Validate syntax
# ---------------------------------------------------------------------------
validate_syntax
# ---------------------------------------------------------------------------
# Step 2: Rsync code to targets
# ---------------------------------------------------------------------------
section "Syncing code"
for host in $HOSTS; do
if is_master "$host"; then
dest="/home/podman/ppf/"
else
dest="/home/podman/ppf/src/"
fi
log_info "${host} ${C_DIM}-> ${dest}${C_RST}"
ansible_cmd "$host" -m synchronize \
-a "src=$PPF_DIR/ dest=$dest rsync_opts='--include=*.py,--include=servers.txt,--include=Dockerfile,--exclude=*'" \
> /dev/null 2>&1 \
&& log_ok "$host synced" \
|| { log_err "$host sync failed"; continue; }
done
# ---------------------------------------------------------------------------
# Step 3: Copy compose file per role
# ---------------------------------------------------------------------------
section "Copying compose files"
for host in $HOSTS; do
if is_master "$host"; then
src="$PPF_DIR/compose.master.yml"
else
src="$PPF_DIR/compose.worker.yml"
fi
ansible_cmd "$host" -m copy \
-a "src=$src dest=/home/podman/ppf/compose.yml owner=podman group=podman" \
> /dev/null 2>&1 \
&& log_ok "$host compose file" \
|| log_err "$host compose copy failed"
done
# ---------------------------------------------------------------------------
# Step 4: Fix ownership
# ---------------------------------------------------------------------------
section "Fixing ownership"
csv=$(hosts_csv $HOSTS)
ansible_cmd "$csv" -m raw -a "chown -R podman:podman /home/podman/ppf/" \
> /dev/null 2>&1 \
&& log_ok "ownership fixed on all targets" \
|| log_err "ownership fix failed on some targets"
# ---------------------------------------------------------------------------
# Step 5: Restart (unless --no-restart)
# ---------------------------------------------------------------------------
if [ "$DO_RESTART" -eq 1 ]; then
section "Restarting containers"
for host in $HOSTS; do
compose_cmd "$host" "restart" > /dev/null 2>&1 \
&& log_ok "$host restarted" \
|| log_err "$host restart failed"
done
# Brief pause for containers to settle
sleep 2
# ---------------------------------------------------------------------------
# Step 6: Show status
# ---------------------------------------------------------------------------
section "Container status"
for host in $HOSTS; do
local_output=$(compose_cmd "$host" "ps" 2>/dev/null) || true
if echo "$local_output" | grep -qi "up\|running"; then
log_ok "$host"
else
log_warn "$host"
fi
echo "$local_output" | grep -v '^\s*$' | while IFS= read -r line; do
log_dim "$line"
done
done
else
log_info "Restart skipped (--no-restart)"
fi
printf "\n"
log_ok "Deploy complete"