tools: rewrite ppf-deploy as playbook wrapper
Replace sequential ansible ad-hoc calls with ansible-playbook. Add ansible_playbook_cmd to shared library. Supports --check for dry runs.
This commit is contained in:
@@ -108,6 +108,17 @@ ansible_cmd() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Runs ansible-playbook with venv activated and ANSIBLE_REMOTE_TMP set.
|
||||||
|
# Usage: ansible_playbook_cmd <ansible-playbook args...>
|
||||||
|
ansible_playbook_cmd() {
|
||||||
|
(
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "$ANSIBLE_VENV"
|
||||||
|
cd "$ANSIBLE_DIR"
|
||||||
|
ANSIBLE_REMOTE_TMP=/tmp/.ansible ansible-playbook "$@"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Remote podman/compose wrappers
|
# Remote podman/compose wrappers
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
142
tools/ppf-deploy
142
tools/ppf-deploy
@@ -2,7 +2,7 @@
|
|||||||
# ppf-deploy -- deploy PPF code to nodes
|
# ppf-deploy -- deploy PPF code to nodes
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# ppf-deploy [--no-restart] [targets...]
|
# ppf-deploy [options] [targets...]
|
||||||
#
|
#
|
||||||
# Targets:
|
# Targets:
|
||||||
# all odin + all workers (default)
|
# all odin + all workers (default)
|
||||||
@@ -12,18 +12,22 @@
|
|||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
# 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
|
# shellcheck disable=SC1091
|
||||||
. "$SCRIPT_DIR/lib/ppf-common.sh"
|
. "$SCRIPT_DIR/lib/ppf-common.sh"
|
||||||
|
|
||||||
|
PLAYBOOK_DIR="$SCRIPT_DIR/playbooks"
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Usage
|
# Usage
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: ppf-deploy [--no-restart] [targets...]
|
Usage: ppf-deploy [options] [targets...]
|
||||||
|
|
||||||
Deploy PPF code to nodes.
|
Deploy PPF code to nodes via Ansible playbook.
|
||||||
|
|
||||||
Targets:
|
Targets:
|
||||||
all odin + all workers (default)
|
all odin + all workers (default)
|
||||||
@@ -33,15 +37,17 @@ Targets:
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
--no-restart sync files only, skip container restart
|
--no-restart sync files only, skip container restart
|
||||||
|
--check dry run (ansible --check --diff)
|
||||||
|
-v verbose ansible output
|
||||||
--help show this help
|
--help show this help
|
||||||
--version show version
|
--version show version
|
||||||
|
|
||||||
Steps:
|
Steps performed:
|
||||||
1. Validate Python syntax locally
|
1. Validate Python syntax locally
|
||||||
2. Rsync *.py + servers.txt to targets
|
2. Rsync *.py + servers.txt (role-aware destinations)
|
||||||
3. Copy compose file per role
|
3. Copy compose file per role
|
||||||
4. Fix ownership (podman:podman)
|
4. Fix ownership (podman:podman)
|
||||||
5. Restart containers (unless --no-restart)
|
5. Restart containers on change (unless --no-restart)
|
||||||
6. Show container status
|
6. Show container status
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
@@ -51,6 +57,8 @@ EOF
|
|||||||
# Parse args
|
# Parse args
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
DO_RESTART=1
|
DO_RESTART=1
|
||||||
|
CHECK_MODE=0
|
||||||
|
VERBOSE=""
|
||||||
TARGETS=""
|
TARGETS=""
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
@@ -58,6 +66,8 @@ while [ $# -gt 0 ]; do
|
|||||||
--help|-h) usage ;;
|
--help|-h) usage ;;
|
||||||
--version|-V) echo "ppf-deploy $PPF_TOOLS_VERSION"; exit 0 ;;
|
--version|-V) echo "ppf-deploy $PPF_TOOLS_VERSION"; exit 0 ;;
|
||||||
--no-restart) DO_RESTART=0 ;;
|
--no-restart) DO_RESTART=0 ;;
|
||||||
|
--check) CHECK_MODE=1 ;;
|
||||||
|
-v) VERBOSE="-v" ;;
|
||||||
-*) die "Unknown option: $1" ;;
|
-*) die "Unknown option: $1" ;;
|
||||||
*) TARGETS="${TARGETS:+$TARGETS }$1" ;;
|
*) TARGETS="${TARGETS:+$TARGETS }$1" ;;
|
||||||
esac
|
esac
|
||||||
@@ -65,103 +75,41 @@ while [ $# -gt 0 ]; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
TARGETS="${TARGETS:-all}"
|
TARGETS="${TARGETS:-all}"
|
||||||
HOSTS=$(resolve_targets $TARGETS)
|
|
||||||
|
|
||||||
[ -z "$HOSTS" ] && die "No valid targets"
|
|
||||||
|
|
||||||
section "Deploy targets"
|
|
||||||
log_info "$HOSTS"
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Step 1: Validate syntax
|
# Pre-flight: local syntax validation
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
validate_syntax
|
validate_syntax
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Step 2: Rsync code to targets
|
# Build ansible-playbook arguments
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
section "Syncing code"
|
ARGS=(-i "$PLAYBOOK_DIR/inventory.ini")
|
||||||
|
ARGS+=(-e "ppf_src=$PPF_DIR")
|
||||||
|
|
||||||
for host in $HOSTS; do
|
if [ "$DO_RESTART" -eq 0 ]; then
|
||||||
if is_master "$host"; then
|
ARGS+=(-e "ppf_restart=false")
|
||||||
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
|
fi
|
||||||
|
|
||||||
printf "\n"
|
if [ "$CHECK_MODE" -eq 1 ]; then
|
||||||
log_ok "Deploy complete"
|
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[@]}"
|
||||||
|
|||||||
Reference in New Issue
Block a user