Files
devnet-scripts/delete-vids-devnet.sh
2026-01-16 17:31:26 -08:00

217 lines
5.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# ------------------------------------------------------------
# delete-vids-devnet.sh
# ------------------------------------------------------------
VERSION="1.0.0"
HOST_TEMPLATE="devnet-node-%d.qortal.link"
HOST_FIXED=""
PORT_START=22221
PORT_END=22227
REMOTE_USER="${USER}"
REMOTE_HOME="/home/${REMOTE_USER}"
SSH_RETRIES=4
SSH_DELAY=5
NODE_SPEC=()
PRIMARY_NODE=4
usage() {
cat <<EOF
delete-vids-devnet.sh v${VERSION}
Usage: $(basename "$0") [options] [--] [-N ...]
Options:
--host HOST Fixed host for all nodes (default: none)
--host-template STR Host template for node numbering (default: ${HOST_TEMPLATE})
--ports A-B Port range for SSH (default: ${PORT_START}-${PORT_END})
--node N Target node N (repeatable)
--nodes LIST Target nodes (comma-separated list)
-h, --help Show this help
Short numeric flags like -1 -3 are also accepted and target nodes 1 and 3.
By default the script runs the delete commands on all nodes in the port range.
EOF
}
log() { printf '[%s] %s\n' "$(date +'%F %T')" "$*" >&2; }
warn() { log "WARNING: $*"; }
parse_ports() {
local spec="$1"
[[ "$spec" =~ ^([0-9]+)-([0-9]+)$ ]] || { echo "Invalid --ports (use A-B)" >&2; exit 1; }
PORT_START="${BASH_REMATCH[1]}"
PORT_END="${BASH_REMATCH[2]}"
(( PORT_START <= PORT_END )) || { echo "--ports start must be <= end" >&2; exit 1; }
}
add_node_spec() {
local spec="$1"
spec="${spec//[[:space:]]/}"
[[ "$spec" =~ ^[0-9]+$ ]] || { echo "Invalid node spec: $spec" >&2; exit 1; }
NODE_SPEC+=( "$spec" )
}
parse_nodes_list() {
local list="$1"
IFS=',' read -r -a parts <<< "$list"
for part in "${parts[@]}"; do
[[ -n "$part" ]] || continue
add_node_spec "$part"
done
}
node_to_port() {
local node="$1"
echo $(( PORT_START + node - 1 ))
}
host_for_port() {
local port="$1"
if [[ -n "$HOST_FIXED" ]]; then
echo "$HOST_FIXED"
return 0
fi
local idx=$((port - PORT_START + 1))
if (( idx < 1 )); then
echo "Invalid port ${port} for template mapping (PORT_START=${PORT_START})" >&2
return 1
fi
printf "$HOST_TEMPLATE" "$idx"
}
while [[ $# -gt 0 ]]; do
case "$1" in
--host) HOST_FIXED="${2:-}"; shift 2;;
--host-template) HOST_TEMPLATE="${2:-}"; shift 2;;
--ports) parse_ports "${2:-}"; shift 2;;
--node) add_node_spec "${2:-}"; shift 2;;
--nodes) parse_nodes_list "${2:-}"; shift 2;;
-h|--help) usage; exit 0;;
--) shift; break;;
-[0-9]*) add_node_spec "${1:1}"; shift;;
[0-9]*) add_node_spec "$1"; shift;;
*) echo "Unknown arg: $1" >&2; usage; exit 1;;
esac
done
NODE_COUNT=$(( PORT_END - PORT_START + 1 ))
(( NODE_COUNT > 0 )) || { echo "Invalid port range ${PORT_START}-${PORT_END}" >&2; exit 1; }
TARGET_NODES_RAW=()
if (( ${#NODE_SPEC[@]} == 0 )); then
for ((i=1; i<=NODE_COUNT; i++)); do
TARGET_NODES_RAW+=( "$i" )
done
else
mapfile -t TARGET_NODES_RAW < <(printf '%s\n' "${NODE_SPEC[@]}" | awk 'NF' | sort -n | uniq)
fi
TARGET_NODES=()
for node in "${TARGET_NODES_RAW[@]}"; do
if [[ ! "$node" =~ ^[0-9]+$ ]]; then
echo "Invalid node index: $node" >&2
exit 1
fi
if (( node == PRIMARY_NODE )); then
warn "Skipping primary node ${PRIMARY_NODE} per policy"
continue
fi
if (( node < 1 || node > NODE_COUNT )); then
echo "Node ${node} is outside the available range 1-${NODE_COUNT}" >&2
exit 1
fi
TARGET_NODES+=( "$node" )
done
if (( ${#TARGET_NODES[@]} == 0 )); then
echo "No target nodes left after applying exclusions (primary node ${PRIMARY_NODE} is protected)." >&2
exit 1
fi
log "Primary node ${PRIMARY_NODE} is protected and will be skipped."
log "Target nodes: ${TARGET_NODES[*]}"
log "Port range: ${PORT_START}-${PORT_END}"
if [[ -n "$HOST_FIXED" ]]; then
log "Host: ${HOST_FIXED}"
else
log "Host template: ${HOST_TEMPLATE}"
fi
log "SSH retries: ${SSH_RETRIES}, start delay ${SSH_DELAY}s"
run_delete_sequence() {
local node="$1"
local port="$2"
local host="$3"
local target="${REMOTE_USER}@${host}"
local attempt=1
local delay="$SSH_DELAY"
while (( attempt <= SSH_RETRIES )); do
log "[node ${node}] running delete commands (attempt ${attempt}/${SSH_RETRIES})"
if ssh -p"${port}" "${target}" bash <<'EOF'
set -euo pipefail
echo "Deleteing Birds Video"
curl -X DELETE \
http://127.0.0.1:22391/arbitrary/resource/VIDEO/Q-Tube/MYTEST2_vid_-the-funniest-birds_sErSoP \
-H 'accept: text/plain' \
-H 'X-API-KEY: 3emLj1L5M1e8uQDob8bF3b'
echo "Deleteing Q-Tube May 15 video"
curl -X DELETE \
http://127.0.0.1:22391/arbitrary/resource/VIDEO/Q-Tube/MYTEST2_vid_q-tube-may-15_0cT8id \
-H 'accept: text/plain' \
-H 'X-API-KEY: 3emLj1L5M1e8uQDob8bF3b'
echo "Deleteing Blood Machines"
curl -X DELETE \
http://127.0.0.1:22391/arbitrary/resource/VIDEO/Q-Tube/MYTEST2_vid_blood-machines-chapter-two-cor_STChYK \
-H 'accept: text/plain' \
-H 'X-API-KEY: 3emLj1L5M1e8uQDob8bF3b'
echo "Deleteing Batman"
curl -X DELETE \
http://127.0.0.1:22391/arbitrary/resource/VIDEO/Q-Tube/MYTEST2_vid_batman_1j2qoI \
-H 'accept: text/plain' \
-H 'X-API-KEY: 3emLj1L5M1e8uQDob8bF3b'
EOF
then
log "[node ${node}] delete sequence succeeded"
return 0
fi
warn "[node ${node}] delete attempt ${attempt} failed"
(( attempt++ ))
sleep "$delay"
delay=$(( delay * 2 ))
done
warn "[node ${node}] delete sequence failed after ${SSH_RETRIES} attempts"
return 1
}
for node in "${TARGET_NODES[@]}"; do
port="$(node_to_port "$node")"
host="$(host_for_port "$port")" || { warn "[node ${node}] host mapping failed; skipping"; continue; }
log "==================== node ${node} (port ${port}) ===================="
log "[node ${node}] host: ${host}"
if ! run_delete_sequence "$node" "$port" "$host"; then
warn "[node ${node}] delete commands failed; moving to next node"
continue
fi
log "[node ${node}] done"
done
log "All nodes processed."