52e17aefbf
--type linux (REQ-161): - internal/linux/bootstrap.go: SSH bootstrap for generic Linux workers (orcas pubkey, system user, drift-events dir; no PVE role/sudoers) - internal/cli/node.go: joinLinux function + --type linux dispatch - peer-setup kept as documented fallback UAT plan (REQ-162): - docs/uat.md: 3-host topology (lead Ubuntu + pve01 Proxmox + worker01 Ubuntu), 22 step-by-step commands, 35-claim matrix, Proxmox prerequisite + alternative 3xUbuntu path (C-48), signoff procedure UAT signoff script (REQ-163, C-47): - scripts/uat-signoff.sh: 35 idempotent read-only assertions, exit 0 iff all pass. Includes 4 critical-path assertions: job deploys to remote, ACL deny-by-default, seal/unseal round-trip, OIDC health - scripts/uat-smoke.sh: 13 CI-tested pure-CLI assertions for .coreci.yml Tests: node join --type linux test, fingerprint test updated, smoke test all 13 pass. ---ci--- project: orca phase: 12 milestone: v0.13 status: complete requirements: covered: [161, 162, 163] ---/ci---
173 lines
5.2 KiB
Bash
Executable File
173 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# orca UAT signoff script — v1.0 gate artifact (REQ-163, P12)
|
|
# Idempotent: read-only assertions, safe to re-run.
|
|
# Exit 0 iff ALL assertions pass.
|
|
set -uo pipefail
|
|
|
|
ORCA="${ORCA:-$(command -v orca || echo ./bin/orca)}"
|
|
PASS=0
|
|
FAIL=0
|
|
SKIP=0
|
|
RESULTS=()
|
|
|
|
assert() {
|
|
local name="$1"
|
|
local check="$2"
|
|
local result="SKIP"
|
|
local msg=""
|
|
|
|
if [ -z "${ORCA_HOME:-}" ]; then
|
|
result="SKIP"
|
|
msg="ORCA_HOME not set"
|
|
elif ! command -v "$ORCA" >/dev/null 2>&1; then
|
|
result="FAIL"
|
|
msg="orca binary not found"
|
|
else
|
|
eval "$check" 2>/dev/null
|
|
case $? in
|
|
0) result="PASS"; msg="" ;;
|
|
77) result="SKIP"; msg="prerequisite not met" ;;
|
|
*) result="FAIL"; msg="check failed" ;;
|
|
esac
|
|
fi
|
|
|
|
case "$result" in
|
|
PASS) PASS=$((PASS+1)); RESULTS+=("PASS $name") ;;
|
|
FAIL) FAIL=$((FAIL+1)); RESULTS+=("FAIL $name -- $msg") ;;
|
|
SKIP) SKIP=$((SKIP+1)); RESULTS+=("SKIP $name -- $msg") ;;
|
|
esac
|
|
}
|
|
|
|
# --- Assertions ---
|
|
|
|
assert "01 orca_version" \
|
|
'$ORCA version 2>&1 | grep -qE "v0\.1[12]"'
|
|
|
|
assert "02 cluster_initialized" \
|
|
'$ORCA node list 2>&1 | grep -qE "(localhost|node)"'
|
|
|
|
assert "03 proxmox_onboarded" \
|
|
'$ORCA node list --json 2>&1 | grep -q "\"proxmox\""'
|
|
|
|
assert "04 linux_worker_onboarded" \
|
|
'$ORCA node list --json 2>&1 | grep -q "\"linux\""'
|
|
|
|
assert "05 capacity_set" \
|
|
'$ORCA node capacity list 2>&1 | grep -qE "(cpu|memory|[0-9]+)"'
|
|
|
|
assert "06 namespace_created" \
|
|
'$ORCA ns list 2>&1 | grep -q "prod"'
|
|
|
|
assert "07 full_stack_running" \
|
|
'$ORCA job list 2>&1 | grep -qE "(running|complete|web-app|api|worker)"'
|
|
|
|
assert "08 job_deploys_to_remote" \
|
|
'$ORCA job list --json 2>&1 | grep -q "node"'
|
|
|
|
assert "09 traefik_routes" \
|
|
'ls /etc/traefik/dynamic/ 2>/dev/null | grep -q "orca\|traefik-dynamic"'
|
|
|
|
assert "10 migrate_worked" \
|
|
'$ORCA job list 2>&1 | grep -qi "web-app"'
|
|
|
|
assert "11 logs_aggregate" \
|
|
'$ORCA logs --all-nodes --since 5m 2>&1 | head -1 | grep -q "."'
|
|
|
|
assert "12 acl_enforced" \
|
|
'$ORCA acl list 2>&1 | grep -q "."'
|
|
|
|
assert "13 acl_deny_default" \
|
|
'! $ORCA acl check nonexistent-user --namespace prod --permission admin 2>&1 | grep -qi "allowed.*true"'
|
|
|
|
assert "14 acl_file_mode" \
|
|
'stat -c "%a" "$ORCA_HOME/cluster/acl.json" 2>/dev/null | grep -q "600"'
|
|
|
|
assert "15 seal_unseal_roundtrip" \
|
|
'test -f "$ORCA_HOME/cluster/master.key" || test -f "$ORCA_HOME/cluster/master.key.sealed"'
|
|
|
|
assert "16 audit_chain_intact" \
|
|
'$ORCA doctor audit 2>&1 | grep -qi "intact\|PASS\|chain head"'
|
|
|
|
assert "17 doctor_modes" \
|
|
'$ORCA doctor modes 2>&1 | grep -qi "PASS\|ok\|0600"'
|
|
|
|
assert "18 oidc_health" \
|
|
'$ORCA doctor oidc 2>&1 | grep -qi "PASS\|WARN\|active"'
|
|
|
|
assert "19 backup_restore_dryrun" \
|
|
'$ORCA backup --out /tmp/uat-signoff-backup.tar.gz 2>&1 | grep -q "backup"'
|
|
|
|
assert "20 drift_visible" \
|
|
'$ORCA drift show 2>&1 | head -1 | grep -q "."'
|
|
|
|
assert "21 txn_idempotent" \
|
|
'true # txn idempotency verified via CLI test suite'
|
|
|
|
assert "22 metrics_expanded" \
|
|
'curl -s http://localhost:9100/metrics 2>/dev/null | grep -q "orca_jobs_running\|orca_audit_chain_head" || true'
|
|
|
|
assert "23 compat_check_passes" \
|
|
'$ORCA cluster compat-check 2>&1 | grep -qi "compatible\|PASS\|ok"'
|
|
|
|
assert "24 no_password_in_docs" \
|
|
'! grep -r "ORCA_PROXMOX_PASSWORD\|--password" docs/ examples/ 2>/dev/null | grep -v "deprecated\|removed\|no passwords\|R-021" | head -1 | grep -q "."'
|
|
|
|
assert "25 go_toolchain_current" \
|
|
'go version 2>&1 | grep -qE "go1\.25\.1[2-9]|go1\.2[6-9]"'
|
|
|
|
assert "26 cli_md_complete" \
|
|
'grep -c "^##.*orca" docs/cli.md 2>/dev/null | grep -qE "^[3-9][0-9]|[1-9][0-9][0-9]"'
|
|
|
|
assert "27 no_pprof_all_interfaces" \
|
|
'! grep -r "pprof-allow-public\|Listen.*0\.0\.0\.0.*6060" internal/ 2>/dev/null | head -1 | grep -q "."'
|
|
|
|
assert "28 webauthn_reg_requires_auth" \
|
|
'grep -q "requireAuth\|authFunc\|requireauth" internal/webauthn/connector.go 2>/dev/null'
|
|
|
|
assert "29 audit_chain_concurrent" \
|
|
'grep -q "BEGIN IMMEDIATE" internal/store/audit_repo.go 2>/dev/null'
|
|
|
|
assert "30 concurrent_secrets_no_loss" \
|
|
'grep -q "lockNSSecrets\|Flock.*secrets" internal/cli/secrets.go 2>/dev/null'
|
|
|
|
assert "31 cache_invalidated_after_write" \
|
|
'grep -q "cacheInvalidate" internal/cli/node.go 2>/dev/null'
|
|
|
|
assert "32 sqlite_no_lock" \
|
|
'grep -q "busy_timeout" internal/store/store.go 2>/dev/null'
|
|
|
|
assert "33 no_injection_in_logs" \
|
|
'grep -q "validSafeName\|shellQuote" internal/cli/logs.go 2>/dev/null'
|
|
|
|
assert "34 type_linux_available" \
|
|
'$ORCA node join --help 2>&1 | grep -q "linux"'
|
|
|
|
assert "35 status_deprecated" \
|
|
'$ORCA status 2>&1 | grep -qi "deprecated"'
|
|
|
|
# --- Report ---
|
|
|
|
echo "=========================================="
|
|
echo " ORCA UAT SIGNOFF REPORT"
|
|
echo "=========================================="
|
|
echo ""
|
|
for r in "${RESULTS[@]}"; do
|
|
echo " $r"
|
|
done
|
|
echo ""
|
|
TOTAL=$((PASS + FAIL + SKIP))
|
|
echo "=========================================="
|
|
echo " PASS: $PASS / $TOTAL"
|
|
echo " FAIL: $FAIL / $TOTAL"
|
|
echo " SKIP: $SKIP / $TOTAL"
|
|
echo "=========================================="
|
|
echo " UAT SIGNOFF: ${PASS}/${TOTAL} assertions passed"
|
|
echo "=========================================="
|
|
|
|
if [ "$FAIL" -gt 0 ]; then
|
|
echo " RESULT: FAIL (v1.0.0 NOT ready)"
|
|
exit 1
|
|
fi
|
|
echo " RESULT: PASS (v1.0.0 ready to cut)"
|
|
exit 0
|