Skip to content

Commit 822f1ca

Browse files
Add MR RBAC test for multitenancy scenario (#446)
* feat: refactoring of fixtures, first test with refactored code Signed-off-by: lugi0 <lgiorgi@redhat.com> * fix: change wording slightly in guide Signed-off-by: lugi0 <lgiorgi@redhat.com> * fix: move classes to utils Signed-off-by: lugi0 <lgiorgi@redhat.com> * feat: add options in fixture handling Signed-off-by: lugi0 <lgiorgi@redhat.com> * feat: add test for RBAC multitenancy scenario Signed-off-by: lugi0 <lgiorgi@redhat.com> * fix: remove code not used Signed-off-by: lugi0 <lgiorgi@redhat.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Signed-off-by: lugi0 <lgiorgi@redhat.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 7c3a558 commit 822f1ca

4 files changed

Lines changed: 446 additions & 2 deletions

File tree

tests/model_registry/conftest.py

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from kubernetes.dynamic import DynamicClient
2020
from pytest_testconfig import config as py_config
2121
from model_registry.types import RegisteredModel
22+
import uuid
2223

2324
from tests.model_registry.constants import (
2425
MR_OPERATOR_NAME,
@@ -531,3 +532,239 @@ def model_registry_pod(admin_client: DynamicClient, model_registry_namespace: st
531532
)
532533
assert len(mr_pod) == 1
533534
return mr_pod[0]
535+
536+
537+
# =============================================================================
538+
# DUPLICATED RESOURCE FIXTURES
539+
# =============================================================================
540+
541+
542+
@pytest.fixture(scope="class")
543+
def db_name_1() -> str:
544+
"""Generate a unique name for the first DB instance."""
545+
return f"db-instance-1-{str(uuid.uuid4())[:8]}"
546+
547+
548+
@pytest.fixture(scope="class")
549+
def db_secret_1(model_registry_namespace: str, db_name_1: str, teardown_resources: bool) -> Generator[Secret, Any, Any]:
550+
"""Create the first DB secret."""
551+
with Secret(
552+
name=db_name_1,
553+
namespace=model_registry_namespace,
554+
string_data=MODEL_REGISTRY_DB_SECRET_STR_DATA,
555+
label=get_model_registry_db_label_dict(db_resource_name=db_name_1),
556+
annotations=MODEL_REGISTRY_DB_SECRET_ANNOTATIONS,
557+
teardown=teardown_resources,
558+
) as secret:
559+
yield secret
560+
561+
562+
@pytest.fixture(scope="class")
563+
def db_pvc_1(
564+
model_registry_namespace: str, db_name_1: str, teardown_resources: bool
565+
) -> Generator[PersistentVolumeClaim, Any, Any]:
566+
"""Create the first DB PVC."""
567+
with PersistentVolumeClaim(
568+
name=db_name_1,
569+
namespace=model_registry_namespace,
570+
accessmodes="ReadWriteOnce",
571+
size="5Gi",
572+
label=get_model_registry_db_label_dict(db_resource_name=db_name_1),
573+
teardown=teardown_resources,
574+
) as pvc:
575+
yield pvc
576+
577+
578+
@pytest.fixture(scope="class")
579+
def db_service_1(
580+
model_registry_namespace: str, db_name_1: str, teardown_resources: bool
581+
) -> Generator[Service, Any, Any]:
582+
"""Create the first DB service."""
583+
with Service(
584+
name=db_name_1,
585+
namespace=model_registry_namespace,
586+
ports=[{"name": "mysql", "port": 3306, "protocol": "TCP", "targetPort": 3306}],
587+
selector={"name": db_name_1},
588+
label=get_model_registry_db_label_dict(db_resource_name=db_name_1),
589+
teardown=teardown_resources,
590+
) as service:
591+
yield service
592+
593+
594+
@pytest.fixture(scope="class")
595+
def db_deployment_1(
596+
model_registry_namespace: str, db_name_1: str, teardown_resources: bool
597+
) -> Generator[Deployment, Any, Any]:
598+
"""Create the first DB deployment."""
599+
with Deployment(
600+
name=db_name_1,
601+
namespace=model_registry_namespace,
602+
template=get_model_registry_deployment_template_dict(secret_name=db_name_1, resource_name=db_name_1),
603+
label=get_model_registry_db_label_dict(db_resource_name=db_name_1),
604+
replicas=1,
605+
revision_history_limit=0,
606+
selector={"matchLabels": {"name": db_name_1}},
607+
strategy={"type": "Recreate"},
608+
wait_for_resource=True,
609+
teardown=teardown_resources,
610+
) as deployment:
611+
deployment.wait_for_replicas(deployed=True)
612+
yield deployment
613+
614+
615+
@pytest.fixture(scope="class")
616+
def model_registry_instance_1(
617+
db_name_1: str, model_registry_namespace: str, teardown_resources: bool, is_model_registry_oauth: bool
618+
) -> Generator[ModelRegistry, Any, Any]:
619+
"""Create the first Model Registry instance (default/oauth)."""
620+
mysql_config = {
621+
"host": f"{db_name_1}.{model_registry_namespace}.svc.cluster.local",
622+
"database": MODEL_REGISTRY_DB_SECRET_STR_DATA["database-name"],
623+
"passwordSecret": {"key": "database-password", "name": db_name_1},
624+
"port": 3306,
625+
"skipDBCreation": False,
626+
"username": MODEL_REGISTRY_DB_SECRET_STR_DATA["database-user"],
627+
}
628+
istio_config = None
629+
oauth_config = None
630+
mr_class_name = ModelRegistry
631+
if is_model_registry_oauth:
632+
LOGGER.warning("Requested Ouath Proxy configuration:")
633+
oauth_config = OAUTH_PROXY_CONFIG_DICT
634+
else:
635+
LOGGER.warning("Requested OSSM configuration:")
636+
istio_config = ISTIO_CONFIG_DICT
637+
mr_class_name = ModelRegistryV1Alpha1
638+
mr_name = f"mr-instance-1-{str(uuid.uuid4())[:8]}"
639+
with mr_class_name(
640+
name=mr_name,
641+
namespace=model_registry_namespace,
642+
grpc={},
643+
rest={},
644+
label=MODEL_REGISTRY_STANDARD_LABELS,
645+
istio=istio_config,
646+
oauth_proxy=oauth_config,
647+
mysql=mysql_config,
648+
wait_for_resource=True,
649+
teardown=teardown_resources,
650+
) as mr_instance:
651+
mr_instance.wait_for_condition(condition="Available", status="True")
652+
mr_instance.wait_for_condition(condition="OAuthProxyAvailable", status="True")
653+
yield mr_instance
654+
655+
656+
# --- Instance 2 Resources ---
657+
658+
659+
@pytest.fixture(scope="class")
660+
def db_name_2() -> str:
661+
"""Generate a unique name for the second DB instance."""
662+
return f"db-instance-2-{str(uuid.uuid4())[:8]}"
663+
664+
665+
@pytest.fixture(scope="class")
666+
def db_secret_2(model_registry_namespace: str, db_name_2: str, teardown_resources: bool) -> Generator[Secret, Any, Any]:
667+
"""Create the second DB secret."""
668+
with Secret(
669+
name=db_name_2,
670+
namespace=model_registry_namespace,
671+
string_data=MODEL_REGISTRY_DB_SECRET_STR_DATA,
672+
label=get_model_registry_db_label_dict(db_resource_name=db_name_2),
673+
annotations=MODEL_REGISTRY_DB_SECRET_ANNOTATIONS,
674+
teardown=teardown_resources,
675+
) as secret:
676+
yield secret
677+
678+
679+
@pytest.fixture(scope="class")
680+
def db_pvc_2(
681+
model_registry_namespace: str, db_name_2: str, teardown_resources: bool
682+
) -> Generator[PersistentVolumeClaim, Any, Any]:
683+
"""Create the second DB PVC."""
684+
with PersistentVolumeClaim(
685+
name=db_name_2,
686+
namespace=model_registry_namespace,
687+
accessmodes="ReadWriteOnce",
688+
size="5Gi",
689+
label=get_model_registry_db_label_dict(db_resource_name=db_name_2),
690+
teardown=teardown_resources,
691+
) as pvc:
692+
yield pvc
693+
694+
695+
@pytest.fixture(scope="class")
696+
def db_service_2(
697+
model_registry_namespace: str, db_name_2: str, teardown_resources: bool
698+
) -> Generator[Service, Any, Any]:
699+
"""Create the second DB service."""
700+
with Service(
701+
name=db_name_2,
702+
namespace=model_registry_namespace,
703+
ports=[{"name": "mysql", "port": 3306, "protocol": "TCP", "targetPort": 3306}],
704+
selector={"name": db_name_2},
705+
label=get_model_registry_db_label_dict(db_resource_name=db_name_2),
706+
teardown=teardown_resources,
707+
) as service:
708+
yield service
709+
710+
711+
@pytest.fixture(scope="class")
712+
def db_deployment_2(
713+
model_registry_namespace: str, db_name_2: str, teardown_resources: bool
714+
) -> Generator[Deployment, Any, Any]:
715+
"""Create the second DB deployment."""
716+
with Deployment(
717+
name=db_name_2,
718+
namespace=model_registry_namespace,
719+
template=get_model_registry_deployment_template_dict(secret_name=db_name_2, resource_name=db_name_2),
720+
label=get_model_registry_db_label_dict(db_resource_name=db_name_2),
721+
replicas=1,
722+
revision_history_limit=0,
723+
selector={"matchLabels": {"name": db_name_2}},
724+
strategy={"type": "Recreate"},
725+
wait_for_resource=True,
726+
teardown=teardown_resources,
727+
) as deployment:
728+
deployment.wait_for_replicas(deployed=True)
729+
yield deployment
730+
731+
732+
@pytest.fixture(scope="class")
733+
def model_registry_instance_2(
734+
model_registry_namespace: str, db_name_2: str, teardown_resources: bool, is_model_registry_oauth: bool
735+
) -> Generator[ModelRegistry, Any, Any]:
736+
"""Create the second Model Registry instance (istio)."""
737+
mysql_config = {
738+
"host": f"{db_name_2}.{model_registry_namespace}.svc.cluster.local",
739+
"database": MODEL_REGISTRY_DB_SECRET_STR_DATA["database-name"],
740+
"passwordSecret": {"key": "database-password", "name": db_name_2},
741+
"port": 3306,
742+
"skipDBCreation": False,
743+
"username": MODEL_REGISTRY_DB_SECRET_STR_DATA["database-user"],
744+
}
745+
istio_config = None
746+
oauth_config = None
747+
mr_class_name = ModelRegistry
748+
if is_model_registry_oauth:
749+
LOGGER.warning("Requested Ouath Proxy configuration:")
750+
oauth_config = OAUTH_PROXY_CONFIG_DICT
751+
else:
752+
LOGGER.warning("Requested OSSM configuration:")
753+
istio_config = ISTIO_CONFIG_DICT
754+
mr_class_name = ModelRegistryV1Alpha1
755+
mr_name = f"mr-instance-2-{str(uuid.uuid4())[:8]}"
756+
with mr_class_name(
757+
name=mr_name,
758+
namespace=model_registry_namespace,
759+
grpc={},
760+
rest={},
761+
label=MODEL_REGISTRY_STANDARD_LABELS,
762+
istio=istio_config,
763+
oauth_proxy=oauth_config,
764+
mysql=mysql_config,
765+
wait_for_resource=True,
766+
teardown=teardown_resources,
767+
) as mr_instance:
768+
mr_instance.wait_for_condition(condition="Available", status="True")
769+
mr_instance.wait_for_condition(condition="OAuthProxyAvailable", status="True")
770+
yield mr_instance

tests/model_registry/python_client/test_model_registry_creation.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
from simple_logger.logger import get_logger
44
from pytest_testconfig import config as py_config
55

6+
# ocp_resources imports
67
from ocp_resources.pod import Pod
8+
79
from tests.model_registry.utils import (
810
execute_model_registry_get_command,
911
validate_no_grpc_container,
@@ -14,6 +16,7 @@
1416
from model_registry import ModelRegistry as ModelRegistryClient
1517
from model_registry.types import RegisteredModel
1618

19+
1720
LOGGER = get_logger(name=__name__)
1821

1922
CUSTOM_NAMESPACE = "model-registry-custom-ns"

0 commit comments

Comments
 (0)