check_fds.sh rief last_seen_at des OPs-Agenten nie an - der Agent fiel zehn
Minuten nach seiner Registrierung dauerhaft vom Schreibtisch, obwohl der
Ping-Check normal weiterlief. Das Skript meldet jetzt zu Beginn "working" und
am Ende (auch bei einem fruehen Abbruch, per trap) "idle" per
POST /api/v1/agents/{id}/activity, analog zum Cron-Skript des
Entwickler-Agenten. Fehler dabei werden nur protokolliert, nicht fatal.
Dafuer braucht monitor-api.conf zusaetzlich MONITOR_AGENT_ID:
register-ops-agent.sh schreibt sie bei einer Neuregistrierung mit und
traegt sie bei einer bestehenden, aber noch unmigrierten Datei ohne
Neuregistrierung nach.
Schliesst #75.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
153 lines
6.4 KiB
Bash
Executable file
153 lines
6.4 KiB
Bash
Executable file
#!/bin/bash
|
|
#
|
|
# Registriert den lokalen OPs-Agenten (Rolle "ops", Issue #66) bei der monitor-API und legt
|
|
# die Zugangsdaten fuer check_fds.sh in monitor-api.conf ab - also genau die beiden Schritte
|
|
# aus "Weg 3" im README, die sich nicht in hosts.conf/credentials.conf erledigen lassen.
|
|
#
|
|
# Aufruf (im Verzeichnis mit docker-compose.yml, die API muss laufen):
|
|
#
|
|
# ./register-ops-agent.sh [Anzeigename] # Standard-Anzeigename: "OPs"
|
|
#
|
|
# Ueberschreibbar per Umgebungsvariable: MONITOR_API_BASE, MONITOR_ADMIN_API_KEY.
|
|
#
|
|
# Wichtig: Den API-Key gibt die API nur bei der Registrierung einmalig heraus - deshalb
|
|
# ueberschreibt das Skript eine vorhandene monitor-api.conf nicht (--force erzwingt es,
|
|
# der alte Agent bleibt dann mit seinem Schreibtisch registriert).
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ENV_FILE="$SCRIPT_DIR/.env"
|
|
API_CONF="${MONITOR_API_CONF:-$SCRIPT_DIR/monitor-api.conf}"
|
|
|
|
DISPLAY_NAME="OPs"
|
|
FORCE=0
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-f|--force) FORCE=1 ;;
|
|
-h|--help) sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \?//'; exit 0 ;;
|
|
-*) echo "Unbekannte Option: $arg" >&2; exit 1 ;;
|
|
*) DISPLAY_NAME="$arg" ;;
|
|
esac
|
|
done
|
|
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
echo "Fehler: curl wird benoetigt." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Werte aus der .env lesen, statt sie zu sourcen: die Datei enthaelt Kommentare und Werte,
|
|
# die als Shell-Code anders bedeuten wuerden, als sie Docker Compose liest.
|
|
env_value() {
|
|
[ -f "$ENV_FILE" ] || return 0
|
|
sed -n "s/^[[:space:]]*$1=//p" "$ENV_FILE" | tail -n1 \
|
|
| sed -e 's/^"\(.*\)"$/\1/' -e "s/^'\(.*\)'\$/\1/"
|
|
}
|
|
|
|
ADMIN_API_KEY="${MONITOR_ADMIN_API_KEY:-$(env_value MONITOR_ADMIN_API_KEY)}"
|
|
API_BASE="${MONITOR_API_BASE:-$(env_value MONITOR_API_BASE)}"
|
|
API_BASE="${API_BASE:-http://localhost:8091}"
|
|
|
|
# In der .env steht die Basis-URL inklusive "/api/v1" (so braucht sie das Frontend),
|
|
# monitor-api.conf dagegen ohne - check_fds.sh haengt den Pfad selbst an.
|
|
API_ROOT="${API_BASE%/}"
|
|
API_ROOT="${API_ROOT%/api/v1}"
|
|
|
|
if [ -z "$ADMIN_API_KEY" ]; then
|
|
echo "Fehler: MONITOR_ADMIN_API_KEY steht weder in der Umgebung noch in $ENV_FILE." >&2
|
|
exit 1
|
|
fi
|
|
if [ "$ADMIN_API_KEY" = "change-me" ]; then
|
|
echo "Fehler: MONITOR_ADMIN_API_KEY ist noch der Beispielwert 'change-me'." >&2
|
|
exit 1
|
|
fi
|
|
json_escape() {
|
|
printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g'
|
|
}
|
|
|
|
# Ein zweiter Agent gleichen Namens wuerde einen weiteren der acht Schreibtische belegen.
|
|
# GET /api/v1/agents ist unauthentifiziert (API.md "Agenten") und dient hier auch als
|
|
# Erreichbarkeitspruefung. Wird vor der Existenzpruefung von $API_CONF geholt, weil eine
|
|
# bestehende, aber noch unmigrierte Datei (Issue #75, siehe unten) die ID aus genau dieser
|
|
# Antwort nachtraegt, statt den Agenten neu zu registrieren.
|
|
agents_json=$(curl -sS --max-time 10 "$API_ROOT/api/v1/agents" 2>/dev/null) || {
|
|
echo "Fehler: API unter $API_ROOT nicht erreichbar. Laeuft 'docker compose up'?" >&2
|
|
exit 1
|
|
}
|
|
|
|
if [ -e "$API_CONF" ] && [ "$FORCE" -ne 1 ]; then
|
|
if ! grep -q '^MONITOR_AGENT_ID=' "$API_CONF"; then
|
|
# Migration (Issue #75): aeltere monitor-api.conf kennen MONITOR_AGENT_ID noch nicht,
|
|
# ohne das check_fds.sh den Aktivitaets-Endpoint nicht adressieren kann. Die ID laesst
|
|
# sich hier ohne Neuregistrierung nachtragen - GET /api/v1/agents kennt sie bereits
|
|
# (Reihenfolge der Felder wie von AgentRepository::hidingKey() geliefert: "id" direkt
|
|
# vor "display_name").
|
|
# "|| true" haengt am Ende der Pipeline: findet keiner der beiden grep-Aufrufe eine
|
|
# Uebereinstimmung, wuerde ihr Exit-Code mit "set -o pipefail" sonst das ganze Skript
|
|
# kommentarlos beenden, statt in die Fehlermeldung darunter zu fallen.
|
|
existing_id=$(printf '%s' "$agents_json" \
|
|
| grep -oE "\"id\":[0-9]+,\"display_name\":\"$(json_escape "$DISPLAY_NAME")\"" \
|
|
| head -n1 | grep -oE '[0-9]+' || true)
|
|
if [ -n "$existing_id" ]; then
|
|
printf 'MONITOR_AGENT_ID="%s"\n' "$existing_id" >> "$API_CONF"
|
|
echo "MONITOR_AGENT_ID fehlte in $API_CONF und wurde nachgetragen (ID $existing_id)."
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
echo "Fehler: $API_CONF existiert bereits - der bisherige OPs-Agent ist offenbar schon" >&2
|
|
echo " registriert. Zum Neuanlegen die Datei wegsichern oder --force angeben." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if printf '%s' "$agents_json" | grep -q "\"display_name\":\"$(json_escape "$DISPLAY_NAME")\""; then
|
|
echo "Fehler: Ein Agent namens \"$DISPLAY_NAME\" ist bereits registriert." >&2
|
|
echo " Anderen Anzeigenamen uebergeben oder den alten Agenten loeschen." >&2
|
|
exit 1
|
|
fi
|
|
|
|
response=$(curl -sS -w '\n%{http_code}' --max-time 10 -X POST "$API_ROOT/api/v1/agents" \
|
|
-H 'Content-Type: application/json' \
|
|
-H "X-Admin-Key: $ADMIN_API_KEY" \
|
|
-d "{\"display_name\": \"$(json_escape "$DISPLAY_NAME")\", \"role\": \"ops\"}")
|
|
|
|
http_code=$(printf '%s' "$response" | tail -n1)
|
|
body=$(printf '%s' "$response" | sed '$d')
|
|
|
|
if [ "$http_code" != "201" ]; then
|
|
echo "Fehler: Registrierung fehlgeschlagen (HTTP $http_code)." >&2
|
|
echo "$body" >&2
|
|
exit 1
|
|
fi
|
|
|
|
api_key=$(printf '%s' "$body" | grep -oE '"api_key":"[0-9a-f]+"' | head -n1 | cut -d'"' -f4)
|
|
agent_id=$(printf '%s' "$body" | grep -oE '"id":[0-9]+' | head -n1 | cut -d: -f2)
|
|
desk_index=$(printf '%s' "$body" | grep -oE '"desk_index":(null|[0-9]+)' | head -n1 | cut -d: -f2)
|
|
|
|
if [ -z "$api_key" ]; then
|
|
echo "Fehler: Die Antwort enthielt keinen api_key:" >&2
|
|
echo "$body" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Erst die Rechte setzen, dann schreiben - sonst stuende das Secret kurzzeitig lesbar da.
|
|
umask 077
|
|
cat > "$API_CONF" <<CONF
|
|
# Zugangsdaten, mit denen check_fds.sh die Ping-Ergebnisse per REST an die monitor-API
|
|
# meldet. Angelegt von register-ops-agent.sh am $(date +%Y-%m-%d) fuer den Agenten
|
|
# "$DISPLAY_NAME" (Rolle "ops", ID $agent_id). Enthaelt ein Secret: chmod 600.
|
|
|
|
MONITOR_API_BASE="$API_ROOT"
|
|
MONITOR_API_KEY="$api_key"
|
|
MONITOR_AGENT_ID="$agent_id"
|
|
CONF
|
|
chmod 600 "$API_CONF"
|
|
|
|
echo "OPs-Agent \"$DISPLAY_NAME\" registriert (ID $agent_id, Schreibtisch $desk_index)."
|
|
echo "Zugangsdaten geschrieben: $API_CONF"
|
|
echo
|
|
echo "Naechste Schritte:"
|
|
echo " 1. Ping-Check testen: $SCRIPT_DIR/check_fds.sh"
|
|
echo " 2. Ergebnis pruefen: curl -s $API_ROOT/api/v1/systems"
|
|
echo " 3. Per Cron einplanen, z.B.:"
|
|
echo " */5 * * * * $SCRIPT_DIR/check_fds.sh >> /var/log/check_fds.log 2>&1"
|