rsyslog/update-gitops-status.sh
dvirlabs 0d0169c97d
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
test
2026-06-09 18:20:34 +03:00

190 lines
8.9 KiB
Bash

#!/bin/bash
# =============================================================================
# GitOps Status Update Script
# Checks Ansible sync status and sends JSON update to gitops-status-server API
#
# This script:
# 1. Runs drift-check.yml to detect configuration drift
# 2. Extracts deployed files from deploy-config.yml
# 3. Reads structured JSON outputs from Ansible playbooks
# 4. Sends comprehensive status to gitops-status-server API
#
# Usage: ./update-gitops-status.sh
# Environment variables:
# - GITOPS_STATUS_SERVER_URL: API endpoint URL
# - REPO_NAME: Repository name
# - SERVER_NAME: Server name
# - MODE: post-deploy or cron (optional, for logging)
# - ANSIBLE_CONFIG: Path to ansible.cfg
# =============================================================================
set -e
# Get configuration from environment variables
API_URL="${GITOPS_STATUS_SERVER_URL}/api/status"
REPO_NAME="${REPO_NAME:-unknown}"
SERVER_NAME="${SERVER_NAME:-unknown}"
MODE="${MODE:-check}"
ANSIBLE_CONFIG="${ANSIBLE_CONFIG:-ansible.cfg}"
PLAYBOOK_DIR="ansible/playbooks"
INVENTORY="ansible/inventory/hosts.yml"
DEPLOY_CONFIG="ansible/deploy-config.yml"
echo "==> GitOps Status Update: $REPO_NAME / $SERVER_NAME"
echo " API URL: $API_URL"
echo " Mode: $MODE"
# Verify required environment variables
if [[ -z "$GITOPS_STATUS_SERVER_URL" || -z "$REPO_NAME" || -z "$SERVER_NAME" ]]; then
echo "ERROR: Missing required environment variables (GITOPS_STATUS_SERVER_URL, REPO_NAME, SERVER_NAME)"
exit 1
fi
# Verify files exist
if [[ ! -f "$INVENTORY" ]]; then
echo "ERROR: Inventory file not found: $INVENTORY"
exit 1
fi
if [[ ! -f "$DEPLOY_CONFIG" ]]; then
echo "ERROR: Deploy config not found: $DEPLOY_CONFIG"
exit 1
fi
# Initialize variables
SYNC_STATUS="UNKNOWN"
DRIFT_COUNT=0
DEPLOYED_FILES="[]"
DRIFTED_FILES="[]"
# ─────────────────────────────────────────────────────────────────────────
# Extract deployed files from deploy-config.yml
# Only extract active items (lines starting with " - name:"), not comments
# ─────────────────────────────────────────────────────────────────────────
echo "==> Extracting deployed files from deploy-config.yml..."
DEPLOYED_FILES=$(grep "^ - name:" "$DEPLOY_CONFIG" | \
sed 's/.*name: "\([^"]*\)".*/\1/' | \
jq -R -s 'split("\n") | map(select(length > 0) | {name: .})')
if [[ "$DEPLOYED_FILES" == "[]" ]] || [[ -z "$DEPLOYED_FILES" ]]; then
echo " WARNING: Could not extract deployed files, using empty array"
DEPLOYED_FILES="[]"
else
echo " ✓ Found deployed files: $(echo "$DEPLOYED_FILES" | jq '.[] | .name' | wc -l) file(s)"
fi
# ─────────────────────────────────────────────────────────────────────────
# Run drift-check playbook to detect configuration drift
# ─────────────────────────────────────────────────────────────────────────
echo "==> Running drift-check playbook..."
ANSIBLE_OUTPUT=$(mktemp)
DRIFT_CHECK_SUCCESS=true
# Run drift-check and capture output
if ansible-playbook -i "$INVENTORY" \
-c local \
"$PLAYBOOK_DIR/drift-check.yml" \
> "$ANSIBLE_OUTPUT" 2>&1; then
SYNC_STATUS="SYNCED"
DRIFT_COUNT=0
DRIFTED_FILES="[]"
echo " ✓ All servers are SYNCED with Git"
else
# Drift detected
DRIFT_CHECK_SUCCESS=false
SYNC_STATUS="OUT_OF_SYNC"
echo " ✗ Configuration drift detected on one or more servers"
fi
# ─────────────────────────────────────────────────────────────────────────
# Extract drift information from JSON output files
# The drift-check.yml playbook creates /tmp/drifted_files_<hostname>.json
# ─────────────────────────────────────────────────────────────────────────
echo "==> Extracting drift information from playbook output..."
TEMP_DRIFTED_FILES=$(mktemp)
echo "[]" > "$TEMP_DRIFTED_FILES"
# Collect drifted files from all servers
for drift_file in /tmp/drifted_files_*.json; do
if [[ -f "$drift_file" ]]; then
echo " Reading drift report: $drift_file"
cat "$drift_file" >> "$TEMP_DRIFTED_FILES"
fi
done
# If we have drift files, use them; otherwise try to extract from Ansible output
if [[ -f "$TEMP_DRIFTED_FILES" ]] && [[ -s "$TEMP_DRIFTED_FILES" ]] && [[ "$(cat "$TEMP_DRIFTED_FILES")" != "[]" ]]; then
# Merge all drifted files into a single array
DRIFTED_FILES=$(jq -s 'add' "$TEMP_DRIFTED_FILES" 2>/dev/null || echo "[]")
DRIFT_COUNT=$(echo "$DRIFTED_FILES" | jq '. | length')
echo " ✓ Found $DRIFT_COUNT drifted file(s)"
else
# Fallback: parse Ansible output for drift indicators
echo " Analyzing Ansible output for drift indicators..."
DRIFT_INDICATORS=$(grep -E "CHANGED|changed:|failed:|drifted|drift" "$ANSIBLE_OUTPUT" | wc -l || true)
if [[ $DRIFT_INDICATORS -gt 0 ]]; then
DRIFT_COUNT=$DRIFT_INDICATORS
# Build minimal drift entries from grep results
DRIFTED_FILES=$(grep -E "CHANGED|changed:|failed:" "$ANSIBLE_OUTPUT" | \
head -10 | \
jq -R -s 'split("\n") | map(select(length > 0) | {name: ., status: "UNKNOWN", reason: "Detected from Ansible output"})' || echo "[]")
echo " Found $DRIFT_COUNT drift indicator(s)"
else
DRIFTED_FILES="[]"
fi
fi
# ─────────────────────────────────────────────────────────────────────────
# Get current timestamp in ISO 8601 format
# ─────────────────────────────────────────────────────────────────────────
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# ─────────────────────────────────────────────────────────────────────────
# Build comprehensive JSON payload
# ─────────────────────────────────────────────────────────────────────────
JSON_PAYLOAD=$(cat <<EOF
{
"repo": "$REPO_NAME",
"server": "$SERVER_NAME",
"sync_status": "$SYNC_STATUS",
"drift_count": $DRIFT_COUNT,
"deployed_files": $DEPLOYED_FILES,
"drifted_files": $DRIFTED_FILES,
"last_check": "$TIMESTAMP"
}
EOF
)
echo ""
echo "==> Sending status update to API..."
echo "$JSON_PAYLOAD" | jq .
# ─────────────────────────────────────────────────────────────────────────
# Send to API using curl
# ─────────────────────────────────────────────────────────────────────────
HTTP_CODE=$(curl -s -o /tmp/api_response.json -w "%{http_code}" \
-X POST "$API_URL" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
if [[ "$HTTP_CODE" == "200" ]]; then
echo " ✓ Status update sent successfully (HTTP $HTTP_CODE)"
cat /tmp/api_response.json | jq . 2>/dev/null || cat /tmp/api_response.json
else
echo " ✗ Failed to send status update (HTTP $HTTP_CODE)"
cat /tmp/api_response.json 2>/dev/null || true
fi
# ─────────────────────────────────────────────────────────────────────────
# Cleanup temporary files
# ─────────────────────────────────────────────────────────────────────────
rm -f "$ANSIBLE_OUTPUT" /tmp/api_response.json "$TEMP_DRIFTED_FILES"
# Exit with success regardless of sync status
# (The script's job is to report status, not to fail on drift)
echo "==> GitOps status update complete"
exit 0