rsyslog/update-gitops-status.sh
dvirlabs db28c9da82
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Migrate from pushgateway to infinity
2026-04-21 12:41:09 +03:00

206 lines
9.7 KiB
Bash

#!/bin/bash
# =============================================================================
# update-gitops-status.sh
#
# Purpose:
# Runs drift-check playbook and generates a JSON status snapshot for
# gitops-status-server. This replaces Pushgateway metric updates with
# richer JSON status suitable for Grafana visualization via Infinity DS.
#
# Flow:
# 1. Execute ansible/playbooks/drift-check.yml (check mode, read-only)
# 2. Capture exit code to determine sync status
# 3. Parse playbook output to extract changed files
# 4. Build structured JSON with metadata
# 5. POST JSON to gitops-status-server API
#
# Usage:
# ./update-gitops-status.sh
#
# Environment Variables:
# GITOPS_STATUS_SERVER_URL - URL of gitops-status-server API
# (default: http://gitops-status-server.observability-stack.svc.cluster.local:80)
# REPO_NAME - Repository name (default: rsyslog)
# SERVER_NAME - Server name (default: rsyslog-lab)
#
# Generated JSON Structure:
# {
# "repo": "rsyslog",
# "server": "rsyslog-lab",
# "sync_status": "SYNCED" or "OUT_OF_SYNC",
# "drift_count": <number>,
# "files": [{"name": "rsyslog.conf"}, {"name": "rsyslog.d/30-lab.conf"}],
# "last_check": "2026-04-21T10:30:00Z"
# }
#
# Exit Codes:
# 0 - Success (JSON posted to gitops-status-server regardless of sync status)
# 1 - Failure (playbook error, network error, JSON post failure, etc.)
#
# =============================================================================
set -euo pipefail
# ─────────────────────────────────────────────────────────────────────────────
# Configuration
# ─────────────────────────────────────────────────────────────────────────────
GITOPS_STATUS_SERVER_URL="${GITOPS_STATUS_SERVER_URL:-http://gitops-status-server.observability-stack.svc.cluster.local:80}"
REPO_NAME="${REPO_NAME:-rsyslog}"
SERVER_NAME="${SERVER_NAME:-rsyslog-lab}"
INVENTORY_FILE="ansible/inventory/hosts.yml"
PLAYBOOK="ansible/playbooks/drift-check.yml"
echo "═══════════════════════════════════════════════════════════════════════════════"
echo " GitOps Status Update"
echo " Repository: $REPO_NAME | Server: $SERVER_NAME"
echo " Target: $GITOPS_STATUS_SERVER_URL"
echo "═══════════════════════════════════════════════════════════════════════════════"
echo ""
# ─────────────────────────────────────────────────────────────────────────────────
# Step 1: Run drift-check playbook
# ─────────────────────────────────────────────────────────────────────────────────
echo "Step 1/4: Running drift-check playbook..."
# Capture playbook output to a temp file for parsing
PLAYBOOK_LOG=$(mktemp)
trap "rm -f $PLAYBOOK_LOG" EXIT
# Run playbook with verbose flag to capture detailed output
# Exit code: 0 = synced, non-zero = drift detected (expected)
set +e
ansible-playbook \
-i "$INVENTORY_FILE" \
"$PLAYBOOK" \
-v \
> "$PLAYBOOK_LOG" 2>&1
DRIFT_RC=$?
set -e
# Show playbook output for debugging
cat "$PLAYBOOK_LOG"
echo ""
# ─────────────────────────────────────────────────────────────────────────────────
# Step 2: Determine sync status and collect changed files
# ─────────────────────────────────────────────────────────────────────────────────
echo "Step 2/4: Analyzing drift detection results..."
CHANGED_FILES=()
DRIFT_COUNT=0
# Exit code 0 = synced (all tasks succeeded)
# Exit code non-zero = drift detected (fail task was reached)
if [ "$DRIFT_RC" -eq 0 ]; then
SYNC_STATUS="SYNCED"
echo " ✓ Status: SYNCED - server configuration matches Git"
else
SYNC_STATUS="OUT_OF_SYNC"
echo " ✗ Status: OUT OF SYNC - configuration drift detected"
# Extract structured drifted files from playbook output
# The drift-check.yml playbook outputs: DRIFTED_FILES=file1,file2,file3
if grep -q "DRIFTED_FILES=" "$PLAYBOOK_LOG"; then
DRIFTED_FILES_STR=$(grep "DRIFTED_FILES=" "$PLAYBOOK_LOG" | head -1 | sed 's/.*DRIFTED_FILES=//' | sed 's/\x1b\[[0-9;]*m//g')
# Parse comma-separated list into array
IFS=',' read -ra CHANGED_FILES <<<"$DRIFTED_FILES_STR"
# Clean up whitespace and convert paths
for i in "${!CHANGED_FILES[@]}"; do
CHANGED_FILES[$i]=$(echo "${CHANGED_FILES[$i]}" | xargs)
# Convert full paths to relative paths for cleaner output
# /etc/rsyslog.conf -> rsyslog.conf
# /etc/rsyslog.d/30-lab.conf -> rsyslog.d/30-lab.conf
if [[ "${CHANGED_FILES[$i]}" == /etc/rsyslog.conf ]]; then
CHANGED_FILES[$i]="rsyslog.conf"
elif [[ "${CHANGED_FILES[$i]}" == /etc/rsyslog.d/* ]]; then
CHANGED_FILES[$i]=$(echo "${CHANGED_FILES[$i]}" | sed 's|^/etc/||')
fi
echo " - Drift detected in: ${CHANGED_FILES[$i]}"
done
DRIFT_COUNT=${#CHANGED_FILES[@]}
fi
fi
echo " Total drift count: $DRIFT_COUNT"
echo ""
# ─────────────────────────────────────────────────────────────────────────────────
# Step 3: Build JSON payload
# ─────────────────────────────────────────────────────────────────────────────────
echo "Step 3/4: Building JSON payload..."
# Convert files array to JSON
FILES_JSON="[]"
if [ ${#CHANGED_FILES[@]} -gt 0 ]; then
FILES_JSON="["
for i in "${!CHANGED_FILES[@]}"; do
if [ "$i" -gt 0 ]; then
FILES_JSON+=","
fi
# Escape special characters in filenames for JSON
escaped_name="${CHANGED_FILES[$i]//\\/\\\\}"
escaped_name="${escaped_name//\"/\\\"}"
FILES_JSON+="{\"name\":\"$escaped_name\"}"
done
FILES_JSON+="]"
fi
# Generate ISO 8601 timestamp
TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
# Build complete JSON status
STATUS_JSON=$(cat <<EOF
{
"repo": "$REPO_NAME",
"server": "$SERVER_NAME",
"sync_status": "$SYNC_STATUS",
"drift_count": $DRIFT_COUNT,
"files": $FILES_JSON,
"last_check": "$TIMESTAMP"
}
EOF
)
echo " Generated JSON:"
echo "$STATUS_JSON" | jq '.' 2>/dev/null || echo "$STATUS_JSON"
echo ""
# ─────────────────────────────────────────────────────────────────────────────────
# Step 4: Send JSON to gitops-status-server
# ─────────────────────────────────────────────────────────────────────────────────
echo "Step 4/4: Sending status to gitops-status-server..."
echo " URL: $GITOPS_STATUS_SERVER_URL/api/status"
echo " Method: POST"
# POST the JSON to the gitops-status-server API
# gitops-status-server should accept the JSON and update its internal state
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST \
-H "Content-Type: application/json" \
-d "$STATUS_JSON" \
"$GITOPS_STATUS_SERVER_URL/api/status" || true)
echo " Response: HTTP $HTTP_CODE"
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
echo ""
echo "═══════════════════════════════════════════════════════════════════════════════"
echo " ✓ Status update successful"
echo " Grafana Infinity datasource will now read the updated JSON from"
echo " gitops-status-server"
echo "═══════════════════════════════════════════════════════════════════════════════"
exit 0
else
echo ""
echo "═══════════════════════════════════════════════════════════════════════════════"
echo " ✗ ERROR: Status update failed with HTTP $HTTP_CODE"
echo " Check gitops-status-server connectivity and API availability"
echo "═══════════════════════════════════════════════════════════════════════════════"
exit 1
fi