#!/usr/bin/env bash # OpsxDB multi-driver CRUD smoke test via local API :8788 set -uo pipefail API="${OPSXDB_API:-http://127.0.0.1:8788}" ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$(dirname "$0")" n_ok=0; n_fail=0 ok() { echo " OK $*"; n_ok=$((n_ok+1)); } bad() { echo " FAIL $*"; n_fail=$((n_fail+1)); } post() { curl -sS -m 30 -H 'Content-Type: application/json' -d "$1" "$API$2" } wait_health() { local name="$1" tries="${2:-60}" for i in $(seq 1 "$tries"); do local st st=$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$name" 2>/dev/null || echo missing) [[ "$st" == "healthy" || "$st" == "running" ]] && return 0 sleep 2 done return 1 } crud_sql() { local driver="$1" host="$2" port="$3" user="$4" password="$5" db="$6" dialect="$7" local base base=$(printf '{"driver":"%s","host":"%s","port":%s,"user":"%s","password":"%s","database":"%s"}' \ "$driver" "$host" "$port" "$user" "$password" "$db") echo "== $driver ==" local tc tc=$(post "$base" /api/db/test-connection) echo "$tc" | grep -q '"ok":true' && ok "test-connection" || { bad "test-connection $tc"; return; } local dbs dbs=$(post "$base" /api/db/databases) echo "$dbs" | grep -q 'databases' && ok "databases" || bad "databases $dbs" local tables tables=$(post "$base" /api/db/tables) echo "$tables" | grep -qi 'users\|key\|tables' && ok "tables" || ok "tables (raw) $tables" local sel ins upd del case "$dialect" in mysql) sel='SELECT id,name FROM users ORDER BY id LIMIT 5' ins="INSERT INTO users (name, email, status) VALUES ('grace','grace@demo.local',1)" upd="UPDATE users SET status=0 WHERE name='grace'" del="DELETE FROM users WHERE name='grace'" ;; postgres) sel='SELECT id,name FROM users ORDER BY id LIMIT 5' ins="INSERT INTO users (name, email, status) VALUES ('grace','grace@demo.local',1)" upd="UPDATE users SET status=0 WHERE name='grace'" del="DELETE FROM users WHERE name='grace'" ;; mssql) sel='SELECT TOP 5 id,name FROM dbo.users ORDER BY id' ins="INSERT INTO dbo.users (name, email, status) VALUES (N'grace',N'grace@demo.local',1)" upd="UPDATE dbo.users SET status=0 WHERE name=N'grace'" del="DELETE FROM dbo.users WHERE name=N'grace'" ;; oracle) sel='SELECT id,name FROM users ORDER BY id FETCH FIRST 5 ROWS ONLY' ins="INSERT INTO users (name, email, status) VALUES ('grace','grace@demo.local',1)" upd="UPDATE users SET status=0 WHERE name='grace'" del="DELETE FROM users WHERE name='grace'" ;; sqlite) sel='SELECT id,name FROM users ORDER BY id LIMIT 5' ins="INSERT INTO users (name, email, status) VALUES ('grace','grace@demo.local',1)" upd="UPDATE users SET status=0 WHERE name='grace'" del="DELETE FROM users WHERE name='grace'" ;; redis) sel='KEYS *' ins='SET opsxdb:demo:grace hello' upd='GET opsxdb:demo:grace' del='DEL opsxdb:demo:grace' ;; esac local body body=$(printf '%s' "$base" | python3 -c 'import json,sys; d=json.load(sys.stdin); d["sql"]=sys.argv[1]; print(json.dumps(d))' "$sel") local r r=$(post "$body" /api/db/exec) echo "$r" | grep -vq '"error":"[^"]' && ok "SELECT/KEYS" || bad "SELECT $r" body=$(printf '%s' "$base" | python3 -c 'import json,sys; d=json.load(sys.stdin); d["sql"]=sys.argv[1]; print(json.dumps(d))' "$ins") r=$(post "$body" /api/db/exec) echo "$r" | grep -vq '"error":"[^"]' && ok "INSERT/SET" || bad "INSERT $r" body=$(printf '%s' "$base" | python3 -c 'import json,sys; d=json.load(sys.stdin); d["sql"]=sys.argv[1]; print(json.dumps(d))' "$upd") r=$(post "$body" /api/db/exec) echo "$r" | grep -vq '"error":"[^"]' && ok "UPDATE/GET" || bad "UPDATE $r" body=$(printf '%s' "$base" | python3 -c 'import json,sys; d=json.load(sys.stdin); d["sql"]=sys.argv[1]; print(json.dumps(d))' "$del") r=$(post "$body" /api/db/exec) echo "$r" | grep -vq '"error":"[^"]' && ok "DELETE/DEL" || bad "DELETE $r" } echo "API=$API" curl -sS -m 5 "$API/api/health" || { echo "API down"; exit 1; } echo # --- SQLite (no docker) --- SQLITE_DB="$ROOT/tests/tmp/demo.sqlite" mkdir -p "$ROOT/tests/tmp" rm -f "$SQLITE_DB" sqlite3 "$SQLITE_DB" < init/sqlite/01_demo.sql crud_sql sqlite "" 0 "" "" "$SQLITE_DB" sqlite # --- MariaDB --- ./dbctl.sh up b wait_health opsxdb-mariadb 40 || true docker exec -i opsxdb-mariadb mariadb -uroot -p'Demo@123' < init/mariadb/01_demo.sql 2>/dev/null \ || docker exec -i opsxdb-mariadb mysql -uroot -p'Demo@123' < init/mariadb/01_demo.sql crud_sql mariadb 127.0.0.1 3307 root 'Demo@123' demo mysql # --- PostgreSQL --- ./dbctl.sh up c wait_health opsxdb-postgres 40 docker exec -i opsxdb-postgres psql -U opsx -d demo < init/postgres/01_demo.sql >/dev/null crud_sql postgresql 127.0.0.1 5432 opsx 'Demo@123' demo postgres # --- Redis --- ./dbctl.sh up f wait_health opsxdb-redis 30 crud_sql redis 127.0.0.1 6379 "" "" 0 redis # --- SQL Server --- ./dbctl.sh up d wait_health opsxdb-mssql 120 || true for i in $(seq 1 60); do if docker exec opsxdb-mssql /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'Demo@12345' -C -Q 'SELECT 1' >/dev/null 2>&1 \ || docker exec opsxdb-mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'Demo@12345' -Q 'SELECT 1' >/dev/null 2>&1; then echo "mssql sqlcmd ready" break fi sleep 3 done docker cp init/mssql/01_demo.sql opsxdb-mssql:/tmp/01_demo.sql docker exec opsxdb-mssql /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'Demo@12345' -C -i /tmp/01_demo.sql \ || docker exec opsxdb-mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'Demo@12345' -i /tmp/01_demo.sql \ || true # login to master then demo CRUD base_master='{"driver":"sqlserver","host":"127.0.0.1","port":1433,"user":"sa","password":"Demo@12345","database":"master"}' echo "== sqlserver master ping ==" r=$(post "$base_master" /api/db/test-connection) echo "$r" | grep -q '"ok":true' && ok "test-connection master" || bad "test-connection master $r" crud_sql sqlserver 127.0.0.1 1433 sa 'Demo@12345' demo mssql # --- Oracle (slow) --- ./dbctl.sh up e wait_health opsxdb-oracle 180 || wait_health opsxdb-oracle 120 || true docker cp init/oracle/01_demo.sql opsxdb-oracle:/tmp/01_demo.sql docker exec opsxdb-oracle bash -lc "echo exit | sqlplus -s opsx/Demo@123@//localhost/XEPDB1 @/tmp/01_demo.sql" \ || docker exec opsxdb-oracle bash -lc "echo exit | sqlplus -s system/Demo@123@//localhost/XEPDB1 @/tmp/01_demo.sql" \ || true crud_sql oracle 127.0.0.1 1521 opsx 'Demo@123' XEPDB1 oracle # --- MySQL last (restore default) --- ./dbctl.sh up a wait_health opsxdb-mysql 40 docker exec -i opsxdb-mysql mysql -uroot -p'Demo@123' < init/mysql/01_demo.sql crud_sql mysql 127.0.0.1 3306 root 'Demo@123' demo mysql echo echo "==== SUMMARY ok=$n_ok fail=$n_fail ====" [[ "$n_fail" -eq 0 ]]