77from ocp_resources .deployment import Deployment
88from ocp_resources .namespace import Namespace
99from ocp_resources .service import Service
10+ from ocp_resources .secret import Secret
1011
1112
1213MILVUS_IMAGE = os .getenv (
3031PGVECTOR_USER = os .getenv ("LLS_VECTOR_IO_PGVECTOR_USER" , "vector_user" )
3132PGVECTOR_PASSWORD = os .getenv ("LLS_VECTOR_IO_PGVECTOR_PASSWORD" , "yourpassword" )
3233
34+ # qdrant v1 unprivileged latest
35+ QDRANT_IMAGE = os .getenv (
36+ "LLS_VECTOR_IO_QDRANT_IMAGE" ,
37+ (
38+ "docker.io/qdrant/qdrant@sha256:"
39+ "9dfabc51ededc48158899a288a19a04de1ab54a11d8c512e1c40eebbd5e2bc92" # pragma: allowlist secret
40+ ),
41+ )
42+
43+ QDRANT_API_KEY = os .getenv ("LLS_VECTOR_IO_QDRANT_API_KEY" , "yourapikey" )
44+ QDRANT_URL = os .getenv ("LLS_VECTOR_IO_QDRANT_URL" , "http://vector-io-qdrant-service:6333" )
45+
3346
3447@pytest .fixture (scope = "class" )
3548def vector_io_provider_deployment_config_factory (
49+ unprivileged_client : DynamicClient ,
50+ unprivileged_model_namespace : Namespace ,
51+ vector_io_secret : Secret ,
3652 request : FixtureRequest ,
37- ) -> Callable [[str ], list [Dict [str , str ]]]:
53+ ) -> Callable [[str ], list [Dict [str , Any ]]]:
3854 """
3955 Factory fixture for deploying vector I/O providers and returning their configuration.
4056
@@ -66,23 +82,35 @@ def vector_io_provider_deployment_config_factory(
6682 * PGVECTOR_USER: Database user
6783 * PGVECTOR_PASSWORD: Database password
6884 * PGVECTOR_DB: Database name
85+ - "qdrant-remote":
86+ * ENABLE_QDRANT: enable qdrant provider
87+ * QDRANT_API_KEY: Qdrant API key
88+ * QDRANT_URL: Qdrant service URL with protocol (e.g., "http://vector-io-qdrant-service:6333")
6989
7090 Example:
7191 def test_with_milvus(vector_io_provider_deployment_config_factory):
7292 env_vars = vector_io_provider_deployment_config_factory("milvus-remote")
7393 # env_vars contains MILVUS_ENDPOINT, MILVUS_TOKEN, etc.
7494 """
95+ _ = unprivileged_client
96+ _ = unprivileged_model_namespace
97+ _ = vector_io_secret
7598
76- def _factory (provider_name : str ) -> list [Dict [str , str ]]:
77- env_vars : list [dict [str , str ]] = []
99+ def _factory (provider_name : str ) -> list [Dict [str , Any ]]:
100+ env_vars : list [dict [str , Any ]] = []
78101
79102 if provider_name is None or provider_name == "milvus" :
80103 # Default case - no additional environment variables needed
81104 pass
82105 elif provider_name == "milvus-remote" :
83106 request .getfixturevalue (argname = "milvus_service" )
84107 env_vars .append ({"name" : "MILVUS_ENDPOINT" , "value" : "http://vector-io-milvus-service:19530" })
85- env_vars .append ({"name" : "MILVUS_TOKEN" , "value" : MILVUS_TOKEN })
108+ env_vars .append (
109+ {
110+ "name" : "MILVUS_TOKEN" ,
111+ "valueFrom" : {"secretKeyRef" : {"name" : "vector-io-secret" , "key" : "milvus-token" }},
112+ },
113+ )
86114 env_vars .append ({"name" : "MILVUS_CONSISTENCY_LEVEL" , "value" : "Bounded" })
87115 elif provider_name == "faiss" :
88116 env_vars .append ({"name" : "ENABLE_FAISS" , "value" : "faiss" })
@@ -95,15 +123,54 @@ def _factory(provider_name: str) -> list[Dict[str, str]]:
95123 env_vars .append ({"name" : "ENABLE_PGVECTOR" , "value" : "true" })
96124 env_vars .append ({"name" : "PGVECTOR_HOST" , "value" : "vector-io-pgvector-service" })
97125 env_vars .append ({"name" : "PGVECTOR_PORT" , "value" : "5432" })
98- env_vars .append ({"name" : "PGVECTOR_USER" , "value" : PGVECTOR_USER })
99- env_vars .append ({"name" : "PGVECTOR_PASSWORD" , "value" : PGVECTOR_PASSWORD })
126+ env_vars .append (
127+ {
128+ "name" : "PGVECTOR_USER" ,
129+ "valueFrom" : {"secretKeyRef" : {"name" : "vector-io-secret" , "key" : "pgvector-user" }},
130+ },
131+ )
132+ env_vars .append (
133+ {
134+ "name" : "PGVECTOR_PASSWORD" ,
135+ "valueFrom" : {"secretKeyRef" : {"name" : "vector-io-secret" , "key" : "pgvector-password" }},
136+ },
137+ )
100138 env_vars .append ({"name" : "PGVECTOR_DB" , "value" : "pgvector" })
139+ elif provider_name == "qdrant-remote" :
140+ request .getfixturevalue (argname = "qdrant_service" )
141+ env_vars .append ({"name" : "ENABLE_QDRANT" , "value" : "true" })
142+ env_vars .append ({"name" : "QDRANT_URL" , "value" : QDRANT_URL })
143+ env_vars .append ({
144+ "name" : "QDRANT_API_KEY" ,
145+ "valueFrom" : {"secretKeyRef" : {"name" : "vector-io-secret" , "key" : "qdrant-api-key" }},
146+ })
101147
102148 return env_vars
103149
104150 return _factory
105151
106152
153+ @pytest .fixture (scope = "class" )
154+ def vector_io_secret (
155+ unprivileged_client : DynamicClient ,
156+ unprivileged_model_namespace : Namespace ,
157+ ) -> Generator [Secret , Any , Any ]:
158+ """Create a secret for the vector I/O providers"""
159+ with Secret (
160+ client = unprivileged_client ,
161+ namespace = unprivileged_model_namespace .name ,
162+ name = "vector-io-secret" ,
163+ type = "Opaque" ,
164+ string_data = {
165+ "qdrant-api-key" : QDRANT_API_KEY ,
166+ "pgvector-user" : PGVECTOR_USER ,
167+ "pgvector-password" : PGVECTOR_PASSWORD ,
168+ "milvus-token" : MILVUS_TOKEN ,
169+ },
170+ ) as secret :
171+ yield secret
172+
173+
107174@pytest .fixture (scope = "class" )
108175def etcd_deployment (
109176 unprivileged_client : DynamicClient ,
@@ -152,8 +219,13 @@ def remote_milvus_deployment(
152219 unprivileged_model_namespace : Namespace ,
153220 etcd_deployment : Deployment ,
154221 etcd_service : Service ,
222+ vector_io_secret : Secret ,
155223) -> Generator [Deployment , Any , Any ]:
156224 """Deploy a remote Milvus instance for vector I/O provider testing."""
225+ _ = etcd_deployment
226+ _ = etcd_service
227+ _ = vector_io_secret
228+
157229 with Deployment (
158230 client = unprivileged_client ,
159231 namespace = unprivileged_model_namespace .name ,
@@ -176,6 +248,8 @@ def milvus_service(
176248 remote_milvus_deployment : Deployment ,
177249) -> Generator [Service , Any , Any ]:
178250 """Create a service for the remote Milvus deployment."""
251+ _ = remote_milvus_deployment
252+
179253 with Service (
180254 client = unprivileged_client ,
181255 namespace = unprivileged_model_namespace .name ,
@@ -272,8 +346,11 @@ def get_etcd_deployment_template() -> Dict[str, Any]:
272346def pgvector_deployment (
273347 unprivileged_client : DynamicClient ,
274348 unprivileged_model_namespace : Namespace ,
349+ vector_io_secret : Secret ,
275350) -> Generator [Deployment , Any , Any ]:
276351 """Deploy a PGVector instance for vector I/O provider testing."""
352+ _ = vector_io_secret
353+
277354 with Deployment (
278355 client = unprivileged_client ,
279356 namespace = unprivileged_model_namespace .name ,
@@ -296,6 +373,8 @@ def pgvector_service(
296373 pgvector_deployment : Deployment ,
297374) -> Generator [Service , Any , Any ]:
298375 """Create a service for the PGVector deployment."""
376+ _ = pgvector_deployment
377+
299378 with Service (
300379 client = unprivileged_client ,
301380 namespace = unprivileged_model_namespace .name ,
@@ -325,8 +404,14 @@ def get_pgvector_deployment_template() -> Dict[str, Any]:
325404 "ports" : [{"containerPort" : 5432 }],
326405 "env" : [
327406 {"name" : "POSTGRES_DB" , "value" : "pgvector" },
328- {"name" : "POSTGRES_USER" , "value" : PGVECTOR_USER },
329- {"name" : "POSTGRES_PASSWORD" , "value" : PGVECTOR_PASSWORD },
407+ {
408+ "name" : "POSTGRES_USER" ,
409+ "valueFrom" : {"secretKeyRef" : {"name" : "vector-io-secret" , "key" : "pgvector-user" }},
410+ },
411+ {
412+ "name" : "POSTGRES_PASSWORD" ,
413+ "valueFrom" : {"secretKeyRef" : {"name" : "vector-io-secret" , "key" : "pgvector-password" }},
414+ },
330415 {"name" : "PGDATA" , "value" : "/var/lib/postgresql/data/pgdata" },
331416 ],
332417 "lifecycle" : {
@@ -350,3 +435,103 @@ def get_pgvector_deployment_template() -> Dict[str, Any]:
350435 "volumes" : [{"name" : "pgdata" , "emptyDir" : {}}],
351436 },
352437 }
438+
439+
440+ @pytest .fixture (scope = "class" )
441+ def qdrant_deployment (
442+ unprivileged_client : DynamicClient ,
443+ unprivileged_model_namespace : Namespace ,
444+ vector_io_secret : Secret ,
445+ ) -> Generator [Deployment , Any , Any ]:
446+ """Deploy a Qdrant instance for vector I/O provider testing."""
447+ _ = vector_io_secret
448+
449+ with Deployment (
450+ client = unprivileged_client ,
451+ namespace = unprivileged_model_namespace .name ,
452+ name = "vector-io-qdrant-deployment" ,
453+ min_ready_seconds = 5 ,
454+ replicas = 1 ,
455+ selector = {"matchLabels" : {"app" : "qdrant" }},
456+ strategy = {"type" : "Recreate" },
457+ template = get_qdrant_deployment_template (),
458+ teardown = True ,
459+ ) as deployment :
460+ deployment .wait_for_replicas (deployed = True , timeout = 240 )
461+ yield deployment
462+
463+
464+ @pytest .fixture (scope = "class" )
465+ def qdrant_service (
466+ unprivileged_client : DynamicClient ,
467+ unprivileged_model_namespace : Namespace ,
468+ qdrant_deployment : Deployment ,
469+ ) -> Generator [Service , Any , Any ]:
470+ """Create a service for the Qdrant deployment."""
471+ _ = qdrant_deployment
472+
473+ with Service (
474+ client = unprivileged_client ,
475+ namespace = unprivileged_model_namespace .name ,
476+ name = "vector-io-qdrant-service" ,
477+ ports = [
478+ {
479+ "name" : "http" ,
480+ "port" : 6333 ,
481+ "targetPort" : 6333 ,
482+ },
483+ {
484+ "name" : "grpc" ,
485+ "port" : 6334 ,
486+ "targetPort" : 6334 ,
487+ },
488+ ],
489+ selector = {"app" : "qdrant" },
490+ wait_for_resource = True ,
491+ ) as service :
492+ yield service
493+
494+
495+ def get_qdrant_deployment_template () -> Dict [str , Any ]:
496+ """Return a Kubernetes deployment for Qdrant"""
497+ return {
498+ "metadata" : {"labels" : {"app" : "qdrant" }},
499+ "spec" : {
500+ "containers" : [
501+ {
502+ "name" : "qdrant" ,
503+ "image" : QDRANT_IMAGE ,
504+ "ports" : [
505+ {
506+ "containerPort" : 6333 ,
507+ "name" : "http" ,
508+ },
509+ {
510+ "containerPort" : 6334 ,
511+ "name" : "grpc" ,
512+ },
513+ ],
514+ "env" : [
515+ {
516+ "name" : "QDRANT__SERVICE__API_KEY" ,
517+ "valueFrom" : {
518+ "secretKeyRef" : {
519+ "name" : "vector-io-secret" ,
520+ "key" : "qdrant-api-key" ,
521+ },
522+ },
523+ },
524+ ],
525+ "volumeMounts" : [
526+ {"name" : "qdrant-storage" , "mountPath" : "/qdrant/storage" },
527+ {
528+ "name" : "qdrant-storage" ,
529+ "mountPath" : "/qdrant/snapshots" ,
530+ "subPath" : "snapshots" ,
531+ },
532+ ],
533+ },
534+ ],
535+ "volumes" : [{"name" : "qdrant-storage" , "emptyDir" : {}}],
536+ },
537+ }
0 commit comments