Skip to content

Commit 13c9529

Browse files
authored
Updates to image validation tests to ensure all ai hub resources are considered (#788)
1 parent 1f8a321 commit 13c9529

File tree

8 files changed

+113
-53
lines changed

8 files changed

+113
-53
lines changed

tests/model_registry/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,4 @@ class ModelRegistryEndpoints:
8080
Deployment: f"{MR_INSTANCE_NAME}-postgres",
8181
Secret: f"{MR_INSTANCE_NAME}-postgres-credentials",
8282
}
83+
MR_POSTGRES_DEPLOYMENT_NAME_STR = f"{MR_INSTANCE_NAME}-postgres"

tests/model_registry/image_validation/conftest.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,33 @@
22

33
import pytest
44
from kubernetes.dynamic import DynamicClient
5-
from pytest_testconfig import config as py_config
65

76
from ocp_resources.pod import Pod
8-
from tests.model_registry.constants import MODEL_REGISTRY_POD_FILTER
97
from utilities.general import wait_for_pods_by_labels
8+
from pytest import FixtureRequest
109

1110

12-
@pytest.fixture(scope="function")
13-
def model_registry_instance_pod_by_label(admin_client: DynamicClient) -> Generator[Pod, Any, Any]:
11+
@pytest.fixture(scope="class")
12+
def model_registry_instance_pods_by_label(
13+
request: FixtureRequest, admin_client: DynamicClient, model_registry_namespace: str
14+
) -> Generator[list[Pod], Any, Any]:
1415
"""Get the model registry instance pod."""
15-
yield wait_for_pods_by_labels(
16-
admin_client=admin_client,
17-
namespace=py_config["model_registry_namespace"],
18-
label_selector=MODEL_REGISTRY_POD_FILTER,
19-
expected_num_pods=1,
20-
)[0]
16+
pods = []
17+
for label in request.param["label_selectors"]:
18+
pods.append(
19+
wait_for_pods_by_labels(
20+
admin_client=admin_client,
21+
namespace=model_registry_namespace,
22+
label_selector=label,
23+
expected_num_pods=1,
24+
)[0]
25+
)
26+
yield pods
27+
28+
29+
@pytest.fixture(scope="function")
30+
def resource_pods(request: FixtureRequest, admin_client: DynamicClient) -> list[Pod]:
31+
namespace = request.param.get("namespace")
32+
label_selector = request.param.get("label_selector")
33+
assert namespace
34+
return list(Pod.get(namespace=namespace, label_selector=label_selector, dyn_client=admin_client))
Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,78 @@
1+
"""
2+
Tests to verify that all Model Registry component images (operator and instance container images)
3+
meet the requirements:
4+
1. Images are hosted in registry.redhat.io
5+
2. Images use sha256 digest instead of tags
6+
3. Images are listed in the CSV's relatedImages section
7+
"""
8+
19
import pytest
210
from typing import Self, Set
311
from simple_logger.logger import get_logger
412
from kubernetes.dynamic import DynamicClient
513

6-
from utilities.general import (
7-
validate_container_images,
8-
)
14+
from tests.model_registry.constants import MR_INSTANCE_NAME, MR_POSTGRES_DEPLOYMENT_NAME_STR, MR_OPERATOR_NAME
15+
from tests.model_registry.image_validation.utils import validate_images
16+
from utilities.constants import Labels
917
from ocp_resources.pod import Pod
10-
from tests.model_registry.utils import get_model_catalog_pod
18+
from pytest_testconfig import config as py_config
1119

1220
LOGGER = get_logger(name=__name__)
21+
pytestmark = [pytest.mark.downstream_only, pytest.mark.skip_must_gather, pytest.mark.smoke]
1322

1423

24+
class TestAIHubResourcesImages:
25+
@pytest.mark.parametrize(
26+
"resource_pods",
27+
[
28+
pytest.param(
29+
{"namespace": py_config["model_registry_namespace"], "label_selector": "component=model-catalog"},
30+
marks=pytest.mark.smoke,
31+
id="test_model_catalog_pods_images",
32+
),
33+
pytest.param(
34+
{
35+
"namespace": py_config["applications_namespace"],
36+
"label_selector": f"{Labels.OpenDataHubIo.NAME}={MR_OPERATOR_NAME}",
37+
},
38+
marks=pytest.mark.smoke,
39+
id="test_model_registry_operator_pods_images",
40+
),
41+
],
42+
indirect=True,
43+
)
44+
def test_verify_pod_images(
45+
self: Self,
46+
admin_client: DynamicClient,
47+
resource_pods: list[Pod],
48+
related_images_refs: Set[str],
49+
):
50+
validate_images(pods_to_validate=resource_pods, related_images_refs=related_images_refs)
51+
52+
53+
@pytest.mark.parametrize(
54+
"model_registry_metadata_db_resources, model_registry_instance, model_registry_instance_pods_by_label",
55+
[
56+
pytest.param({}, {}, {"label_selectors": [f"app={MR_INSTANCE_NAME}"]}),
57+
pytest.param(
58+
{"db_name": "default"},
59+
{"db_name": "default"},
60+
{"label_selectors": [f"app={MR_INSTANCE_NAME}", f"app={MR_POSTGRES_DEPLOYMENT_NAME_STR}"]},
61+
),
62+
],
63+
indirect=True,
64+
)
1565
@pytest.mark.usefixtures(
1666
"updated_dsc_component_state_scope_session",
17-
"model_registry_namespace",
1867
"model_registry_metadata_db_resources",
1968
"model_registry_instance",
69+
"model_registry_instance_pods_by_label",
2070
)
21-
@pytest.mark.downstream_only
2271
class TestModelRegistryImages:
23-
"""
24-
Tests to verify that all Model Registry component images (operator and instance container images)
25-
meet the requirements:
26-
1. Images are hosted in registry.redhat.io
27-
2. Images use sha256 digest instead of tags
28-
3. Images are listed in the CSV's relatedImages section
29-
"""
30-
31-
@pytest.mark.smoke
32-
@pytest.mark.skip_must_gather
33-
def test_verify_model_registry_images(
72+
def test_verify_model_registry_pod_images(
3473
self: Self,
3574
admin_client: DynamicClient,
36-
model_registry_operator_pod: Pod,
37-
model_registry_instance_pod_by_label: Pod,
38-
model_registry_namespace: str,
75+
model_registry_instance_pods_by_label: list[Pod],
3976
related_images_refs: Set[str],
4077
):
41-
model_catalog_pod = get_model_catalog_pod(
42-
client=admin_client, model_registry_namespace=model_registry_namespace
43-
)[0]
44-
validation_errors = []
45-
for pod in [model_registry_operator_pod, model_registry_instance_pod_by_label, model_catalog_pod]:
46-
validation_errors.extend(
47-
validate_container_images(
48-
pod=pod, valid_image_refs=related_images_refs, skip_patterns=["openshift-service-mesh"]
49-
)
50-
)
51-
52-
if validation_errors:
53-
pytest.fail("\n".join(validation_errors))
78+
validate_images(pods_to_validate=model_registry_instance_pods_by_label, related_images_refs=related_images_refs)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from typing import Set
2+
from simple_logger.logger import get_logger
3+
import pytest
4+
from ocp_resources.pod import Pod
5+
from utilities.general import validate_container_images
6+
7+
LOGGER = get_logger(name=__name__)
8+
9+
10+
def validate_images(pods_to_validate: list[Pod], related_images_refs: Set[str]):
11+
validation_errors = []
12+
for pod in pods_to_validate:
13+
LOGGER.info(f"Validating {pod.name} in {pod.namespace}")
14+
validation_errors.extend(
15+
validate_container_images(
16+
pod=pod,
17+
valid_image_refs=related_images_refs,
18+
)
19+
)
20+
21+
if validation_errors:
22+
pytest.fail("\n".join(validation_errors))

tests/model_registry/scc/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
from ocp_resources.namespace import Namespace
55
from ocp_resources.pod import Pod
66
from ocp_resources.deployment import Deployment
7-
from tests.model_registry.scc.constants import MR_POSTGRES_DEPLOYMENT_NAME_STR
87
from tests.model_registry.scc.utils import get_pod_by_deployment_name
9-
from tests.model_registry.constants import MR_INSTANCE_NAME
8+
from tests.model_registry.constants import MR_INSTANCE_NAME, MR_POSTGRES_DEPLOYMENT_NAME_STR
109

1110
from kubernetes.dynamic import DynamicClient
1211
from simple_logger.logger import get_logger
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
from tests.model_registry.constants import MR_INSTANCE_NAME
2-
31
MODEL_CATALOG_STR = "model-catalog"
4-
MR_POSTGRES_DEPLOYMENT_NAME_STR = f"{MR_INSTANCE_NAME}-postgres"

tests/model_registry/scc/test_model_registry_scc.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55

66
from ocp_resources.pod import Pod
77
from ocp_resources.deployment import Deployment
8-
from tests.model_registry.scc.constants import MR_POSTGRES_DEPLOYMENT_NAME_STR
98
from tests.model_registry.scc.utils import (
109
validate_deployment_scc,
1110
validate_pod_scc,
1211
)
13-
from tests.model_registry.constants import MR_INSTANCE_NAME
14-
12+
from tests.model_registry.constants import MR_INSTANCE_NAME, MR_POSTGRES_DEPLOYMENT_NAME_STR
1513

1614
LOGGER = get_logger(name=__name__)
1715

utilities/general.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,15 @@ def validate_container_images(
289289
# Validate image format
290290
is_valid, error_msg = validate_image_format(image=image)
291291
if not is_valid:
292-
validation_errors.append(f"Pod {pod.name} image validation failed: {error_msg}")
292+
validation_errors.append(
293+
f"Pod {pod.name} in namespace: {pod.namespace} image validation failed: {error_msg}"
294+
)
293295

294296
# Check if image is in valid references
295297
if image not in valid_image_refs:
296-
validation_errors.append(f"Pod {pod.name} image {image} is not in valid image references")
298+
validation_errors.append(
299+
f"Pod {pod.name}, namespace: {pod.namespace} image {image} is not in valid image references"
300+
)
297301

298302
return validation_errors
299303

0 commit comments

Comments
 (0)