#!/bin/bash # ppf-deploy -- deploy PPF code to nodes # # Usage: # ppf-deploy [options] [targets...] # # Targets: # all odin + all workers (default) # workers cassius, edge, sentinel # master odin # specific host(s) set -eu # Resolve to real path (handles symlinks from ~/.local/bin/) SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")" SCRIPT_DIR="$(dirname "$(readlink -f "$SCRIPT_PATH")")" # shellcheck disable=SC1091 . "$SCRIPT_DIR/lib/ppf-common.sh" PLAYBOOK_DIR="$SCRIPT_DIR/playbooks" # --------------------------------------------------------------------------- # Usage # --------------------------------------------------------------------------- usage() { cat < specific host(s) Options: --no-restart sync files only, skip container restart --check dry run (ansible --check --diff) -v verbose ansible output --help show this help --version show version Steps performed: 1. Validate Python syntax locally 2. Rsync *.py + servers.txt (role-aware destinations) 3. Copy compose file per role 4. Fix ownership (podman:podman) 5. Restart containers on change (unless --no-restart) 6. Show container status EOF exit 0 } # --------------------------------------------------------------------------- # Parse args # --------------------------------------------------------------------------- DO_RESTART=1 CHECK_MODE=0 VERBOSE="" 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 ;; --check) CHECK_MODE=1 ;; -v) VERBOSE="-v" ;; -*) die "Unknown option: $1" ;; *) TARGETS="${TARGETS:+$TARGETS }$1" ;; esac shift done TARGETS="${TARGETS:-all}" # --------------------------------------------------------------------------- # Pre-flight: local syntax validation # --------------------------------------------------------------------------- validate_syntax # --------------------------------------------------------------------------- # Build ansible-playbook arguments # --------------------------------------------------------------------------- ARGS=(-i "$PLAYBOOK_DIR/inventory.ini") ARGS+=(-e "ppf_src=$PPF_DIR") if [ "$DO_RESTART" -eq 0 ]; then ARGS+=(-e "ppf_restart=false") fi if [ "$CHECK_MODE" -eq 1 ]; then ARGS+=(--check --diff) fi [ -n "$VERBOSE" ] && ARGS+=("$VERBOSE") # Target resolution: map aliases to ansible --limit case "$TARGETS" in all) ;; # no --limit = all hosts in inventory *) LIMIT=$(resolve_targets $TARGETS | tr ' ' ',') ARGS+=(--limit "$LIMIT") ;; esac ARGS+=("$PLAYBOOK_DIR/deploy.yml") # --------------------------------------------------------------------------- # Run playbook # --------------------------------------------------------------------------- section "Deploying to ${TARGETS}" ansible_playbook_cmd "${ARGS[@]}"