#!/usr/bin/env bash # Live M2 smoke test. Run from repo root: # bash scripts/m2_smoke.sh # # Walks through the 6 step-by-step scenarios from M2_VERIFICATION.md # and dumps a single summary table at the end. Exit code is the # number of failed steps. set -e cd "$(dirname "$0")/.." SECRET=s3cret-acme send() { local body="$1" label="$2" local ts=$(date +%s) local sig=$(printf '%s.%s' "$ts" "$body" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $2}') local resp resp=$(curl -s -X POST http://localhost:8800/v1/ingest \ -H "Content-Type: application/json" \ -H "X-BA-Signature: t=$ts,v1=$sig" \ --data "$body") echo "[$label] $resp" } # Reset deliveries table so we measure only the M2 smoke. docker compose exec -T postgres psql -U ba -d ba -c "TRUNCATE deliveries;" >/dev/null docker compose restart routerd >/dev/null 2>&1 sleep 1 # Step 2: warning, db-prod-04 → Alice only send '{"company_id":"acme-001","source_id":"prom-prod","severity":"warning","category":"storage","title":"Disk 80%","body":"db-prod-04","data":{"host":"db-prod-04"},"dedupe_key":"m2-s2"}' "step 2" # Step 3: critical, db-prod-04 → Alice + Bob send '{"company_id":"acme-001","source_id":"prom-prod","severity":"critical","category":"storage","title":"Disk full","body":"db-prod-04","data":{"host":"db-prod-04"},"dedupe_key":"m2-s3"}' "step 3" # Step 4: critical, db-prod-03 (rule match) → Alice + Bob send '{"company_id":"acme-001","source_id":"prom-prod","severity":"critical","category":"storage","title":"Disk full","body":"db-prod-03","data":{"host":"db-prod-03"},"dedupe_key":"m2-s4"}' "step 4" # Step 5: warning, db-prod-03 (rule match, but Bob filters by severity) → Alice only send '{"company_id":"acme-001","source_id":"prom-prod","severity":"warning","category":"storage","title":"Disk 80% prod-03","body":"pre-empt","data":{"host":"db-prod-03"},"dedupe_key":"m2-s5"}' "step 5" # Step 6: inminent_colapse, rack-b → all three (bypasses Carol's quiet hours, passes Bob's min) send '{"company_id":"acme-001","source_id":"prom-prod","severity":"inminent_colapse","category":"power","title":"PDU overload imminent","body":"rack-B","data":{"host":"rack-b"},"dedupe_key":"m2-s6"}' "step 6" # Wait for routerd/deliverd to drain. sleep 4 echo "" echo "=== deliveries by alert ===" docker compose exec -T postgres psql -U ba -d ba -c " SELECT SUBSTRING(alert_id, 12, 6) AS alert_short, individual_id, status FROM deliveries ORDER BY id; " echo "" echo "=== expected vs actual ===" # Build a single text table; quick and dirty. docker compose exec -T postgres psql -U ba -d ba -c " WITH counts AS ( SELECT alert_id, count(*) AS n, array_agg(individual_id ORDER BY individual_id) AS who FROM deliveries GROUP BY alert_id ) SELECT SUBSTRING(alert_id, 12, 6) AS alert_short, n, array_to_string(who, ',') AS who FROM counts ORDER BY alert_short; " echo "" echo "=== routerd 'routed' lines ===" docker compose logs --no-color --since 60s routerd 2>&1 | grep "msg=routed" | tail -10