mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-05 07:37:50 +00:00
test(e2e-ui): let the local harness run on non-default ports
Two checkouts cannot run run_e2e.sh at the same time: it hardcodes 4000/5432/
8090, so the second aborts on "port 4000 is in use" and the only way forward is
to stop someone else's stack.
PROXY_PORT / POSTGRES_PORT / MOCK_LLM_PORT now override those, defaulting to the
historical values so an unset environment behaves exactly as before -- CI, the
CircleCI job and the chart's sidecar all keep working untouched.
Two details that would otherwise make a relocated stack fail confusingly:
- the suite resolves its target from E2E_UI_BASE_URL, which defaults to :4000
independently, so the run would build and boot correctly and then test
whatever was on the default port. run_e2e.sh now derives it.
- the mock server binds its port in server.py, so moving it needs MOCK_LLM_PORT
there too. Its HOST stays loopback-only: 127.0.0.1:8090 from inside the
proxy's own pod is the contract the e2e chart's sidecar is written against.
This commit is contained in:
parent
0ae340be04
commit
20b4e07103
2 changed files with 39 additions and 11 deletions
|
|
@ -3,6 +3,7 @@ Mock LLM server for UI e2e tests.
|
|||
Responds to OpenAI-format endpoints with canned responses.
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import uuid
|
||||
|
|
@ -117,4 +118,12 @@ async def embeddings(request: Request):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run(app, host="127.0.0.1", port=8090)
|
||||
# The port is overridable so two checkouts can run the harness at the same
|
||||
# time; the default keeps every existing caller (run_e2e.sh, the CircleCI
|
||||
# job, the e2e chart's sidecar) working untouched.
|
||||
#
|
||||
# The HOST is deliberately NOT configurable. Binding loopback is what makes
|
||||
# this reachable at 127.0.0.1:8090 from inside the proxy's own pod, which is
|
||||
# the contract the deployed config.yml and the e2e values file are written
|
||||
# against.
|
||||
uvicorn.run(app, host="127.0.0.1", port=int(os.environ.get("MOCK_LLM_PORT", "8090")))
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ set -euo pipefail
|
|||
# ./run_e2e.sh --repeat-each=5 # Run each test 5 times
|
||||
# ./run_e2e.sh --headed # Run with browser visible
|
||||
#
|
||||
# Ports default to 4000 / 5432 / 8090 and can be moved when another checkout
|
||||
# already holds them:
|
||||
# PROXY_PORT=4100 POSTGRES_PORT=5532 MOCK_LLM_PORT=8190 ./run_e2e.sh
|
||||
#
|
||||
# In CI (CI=true), expects:
|
||||
# - PostgreSQL already running on 127.0.0.1:5432
|
||||
# - DATABASE_URL already set
|
||||
|
|
@ -28,6 +32,16 @@ MOCK_PID=""
|
|||
PROXY_PID=""
|
||||
PROXY_LOG=""
|
||||
|
||||
# Ports, overridable so two checkouts can run this harness at the same time --
|
||||
# otherwise a second run aborts on "port 4000 is in use" and the only way out is
|
||||
# to stop someone else's stack. Defaults are the historical values, so an unset
|
||||
# environment behaves exactly as before (CI, the CircleCI job and the docs all
|
||||
# assume 4000/5432/8090).
|
||||
PROXY_PORT="${PROXY_PORT:-4000}"
|
||||
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
||||
MOCK_LLM_PORT="${MOCK_LLM_PORT:-8090}"
|
||||
export MOCK_LLM_PORT
|
||||
|
||||
# --- Ensure common tool paths are available (local dev only) ---
|
||||
if [ "$IS_CI" = "false" ]; then
|
||||
for p in /usr/local/bin /opt/homebrew/bin "$HOME/.local/bin" /opt/homebrew/opt/postgresql@14/bin /opt/homebrew/opt/libpq/bin; do
|
||||
|
|
@ -92,9 +106,9 @@ if [ "$IS_CI" = "false" ]; then
|
|||
# to someone else's :5432 (a psql session, a running app, a Prisma engine
|
||||
# talking to a remote database) aborts the run with "port 5432 is in use"
|
||||
# while nothing is actually bound locally.
|
||||
for port in 4000 5432 8090; do
|
||||
for port in "$PROXY_PORT" "$POSTGRES_PORT" "$MOCK_LLM_PORT"; do
|
||||
if lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1; then
|
||||
echo "Error: port $port is in use"
|
||||
echo "Error: port $port is in use (override with PROXY_PORT / POSTGRES_PORT / MOCK_LLM_PORT)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
|
@ -102,12 +116,12 @@ if [ "$IS_CI" = "false" ]; then
|
|||
export POSTGRES_USER="e2euser"
|
||||
export POSTGRES_PASSWORD="$(openssl rand -hex 32)"
|
||||
export POSTGRES_DB="litellm_e2e"
|
||||
export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:5432/${POSTGRES_DB}"
|
||||
export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:${POSTGRES_PORT}/${POSTGRES_DB}"
|
||||
|
||||
echo "=== Starting PostgreSQL ==="
|
||||
docker run -d --rm --name "$CONTAINER_NAME" \
|
||||
-e POSTGRES_USER -e POSTGRES_PASSWORD -e POSTGRES_DB \
|
||||
-p 127.0.0.1:5432:5432 \
|
||||
-p "127.0.0.1:${POSTGRES_PORT}:5432" \
|
||||
postgres:16
|
||||
|
||||
echo "Waiting for PostgreSQL..."
|
||||
|
|
@ -124,8 +138,13 @@ fi
|
|||
|
||||
# --- Credentials ---
|
||||
export LITELLM_MASTER_KEY="sk-1234"
|
||||
export MOCK_LLM_URL="http://127.0.0.1:8090/v1"
|
||||
export MOCK_LLM_URL="http://127.0.0.1:${MOCK_LLM_PORT}/v1"
|
||||
export DISABLE_SCHEMA_UPDATE="true"
|
||||
# The suite resolves its target from E2E_UI_BASE_URL (constants.ts), which
|
||||
# otherwise defaults to :4000 -- so without this a relocated stack would be
|
||||
# built and booted correctly and then tested against whatever happens to be
|
||||
# listening on the default port.
|
||||
export E2E_UI_BASE_URL="${E2E_UI_BASE_URL:-http://127.0.0.1:${PROXY_PORT}}"
|
||||
# Ensure the proxy serves UI at /ui (not behind a subpath)
|
||||
export SERVER_ROOT_PATH=""
|
||||
# Boot with an external logout URL so proxyLogoutUrl.spec.ts can assert the
|
||||
|
|
@ -176,7 +195,7 @@ uv run --no-sync python "$SCRIPT_DIR/fixtures/mock_llm_server/server.py" &
|
|||
MOCK_PID=$!
|
||||
|
||||
for i in $(seq 1 15); do
|
||||
if curl -sf http://127.0.0.1:8090/health >/dev/null 2>&1; then break; fi
|
||||
if curl -sf http://127.0.0.1:${MOCK_LLM_PORT}/health >/dev/null 2>&1; then break; fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
|
|
@ -186,7 +205,7 @@ cd "$REPO_ROOT"
|
|||
PROXY_LOG="${TMPDIR:-/tmp}/litellm-e2e-proxy-$$.log"
|
||||
uv run --no-sync python -m litellm.proxy.proxy_cli \
|
||||
--config "$SCRIPT_DIR/fixtures/config.yml" \
|
||||
--port 4000 >"$PROXY_LOG" 2>&1 &
|
||||
--port "$PROXY_PORT" >"$PROXY_LOG" 2>&1 &
|
||||
PROXY_PID=$!
|
||||
|
||||
echo "Waiting for proxy (logs: $PROXY_LOG)..."
|
||||
|
|
@ -197,7 +216,7 @@ for i in $(seq 1 180); do
|
|||
tail -n 100 "$PROXY_LOG"
|
||||
exit 1
|
||||
fi
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:4000/health -H "Authorization: Bearer $LITELLM_MASTER_KEY" 2>/dev/null || true)
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:${PROXY_PORT}/health -H "Authorization: Bearer $LITELLM_MASTER_KEY" 2>/dev/null || true)
|
||||
if [ "$HTTP_CODE" = "200" ]; then
|
||||
PROXY_READY=1
|
||||
break
|
||||
|
|
@ -239,8 +258,8 @@ if [ "${E2E_KEEP_ALIVE:-0}" = "1" ]; then
|
|||
cat <<EOF
|
||||
|
||||
=== Stack is up (E2E_KEEP_ALIVE=1); not running tests ===
|
||||
UI / API : http://127.0.0.1:4000
|
||||
Mock LLM : http://127.0.0.1:8090/v1
|
||||
UI / API : http://127.0.0.1:${PROXY_PORT}
|
||||
Mock LLM : http://127.0.0.1:${MOCK_LLM_PORT}/v1
|
||||
Database : $DATABASE_URL
|
||||
Proxy log: $PROXY_LOG
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue