1- import os
21import pytest
32from pytest import Config
4- import schemathesis
53from typing import Generator , Any
64
75from ocp_resources .infrastructure import Infrastructure
1412from ocp_resources .deployment import Deployment
1513
1614from ocp_resources .model_registry_modelregistry_opendatahub_io import ModelRegistry
17- from schemathesis .specs .openapi .schemas import BaseOpenAPISchema
18- from schemathesis .generation .stateful .state_machine import APIStateMachine
19- from schemathesis .core .transport import Response
20- from schemathesis .generation .case import Case
2115from ocp_resources .resource import ResourceEditor
2216
2317from pytest import FixtureRequest
3731 ISTIO_CONFIG_DICT ,
3832)
3933from tests .model_registry .rest_api .utils import ModelRegistryV1Alpha1
40- from utilities .constants import Labels
34+ from utilities .constants import Labels , Protocols
4135from tests .model_registry .utils import (
4236 get_endpoint_from_mr_service ,
4337 get_mr_service_by_label ,
4438 get_model_registry_deployment_template_dict ,
4539 get_model_registry_db_label_dict ,
4640 wait_for_pods_running ,
4741)
48- from utilities .constants import Protocols , DscComponents
42+ from utilities .constants import DscComponents
4943from model_registry import ModelRegistry as ModelRegistryClient
5044from semver import Version
5145from utilities .general import wait_for_pods_by_labels
@@ -235,7 +229,7 @@ def model_registry_instance_mysql(
235229 mr .wait_for_condition (condition = "Available" , status = "True" )
236230 mr .wait_for_condition (condition = "OAuthProxyAvailable" , status = "True" )
237231 wait_for_pods_running (
238- admin_client = admin_client , namespace_name = model_registry_namespace , number_of_consecutive_checks = 3
232+ admin_client = admin_client , namespace_name = model_registry_namespace , number_of_consecutive_checks = 6
239233 )
240234 yield mr
241235
@@ -279,43 +273,6 @@ def model_registry_instance_rest_endpoint(admin_client: DynamicClient, model_reg
279273 )
280274
281275
282- @pytest .fixture (scope = "class" )
283- def generated_schema (pytestconfig : Config , model_registry_instance_rest_endpoint : str ) -> BaseOpenAPISchema :
284- os .environ ["API_HOST" ] = model_registry_instance_rest_endpoint
285- config = schemathesis .config .SchemathesisConfig .from_path (f"{ pytestconfig .rootpath } /schemathesis.toml" )
286- schema = schemathesis .openapi .from_url (
287- url = "https://raw.githubusercontent.com/kubeflow/model-registry/main/api/openapi/model-registry.yaml" ,
288- config = config ,
289- )
290- return schema
291-
292-
293- @pytest .fixture ()
294- def state_machine (generated_schema : BaseOpenAPISchema , current_client_token : str ) -> APIStateMachine :
295- BaseAPIWorkflow = generated_schema .as_state_machine ()
296-
297- class APIWorkflow (BaseAPIWorkflow ): # type: ignore
298- headers : dict [str , str ]
299-
300- def setup (self ) -> None :
301- self .headers = {"Authorization" : f"Bearer { current_client_token } " , "Content-Type" : "application/json" }
302-
303- def before_call (self , case : Case ) -> None :
304- LOGGER .info (f"Checking: { case .method } { case .path } " )
305-
306- # these kwargs are passed to requests.request()
307- def get_call_kwargs (self , case : Case ) -> dict [str , Any ]:
308- return {"verify" : False , "headers" : self .headers }
309-
310- def after_call (self , response : Response , case : Case ) -> None :
311- LOGGER .info (
312- f"Method tested: { case .method } , API: { case .path } , response code:{ response .status_code } ,"
313- f" Full Response:{ response .text } "
314- )
315-
316- return APIWorkflow
317-
318-
319276@pytest .fixture (scope = "class" )
320277def updated_dsc_component_state_scope_class (
321278 pytestconfig : Config ,
@@ -481,6 +438,55 @@ def model_registry_instance_pod(admin_client: DynamicClient) -> Generator[Pod, A
481438 )[0 ]
482439
483440
441+ @pytest .fixture ()
442+ def model_registry_db_instance_pod (admin_client : DynamicClient ) -> Generator [Pod , Any , Any ]:
443+ """Get the model registry instance pod."""
444+ yield wait_for_pods_by_labels (
445+ admin_client = admin_client ,
446+ namespace = py_config ["model_registry_namespace" ],
447+ label_selector = f"name={ DB_RESOURCES_NAME } " ,
448+ expected_num_pods = 1 ,
449+ )[0 ]
450+
451+
452+ @pytest .fixture ()
453+ def set_mr_db_dirty (model_registry_db_instance_pod : Pod ) -> int :
454+ """Set the model registry database dirty and return the latest migration version"""
455+ output = model_registry_db_instance_pod .execute (
456+ command = [
457+ "mysql" ,
458+ "-u" ,
459+ MODEL_REGISTRY_DB_SECRET_STR_DATA ["database-user" ],
460+ f"-p{ MODEL_REGISTRY_DB_SECRET_STR_DATA ['database-password' ]} " ,
461+ "-e" ,
462+ "SELECT version FROM schema_migrations ORDER BY version DESC LIMIT 1;" ,
463+ MODEL_REGISTRY_DB_SECRET_STR_DATA ["database-name" ],
464+ ]
465+ )
466+ latest_migration_version = int (output .strip ().split ()[1 ])
467+ model_registry_db_instance_pod .execute (
468+ command = [
469+ "mysql" ,
470+ "-u" ,
471+ MODEL_REGISTRY_DB_SECRET_STR_DATA ["database-user" ],
472+ f"-p{ MODEL_REGISTRY_DB_SECRET_STR_DATA ['database-password' ]} " ,
473+ "-e" ,
474+ f"UPDATE schema_migrations SET dirty = 1 WHERE version = { latest_migration_version } ;" ,
475+ MODEL_REGISTRY_DB_SECRET_STR_DATA ["database-name" ],
476+ ]
477+ )
478+ return latest_migration_version
479+
480+
481+ @pytest .fixture ()
482+ def delete_mr_deployment () -> None :
483+ """Delete the model registry deployment"""
484+ mr_deployment = Deployment (
485+ name = MR_INSTANCE_NAME , namespace = py_config ["model_registry_namespace" ], ensure_exists = True
486+ )
487+ mr_deployment .delete (wait = True )
488+
489+
484490@pytest .fixture (scope = "class" )
485491def is_model_registry_oauth (request : FixtureRequest ) -> bool :
486492 return getattr (request , "param" , {}).get ("use_oauth_proxy" , True )
@@ -490,3 +496,18 @@ def is_model_registry_oauth(request: FixtureRequest) -> bool:
490496def api_server_url (admin_client : DynamicClient ) -> str :
491497 infrastructure = Infrastructure (client = admin_client , name = "cluster" , ensure_exists = True )
492498 return infrastructure .instance .status .apiServerURL
499+
500+
501+ @pytest .fixture (scope = "class" )
502+ def model_registry_rest_url (model_registry_instance_rest_endpoint : str ) -> str :
503+ # address and port need to be split in the client instantiation
504+ return f"{ Protocols .HTTPS } ://{ model_registry_instance_rest_endpoint } "
505+
506+
507+ @pytest .fixture (scope = "class" )
508+ def model_registry_rest_headers (current_client_token : str ) -> dict [str , str ]:
509+ return {
510+ "Authorization" : f"Bearer { current_client_token } " ,
511+ "accept" : "application/json" ,
512+ "Content-Type" : "application/json" ,
513+ }
0 commit comments