mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-18 05:47:38 +00:00
test: integration suite with real Traefik, redis-shared limits, streaming assertions
Adds integration/ (separate module): docker compose stack with real Traefik v3.5 + localPlugins, mock openai/anthropic/gemini/tool providers, shared Redis, and a raw-TCP streaming timing probe. 6/7 tests pass; streaming incrementality fails on a confirmed external yaegi/Traefik bug (see task-15-report.md), not a plugin defect. Fixes 4 real Yaegi-interpretation bugs surfaced by running the plugin under real Traefik for the first time (none caught by go test or yaegi-check, which never exercises chat/embeddings/streaming/Redis): - .traefik.yml: add basePkg (Traefik derives the yaegi binding identifier from the module path, not the package's own declared name; without this override the plugin never loads at all). - registry.go: resolveAgainst's multi-value return panicked yaegi on an inline string concatenation; assign to a local first. - routes_unified.go: errors.As panicked yaegi on interpreted pointer error types; use plain type assertions (both types are always returned bare, never wrapped). - sse.go: readSSE's dispatch closure hit the same multi-value-assignment panic as registry.go; split into separate statements. - resp.go: respErr as a defined string type was indistinguishable from a plain string in a yaegi type assertion, misreading every successful Redis SELECT reply as failed and silently disabling rate limiting; changed to a struct.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
networks:
|
||||
llmgw-integration:
|
||||
driver: bridge
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
networks: ["llmgw-integration"]
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 2s
|
||||
timeout: 2s
|
||||
retries: 15
|
||||
|
||||
mockopenai:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mock/Dockerfile
|
||||
command: ["-mode", "openai"]
|
||||
networks: ["llmgw-integration"]
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:8080/healthz"]
|
||||
interval: 2s
|
||||
timeout: 2s
|
||||
retries: 15
|
||||
|
||||
mockanthropic:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mock/Dockerfile
|
||||
command: ["-mode", "anthropic"]
|
||||
networks: ["llmgw-integration"]
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:8080/healthz"]
|
||||
interval: 2s
|
||||
timeout: 2s
|
||||
retries: 15
|
||||
|
||||
mockgemini:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mock/Dockerfile
|
||||
command: ["-mode", "gemini"]
|
||||
networks: ["llmgw-integration"]
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:8080/healthz"]
|
||||
interval: 2s
|
||||
timeout: 2s
|
||||
retries: 15
|
||||
|
||||
mocktool:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mock/Dockerfile
|
||||
command: ["-mode", "tool"]
|
||||
networks: ["llmgw-integration"]
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:8080/healthz"]
|
||||
interval: 2s
|
||||
timeout: 2s
|
||||
retries: 15
|
||||
|
||||
traefik1:
|
||||
image: traefik:v3.5
|
||||
command: ["--configfile=/etc/traefik/traefik.yml"]
|
||||
networks: ["llmgw-integration"]
|
||||
ports:
|
||||
- "19081:80"
|
||||
volumes:
|
||||
- ../:/plugins-local/src/github.com/lukaszraczylo/traefik-llmgateway:ro
|
||||
- ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
|
||||
- ./traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
|
||||
- ./users:/users:ro
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
mockopenai:
|
||||
condition: service_healthy
|
||||
mockanthropic:
|
||||
condition: service_healthy
|
||||
mockgemini:
|
||||
condition: service_healthy
|
||||
mocktool:
|
||||
condition: service_healthy
|
||||
|
||||
traefik2:
|
||||
image: traefik:v3.5
|
||||
command: ["--configfile=/etc/traefik/traefik.yml"]
|
||||
networks: ["llmgw-integration"]
|
||||
ports:
|
||||
- "19082:80"
|
||||
volumes:
|
||||
- ../:/plugins-local/src/github.com/lukaszraczylo/traefik-llmgateway:ro
|
||||
- ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
|
||||
- ./traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
|
||||
- ./users:/users:ro
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
mockopenai:
|
||||
condition: service_healthy
|
||||
mockanthropic:
|
||||
condition: service_healthy
|
||||
mockgemini:
|
||||
condition: service_healthy
|
||||
mocktool:
|
||||
condition: service_healthy
|
||||
|
||||
# In-network streaming timing prober. Never started by `up`; the test
|
||||
# invokes it on demand via `docker compose run --rm probe`, from inside
|
||||
# this same compose network so its raw-TCP read against traefik1
|
||||
# reflects true inter-chunk arrival timing instead of the buffered
|
||||
# behaviour Docker Desktop's host port-proxy would introduce.
|
||||
probe:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: mock/Dockerfile
|
||||
command: ["-probe", "-target", "traefik1:80", "-apikey", "sk-int-alice", "-model", "openai/gpt-mock"]
|
||||
networks: ["llmgw-integration"]
|
||||
profiles: ["probe"]
|
||||
depends_on:
|
||||
- traefik1
|
||||
Reference in New Issue
Block a user