mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
One aliased key owned by a user with an email drives chat, queued chat, messages, responses, embeddings, the Gemini passthrough, a batch file upload, and a batch create against a live proxy. Each row must carry api_key equal to the key's LiteLLM_VerificationToken.token and the alias in metadata, and /spend/logs?api_key= and /user/daily/activity must report the key with its alias and email. Health-check rows must keep the literal service-account key, and the batch cost row for a completed marker batch must join the key that created it. A re-hashed api_key (the v1.99.0 regression fixed by #39568 and #39572) now fails the Buildkite e2e stage naming the write path Resolves MAT-180
58 lines
2.3 KiB
Python
58 lines
2.3 KiB
Python
"""Spend-tracking suite's `client` fixture and driver-model registration.
|
|
|
|
The shared lifecycle (resources/scoped_key), proxy liveness gate, and e2e marker
|
|
live in the parent tests/e2e/conftest.py. SpendClient exposes the shared ProxyClient
|
|
(ProxyClientProvider), so the `resources` fixture cleans up keys and customers this
|
|
suite creates.
|
|
|
|
The suite drives real calls through three deployments. On the stage gateway they
|
|
are baked into the proxy config; on a local dev proxy they usually are not, so
|
|
`driver_models` registers whichever are missing via /model/new and deletes only
|
|
the ones it created, never a config-baked deployment. Each registration carries
|
|
the provider key from the test runner's env when set (so a local proxy whose
|
|
container env lacks the key still works); otherwise it falls back to an
|
|
os.environ reference resolved from the proxy's own env, the stage convention.
|
|
"""
|
|
|
|
import os
|
|
from typing import Iterator
|
|
|
|
import pytest
|
|
|
|
from models import LiteLLMParamsBody
|
|
from spend_e2e_client import SpendClient, build_client
|
|
from proxy_client import ProxyClient
|
|
|
|
|
|
def _driver_params(provider_model: str, env_var: str) -> LiteLLMParamsBody:
|
|
return LiteLLMParamsBody(
|
|
model=provider_model,
|
|
api_key=os.environ.get(env_var) or f"os.environ/{env_var}",
|
|
)
|
|
|
|
|
|
DRIVER_MODELS: tuple[tuple[str, str, str], ...] = (
|
|
("gemini-2.5-flash", "gemini/gemini-2.5-flash", "GEMINI_API_KEY"),
|
|
("claude-haiku-4-5", "anthropic/claude-haiku-4-5", "ANTHROPIC_API_KEY"),
|
|
("openai-text-embedding-3-small", "openai/text-embedding-3-small", "OPENAI_API_KEY"),
|
|
("openai-responses-codex", "openai/gpt-5.3-codex", "OPENAI_API_KEY"),
|
|
("openai-gpt-4o-mini", "openai/gpt-4o-mini", "OPENAI_API_KEY"),
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def client(proxy: ProxyClient) -> SpendClient:
|
|
return build_client(proxy)
|
|
|
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
def driver_models(client: SpendClient) -> Iterator[None]:
|
|
existing = frozenset(entry.model_name for entry in client.proxy.model_info())
|
|
created = tuple(
|
|
client.proxy.create_model(name, _driver_params(provider_model, env_var))
|
|
for name, provider_model, env_var in DRIVER_MODELS
|
|
if name not in existing
|
|
)
|
|
yield
|
|
for model_id in created:
|
|
client.proxy.delete_model(model_id)
|