2929from model_registry import ModelRegistry as ModelRegistryClient
3030
3131from utilities .infra import create_ns
32- from utilities .constants import OCIRegistry , MinIo , Protocols , Labels
32+ from utilities .constants import OCIRegistry , MinIo , Protocols , Labels , ApiGroups
3333from utilities .general import b64_encoded_string
34- from tests .model_registry .async_job .utils import get_async_job_s3_secret_dict , upload_test_model_to_minio_from_image
34+ from tests .model_registry .async_job .utils import upload_test_model_to_minio_from_image
3535from tests .model_registry .utils import get_mr_service_by_label , get_endpoint_from_mr_service
3636from tests .model_registry .async_job .constants import REPO_NAME
37+ from utilities .general import get_s3_secret_dict
3738
3839
3940# We need to upstream this to the wrapper library
@@ -57,24 +58,31 @@ def s3_secret_for_async_job(
5758 service_account : ServiceAccount ,
5859 minio_service : Service ,
5960) -> Generator [Secret , Any , Any ]:
60- """Create S3 credentials secret for async upload job"""
61+ """Create S3 data connection for async upload job"""
6162 # Construct MinIO endpoint from service
6263 minio_endpoint = (
6364 f"http://{ minio_service .name } .{ minio_service .namespace } .svc.cluster.local:{ MinIo .Metadata .DEFAULT_PORT } "
6465 )
6566
6667 with Secret (
6768 client = admin_client ,
68- name = f"async-job-s3-secret -{ shortuuid .uuid ().lower ()} " ,
69+ name = f"async-job-s3-connection -{ shortuuid .uuid ().lower ()} " ,
6970 namespace = service_account .namespace ,
70- data_dict = get_async_job_s3_secret_dict (
71- access_key = MinIo .Credentials .ACCESS_KEY_VALUE ,
72- secret_access_key = MinIo .Credentials .SECRET_KEY_VALUE ,
73- s3_bucket = MinIo .Buckets .MODELMESH_EXAMPLE_MODELS ,
74- s3_endpoint = minio_endpoint ,
75- s3_region = "us-east-1" , # Default region for MinIO
71+ data_dict = get_s3_secret_dict (
72+ aws_access_key = MinIo .Credentials .ACCESS_KEY_VALUE ,
73+ aws_secret_access_key = MinIo .Credentials .SECRET_KEY_VALUE ,
74+ aws_s3_bucket = MinIo .Buckets .MODELMESH_EXAMPLE_MODELS ,
75+ aws_s3_endpoint = minio_endpoint ,
76+ aws_default_region = "us-east-1" , # Default region for MinIO
7677 ),
77- type = "Opaque" ,
78+ label = {
79+ Labels .OpenDataHub .DASHBOARD : "true" ,
80+ Labels .OpenDataHubIo .MANAGED : "true" ,
81+ },
82+ annotations = {
83+ f"{ ApiGroups .OPENDATAHUB_IO } /connection-type" : "s3" ,
84+ "openshift.io/display-name" : "My S3 Credentials" ,
85+ },
7886 ) as secret :
7987 yield secret
8088
@@ -85,27 +93,36 @@ def oci_secret_for_async_job(
8593 service_account : ServiceAccount ,
8694 oci_registry_host : str ,
8795) -> Generator [Secret , Any , Any ]:
88- """Create OCI registry credentials secret for async upload job"""
96+ """Create OCI registry data connection for async upload job"""
8997
9098 # Create anonymous dockerconfig for OCI registry (no authentication)
91- # This matches the zot registry setup which allows anonymous access
9299 dockerconfig = {
93100 "auths" : {
94101 f"{ oci_registry_host } :{ OCIRegistry .Metadata .DEFAULT_PORT } " : {
95102 "auth" : "" ,
96- "email" : "user@example.com" , # Anonymous access
103+ "email" : "user@example.com" ,
97104 }
98105 }
99106 }
100107
108+ data_dict = {
109+ ".dockerconfigjson" : b64_encoded_string (json .dumps (dockerconfig )),
110+ "ACCESS_TYPE" : b64_encoded_string (json .dumps ('["Push,Pull"]' )),
111+ "OCI_HOST" : b64_encoded_string (json .dumps (f"{ oci_registry_host } :{ OCIRegistry .Metadata .DEFAULT_PORT } " )),
112+ }
113+
101114 with Secret (
102115 client = admin_client ,
103- name = f"async-job-oci-secret -{ shortuuid .uuid ().lower ()} " ,
116+ name = f"async-job-oci-connection -{ shortuuid .uuid ().lower ()} " ,
104117 namespace = service_account .namespace ,
105- data_dict = {
106- ".dockerconfigjson" : b64_encoded_string (json .dumps (dockerconfig )),
107- "ACCESS_TYPE" : b64_encoded_string (json .dumps ('["Push,Pull"]' )),
108- "OCI_HOST" : b64_encoded_string (json .dumps (f"{ oci_registry_host } :{ OCIRegistry .Metadata .DEFAULT_PORT } " )),
118+ data_dict = data_dict ,
119+ label = {
120+ Labels .OpenDataHub .DASHBOARD : "true" ,
121+ Labels .OpenDataHubIo .MANAGED : "true" ,
122+ },
123+ annotations = {
124+ f"{ ApiGroups .OPENDATAHUB_IO } /connection-type-ref" : "oci-v1" ,
125+ "openshift.io/display-name" : "My OCI Credentials" ,
109126 },
110127 type = "kubernetes.io/dockerconfigjson" ,
111128 ) as secret :
@@ -125,18 +142,78 @@ def model_sync_async_job(
125142 mr_access_role_binding : RoleBinding ,
126143 teardown_resources : bool ,
127144) -> Generator [Job , Any , Any ]:
128- """Core Job fixture focused on Job deployment and configuration"""
129- # Get dynamic OCI URI from route
130- dynamic_oci_uri = f"{ oci_registry_host } /{ REPO_NAME } "
131-
132- # Get model registry service and endpoint
133- mr_instance = model_registry_instance [0 ] # Use first instance
145+ """
146+ Job fixture for async model upload with mounted secret files.
147+
148+ This fixture creates a Kubernetes Job that:
149+ 1. Mounts S3 credentials for source model access
150+ 2. Mounts OCI credentials for destination registry
151+ 3. Configures environment variables for model sync parameters
152+ 4. Waits for job completion before yielding
153+
154+ Args:
155+ admin_client: Kubernetes client for resource management
156+ sa_token: Service account token for Model Registry authentication
157+ service_account: Service account for the job
158+ model_registry_namespace: Namespace containing Model Registry
159+ model_registry_instance: List of Model Registry instances
160+ s3_secret_for_async_job: Secret containing S3 credentials
161+ oci_secret_for_async_job: Secret containing OCI registry credentials
162+ oci_registry_host: OCI registry hostname
163+ mr_access_role_binding: Role binding for Model Registry access
164+ teardown_resources: Whether to clean up resources after test
165+
166+ Returns:
167+ Generator yielding the created Job resource
168+ """
169+
170+ # Get Model Registry service endpoint for connection
171+ mr_instance = model_registry_instance [0 ]
134172 mr_service = get_mr_service_by_label (
135173 client = admin_client , namespace_name = model_registry_namespace , mr_instance = mr_instance
136174 )
137175 mr_endpoint = get_endpoint_from_mr_service (svc = mr_service , protocol = Protocols .REST )
138176 mr_host = mr_endpoint .split (":" )[0 ]
139- mr_port = mr_endpoint .split (":" )[1 ]
177+
178+ # Volume mounts for credentials
179+ volume_mounts = [
180+ {
181+ "name" : "source-credentials" ,
182+ "readOnly" : True ,
183+ "mountPath" : VOLUME_MOUNTS ["SOURCE_CREDS_PATH" ],
184+ },
185+ {
186+ "name" : "destination-credentials" ,
187+ "readOnly" : True ,
188+ "mountPath" : VOLUME_MOUNTS ["DEST_CREDS_PATH" ],
189+ },
190+ ]
191+
192+ environment_variables = [
193+ # Source configuration - S3 credentials and model location
194+ {"name" : "MODEL_SYNC_SOURCE_TYPE" , "value" : MODEL_SYNC_CONFIG ["SOURCE_TYPE" ]},
195+ {"name" : "MODEL_SYNC_SOURCE_AWS_KEY" , "value" : MODEL_SYNC_CONFIG ["SOURCE_AWS_KEY" ]},
196+ {"name" : "MODEL_SYNC_SOURCE_S3_CREDENTIALS_PATH" , "value" : VOLUME_MOUNTS ["SOURCE_CREDS_PATH" ]},
197+ # Model identification parameters
198+ {"name" : "MODEL_SYNC_MODEL_ID" , "value" : MODEL_SYNC_CONFIG ["MODEL_ID" ]},
199+ {"name" : "MODEL_SYNC_MODEL_VERSION_ID" , "value" : MODEL_SYNC_CONFIG ["MODEL_VERSION_ID" ]},
200+ {"name" : "MODEL_SYNC_MODEL_ARTIFACT_ID" , "value" : MODEL_SYNC_CONFIG ["MODEL_ARTIFACT_ID" ]},
201+ # Model Registry connection parameters
202+ {"name" : "MODEL_SYNC_REGISTRY_SERVER_ADDRESS" , "value" : f"https://{ mr_host } " },
203+ {"name" : "MODEL_SYNC_REGISTRY_USER_TOKEN" , "value" : sa_token },
204+ {"name" : "MODEL_SYNC_REGISTRY_IS_SECURE" , "value" : "False" },
205+ # OCI destination configuration
206+ {
207+ "name" : "MODEL_SYNC_DESTINATION_OCI_REGISTRY" ,
208+ "value" : f"{ oci_registry_host } :{ OCIRegistry .Metadata .DEFAULT_PORT } " ,
209+ },
210+ {"name" : "MODEL_SYNC_DESTINATION_OCI_URI" , "value" : f"{ oci_registry_host } /{ REPO_NAME } " },
211+ {"name" : "MODEL_SYNC_DESTINATION_OCI_BASE_IMAGE" , "value" : MODEL_SYNC_CONFIG ["DESTINATION_OCI_BASE_IMAGE" ]},
212+ {
213+ "name" : "MODEL_SYNC_DESTINATION_OCI_ENABLE_TLS_VERIFY" ,
214+ "value" : MODEL_SYNC_CONFIG ["DESTINATION_OCI_ENABLE_TLS_VERIFY" ],
215+ },
216+ ]
140217
141218 with JobWithVolumes (
142219 client = admin_client ,
@@ -149,84 +226,13 @@ def model_sync_async_job(
149226 {
150227 "name" : "async-upload" ,
151228 "image" : ASYNC_UPLOAD_IMAGE ,
152- "volumeMounts" : [
153- {
154- "name" : "source-credentials" ,
155- "readOnly" : True ,
156- "mountPath" : VOLUME_MOUNTS ["SOURCE_CREDS_PATH" ],
157- },
158- {
159- "name" : "destination-credentials" ,
160- "readOnly" : True ,
161- "mountPath" : VOLUME_MOUNTS ["DEST_CREDS_PATH" ],
162- },
163- ],
164- "env" : [
165- # Proxy settings
166- {"name" : "HTTP_PROXY" , "value" : "" },
167- {"name" : "HTTPS_PROXY" , "value" : "" },
168- {"name" : "NO_PROXY" , "value" : "*.svc.cluster.local" },
169- # Source configuration
170- {"name" : "MODEL_SYNC_SOURCE_TYPE" , "value" : MODEL_SYNC_CONFIG ["SOURCE_TYPE" ]},
171- {"name" : "MODEL_SYNC_SOURCE_AWS_KEY" , "value" : MODEL_SYNC_CONFIG ["SOURCE_AWS_KEY" ]},
172- {
173- "name" : "MODEL_SYNC_SOURCE_S3_CREDENTIALS_PATH" ,
174- "value" : VOLUME_MOUNTS ["SOURCE_CREDS_PATH" ],
175- },
176- # Destination configuration
177- {"name" : "MODEL_SYNC_DESTINATION_TYPE" , "value" : MODEL_SYNC_CONFIG ["DESTINATION_TYPE" ]},
178- {
179- "name" : "MODEL_SYNC_DESTINATION_OCI_URI" ,
180- "value" : f"{ dynamic_oci_uri } " ,
181- },
182- {
183- "name" : "MODEL_SYNC_DESTINATION_OCI_REGISTRY" ,
184- "value" : f"{ oci_registry_host } :{ OCIRegistry .Metadata .DEFAULT_PORT } " ,
185- },
186- {
187- "name" : "MODEL_SYNC_DESTINATION_OCI_CREDENTIALS_PATH" ,
188- "value" : VOLUME_MOUNTS ["DEST_DOCKERCONFIG_PATH" ],
189- },
190- {
191- "name" : "MODEL_SYNC_DESTINATION_OCI_BASE_IMAGE" ,
192- "value" : MODEL_SYNC_CONFIG ["DESTINATION_OCI_BASE_IMAGE" ],
193- },
194- {
195- "name" : "MODEL_SYNC_DESTINATION_OCI_ENABLE_TLS_VERIFY" ,
196- "value" : MODEL_SYNC_CONFIG ["DESTINATION_OCI_ENABLE_TLS_VERIFY" ],
197- },
198- # Model parameters
199- {"name" : "MODEL_SYNC_MODEL_ID" , "value" : MODEL_SYNC_CONFIG ["MODEL_ID" ]},
200- {"name" : "MODEL_SYNC_MODEL_VERSION_ID" , "value" : MODEL_SYNC_CONFIG ["MODEL_VERSION_ID" ]},
201- {
202- "name" : "MODEL_SYNC_MODEL_ARTIFACT_ID" ,
203- "value" : MODEL_SYNC_CONFIG ["MODEL_ARTIFACT_ID" ],
204- },
205- # Model Registry client params
206- {
207- "name" : "MODEL_SYNC_REGISTRY_SERVER_ADDRESS" ,
208- "value" : f"https://{ mr_host } " ,
209- },
210- {"name" : "MODEL_SYNC_REGISTRY_PORT" , "value" : mr_port },
211- {"name" : "MODEL_SYNC_REGISTRY_AUTHOR" , "value" : "RHOAI async job test" },
212- {"name" : "MODEL_SYNC_REGISTRY_USER_TOKEN" , "value" : sa_token },
213- {"name" : "MODEL_SYNC_REGISTRY_IS_SECURE" , "value" : "False" },
214- ],
229+ "volumeMounts" : volume_mounts ,
230+ "env" : environment_variables ,
215231 }
216232 ],
217233 volumes = [
218- {
219- "name" : "source-credentials" ,
220- "secret" : {
221- "secretName" : s3_secret_for_async_job .name ,
222- },
223- },
224- {
225- "name" : "destination-credentials" ,
226- "secret" : {
227- "secretName" : oci_secret_for_async_job .name ,
228- },
229- },
234+ {"name" : "source-credentials" , "secret" : {"secretName" : s3_secret_for_async_job .name }},
235+ {"name" : "destination-credentials" , "secret" : {"secretName" : oci_secret_for_async_job .name }},
230236 ],
231237 teardown = teardown_resources ,
232238 ) as job :
0 commit comments