145 lines
5.7 KiB
Bash
145 lines
5.7 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# INSTALL-01: First Install Verification Test
|
||
|
|
# Tests that a freshly installed Archipelago node has all core services operational.
|
||
|
|
# Usage: bash scripts/test-first-install.sh [host] [password]
|
||
|
|
|
||
|
|
set -uo pipefail
|
||
|
|
|
||
|
|
HOST="${1:-192.168.1.228}"
|
||
|
|
PASS="${2:-password123}"
|
||
|
|
PASS_COUNT=0
|
||
|
|
FAIL_COUNT=0
|
||
|
|
SSH_KEY="${ARCHIPELAGO_SSH_KEY:-$HOME/.ssh/archipelago-deploy}"
|
||
|
|
|
||
|
|
green() { printf "\033[32m PASS \033[0m %s\n" "$1"; ((PASS_COUNT++)); }
|
||
|
|
red() { printf "\033[31m FAIL \033[0m %s\n" "$1"; ((FAIL_COUNT++)); }
|
||
|
|
header(){ printf "\n\033[1;36m--- %s ---\033[0m\n" "$1"; }
|
||
|
|
|
||
|
|
rpc() {
|
||
|
|
local method="$1"
|
||
|
|
local params="${2:-{}}"
|
||
|
|
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "archipelago@${HOST}" \
|
||
|
|
"curl -s -c /tmp/test-cookies.txt -b /tmp/test-cookies.txt -X POST http://localhost/rpc/v1 \
|
||
|
|
-H 'Content-Type: application/json' \
|
||
|
|
-H \"X-CSRF-Token: \$(grep csrf_token /tmp/test-cookies.txt 2>/dev/null | awk '{print \$NF}')\" \
|
||
|
|
-d '{\"method\":\"$method\",\"params\":$params}'" 2>/dev/null
|
||
|
|
}
|
||
|
|
|
||
|
|
header "Authentication"
|
||
|
|
LOGIN=$(ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "archipelago@${HOST}" \
|
||
|
|
"curl -s -c /tmp/test-cookies.txt -X POST http://localhost/rpc/v1 \
|
||
|
|
-H 'Content-Type: application/json' \
|
||
|
|
-d '{\"method\":\"auth.login\",\"params\":{\"password\":\"$PASS\"}}'" 2>/dev/null)
|
||
|
|
if echo "$LOGIN" | grep -q '"error":null'; then
|
||
|
|
green "Login successful"
|
||
|
|
else
|
||
|
|
red "Login failed: $LOGIN"
|
||
|
|
echo "Cannot continue without authentication."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "1. Node DID"
|
||
|
|
DID_RESULT=$(rpc "node.did")
|
||
|
|
DID=$(echo "$DID_RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('result',{}).get('did',''))" 2>/dev/null)
|
||
|
|
if [[ "$DID" == did:key:z* ]]; then
|
||
|
|
green "Node DID format valid: ${DID:0:32}..."
|
||
|
|
else
|
||
|
|
red "Invalid DID format: $DID"
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "2. Nostr Pubkey"
|
||
|
|
NOSTR_RESULT=$(rpc "node.nostr-pubkey")
|
||
|
|
NPUB=$(echo "$NOSTR_RESULT" | python3 -c "import sys,json; r=json.load(sys.stdin).get('result',{}); print(r.get('nostr_npub',''))" 2>/dev/null)
|
||
|
|
HEX=$(echo "$NOSTR_RESULT" | python3 -c "import sys,json; r=json.load(sys.stdin).get('result',{}); print(r.get('nostr_pubkey',''))" 2>/dev/null)
|
||
|
|
if [[ "$NPUB" == npub1* ]] && [[ ${#HEX} -eq 64 ]]; then
|
||
|
|
green "Nostr pubkey valid: npub=${NPUB:0:16}... hex=${HEX:0:16}..."
|
||
|
|
else
|
||
|
|
red "Invalid Nostr pubkey: npub=$NPUB hex=$HEX"
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "3. Identity Create"
|
||
|
|
ID_RESULT=$(rpc "identity.create" '{"name":"Test User"}')
|
||
|
|
ID_DID=$(echo "$ID_RESULT" | python3 -c "import sys,json; r=json.load(sys.stdin).get('result',{}); print(r.get('did',''))" 2>/dev/null)
|
||
|
|
if [[ "$ID_DID" == did:key:* ]]; then
|
||
|
|
green "Identity created with DID: ${ID_DID:0:32}..."
|
||
|
|
else
|
||
|
|
# May already exist, try listing
|
||
|
|
LIST_RESULT=$(rpc "identity.list")
|
||
|
|
LIST_COUNT=$(echo "$LIST_RESULT" | python3 -c "import sys,json; r=json.load(sys.stdin).get('result',{}); ids=r.get('identities',[]); print(len(ids))" 2>/dev/null)
|
||
|
|
if [[ "$LIST_COUNT" -gt 0 ]]; then
|
||
|
|
green "Identity exists ($LIST_COUNT identities found)"
|
||
|
|
else
|
||
|
|
red "Identity create failed: $ID_RESULT"
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "4. Identity List"
|
||
|
|
LIST_RESULT=$(rpc "identity.list")
|
||
|
|
LIST_COUNT=$(echo "$LIST_RESULT" | python3 -c "import sys,json; r=json.load(sys.stdin).get('result',{}); ids=r.get('identities',[]); print(len(ids))" 2>/dev/null)
|
||
|
|
if [[ "$LIST_COUNT" -gt 0 ]]; then
|
||
|
|
green "Identity list has $LIST_COUNT identit(ies)"
|
||
|
|
else
|
||
|
|
red "No identities found"
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "5. Tor Address"
|
||
|
|
TOR_RESULT=$(rpc "node.tor-address")
|
||
|
|
TOR_ADDR=$(echo "$TOR_RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('result',{}).get('tor_address',''))" 2>/dev/null)
|
||
|
|
if [[ "$TOR_ADDR" == *.onion ]]; then
|
||
|
|
green "Tor address valid: ${TOR_ADDR:0:24}..."
|
||
|
|
else
|
||
|
|
red "No Tor address found"
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "6. Webhook Config"
|
||
|
|
WH_RESULT=$(rpc "webhook.get-config")
|
||
|
|
WH_ERROR=$(echo "$WH_RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('error',{}) or 'none')" 2>/dev/null)
|
||
|
|
if [[ "$WH_ERROR" != "none" ]] && [[ "$WH_ERROR" != "None" ]]; then
|
||
|
|
# webhook.get-config may not exist, which is fine (disabled by default)
|
||
|
|
green "Webhooks not configured (default/disabled)"
|
||
|
|
else
|
||
|
|
WH_ENABLED=$(echo "$WH_RESULT" | python3 -c "import sys,json; r=json.load(sys.stdin).get('result',{}); print(r.get('enabled', False))" 2>/dev/null)
|
||
|
|
if [[ "$WH_ENABLED" == "False" ]]; then
|
||
|
|
green "Webhooks disabled by default"
|
||
|
|
else
|
||
|
|
green "Webhook config accessible (enabled=$WH_ENABLED)"
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "7. Health Monitor"
|
||
|
|
STATS_RESULT=$(rpc "system.stats")
|
||
|
|
CONTAINER_COUNT=$(echo "$STATS_RESULT" | python3 -c "
|
||
|
|
import sys,json
|
||
|
|
r=json.load(sys.stdin).get('result',{})
|
||
|
|
print(r.get('container_count', r.get('running_containers', -1)))
|
||
|
|
" 2>/dev/null)
|
||
|
|
if [[ "$CONTAINER_COUNT" -gt 0 ]]; then
|
||
|
|
green "Health monitor reports $CONTAINER_COUNT containers"
|
||
|
|
else
|
||
|
|
# Try alternate endpoint
|
||
|
|
HEALTH=$(ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "archipelago@${HOST}" \
|
||
|
|
"curl -s http://localhost/health" 2>/dev/null)
|
||
|
|
if [[ "$HEALTH" == "OK" ]]; then
|
||
|
|
green "Health endpoint returns OK"
|
||
|
|
else
|
||
|
|
red "Health monitor check failed (containers=$CONTAINER_COUNT)"
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
header "8. DWN Status"
|
||
|
|
DWN_RESULT=$(rpc "dwn.status")
|
||
|
|
DWN_RUNNING=$(echo "$DWN_RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('result',{}).get('running', False))" 2>/dev/null)
|
||
|
|
DWN_MSG=$(echo "$DWN_RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('result',{}).get('message_count', -1))" 2>/dev/null)
|
||
|
|
if [[ "$DWN_RUNNING" == "True" ]]; then
|
||
|
|
green "DWN operational (messages: $DWN_MSG)"
|
||
|
|
else
|
||
|
|
red "DWN not running"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Summary
|
||
|
|
echo ""
|
||
|
|
echo "==============================="
|
||
|
|
printf "Results: \033[32m%d passed\033[0m, \033[31m%d failed\033[0m\n" "$PASS_COUNT" "$FAIL_COUNT"
|
||
|
|
echo "==============================="
|
||
|
|
[[ "$FAIL_COUNT" -eq 0 ]] && exit 0 || exit 1
|