2828from utilities .general import wait_for_oauth_openshift_deployment
2929from ocp_resources .secret import Secret
3030from tests .model_serving .model_server .maas_billing .utils import get_total_tokens
31+ from utilities .infra import get_data_science_cluster
3132from tests .model_serving .model_server .maas_billing .utils import (
3233 detect_scheme_via_llmisvc ,
3334 host_from_ingress_domain ,
3435 mint_token ,
35- llmis_name ,
3636 patch_llmisvc_with_maas_router ,
3737 create_maas_group ,
3838 build_maas_headers ,
3939 get_maas_models_response ,
4040 verify_chat_completions ,
4141 maas_gateway_rate_limits_patched ,
4242 ensure_maas_gateway_and_policies ,
43+ detect_maas_control_plane_namespace ,
44+ get_tier_mapping_configmap ,
4345)
4446
4547LOGGER = get_logger (name = __name__ )
@@ -82,6 +84,7 @@ def minted_token(request_session_http, base_url: str, current_client_token: str)
8284def base_url (maas_scheme : str , maas_host : str ) -> str :
8385 return f"{ maas_scheme } ://{ maas_host } /maas-api"
8486
87+
8588@pytest .fixture (scope = "class" )
8689def model_url (
8790 maas_scheme : str ,
@@ -106,6 +109,7 @@ def maas_models(
106109 base_url : str ,
107110 maas_headers : dict ,
108111 maas_inference_service_tinyllama : LLMInferenceService ,
112+ maas_gateway_and_policies ,
109113):
110114 resp = get_maas_models_response (
111115 session = request_session_http ,
@@ -435,6 +439,9 @@ def maas_token_for_actor(
435439 request_session_http : requests .Session ,
436440 base_url : str ,
437441 ocp_token_for_actor : str ,
442+ maas_control_plane_namespace : str ,
443+ maas_controller_enabled_latest ,
444+ maas_gateway_and_policies ,
438445) -> str :
439446 """
440447 Mint a MaaS token once per actor (admin / free / premium) and reuse it
@@ -532,106 +539,13 @@ def exercise_rate_limiter(
532539 return status_codes_list
533540
534541
535- # @pytest.fixture(scope="class")
536- # def maas_inference_service_tinyllama(
537- # admin_client: DynamicClient,
538- # unprivileged_model_namespace: Namespace,
539- # model_service_account: ServiceAccount,
540- # ) -> Generator[LLMInferenceService, None, None]:
541- # """
542- # TinyLlama S3-backed LLMInferenceService wired through MaaS for tests.
543- # """
544- # with (
545- # create_llmisvc(
546- # client=admin_client,
547- # name="llm-s3-tinyllama",
548- # namespace=unprivileged_model_namespace.name,
549- # storage_uri=ModelStorage.TINYLLAMA_S3,
550- # container_image=ContainerImages.VLLM_CPU,
551- # container_resources={
552- # "limits": {"cpu": "2", "memory": "12Gi"},
553- # "requests": {"cpu": "1", "memory": "8Gi"},
554- # },
555- # service_account=model_service_account.name,
556- # wait=True,
557- # timeout=Timeout.TIMEOUT_15MIN,
558- # ) as llm_service,
559- # patch_llmisvc_with_maas_router(llm_service=llm_service),
560- # ):
561- # llmd_instance = llm_service.instance
562- # model_spec = llmd_instance.spec.model
563-
564- # storage_uri = model_spec.uri
565- # assert storage_uri == ModelStorage.TINYLLAMA_S3, (
566- # f"Unexpected storage_uri on TinyLlama LLMInferenceService: {storage_uri}"
567- # )
568-
569- # status = llmd_instance.status
570- # conditions = {condition.type: condition.status for condition in status.conditions}
571- # assert conditions.get("Ready") == "True", f"TinyLlama LLMInferenceService not Ready, conditions={conditions}"
572-
573- # LOGGER.info(
574- # f"MaaS: TinyLlama S3 LLMInferenceService "
575- # f"{llm_service.namespace}/{llm_service.name} "
576- # f"is Ready with storage_uri={storage_uri}"
577- # )
578-
579- # yield llm_service
580-
581- # LOGGER.info(
582- # f"MaaS: TinyLlama S3 LLMInferenceService "
583- # f"{llm_service.namespace}/{llm_service.name} "
584- # f"will be deleted at teardown"
585- # )
586-
587- # @pytest.fixture(scope="class")
588- # def maas_inference_service_tinyllama(
589- # admin_client: DynamicClient,
590- # unprivileged_model_namespace: Namespace,
591- # model_service_account: ServiceAccount,
592- # ) -> Generator[LLMInferenceService, None, None]:
593- # """
594- # TinyLlama S3-backed LLMInferenceService wired through MaaS for tests.
595- # """
596- # with create_llmisvc(
597- # client=admin_client,
598- # name="llm-s3-tinyllama",
599- # namespace=unprivileged_model_namespace.name,
600- # storage_uri=ModelStorage.TINYLLAMA_S3,
601- # container_image=ContainerImages.VLLM_CPU,
602- # container_resources={
603- # "limits": {"cpu": "2", "memory": "12Gi"},
604- # "requests": {"cpu": "1", "memory": "8Gi"},
605- # },
606- # service_account=model_service_account.name,
607- # wait=False, # 🔴 IMPORTANT CHANGE
608- # timeout=Timeout.TIMEOUT_15MIN,
609- # ) as llm_service:
610-
611- # # ✅ Patch IMMEDIATELY
612- # with patch_llmisvc_with_maas_router(llm_service=llm_service):
613-
614- # # Now wait for readiness AFTER patch
615- # llm_service.wait_for_condition(
616- # condition="Ready",
617- # status="True",
618- # timeout=Timeout.TIMEOUT_15MIN,
619- # )
620-
621- # # llm_service.refresh()
622-
623- # LOGGER.info(
624- # "MaaS: TinyLlama LLMI %s/%s Ready and patched",
625- # llm_service.namespace,
626- # llm_service.name,
627- # )
628-
629- # yield llm_service
630542@pytest .fixture (scope = "class" )
631543def maas_inference_service_tinyllama (
632544 admin_client : DynamicClient ,
633545 unprivileged_model_namespace : Namespace ,
634546 model_service_account : ServiceAccount ,
547+ maas_control_plane_namespace : str ,
548+ maas_gateway_and_policies ,
635549) -> Generator [LLMInferenceService , None , None ]:
636550 """
637551 TinyLlama S3-backed LLMInferenceService wired through MaaS for tests.
@@ -647,18 +561,15 @@ def maas_inference_service_tinyllama(
647561 "requests" : {"cpu" : "1" , "memory" : "8Gi" },
648562 },
649563 service_account = model_service_account .name ,
650- wait = False ,
564+ wait = False ,
651565 timeout = Timeout .TIMEOUT_15MIN ,
652566 ) as llm_service :
653-
654- # Patch immediately so the controller creates HTTPRoute on MaaS gateway
655- with patch_llmisvc_with_maas_router (llm_service = llm_service ):
656-
567+ with patch_llmisvc_with_maas_router (
568+ llm_service = llm_service ,
569+ ):
657570 inst = llm_service .instance
658571 storage_uri = inst .spec .model .uri
659- assert storage_uri == ModelStorage .TINYLLAMA_S3 , (
660- f"Unexpected storage_uri on TinyLlama LLMI: { storage_uri } "
661- )
572+ assert storage_uri == ModelStorage .TINYLLAMA_S3 , f"Unexpected storage_uri on TinyLlama LLMI: { storage_uri } "
662573
663574 llm_service .wait_for_condition (
664575 condition = "Ready" ,
@@ -673,16 +584,14 @@ def maas_inference_service_tinyllama(
673584
674585 yield llm_service
675586
587+
676588@pytest .fixture (scope = "class" )
677589def maas_scheme (admin_client : DynamicClient , unprivileged_model_namespace : Namespace ) -> str :
678590 return detect_scheme_via_llmisvc (
679591 client = admin_client ,
680592 namespace = unprivileged_model_namespace .name ,
681593 )
682594
683- # @pytest.fixture(scope="class")
684- # def maas_scheme() -> str:
685- # return "https"
686595
687596@pytest .fixture (scope = "class" )
688597def maas_host (admin_client ):
@@ -693,6 +602,7 @@ def maas_host(admin_client):
693602def maas_gateway_rate_limits (
694603 admin_client : DynamicClient ,
695604 maas_gateway_and_policies ,
605+ maas_tier_mapping_cm ,
696606) -> Generator [None , None , None ]:
697607 with maas_gateway_rate_limits_patched (
698608 admin_client = admin_client ,
@@ -702,6 +612,7 @@ def maas_gateway_rate_limits(
702612 ):
703613 yield
704614
615+
705616@pytest .fixture (scope = "session" )
706617def maas_gateway_api_hostname (admin_client : DynamicClient ) -> str :
707618 return host_from_ingress_domain (client = admin_client )
@@ -711,7 +622,7 @@ def maas_gateway_api_hostname(admin_client: DynamicClient) -> str:
711622def maas_gateway_and_policies (
712623 admin_client : DynamicClient ,
713624 maas_gateway_api_hostname : str ,
714- # maas_controller_enabled ,
625+ maas_controller_enabled_latest ,
715626) -> Generator [None , None , None ]:
716627 """
717628 Ensure MaaS Gateway + Kuadrant policies exist once per test session.
@@ -722,38 +633,49 @@ def maas_gateway_and_policies(
722633 ):
723634 yield
724635
725- # @pytest.fixture(scope="session")
726- # def maas_controller_enabled(admin_client):
727- # """
728- # Enable MaaS controller via DataScienceCluster component toggle.
729- # Fails fast if the MaaS DSC component key is not present.
730- # """
731- # data_science_cluster = DataScienceCluster(client=admin_client, name=DSC_NAME)
732- # data_science_cluster.get()
733-
734- # components_section = (data_science_cluster.instance.get("spec") or {}).get("components") or {}
735- # if MAAS_DSC_COMPONENT_KEY not in components_section:
736- # raise RuntimeError(
737- # f"MaaS tests require DSC component '{MAAS_DSC_COMPONENT_KEY}', but it is missing. "
738- # f"Available DSC components: {sorted(list(components_section.keys()))}"
739- # )
740-
741- # current_component_state = (
742- # (components_section.get(MAAS_DSC_COMPONENT_KEY) or {}).get("managementState")
743- # )
744- # if current_component_state == "Managed":
745- # wait_for_data_science_cluster_ready(data_science_cluster=data_science_cluster)
746- # yield
747- # return
748-
749- # patch_body = {
750- # "spec": {
751- # "components": {
752- # MAAS_DSC_COMPONENT_KEY: {"managementState": "Managed"},
753- # }
754- # }
755- # }
756-
757- # with ResourceEditor(patches={data_science_cluster: patch_body}):
758- # wait_for_data_science_cluster_ready(data_science_cluster=data_science_cluster)
759- # yield
636+
637+ @pytest .fixture (scope = "session" )
638+ def maas_controller_enabled_latest (admin_client : DynamicClient ):
639+ dsc_resource = get_data_science_cluster (client = admin_client )
640+ dsc_resource .get ()
641+
642+ original_components = dsc_resource .instance .spec .components
643+
644+ kserve = original_components .get ("kserve" ) or {}
645+ maas = kserve .get ("modelsAsService" ) or {}
646+ if (maas .get ("managementState" ) or "Removed" ) == "Managed" :
647+ dsc_resource .wait_for_condition (condition = "ModelsAsServiceReady" , status = "True" , timeout = Timeout .TIMEOUT_15MIN )
648+ yield dsc_resource
649+ return
650+
651+ component_patch = {"kserve" : {"modelsAsService" : {"managementState" : "Managed" }}}
652+
653+ with ResourceEditor (patches = {dsc_resource : {"spec" : {"components" : component_patch }}}):
654+ dsc_resource .wait_for_condition (condition = "ModelsAsServiceReady" , status = "True" , timeout = Timeout .TIMEOUT_15MIN )
655+ dsc_resource .wait_for_condition (condition = "Ready" , status = "True" , timeout = Timeout .TIMEOUT_15MIN )
656+ yield dsc_resource
657+
658+
659+ @pytest .fixture (scope = "session" )
660+ def maas_control_plane_namespace (admin_client : DynamicClient ) -> str :
661+ return detect_maas_control_plane_namespace (admin_client = admin_client )
662+
663+
664+ @pytest .fixture (scope = "session" )
665+ def maas_tier_mapping_cm (
666+ admin_client : DynamicClient ,
667+ maas_control_plane_namespace : str ,
668+ ):
669+ """
670+ Ensure MaaS tier mapping ConfigMap is present and readable.
671+ """
672+ config_map = get_tier_mapping_configmap (
673+ admin_client = admin_client ,
674+ namespace = maas_control_plane_namespace ,
675+ )
676+
677+ LOGGER .info (
678+ f"MaaS tier mapping ConfigMap detected: namespace={ maas_control_plane_namespace } , name={ config_map .name } "
679+ )
680+
681+ return config_map
0 commit comments