Skip to content

Commit 33cdf59

Browse files
committed
test: add qdrant vector_io tests
1 parent 7fd9561 commit 33cdf59

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

tests/fixtures/vector_io.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from ocp_resources.deployment import Deployment
88
from ocp_resources.namespace import Namespace
99
from ocp_resources.service import Service
10+
from ocp_resources.secret import Secret
1011

1112

1213
MILVUS_IMAGE = os.getenv(
@@ -30,6 +31,14 @@
3031
PGVECTOR_USER = os.getenv("LLS_VECTOR_IO_PGVECTOR_USER", "vector_user")
3132
PGVECTOR_PASSWORD = os.getenv("LLS_VECTOR_IO_PGVECTOR_PASSWORD", "yourpassword")
3233

34+
QDRANT_IMAGE = os.getenv(
35+
"LLS_VECTOR_IO_QDRANT_IMAGE",
36+
(
37+
"docker.io/qdrant/qdrant@sha256:"
38+
"26509b92c44ded1ad344e18a005383c20bb3fbf9dbf4d337265a230b2aa89e79" # pragma: allowlist secret"
39+
),
40+
)
41+
3342

3443
@pytest.fixture(scope="class")
3544
def vector_io_provider_deployment_config_factory(
@@ -66,6 +75,10 @@ def vector_io_provider_deployment_config_factory(
6675
* PGVECTOR_USER: Database user
6776
* PGVECTOR_PASSWORD: Database password
6877
* PGVECTOR_DB: Database name
78+
- "qdrant-remote":
79+
* ENABLE_QDRANT: enable qdrant provider
80+
* QDRANT_API_KEY: Qdrant API key
81+
* QDRANT_URL: Qdrant service URL with protocol (e.g., "http://vector-io-qdrant-service:6333")
6982
7083
Example:
7184
def test_with_milvus(vector_io_provider_deployment_config_factory):
@@ -98,6 +111,14 @@ def _factory(provider_name: str) -> list[Dict[str, str]]:
98111
env_vars.append({"name": "PGVECTOR_USER", "value": PGVECTOR_USER})
99112
env_vars.append({"name": "PGVECTOR_PASSWORD", "value": PGVECTOR_PASSWORD})
100113
env_vars.append({"name": "PGVECTOR_DB", "value": "pgvector"})
114+
elif provider_name == "qdrant-remote":
115+
request.getfixturevalue(argname="qdrant_service")
116+
env_vars.append({"name": "ENABLE_QDRANT", "value": "true"})
117+
env_vars.append({"name": "QDRANT_URL", "value": "http://vector-io-qdrant-service:6333"})
118+
env_vars.append({
119+
"name": "QDRANT_API_KEY",
120+
"valueFrom": {"secretKeyRef": {"name": "qdrant-secret", "key": "api-key"}},
121+
})
101122

102123
return env_vars
103124

@@ -350,3 +371,116 @@ def get_pgvector_deployment_template() -> Dict[str, Any]:
350371
"volumes": [{"name": "pgdata", "emptyDir": {}}],
351372
},
352373
}
374+
375+
376+
@pytest.fixture(scope="class")
377+
def qdrant_deployment(
378+
unprivileged_client: DynamicClient,
379+
unprivileged_model_namespace: Namespace,
380+
qdrant_secret: Secret,
381+
) -> Generator[Deployment, Any, Any]:
382+
"""Deploy a Qdrant instance for vector I/O provider testing."""
383+
with Deployment(
384+
client=unprivileged_client,
385+
namespace=unprivileged_model_namespace.name,
386+
name="vector-io-qdrant-deployment",
387+
min_ready_seconds=5,
388+
replicas=1,
389+
selector={"matchLabels": {"app": "qdrant"}},
390+
strategy={"type": "Recreate"},
391+
template=get_qdrant_deployment_template(),
392+
teardown=True,
393+
) as deployment:
394+
deployment.wait_for_replicas(deployed=True, timeout=240)
395+
yield deployment
396+
397+
398+
@pytest.fixture(scope="class")
399+
def qdrant_service(
400+
unprivileged_client: DynamicClient,
401+
unprivileged_model_namespace: Namespace,
402+
qdrant_deployment: Deployment,
403+
) -> Generator[Service, Any, Any]:
404+
"""Create a service for the Qdrant deployment."""
405+
with Service(
406+
client=unprivileged_client,
407+
namespace=unprivileged_model_namespace.name,
408+
name="vector-io-qdrant-service",
409+
ports=[
410+
{
411+
"name": "http",
412+
"port": 6333,
413+
"targetPort": 6333,
414+
},
415+
{
416+
"name": "grpc",
417+
"port": 6334,
418+
"targetPort": 6334,
419+
},
420+
],
421+
selector={"app": "qdrant"},
422+
wait_for_resource=True,
423+
) as service:
424+
yield service
425+
426+
427+
@pytest.fixture(scope="class")
428+
def qdrant_secret(
429+
unprivileged_client: DynamicClient,
430+
unprivileged_model_namespace: Namespace,
431+
) -> Generator[Secret, Any, Any]:
432+
"""Return a Kubernetes Secret for Qdrant"""
433+
with Secret(
434+
client=unprivileged_client,
435+
namespace=unprivileged_model_namespace.name,
436+
name="qdrant-secret",
437+
type="Opaque",
438+
string_data={"api-key": "yourapikey"},
439+
) as secret:
440+
yield secret
441+
442+
443+
def get_qdrant_deployment_template() -> Dict[str, Any]:
444+
"""Return a Kubernetes deployment for Qdrant"""
445+
return {
446+
"metadata": {"labels": {"app": "qdrant"}},
447+
"spec": {
448+
"securityContext": {"runAsNonRoot": True, "seccompProfile": {"type": "RuntimeDefault"}},
449+
"containers": [
450+
{
451+
"name": "qdrant",
452+
"image": QDRANT_IMAGE,
453+
"ports": [
454+
{
455+
"containerPort": 6333,
456+
"name": "http",
457+
},
458+
{
459+
"containerPort": 6334,
460+
"name": "grpc",
461+
},
462+
],
463+
"env": [
464+
{
465+
"name": "QDRANT__SERVICE__API_KEY",
466+
"valueFrom": {
467+
"secretKeyRef": {
468+
"name": "qdrant-secret",
469+
"key": "api-key",
470+
},
471+
},
472+
},
473+
],
474+
"volumeMounts": [
475+
{"name": "qdrant-storage", "mountPath": "/qdrant/storage"},
476+
{
477+
"name": "qdrant-storage",
478+
"mountPath": "/qdrant/snapshots",
479+
"subPath": "snapshots",
480+
},
481+
],
482+
},
483+
],
484+
"volumes": [{"name": "qdrant-storage", "emptyDir": {}}],
485+
},
486+
}

tests/llama_stack/vector_io/test_vector_stores.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@
5454
{"vector_io_provider": "pgvector"},
5555
id="vector_io_provider_pgvector",
5656
),
57+
pytest.param(
58+
{"name": "test-llamastack-vector-stores", "randomize_name": True},
59+
{
60+
"llama_stack_storage_size": "2Gi",
61+
"vector_io_provider": "qdrant-remote",
62+
},
63+
{"vector_io_provider": "qdrant-remote"},
64+
id="vector_io_provider_qdrant-remote",
65+
),
5766
],
5867
indirect=True,
5968
)

0 commit comments

Comments
 (0)