sync: auto-sync from HOWARD-HOME at 2026-07-03 17:00:12

Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-03 17:00:12
This commit is contained in:
2026-07-03 17:00:47 -07:00
parent 78f794a924
commit e0e3dd0d82
9 changed files with 478 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# gps-rmm-progress-check.sh — daily GPS->GuruRMM enrollment progress check.
#
# Reads projects/gps-rmm-audit/targets.json (GPS device target per client),
# pulls live GuruRMM /api/agents, computes per-client enrollment gaps, and DMs
# Howard a one-message summary. When every tracked client has met its target it
# reports "COMPLETE" so the scheduled task can be retired.
#
# Usage:
# bash gps-rmm-progress-check.sh # check + DM Howard
# bash gps-rmm-progress-check.sh --dry-run # check + print, no Discord
#
# Registered as a daily Windows scheduled task. Read-only against RMM.
set -u
ROOT="${CLAUDETOOLS_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
TARGETS="$ROOT/projects/gps-rmm-audit/targets.json"
DRY=0; [ "${1:-}" = "--dry-run" ] && DRY=1
[ -f "$TARGETS" ] || { echo "[ERROR] targets.json not found at $TARGETS" >&2; exit 1; }
# --- auth + fetch agents ---
eval "$(bash "$ROOT/.claude/scripts/rmm-auth.sh" 2>/dev/null)" >/dev/null
if [ -z "${TOKEN:-}" ] || [ -z "${RMM:-}" ]; then
echo "[ERROR] RMM auth failed" >&2
bash "$ROOT/.claude/scripts/log-skill-error.sh" "gps-rmm-progress-check" "RMM auth failed" >/dev/null 2>&1
exit 1
fi
AGENTS=$(curl -s "$RMM/api/agents" -H "Authorization: Bearer $TOKEN" | tr -d '\000-\037')
[ "${AGENTS:0:1}" = "[" ] || { echo "[ERROR] /api/agents not an array: ${AGENTS:0:100}" >&2; \
bash "$ROOT/.claude/scripts/log-skill-error.sh" "gps-rmm-progress-check" "GET /api/agents non-array" >/dev/null 2>&1; exit 1; }
# --- per-client live agent counts (unique hostnames, to ignore dup agent rows) ---
COUNTS=$(echo "$AGENTS" | jq -r '[.[] | {c:.client_name, h:(.hostname|ascii_downcase)}]
| group_by(.c) | map({client:.[0].c, n:( [.[].h] | unique | length )}) | .[] | "\(.n)\t\(.client)"')
# --- compare targets vs live ---
REPORT=""; DONE_ALL=1; TOTAL_TARGET=0; TOTAL_HAVE=0; GAP_CLIENTS=0
while IFS=$'\t' read -r TGT NAME BUCKET; do
[ -z "$NAME" ] && continue
HAVE=$(echo "$COUNTS" | awk -F'\t' -v n="$NAME" '$2==n{print $1; found=1} END{if(!found)print 0}' | head -1)
HAVE=${HAVE:-0}
TOTAL_TARGET=$((TOTAL_TARGET + TGT))
TOTAL_HAVE=$((TOTAL_HAVE + HAVE))
if [ "$HAVE" -lt "$TGT" ]; then
DONE_ALL=0; GAP_CLIENTS=$((GAP_CLIENTS+1))
GAP=$((TGT - HAVE))
STATE=$([ "$HAVE" -eq 0 ] && echo "NO ORG/AGENTS" || echo "short")
REPORT="${REPORT} - ${NAME}: ${HAVE}/${TGT} in RMM (${STATE}, gap ${GAP}) [${BUCKET}]\n"
fi
done < <(jq -r '.clients[] | "\(.target)\t\(.client)\t\(.bucket)"' "$TARGETS")
DATE=$(date +%Y-%m-%d)
if [ "$DONE_ALL" -eq 1 ]; then
MSG="**GPS->RMM enrollment: COMPLETE (${DATE})** All tracked GPS clients meet their RMM device target (${TOTAL_HAVE}/${TOTAL_TARGET}). You can retire the daily check task (schtasks /Delete /TN GPS-RMM-Progress)."
else
MSG="**GPS->RMM enrollment check ${DATE}** — ${TOTAL_HAVE}/${TOTAL_TARGET} devices in RMM; ${GAP_CLIENTS} clients still short:\n${REPORT}(Glaz-Tech excluded pending billing review. Source: projects/gps-rmm-audit/targets.json)"
fi
if [ "$DRY" -eq 1 ]; then
echo -e "$MSG"
exit 0
fi
echo -e "$MSG" | bash "$ROOT/.claude/scripts/discord-dm.sh" howard