Skip to content

Commit c8db8ac

Browse files
Upgrade support for custom MC scenario (#736)
* Upgrade support for custom MC scenario * updates! 2c9819d * Add custom catalog tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Address review comments --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent e01a5a3 commit c8db8ac

19 files changed

+1135
-986
lines changed

conftest.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,17 @@ def _add_upgrade_test(_item: Item, _upgrade_deployment_modes: list[str]) -> bool
247247
# Add support to be able to reuse tests in both upgrade and fresh install scenarios
248248
if "install" in item.keywords:
249249
non_upgrade_tests.append(item)
250-
250+
if "post_upgrade" in item.keywords:
251+
post_upgrade_tests.append(item)
251252
elif "post_upgrade" in item.keywords and _add_upgrade_test(
252253
_item=item, _upgrade_deployment_modes=upgrade_deployment_modes
253254
):
254255
post_upgrade_tests.append(item)
255256
# Add support to be able to reuse tests in both upgrade and fresh install scenarios
256257
if "install" in item.keywords:
257258
non_upgrade_tests.append(item)
258-
259+
if "pre_upgrade" in item.keywords:
260+
pre_upgrade_tests.append(item)
259261
else:
260262
non_upgrade_tests.append(item)
261263

tests/model_registry/conftest.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from ocp_resources.infrastructure import Infrastructure
1414
from ocp_resources.oauth import OAuth
1515
from ocp_resources.pod import Pod
16+
from ocp_resources.route import Route
1617
from ocp_resources.secret import Secret
1718
from ocp_resources.namespace import Namespace
1819
from ocp_resources.service import Service
@@ -43,6 +44,7 @@
4344
DB_RESOURCE_NAME,
4445
MR_INSTANCE_NAME,
4546
MODEL_REGISTRY_POD_FILTER,
47+
DEFAULT_CUSTOM_MODEL_CATALOG,
4648
KUBERBACPROXY_STR,
4749
)
4850
from utilities.constants import Labels, Protocols
@@ -591,3 +593,28 @@ def user_credentials_rbac() -> dict[str, str]:
591593
"idp_name": f"test-htpasswd-idp-{random_str}",
592594
"secret_name": f"test-htpasswd-secret-{random_str}",
593595
}
596+
597+
598+
@pytest.fixture(scope="class")
599+
def catalog_config_map(admin_client: DynamicClient, model_registry_namespace: str) -> ConfigMap:
600+
return ConfigMap(name=DEFAULT_CUSTOM_MODEL_CATALOG, client=admin_client, namespace=model_registry_namespace)
601+
602+
603+
@pytest.fixture(scope="class")
604+
def model_catalog_routes(admin_client: DynamicClient, model_registry_namespace: str) -> list[Route]:
605+
return list(
606+
Route.get(namespace=model_registry_namespace, label_selector="component=model-catalog", dyn_client=admin_client)
607+
)
608+
609+
610+
@pytest.fixture(scope="class")
611+
def model_catalog_rest_url(model_registry_namespace: str, model_catalog_routes: list[Route]) -> list[str]:
612+
assert model_catalog_routes, f"Model catalog routes does not exist in {model_registry_namespace}"
613+
route_urls = [
614+
f"https://{route.instance.spec.host}:443/api/model_catalog/v1alpha1/" for route in model_catalog_routes
615+
]
616+
assert route_urls, (
617+
"Model catalog routes information could not be found from "
618+
f"routes:{[route.name for route in model_catalog_routes]}"
619+
)
620+
return route_urls

tests/model_registry/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,7 @@ class ModelRegistryEndpoints:
6565
}
6666
MODEL_REGISTRY_POD_FILTER: str = "component=model-registry"
6767
DEFAULT_CUSTOM_MODEL_CATALOG: str = "model-catalog-sources"
68+
SAMPLE_MODEL_NAME1 = "mistralai/Mistral-7B-Instruct-v0.3"
69+
CUSTOM_CATALOG_ID1: str = "sample_custom_catalog1"
6870
DEFAULT_MODEL_CATALOG_CM: str = "model-catalog-default-sources"
6971
KUBERBACPROXY_STR: str = "KubeRBACProxyAvailable"

tests/model_registry/model_catalog/conftest.py

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,29 @@
1010
from ocp_resources.config_map import ConfigMap
1111
from ocp_resources.resource import ResourceEditor
1212

13-
from ocp_resources.route import Route
1413
from ocp_resources.service_account import ServiceAccount
15-
from tests.model_registry.constants import DEFAULT_CUSTOM_MODEL_CATALOG
1614
from tests.model_registry.model_catalog.constants import (
1715
SAMPLE_MODEL_NAME3,
18-
CUSTOM_CATALOG_ID1,
1916
DEFAULT_CATALOG_FILE,
2017
CATALOG_CONTAINER,
2118
REDHAT_AI_CATALOG_ID,
2219
)
23-
from tests.model_registry.model_catalog.utils import (
20+
from tests.model_registry.constants import CUSTOM_CATALOG_ID1
21+
from tests.model_registry.utils import (
22+
get_rest_headers,
2423
is_model_catalog_ready,
24+
get_model_catalog_pod,
2525
wait_for_model_catalog_api,
26-
get_model_str,
2726
execute_get_command,
28-
get_model_catalog_pod,
27+
get_model_str,
2928
)
30-
from tests.model_registry.utils import get_rest_headers
3129
from utilities.infra import get_openshift_token, login_with_user_password, create_inference_token
3230
from utilities.user_utils import UserTestSession
3331

3432

3533
LOGGER = get_logger(name=__name__)
3634

3735

38-
@pytest.fixture(scope="class")
39-
def catalog_config_map(admin_client: DynamicClient, model_registry_namespace: str) -> ConfigMap:
40-
return ConfigMap(name=DEFAULT_CUSTOM_MODEL_CATALOG, client=admin_client, namespace=model_registry_namespace)
41-
42-
4336
@pytest.fixture(scope="class")
4437
def model_catalog_config_map(
4538
request: pytest.FixtureRequest, admin_client: DynamicClient, model_registry_namespace: str
@@ -50,26 +43,6 @@ def model_catalog_config_map(
5043
return ConfigMap(name=configmap_name, client=admin_client, namespace=model_registry_namespace, ensure_exists=True)
5144

5245

53-
@pytest.fixture(scope="class")
54-
def model_catalog_routes(admin_client: DynamicClient, model_registry_namespace: str) -> list[Route]:
55-
return list(
56-
Route.get(namespace=model_registry_namespace, label_selector="component=model-catalog", dyn_client=admin_client)
57-
)
58-
59-
60-
@pytest.fixture(scope="class")
61-
def model_catalog_rest_url(model_registry_namespace: str, model_catalog_routes: list[Route]) -> list[str]:
62-
assert model_catalog_routes, f"Model catalog routes does not exist in {model_registry_namespace}"
63-
route_urls = [
64-
f"https://{route.instance.spec.host}:443/api/model_catalog/v1alpha1/" for route in model_catalog_routes
65-
]
66-
assert route_urls, (
67-
"Model catalog routes information could not be found from "
68-
f"routes:{[route.name for route in model_catalog_routes]}"
69-
)
70-
return route_urls
71-
72-
7346
@pytest.fixture(scope="class")
7447
def updated_catalog_config_map(
7548
request: pytest.FixtureRequest,

tests/model_registry/model_catalog/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from typing import Any
22

3-
CUSTOM_CATALOG_ID1: str = "sample_custom_catalog1"
3+
from tests.model_registry.constants import SAMPLE_MODEL_NAME1, CUSTOM_CATALOG_ID1
4+
45
CUSTOM_CATALOG_ID2: str = "sample_custom_catalog2"
5-
SAMPLE_MODEL_NAME1 = "mistralai/Mistral-7B-Instruct-v0.3"
66

77
SAMPLE_MODEL_NAME2 = "mistralai/Devstral-Small-2505"
88
EXPECTED_CUSTOM_CATALOG_VALUES: list[dict[str, str]] = [{"id": CUSTOM_CATALOG_ID1, "model_name": SAMPLE_MODEL_NAME1}]

tests/model_registry/model_catalog/test_custom_model_catalog.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
from tests.model_registry.model_catalog.constants import (
22
EXPECTED_CUSTOM_CATALOG_VALUES,
3-
CUSTOM_CATALOG_ID1,
4-
SAMPLE_MODEL_NAME1,
53
CUSTOM_CATALOG_ID2,
64
SAMPLE_MODEL_NAME2,
75
MULTIPLE_CUSTOM_CATALOG_VALUES,
86
SAMPLE_MODEL_NAME3,
97
)
8+
from tests.model_registry.constants import SAMPLE_MODEL_NAME1, CUSTOM_CATALOG_ID1
109
from ocp_resources.config_map import ConfigMap
1110
import pytest
1211
from simple_logger.logger import get_logger
1312
from typing import Self
13+
from kubernetes.dynamic.exceptions import ResourceNotFoundError
1414

15-
from tests.model_registry.model_catalog.utils import (
15+
from tests.model_registry.utils import (
1616
execute_get_command,
17-
get_catalog_str,
1817
get_sample_yaml_str,
19-
ResourceNotFoundError,
18+
get_catalog_str,
19+
validate_model_catalog_sources,
2020
)
2121

2222
LOGGER = get_logger(name=__name__)
@@ -32,6 +32,7 @@
3232
},
3333
EXPECTED_CUSTOM_CATALOG_VALUES,
3434
id="test_file_test_catalog",
35+
marks=(pytest.mark.pre_upgrade, pytest.mark.post_upgrade, pytest.mark.install),
3536
),
3637
pytest.param(
3738
{
@@ -62,15 +63,10 @@ def test_model_custom_catalog_list_sources(
6263
"""
6364
Validate sources api for model catalog
6465
"""
65-
url = f"{model_catalog_rest_url[0]}sources"
66-
results = execute_get_command(
67-
url=url,
68-
headers=model_registry_rest_headers,
69-
)["items"]
70-
ids_from_query = [result_entry["id"] for result_entry in results]
71-
ids_expected = [expected_entry["id"] for expected_entry in expected_catalog_values]
72-
assert set(ids_expected).issubset(set(ids_from_query)), (
73-
f"Expected model catalogs: {expected_catalog_values}. Actual model catalogs: {results}"
66+
validate_model_catalog_sources(
67+
model_catalog_sources_url=f"{model_catalog_rest_url[0]}sources",
68+
rest_headers=model_registry_rest_headers,
69+
expected_catalog_values=expected_catalog_values,
7470
)
7571

7672
def test_model_custom_catalog_get_models_by_source(

tests/model_registry/model_catalog/test_default_model_catalog.py

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pytest
22
import random
3+
4+
import yaml
35
from kubernetes.dynamic import DynamicClient
46
from dictdiffer import diff
57
from ocp_resources.deployment import Deployment
@@ -10,18 +12,17 @@
1012
from ocp_resources.config_map import ConfigMap
1113
from ocp_resources.route import Route
1214
from ocp_resources.service import Service
15+
1316
from tests.model_registry.constants import DEFAULT_CUSTOM_MODEL_CATALOG, DEFAULT_MODEL_CATALOG_CM
14-
from tests.model_registry.model_catalog.constants import REDHAT_AI_CATALOG_ID, CATALOG_CONTAINER
17+
from tests.model_registry.model_catalog.constants import REDHAT_AI_CATALOG_ID, CATALOG_CONTAINER, DEFAULT_CATALOGS
1518
from tests.model_registry.model_catalog.utils import (
1619
validate_model_catalog_enabled,
17-
execute_get_command,
1820
validate_model_catalog_resource,
1921
get_validate_default_model_catalog_source,
2022
extract_schema_fields,
21-
get_model_catalog_pod,
22-
validate_model_catalog_configmap_data,
23+
validate_default_catalog,
2324
)
24-
from tests.model_registry.utils import get_rest_headers
25+
from tests.model_registry.utils import get_rest_headers, get_model_catalog_pod, execute_get_command
2526
from utilities.user_utils import UserTestSession
2627

2728
LOGGER = get_logger(name=__name__)
@@ -36,23 +37,41 @@
3637
@pytest.mark.skip_must_gather
3738
class TestModelCatalogGeneral:
3839
@pytest.mark.parametrize(
39-
"model_catalog_config_map, expected_catalogs",
40+
"model_catalog_config_map, expected_catalogs, validate_catalog",
4041
[
4142
pytest.param(
4243
{"configmap_name": DEFAULT_CUSTOM_MODEL_CATALOG},
4344
0,
44-
id="test_model_catalog_sources_configmap",
45+
False,
46+
id="test_model_catalog_sources_configmap_install",
47+
marks=pytest.mark.install,
48+
),
49+
pytest.param(
50+
{"configmap_name": DEFAULT_CUSTOM_MODEL_CATALOG},
51+
1,
52+
False,
53+
id="test_model_catalog_sources_configmap_upgrade",
54+
marks=(pytest.mark.pre_upgrade, pytest.mark.post_upgrade),
4555
),
4656
pytest.param(
4757
{"configmap_name": DEFAULT_MODEL_CATALOG_CM},
4858
2,
59+
True,
4960
id="test_model_catalog_default_sources_configmap",
5061
),
5162
],
5263
indirect=["model_catalog_config_map"],
5364
)
54-
def test_config_map_exists(self: Self, model_catalog_config_map: ConfigMap, expected_catalogs: int):
55-
validate_model_catalog_configmap_data(configmap=model_catalog_config_map, num_catalogs=expected_catalogs)
65+
def test_config_map_exists(
66+
self: Self, model_catalog_config_map: ConfigMap, expected_catalogs: int, validate_catalog: bool
67+
) -> None:
68+
assert model_catalog_config_map.exists, f"{model_catalog_config_map.name} does not exist"
69+
catalogs = yaml.safe_load(model_catalog_config_map.instance.data["sources.yaml"])["catalogs"]
70+
assert len(catalogs) == expected_catalogs, (
71+
f"{model_catalog_config_map.name} should have {expected_catalogs} catalog"
72+
)
73+
if validate_catalog:
74+
validate_default_catalog(catalogs=catalogs)
5675

5776
@pytest.mark.parametrize(
5877
"resource_name, expected_resource_count",
@@ -80,6 +99,7 @@ def test_config_map_exists(self: Self, model_catalog_config_map: ConfigMap, expe
8099
],
81100
)
82101
@pytest.mark.post_upgrade
102+
@pytest.mark.pre_upgrade
83103
@pytest.mark.install
84104
def test_model_catalog_resources_exists(
85105
self: Self,
@@ -95,9 +115,15 @@ def test_model_catalog_resources_exists(
95115
expected_resource_count=expected_resource_count,
96116
)
97117

118+
@pytest.mark.post_upgrade
119+
@pytest.mark.pre_upgrade
120+
@pytest.mark.install
98121
def test_operator_pod_enabled_model_catalog(self: Self, model_registry_operator_pod: Pod):
99122
assert validate_model_catalog_enabled(pod=model_registry_operator_pod)
100123

124+
@pytest.mark.post_upgrade
125+
@pytest.mark.pre_upgrade
126+
@pytest.mark.install
101127
def test_model_catalog_uses_postgres(self: Self, admin_client: DynamicClient, model_registry_namespace: str):
102128
"""
103129
Validate that model catalog pod is using PostgreSQL database
@@ -119,6 +145,7 @@ def test_model_catalog_uses_postgres(self: Self, admin_client: DynamicClient, mo
119145
pytest.param(
120146
{},
121147
id="test_model_catalog_source_admin_user",
148+
marks=(pytest.mark.pre_upgrade, pytest.mark.post_upgrade, pytest.mark.install),
122149
),
123150
pytest.param(
124151
{"user_type": "test"},
@@ -134,16 +161,29 @@ def test_model_catalog_uses_postgres(self: Self, admin_client: DynamicClient, mo
134161
class TestModelCatalogDefault:
135162
def test_model_catalog_default_catalog_sources(
136163
self,
164+
pytestconfig: pytest.Config,
137165
test_idp_user: UserTestSession,
138166
model_catalog_rest_url: list[str],
139167
user_token_for_api_calls: str,
140168
):
141169
"""
142170
Validate specific user can access default model catalog source
143171
"""
144-
get_validate_default_model_catalog_source(
145-
token=user_token_for_api_calls, model_catalog_url=f"{model_catalog_rest_url[0]}sources"
146-
)
172+
LOGGER.info("Attempting client connection with token")
173+
result = execute_get_command(
174+
url=f"{model_catalog_rest_url[0]}sources",
175+
headers=get_rest_headers(token=user_token_for_api_calls),
176+
)["items"]
177+
assert result
178+
items_to_validate = []
179+
if pytestconfig.option.pre_upgrade or pytestconfig.option.post_upgrade:
180+
for catalog in result:
181+
if catalog["id"] in DEFAULT_CATALOGS.keys():
182+
items_to_validate.append(catalog)
183+
assert len(items_to_validate) + 1 == len(result)
184+
else:
185+
items_to_validate = result
186+
get_validate_default_model_catalog_source(catalogs=items_to_validate)
147187

148188
def test_model_default_catalog_get_models_by_source(
149189
self: Self,
@@ -191,6 +231,9 @@ def test_model_default_catalog_get_model_artifact(
191231
assert result[0]["uri"]
192232

193233

234+
@pytest.mark.post_upgrade
235+
@pytest.mark.pre_upgrade
236+
@pytest.mark.install
194237
@pytest.mark.skip_must_gather
195238
class TestModelCatalogDefaultData:
196239
"""Test class for validating default catalog data (not user-specific)"""

tests/model_registry/model_catalog/test_filter_options_endpoint.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from typing import Self
33
from simple_logger.logger import get_logger
44

5-
from tests.model_registry.model_catalog.utils import execute_get_command, validate_filter_options_structure
6-
from tests.model_registry.utils import get_rest_headers
5+
from tests.model_registry.model_catalog.utils import validate_filter_options_structure
6+
from tests.model_registry.utils import get_rest_headers, execute_get_command
77
from utilities.user_utils import UserTestSession
88

99
LOGGER = get_logger(name=__name__)

tests/model_registry/model_catalog/test_model_catalog_negative.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
from ocp_resources.resource import ResourceEditor
1010
from tests.model_registry.constants import DEFAULT_MODEL_CATALOG_CM
1111
from tests.model_registry.model_catalog.constants import DEFAULT_CATALOGS, CATALOG_CONTAINER
12-
from tests.model_registry.model_catalog.utils import validate_model_catalog_configmap_data, is_model_catalog_ready
13-
from tests.model_registry.utils import get_model_catalog_pod
12+
from tests.model_registry.model_catalog.utils import validate_model_catalog_configmap_data
13+
from tests.model_registry.utils import get_model_catalog_pod, is_model_catalog_ready
1414
from timeout_sampler import TimeoutExpiredError
1515

1616
from utilities.general import wait_for_container_status

tests/model_registry/model_catalog/test_model_search.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
REDHAT_AI_CATALOG_ID,
1010
VALIDATED_CATALOG_ID,
1111
)
12-
from tests.model_registry.model_catalog.utils import (
12+
from tests.model_registry.utils import (
1313
execute_get_command,
1414
)
1515

0 commit comments

Comments
 (0)