|
19 | 19 | from kubernetes.dynamic import DynamicClient |
20 | 20 | from pytest_testconfig import config as py_config |
21 | 21 | from model_registry.types import RegisteredModel |
| 22 | +import uuid |
22 | 23 |
|
23 | 24 | from tests.model_registry.constants import ( |
24 | 25 | MR_OPERATOR_NAME, |
@@ -531,3 +532,239 @@ def model_registry_pod(admin_client: DynamicClient, model_registry_namespace: st |
531 | 532 | ) |
532 | 533 | assert len(mr_pod) == 1 |
533 | 534 | 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 |
0 commit comments