From cf83072c38dd1532d4c53e061bba070021057be9 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Tue, 9 Jun 2026 17:40:36 +0300 Subject: [PATCH] test --- ansible/playbooks/validate.yml | 40 +++++---- update-gitops-status.sh | 143 ++++++++++++++++++++++++--------- 2 files changed, 129 insertions(+), 54 deletions(-) diff --git a/ansible/playbooks/validate.yml b/ansible/playbooks/validate.yml index 83b188d..74ba8d3 100644 --- a/ansible/playbooks/validate.yml +++ b/ansible/playbooks/validate.yml @@ -1,41 +1,49 @@ --- # ============================================================================= # VALIDATE PLAYBOOK -# Purpose: Verify that dvir.txt exists and is readable on target servers +# Purpose: Verify that all configured files exist and are readable on servers # Usage: ansible-playbook validate.yml -# Output: Success if file exists and is readable, Failure if not +# Output: Success if all files exist and readable, Failure if any are missing # ============================================================================= -- name: Validate file exists +- name: Validate deployed files hosts: all gather_facts: false + vars_files: + - ../deploy-config.yml tasks: # ───────────────────────────────────────────────────────────────────── - # TASK 1: Check file status + # TASK 1: Check each configured file status # Gathers file stats (exists, readable, permissions, etc.) # ───────────────────────────────────────────────────────────────────── - - name: Check if file is readable + - name: Check if file is readable ({{ item.name }}) stat: - path: /tmp/dvir.txt - register: file_stat + path: "{{ item.dest }}" + register: file_stats + loop: "{{ deploy_items }}" + loop_control: + loop_var: item + label: "{{ item.name }}" # ───────────────────────────────────────────────────────────────────── - # TASK 2: Assert file requirements - # Verifies that the file exists and is readable - # Fails the playbook if either condition is false + # TASK 2: Verify each file exists and is readable + # Fails if any configured file is missing or not readable # ───────────────────────────────────────────────────────────────────── - - name: Verify file exists and is readable + - name: Verify all files exist and are readable assert: that: - - file_stat.stat.exists - - file_stat.stat.readable - msg: "dvir.txt not found or not readable" + - item.stat.exists + - item.stat.readable + msg: "{{ item.item.name }} ({{ item.item.dest }}) is missing or not readable" + loop: "{{ file_stats.results }}" + loop_control: + label: "{{ item.item.name }}" # ───────────────────────────────────────────────────────────────────── # TASK 3: Display validation result - # Shows success message if all checks passed + # Shows success message if all files passed validation # ───────────────────────────────────────────────────────────────────── - name: Display validation result debug: - msg: "✓ dvir.txt is valid and readable" + msg: "✓ All {{ deploy_items | length }} file(s) are valid and readable on {{ inventory_hostname }}" diff --git a/update-gitops-status.sh b/update-gitops-status.sh index 11fa1a6..baa16d1 100644 --- a/update-gitops-status.sh +++ b/update-gitops-status.sh @@ -2,6 +2,13 @@ # ============================================================================= # 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 @@ -19,6 +26,9 @@ 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" @@ -30,61 +40,110 @@ if [[ -z "$GITOPS_STATUS_SERVER_URL" || -z "$REPO_NAME" || -z "$SERVER_NAME" ]]; exit 1 fi -# Run Ansible validation to check sync status -echo "==> Running Ansible sync check..." -ANSIBLE_OUTPUT=$(mktemp) +# 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="[]" -# Try to run the validate playbook and capture output -if ansible-playbook -i ansible/inventory/hosts.yml \ +# ───────────────────────────────────────────────────────────────────────── +# Extract deployed files from deploy-config.yml +# ───────────────────────────────────────────────────────────────────────── +echo "==> Extracting deployed files from deploy-config.yml..." +DEPLOYED_FILES=$(grep -A1 "name:" "$DEPLOY_CONFIG" | grep "name:" | \ + 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 \ - ansible/playbooks/validate.yml \ - -vv > "$ANSIBLE_OUTPUT" 2>&1; then + "$PLAYBOOK_DIR/drift-check.yml" \ + > "$ANSIBLE_OUTPUT" 2>&1; then SYNC_STATUS="SYNCED" DRIFT_COUNT=0 - echo " ✓ Server is SYNCED with Git" + DRIFTED_FILES="[]" + echo " ✓ All servers are SYNCED with Git" else - # If playbook fails, it means there's drift/differences + # Drift detected + DRIFT_CHECK_SUCCESS=false SYNC_STATUS="OUT_OF_SYNC" - # Parse output to extract changed files - # Look for "CHANGED" or "failed" tasks - CHANGED_TASKS=$(grep -E "CHANGED|changed:|failed:" "$ANSIBLE_OUTPUT" | wc -l || true) - DRIFT_COUNT=$((CHANGED_TASKS > 0 ? CHANGED_TASKS : 1)) + 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_.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) - # Try to extract file information from Ansible output - # This is a best-effort attempt based on common Ansible patterns - CHANGED_FILES=$(grep -oE "path=([^ ]+)|src=([^ ]+)" "$ANSIBLE_OUTPUT" | cut -d= -f2 | sort -u | head -20) - - if [[ -n "$CHANGED_FILES" ]]; then - # Format changed files as JSON array - DRIFTED_FILES=$(echo "$CHANGED_FILES" | jq -R -s 'split("\n") | map(select(length > 0) | {name: .})') + 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 - - echo " ✗ Server is OUT_OF_SYNC with Git (drift count: $DRIFT_COUNT)" -fi - -# Get list of all managed files (best effort) -if [[ -f "ansible/playbooks/apply.yml" ]]; then - # Extract file paths from the apply playbook - MANAGED_FILES=$(grep -E "src:|path:|name:" ansible/playbooks/apply.yml | \ - grep -oE "'[^']+'" | tr -d "'" | sort -u | head -50) - - if [[ -n "$MANAGED_FILES" ]]; then - DEPLOYED_FILES=$(echo "$MANAGED_FILES" | jq -R -s 'split("\n") | map(select(length > 0) | {name: .})') - fi fi +# ───────────────────────────────────────────────────────────────────────── # Get current timestamp in ISO 8601 format +# ───────────────────────────────────────────────────────────────────────── TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") -# Build JSON payload +# ───────────────────────────────────────────────────────────────────────── +# Build comprehensive JSON payload +# ───────────────────────────────────────────────────────────────────────── JSON_PAYLOAD=$(cat < 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" \ @@ -109,13 +171,18 @@ HTTP_CODE=$(curl -s -o /tmp/api_response.json -w "%{http_code}" \ if [[ "$HTTP_CODE" == "200" ]]; then echo " ✓ Status update sent successfully (HTTP $HTTP_CODE)" - cat /tmp/api_response.json | jq . + 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 + cat /tmp/api_response.json 2>/dev/null || true fi -# Cleanup -rm -f "$ANSIBLE_OUTPUT" /tmp/api_response.json +# ───────────────────────────────────────────────────────────────────────── +# 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