250 lines
8.0 KiB
Bash
250 lines
8.0 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
|
fail() {
|
|
echo "FAIL: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
assert_contains() {
|
|
local haystack="$1"
|
|
local needle="$2"
|
|
if [[ "$haystack" != *"$needle"* ]]; then
|
|
fail "expected to find [$needle] in [$haystack]"
|
|
fi
|
|
}
|
|
|
|
run_test_build_subscription_access_prep_sql() {
|
|
# shellcheck disable=SC1091
|
|
source "$ROOT_DIR/scripts/host_access_prep_lib.sh"
|
|
|
|
local sql
|
|
sql="$(build_subscription_access_prep_sql 42 'sk-test-123' 7 10 30 1 'hermes remote subscription validation')"
|
|
|
|
assert_contains "$sql" "UPDATE users"
|
|
assert_contains "$sql" "balance < 10"
|
|
assert_contains "$sql" "UPDATE api_keys"
|
|
assert_contains "$sql" "group_id = 7"
|
|
assert_contains "$sql" "key = 'sk-test-123'"
|
|
assert_contains "$sql" "INSERT INTO user_subscriptions"
|
|
assert_contains "$sql" "ON CONFLICT (user_id, group_id) WHERE deleted_at IS NULL"
|
|
assert_contains "$sql" "now() + interval '30 days'"
|
|
|
|
local quoted_sql
|
|
quoted_sql="$(build_bind_api_key_group_sql "sk-o'reilly" 7)"
|
|
assert_contains "$quoted_sql" "WHERE key = 'sk-o''reilly'"
|
|
}
|
|
|
|
run_test_real_host_acceptance_after_import_hook() {
|
|
local tmpdir fakebin artifact_dir hook_file
|
|
tmpdir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmpdir"' RETURN
|
|
fakebin="$tmpdir/bin"
|
|
artifact_dir="$tmpdir/artifacts"
|
|
hook_file="$artifact_dir/hook.txt"
|
|
mkdir -p "$fakebin"
|
|
|
|
cat > "$fakebin/curl" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
url=""
|
|
for arg in "$@"; do
|
|
if [[ "$arg" == http://* || "$arg" == https://* ]]; then
|
|
url="$arg"
|
|
fi
|
|
done
|
|
[[ -n "$url" ]] || {
|
|
echo "missing url in curl args: $*" >&2
|
|
exit 1
|
|
}
|
|
case "$url" in
|
|
*/api/hosts/test-host)
|
|
printf '%s\n' '{"host_id":"test-host"}'
|
|
;;
|
|
*/api/hosts/test-host/probe)
|
|
printf '%s\n' '{"ok":true}'
|
|
;;
|
|
*/api/packs/install)
|
|
printf '%s\n' '{"pack_id":1}'
|
|
;;
|
|
*/api/providers/deepseek/preview-import)
|
|
printf '%s\n' '{"available":true}'
|
|
;;
|
|
*/api/providers/deepseek/import)
|
|
printf '%s\n' '{"batch_id":123,"batch_status":"partially_succeeded","access_status":"broken"}'
|
|
;;
|
|
*/api/import-batches/123)
|
|
printf '%s\n' '{"managed_resources":[{"ResourceType":"group","HostResourceID":"7","ResourceName":"DeepSeek 默认分组"}]}'
|
|
;;
|
|
*/api/providers/deepseek/access/preview)
|
|
printf '%s\n' '{"available":true}'
|
|
;;
|
|
*/api/providers/deepseek/access/status)
|
|
printf '%s\n' '{"latest_access_status":"subscription_ready"}'
|
|
;;
|
|
*/api/providers/deepseek/status)
|
|
printf '%s\n' '{"status":"ready"}'
|
|
;;
|
|
*/api/providers/deepseek/reconcile)
|
|
printf '%s\n' '{"status":"in_sync"}'
|
|
;;
|
|
*/api/import-batches/123/rollback)
|
|
printf '%s\n' '{"status":"rolled_back"}'
|
|
;;
|
|
*)
|
|
echo "unexpected curl url: $url" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
EOF
|
|
chmod +x "$fakebin/curl"
|
|
|
|
PATH="$fakebin:$PATH" \
|
|
ARTIFACT_DIR="$artifact_dir" \
|
|
CRM_BASE_URL="http://crm.example.com" \
|
|
CRM_ADMIN_TOKEN="token" \
|
|
HOST_NAME="test-host" \
|
|
HOST_BASE_URL="http://host.example.com" \
|
|
PACK_PATH="/tmp/openai-pack" \
|
|
PROVIDER_ID="deepseek" \
|
|
HOST_API_KEY="host-key" \
|
|
MODE="partial" \
|
|
ACCESS_MODE="subscription" \
|
|
ACCESS_API_KEY="user-key" \
|
|
SUBSCRIPTION_USERS="42" \
|
|
SKIP_ROLLBACK="1" \
|
|
AFTER_IMPORT_HOOK_COMMAND='printf "%s\n" "$BATCH_ID:$BATCH_DETAIL_FILE:$ACCESS_MODE" > "$ARTIFACT_DIR/hook.txt"' \
|
|
"$ROOT_DIR/scripts/real_host_acceptance.sh" >/dev/null
|
|
|
|
[[ -f "$hook_file" ]] || fail "after-import hook did not create $hook_file"
|
|
local hook_contents
|
|
hook_contents="$(cat "$hook_file")"
|
|
assert_contains "$hook_contents" "123:"
|
|
assert_contains "$hook_contents" "05a-batch-detail-pre-access.json:subscription"
|
|
}
|
|
|
|
run_test_import_remote43_provider_subscription_prep() {
|
|
local tmpdir fakebin artifact_dir ssh_log psql_sql
|
|
tmpdir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmpdir"' RETURN
|
|
fakebin="$tmpdir/bin"
|
|
artifact_dir="$tmpdir/artifacts"
|
|
ssh_log="$artifact_dir/ssh-log.txt"
|
|
psql_sql="$artifact_dir/prep.sql"
|
|
mkdir -p "$fakebin"
|
|
|
|
cat > "$fakebin/ssh" <<'EOF'
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
log_dir="${FAKE_REMOTE_LOG_DIR:?missing FAKE_REMOTE_LOG_DIR}"
|
|
cmd="${*: -1}"
|
|
printf '%s\n' "$cmd" >> "$log_dir/ssh-log.txt"
|
|
case "$cmd" in
|
|
*"grep ^SUB2API_CRM_ADMIN_TOKEN="*)
|
|
printf '%s\n' 'crm-token'
|
|
;;
|
|
*"select value from settings where key='admin_api_key'"*)
|
|
printf '%s\n' 'admin-key'
|
|
;;
|
|
*"select id from users where role='admin'"*)
|
|
printf '%s\n' '1'
|
|
;;
|
|
*"select id from users where email like 'relay-sub-%@sub2api.local'"*)
|
|
printf '%s\n' '42'
|
|
;;
|
|
*"select k.key from users u join api_keys k on k.user_id=u.id"*)
|
|
printf '%s\n' 'user-key'
|
|
;;
|
|
*"curl -sS -D /tmp/import_headers.txt"*"/api/providers/deepseek/import"*)
|
|
printf '%s\n' '{"batch_id":123,"batch_status":"partially_succeeded","access_status":"broken"}' > /tmp/import_body.json
|
|
printf '%s\n' 'HTTP/1.1 200 OK' > /tmp/import_headers.txt
|
|
;;
|
|
"cat /tmp/import_headers.txt")
|
|
cat /tmp/import_headers.txt
|
|
;;
|
|
"cat /tmp/import_body.json")
|
|
cat /tmp/import_body.json
|
|
;;
|
|
*"curl -sS -H 'Authorization: Bearer *** http://127.0.0.1:18088/api/import-batches/123"*)
|
|
printf '%s\n' '{"managed_resources":[{"ResourceType":"group","HostResourceID":"7","ResourceName":"DeepSeek 默认分组"}]}'
|
|
;;
|
|
*"curl -sS -D /tmp/chat_headers.txt"*)
|
|
printf '%s\n' 'HTTP/1.1 200 OK' > /tmp/chat_headers.txt
|
|
printf '%s\n' '{"choices":[{"message":{"content":"pong"}}]}' > /tmp/chat_body.json
|
|
;;
|
|
"cat /tmp/chat_headers.txt")
|
|
cat /tmp/chat_headers.txt
|
|
;;
|
|
"cat /tmp/chat_body.json")
|
|
cat /tmp/chat_body.json
|
|
;;
|
|
*"curl -sS -H 'Authorization: Bearer *** http://127.0.0.1:18088/api/providers/deepseek/status"*)
|
|
printf '%s\n' '{"status":"ready"}'
|
|
;;
|
|
*"curl -sS -H 'Authorization: Bearer *** http://127.0.0.1:18088/api/providers/deepseek/access/status"*)
|
|
printf '%s\n' '{"latest_access_status":"subscription_ready"}'
|
|
;;
|
|
*"curl -sS -X POST -H 'Authorization: Bearer *** -H 'Content-Type: application/json' http://127.0.0.1:18088/api/providers/deepseek/access/preview"*)
|
|
printf '%s\n' '{"available":true}'
|
|
;;
|
|
*"curl -sS -H 'Authorization: Bearer *** http://127.0.0.1:18088/api/providers/deepseek/reconcile"*)
|
|
printf '%s\n' '{"status":"in_sync"}'
|
|
;;
|
|
*"sudo -n docker exec -i sub2api-relaymgr-pg psql -U sub2api -d sub2api -At -F ''"*)
|
|
printf '%s\n' '{"group_id":7,"subscription":{"status":"active"},"key":{"group_id":7}}'
|
|
;;
|
|
*"sudo -n docker exec -i sub2api-relaymgr-pg psql -U sub2api -d sub2api"*)
|
|
CMD="$cmd" LOG_DIR="$log_dir" python3 - <<'PY'
|
|
import base64, os, re, pathlib
|
|
cmd = os.environ['CMD']
|
|
log_dir = pathlib.Path(os.environ['LOG_DIR'])
|
|
match = re.search(r"printf '%s' '([^']+)' \| base64 -d", cmd)
|
|
if not match:
|
|
raise SystemExit(f'failed to extract base64 payload from: {cmd}')
|
|
log_dir.joinpath('prep.sql').write_bytes(base64.b64decode(match.group(1)))
|
|
PY
|
|
;;
|
|
*"sudo -n docker exec sub2api-relaymgr-redis redis-cli FLUSHDB"*)
|
|
printf '%s\n' 'OK'
|
|
;;
|
|
*)
|
|
echo "unexpected ssh command: $cmd" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
EOF
|
|
chmod +x "$fakebin/ssh"
|
|
|
|
PATH="$fakebin:$PATH" \
|
|
FAKE_REMOTE_LOG_DIR="$artifact_dir" \
|
|
KEY="/does/not/matter" \
|
|
REMOTE="fake@host" \
|
|
CRM_BASE="http://127.0.0.1:18088" \
|
|
HOST_BASE="http://127.0.0.1:18087" \
|
|
ROOT="$artifact_dir/root" \
|
|
ART="$artifact_dir/run" \
|
|
PACK_PATH="/tmp/openai-pack" \
|
|
UPSTREAM_KEY="upstream-test-key" \
|
|
SUBSCRIPTION_DAYS=30 \
|
|
MIN_BALANCE=10 \
|
|
SKIP_ROLLBACK=1 \
|
|
bash "$ROOT_DIR/scripts/import_remote43_provider.sh" deepseek gpt-4 UPSTREAM_KEY >/dev/null
|
|
|
|
[[ -f "$psql_sql" ]] || fail "prep sql was not captured"
|
|
local prep_sql
|
|
prep_sql="$(cat "$psql_sql")"
|
|
assert_contains "$prep_sql" "UPDATE users"
|
|
assert_contains "$prep_sql" "UPDATE api_keys"
|
|
assert_contains "$prep_sql" "INSERT INTO user_subscriptions"
|
|
assert_contains "$prep_sql" "group_id = 7"
|
|
[[ -s "$ssh_log" ]] || fail "ssh log was empty"
|
|
}
|
|
|
|
run_test_build_subscription_access_prep_sql
|
|
run_test_real_host_acceptance_after_import_hook
|
|
run_test_import_remote43_provider_subscription_prep
|
|
|
|
echo "PASS: real host script regression checks"
|