Skip to content

Commit 26c111d

Browse files
authored
Merge branch '2.25' into 2.25
2 parents 7d14e7d + ccf2477 commit 26c111d

File tree

22 files changed

+357
-180
lines changed

22 files changed

+357
-180
lines changed

conftest.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,14 +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)
259+
if "pre_upgrade" in item.keywords:
260+
pre_upgrade_tests.append(item)
258261
else:
259262
non_upgrade_tests.append(item)
260263

tests/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import Any, Callable, Generator
66

77
import pytest
8+
from semver import Version
89
import shortuuid
910
import yaml
1011
from _pytest._py.path import LocalPath
@@ -13,6 +14,7 @@
1314
from kubernetes.dynamic.exceptions import ResourceNotFoundError
1415

1516
from ocp_resources.cluster_service_version import ClusterServiceVersion
17+
from ocp_resources.cluster_version import ClusterVersion
1618
from ocp_resources.config_map import ConfigMap
1719
from ocp_resources.deployment import Deployment
1820
from ocp_resources.dsc_initialization import DSCInitialization
@@ -629,6 +631,20 @@ def bin_directory_to_os_path(os_path_environment: str, bin_directory: LocalPath,
629631
os.environ["PATH"] = f"{bin_directory}:{os_path_environment}"
630632

631633

634+
@pytest.fixture(scope="session")
635+
def openshift_version(admin_client: DynamicClient) -> Version:
636+
"""Get the OpenShift cluster version."""
637+
cluster_version = ClusterVersion(client=admin_client, name="version", ensure_exists=True)
638+
639+
if not cluster_version.instance.status.history:
640+
raise ValueError("ClusterVersion history is empty")
641+
642+
try:
643+
return Version.parse(version=str(cluster_version.instance.status.history[0].version))
644+
except (ValueError, TypeError) as e:
645+
raise ValueError(f"Failed to parse OpenShift version: {e}") from e
646+
647+
632648
@pytest.fixture(scope="session")
633649
def oc_binary_path(bin_directory: LocalPath) -> str:
634650
installed_oc_binary_path = os.getenv("OC_BINARY_PATH")

tests/llama_stack/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from ocp_resources.deployment import Deployment
1111
from ocp_resources.llama_stack_distribution import LlamaStackDistribution
1212
from ocp_resources.namespace import Namespace
13+
from semver import Version
1314
from simple_logger.logger import get_logger
1415
from utilities.general import generate_random_name
1516
from tests.llama_stack.utils import (
@@ -19,6 +20,7 @@
1920
from utilities.constants import DscComponents, Timeout
2021
from utilities.data_science_cluster_utils import update_components_in_dsc
2122
from tests.llama_stack.constants import (
23+
LLS_OPENSHIFT_MINIMAL_VERSION,
2224
ModelInfo,
2325
)
2426

@@ -216,6 +218,20 @@ def _get_llama_stack_distribution_deployment(
216218
yield deployment
217219

218220

221+
@pytest.fixture(scope="session", autouse=True)
222+
def skip_llama_stack_if_not_supported_openshift_version(
223+
admin_client: DynamicClient, openshift_version: Version
224+
) -> None:
225+
"""Skip llama-stack tests if OpenShift version is not supported (< 4.17) by llama-stack-operator"""
226+
if openshift_version < LLS_OPENSHIFT_MINIMAL_VERSION:
227+
message = (
228+
f"Skipping llama-stack tests, as llama-stack-operator is not supported "
229+
f"on OpenShift {openshift_version} ({LLS_OPENSHIFT_MINIMAL_VERSION} or newer required)"
230+
)
231+
LOGGER.info(message)
232+
pytest.skip(reason=message)
233+
234+
219235
@pytest.fixture(scope="class")
220236
def unprivileged_llama_stack_distribution_deployment(
221237
unprivileged_client: DynamicClient,

tests/llama_stack/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from enum import Enum
33
from typing import List, NamedTuple, TypedDict
44
from llama_stack_client.types import Model
5+
from semver import VersionInfo
6+
import semver
57

68

79
class LlamaStackProviders:
@@ -26,6 +28,7 @@ class ModelInfo(NamedTuple):
2628

2729

2830
LLS_CORE_POD_FILTER: str = "app=llama-stack"
31+
LLS_OPENSHIFT_MINIMAL_VERSION: VersionInfo = semver.VersionInfo.parse("4.17.0")
2932

3033

3134
class TurnExpectation(TypedDict):

tests/model_explainability/trustyai_service/conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ def mariadb(
208208
mariadb_dict["spec"]["username"] = DB_USERNAME
209209

210210
mariadb_dict["spec"]["replicas"] = 1
211+
212+
# Need to fix MariaDB version due to an issue with the default version in certain environments
213+
# Using the same registry and image used by the MariaDB operator
214+
# --just changing the tag to point to a stable version
215+
mariadb_dict["spec"]["image"] = "docker-registry1.mariadb.com/library/mariadb:10.11.8"
211216
mariadb_dict["spec"]["galera"]["enabled"] = False
212217
mariadb_dict["spec"]["metrics"]["enabled"] = False
213218
mariadb_dict["spec"]["tls"] = {"enabled": True, "required": True}

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_MODEL_CATALOG,
4648
)
4749
from utilities.constants import Labels, Protocols
4850
from tests.model_registry.utils import (
@@ -590,3 +592,28 @@ def user_credentials_rbac() -> dict[str, str]:
590592
"idp_name": f"test-htpasswd-idp-{random_str}",
591593
"secret_name": f"test-htpasswd-secret-{random_str}",
592594
}
595+
596+
597+
@pytest.fixture(scope="class")
598+
def model_catalog_rest_url(model_registry_namespace: str, model_catalog_routes: list[Route]) -> list[str]:
599+
assert model_catalog_routes, f"Model catalog routes does not exist in {model_registry_namespace}"
600+
route_urls = [
601+
f"https://{route.instance.spec.host}:443/api/model_catalog/v1alpha1/" for route in model_catalog_routes
602+
]
603+
assert route_urls, (
604+
"Model catalog routes information could not be found from "
605+
f"routes:{[route.name for route in model_catalog_routes]}"
606+
)
607+
return route_urls
608+
609+
610+
@pytest.fixture(scope="class")
611+
def catalog_config_map(admin_client: DynamicClient, model_registry_namespace: str) -> ConfigMap:
612+
return ConfigMap(name=DEFAULT_MODEL_CATALOG, client=admin_client, namespace=model_registry_namespace)
613+
614+
615+
@pytest.fixture(scope="class")
616+
def model_catalog_routes(admin_client: DynamicClient, model_registry_namespace: str) -> list[Route]:
617+
return list(
618+
Route.get(namespace=model_registry_namespace, label_selector="component=model-catalog", dyn_client=admin_client)
619+
)

tests/model_registry/constants.py

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

tests/model_registry/model_catalog/conftest.py

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import random
22
from typing import Generator, Any
3+
34
from simple_logger.logger import get_logger
45

56
import pytest
@@ -8,67 +9,47 @@
89
from ocp_resources.config_map import ConfigMap
910
from ocp_resources.resource import ResourceEditor
1011

11-
from ocp_resources.route import Route
1212
from ocp_resources.service_account import ServiceAccount
13-
from tests.model_registry.constants import DEFAULT_MODEL_CATALOG
14-
from tests.model_registry.model_catalog.constants import SAMPLE_MODEL_NAME3, CUSTOM_CATALOG_ID1, DEFAULT_CATALOG_ID
15-
from tests.model_registry.model_catalog.utils import (
13+
from tests.model_registry.constants import CUSTOM_CATALOG_ID1
14+
from tests.model_registry.model_catalog.constants import SAMPLE_MODEL_NAME3, DEFAULT_CATALOG_ID
15+
from tests.model_registry.utils import (
16+
get_rest_headers,
1617
is_model_catalog_ready,
1718
wait_for_model_catalog_api,
1819
get_model_str,
1920
execute_get_command,
21+
get_custom_model_catalog_cm_data,
2022
)
21-
from tests.model_registry.utils import get_rest_headers
2223
from utilities.infra import get_openshift_token, login_with_user_password, create_inference_token
2324
from utilities.user_utils import UserTestSession
2425

2526
LOGGER = get_logger(name=__name__)
2627

2728

28-
@pytest.fixture(scope="class")
29-
def catalog_config_map(admin_client: DynamicClient, model_registry_namespace: str) -> ConfigMap:
30-
return ConfigMap(name=DEFAULT_MODEL_CATALOG, client=admin_client, namespace=model_registry_namespace)
31-
32-
33-
@pytest.fixture(scope="class")
34-
def model_catalog_routes(admin_client: DynamicClient, model_registry_namespace: str) -> list[Route]:
35-
return list(
36-
Route.get(namespace=model_registry_namespace, label_selector="component=model-catalog", dyn_client=admin_client)
37-
)
38-
39-
40-
@pytest.fixture(scope="class")
41-
def model_catalog_rest_url(model_registry_namespace: str, model_catalog_routes: list[Route]) -> list[str]:
42-
assert model_catalog_routes, f"Model catalog routes does not exist in {model_registry_namespace}"
43-
route_urls = [
44-
f"https://{route.instance.spec.host}:443/api/model_catalog/v1alpha1/" for route in model_catalog_routes
45-
]
46-
assert route_urls, (
47-
"Model catalog routes information could not be found from "
48-
f"routes:{[route.name for route in model_catalog_routes]}"
49-
)
50-
return route_urls
51-
52-
5329
@pytest.fixture(scope="class")
5430
def updated_catalog_config_map(
31+
pytestconfig: pytest.Config,
5532
request: pytest.FixtureRequest,
5633
catalog_config_map: ConfigMap,
5734
model_registry_namespace: str,
5835
admin_client: DynamicClient,
5936
model_catalog_rest_url: list[str],
6037
model_registry_rest_headers: dict[str, str],
6138
) -> Generator[ConfigMap, None, None]:
62-
patches = {"data": {"sources.yaml": request.param["sources_yaml"]}}
63-
if "sample_yaml" in request.param:
64-
for key in request.param["sample_yaml"]:
65-
patches["data"][key] = request.param["sample_yaml"][key]
66-
67-
with ResourceEditor(patches={catalog_config_map: patches}):
39+
if pytestconfig.option.post_upgrade or pytestconfig.option.pre_upgrade:
40+
yield
41+
else:
42+
with ResourceEditor(
43+
patches={
44+
catalog_config_map: get_custom_model_catalog_cm_data(
45+
catalog_config_map=catalog_config_map, param=request.param
46+
)
47+
}
48+
):
49+
is_model_catalog_ready(client=admin_client, model_registry_namespace=model_registry_namespace)
50+
wait_for_model_catalog_api(url=model_catalog_rest_url[0], headers=model_registry_rest_headers)
51+
yield catalog_config_map
6852
is_model_catalog_ready(client=admin_client, model_registry_namespace=model_registry_namespace)
69-
wait_for_model_catalog_api(url=model_catalog_rest_url[0], headers=model_registry_rest_headers)
70-
yield catalog_config_map
71-
is_model_catalog_ready(client=admin_client, model_registry_namespace=model_registry_namespace)
7253

7354

7455
@pytest.fixture(scope="class")

tests/model_registry/model_catalog/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
CUSTOM_CATALOG_ID1: str = "sample_custom_catalog1"
1+
from tests.model_registry.constants import CUSTOM_CATALOG_ID1, SAMPLE_MODEL_NAME1
2+
23
CUSTOM_CATALOG_ID2: str = "sample_custom_catalog2"
3-
SAMPLE_MODEL_NAME1 = "mistralai/Mistral-7B-Instruct-v0.3"
44

55
SAMPLE_MODEL_NAME2 = "mistralai/Devstral-Small-2505"
66
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: 11 additions & 15 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 CUSTOM_CATALOG_ID1, SAMPLE_MODEL_NAME1
109
from ocp_resources.config_map import ConfigMap
1110
import pytest
1211
from simple_logger.logger import get_logger
1312
from typing import Self
1413

15-
from tests.model_registry.model_catalog.utils import (
16-
execute_get_command,
14+
from kubernetes.dynamic.exceptions import ResourceNotFoundError
15+
from tests.model_registry.utils import (
1716
get_catalog_str,
1817
get_sample_yaml_str,
19-
ResourceNotFoundError,
18+
execute_get_command,
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.install),
3536
),
3637
pytest.param(
3738
{
@@ -62,16 +63,11 @@ 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-
71-
assert len(results) == len(expected_catalog_values)
72-
ids_from_query = [result_entry["id"] for result_entry in results]
73-
ids_expected = [expected_entry["id"] for expected_entry in expected_catalog_values]
74-
assert sorted(ids_from_query) == sorted(ids_expected), f"Expected: {expected_catalog_values}. Actual: {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,
70+
)
7571

7672
def test_model_custom_catalog_get_models_by_source(
7773
self: Self,

0 commit comments

Comments
 (0)