Skip to content

Commit 79e9e3e

Browse files
feat: Add test for verifying updates to imagepullsecrets
Signed-off-by: Vedant Mahabaleshwarkar <vmahabal@redhat.com>
1 parent 560f952 commit 79e9e3e

File tree

5 files changed

+139
-0
lines changed

5 files changed

+139
-0
lines changed

tests/model_serving/model_server/inference_service_configuration/conftest.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@
44
from kubernetes.dynamic import DynamicClient
55
from ocp_resources.inference_service import InferenceService
66
from ocp_resources.pod import Pod
7+
from ocp_resources.namespace import Namespace
8+
from ocp_resources.serving_runtime import ServingRuntime
9+
from utilities.inference_utils import create_isvc
10+
from utilities.constants import KServeDeploymentType
11+
712

813
from tests.model_serving.model_server.inference_service_configuration.constants import (
914
ISVC_ENV_VARS,
15+
UPDATED_PULL_SECRET,
16+
ORIGINAL_PULL_SECRET,
1017
)
1118
from tests.model_serving.model_server.inference_service_configuration.utils import (
1219
update_inference_service,
@@ -65,3 +72,58 @@ def patched_isvc_replicas(
6572
wait_for_new_pods=request.param["wait-for-new-pods"],
6673
):
6774
yield ovms_kserve_inference_service
75+
76+
77+
@pytest.fixture(scope="class")
78+
def model_car_raw_inference_service_with_pull_secret(
79+
request: pytest.FixtureRequest,
80+
unprivileged_client: DynamicClient,
81+
unprivileged_model_namespace: Namespace,
82+
serving_runtime_from_template: ServingRuntime,
83+
) -> Generator[InferenceService, Any, Any]:
84+
with create_isvc(
85+
client=unprivileged_client,
86+
name="model-car-raw",
87+
namespace=unprivileged_model_namespace.name,
88+
runtime=serving_runtime_from_template.name,
89+
storage_uri=request.param["storage-uri"],
90+
model_format=serving_runtime_from_template.instance.spec.supportedModelFormats[0].name,
91+
deployment_mode=KServeDeploymentType.RAW_DEPLOYMENT,
92+
image_pull_secrets=[ORIGINAL_PULL_SECRET],
93+
wait_for_predictor_pods=False, # Until modelcar initContainer completed, other containers may have Error status
94+
) as isvc:
95+
yield isvc
96+
97+
98+
@pytest.fixture(scope="class")
99+
def updated_isvc_pull_secret(
100+
request: pytest.FixtureRequest,
101+
unprivileged_client: DynamicClient,
102+
model_car_raw_inference_service_with_pull_secret: InferenceService,
103+
) -> Generator[InferenceService, Any, Any]:
104+
with update_inference_service(
105+
client=unprivileged_client,
106+
isvc=model_car_raw_inference_service_with_pull_secret,
107+
isvc_updated_dict={"spec": {"predictor": {"imagePullSecrets": [{"name": UPDATED_PULL_SECRET}]}}},
108+
):
109+
yield model_car_raw_inference_service_with_pull_secret
110+
111+
112+
@pytest.fixture(scope="class")
113+
def updated_isvc_remove_pull_secret(
114+
request: pytest.FixtureRequest,
115+
unprivileged_client: DynamicClient,
116+
model_car_raw_inference_service_with_pull_secret: InferenceService,
117+
) -> Generator[InferenceService, Any, Any]:
118+
with update_inference_service(
119+
client=unprivileged_client,
120+
isvc=model_car_raw_inference_service_with_pull_secret,
121+
isvc_updated_dict={
122+
"spec": {
123+
"predictor": {
124+
"imagePullSecrets": None # Explicitly remove the field
125+
}
126+
}
127+
},
128+
):
129+
yield model_car_raw_inference_service_with_pull_secret

tests/model_serving/model_server/inference_service_configuration/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
{"name": "TEST_ENV_VAR1", "value": "test_value1"},
1111
{"name": "TEST_ENV_VAR2", "value": "test_value2"},
1212
]
13+
14+
ORIGINAL_PULL_SECRET: str = "pull-secret-1" # pragma: allowlist-secret
15+
UPDATED_PULL_SECRET: str = "updated-pull-secret" # pragma: allowlist-secret
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
3+
from tests.model_serving.model_server.inference_service_configuration.utils import verify_pull_secret
4+
from tests.model_serving.model_server.inference_service_configuration.constants import (
5+
ORIGINAL_PULL_SECRET,
6+
UPDATED_PULL_SECRET,
7+
)
8+
from utilities.constants import ModelFormat, ModelName, RuntimeTemplates
9+
10+
11+
@pytest.mark.parametrize(
12+
"unprivileged_model_namespace, serving_runtime_from_template, model_car_raw_inference_service_with_pull_secret",
13+
[
14+
pytest.param(
15+
{"name": f"{ModelFormat.OPENVINO}-model-car"},
16+
{
17+
"name": f"{ModelName.MNIST}-runtime",
18+
"template-name": RuntimeTemplates.OVMS_KSERVE,
19+
"multi-model": False,
20+
},
21+
{
22+
# Using mnist-8-1 model from OCI image
23+
"storage-uri": "oci://quay.io/mwaykole/test@sha256:8a3217bcfa2cc5fa3d07496cff8b234acdf2c9725dd307dc0a80401f55e1a11c" # noqa: E501
24+
},
25+
)
26+
],
27+
indirect=True,
28+
)
29+
class TestISVCPullSecretUpdate:
30+
@pytest.mark.smoke
31+
def test_initial_pull_secret_set(self, model_car_raw_inference_service_with_pull_secret):
32+
"""Ensure initial pull secret is correctly set in the pod"""
33+
verify_pull_secret(
34+
isvc=model_car_raw_inference_service_with_pull_secret, pull_secret=ORIGINAL_PULL_SECRET, secret_exists=True
35+
)
36+
37+
def test_update_pull_secret(self, updated_isvc_pull_secret):
38+
"""Update the pull secret and verify it is reflected in the new pod"""
39+
verify_pull_secret(isvc=updated_isvc_pull_secret, pull_secret=UPDATED_PULL_SECRET, secret_exists=True)
40+
41+
def test_remove_pull_secret(self, updated_isvc_remove_pull_secret):
42+
verify_pull_secret(isvc=updated_isvc_remove_pull_secret, pull_secret=UPDATED_PULL_SECRET, secret_exists=False)

tests/model_serving/model_server/inference_service_configuration/utils.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,32 @@ def wait_for_new_running_inference_pods(
108108
except TimeoutError:
109109
LOGGER.error(f"Timeout waiting for pods {oring_pods_names} to be replaced")
110110
raise
111+
112+
113+
def verify_pull_secret(isvc: InferenceService, pull_secret: str, secret_exists: bool) -> None:
114+
"""
115+
Verify that the ImagePullSecret in the InferenceService pods match the expected values.
116+
117+
Args:
118+
isvc (InferenceService): InferenceService object.
119+
pull_secret (str): Pull secret to verify
120+
secret_exists (bool): False if the pull secret should not exist in the pod.
121+
122+
Raises:
123+
AssertionError: If the imagePullSecrets do not match the expected presence or name.
124+
"""
125+
pod = get_pods_by_isvc_label(
126+
client=isvc.client,
127+
isvc=isvc,
128+
)[0]
129+
image_pull_secrets = pod.instance.spec.imagePullSecrets or []
130+
131+
secrets = [s.name for s in image_pull_secrets]
132+
133+
if secret_exists:
134+
assert secrets, "Expected imagePullSecrets to exist, but none were found."
135+
assert pull_secret in secrets, f"Expected pull secret '{pull_secret}' not found in imagePullSecrets: {secrets}"
136+
else:
137+
assert pull_secret not in secrets, (
138+
f"Did not expect pull secret '{pull_secret}', but found in imagePullSecrets: {secrets}"
139+
)

utilities/inference_utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ def create_isvc(
534534
resources: dict[str, Any] | None = None,
535535
volumes: dict[str, Any] | None = None,
536536
volumes_mounts: dict[str, Any] | None = None,
537+
image_pull_secrets: list[str] | None = None,
537538
model_version: str | None = None,
538539
wait_for_predictor_pods: bool = True,
539540
autoscaler_mode: str | None = None,
@@ -608,6 +609,8 @@ def create_isvc(
608609
predictor_dict["model"]["storage"] = {"key": storage_key, "path": storage_path}
609610
if model_service_account:
610611
predictor_dict["serviceAccountName"] = model_service_account
612+
if image_pull_secrets:
613+
predictor_dict["imagePullSecrets"] = [{"name": name} for name in image_pull_secrets]
611614

612615
if min_replicas:
613616
predictor_dict["minReplicas"] = min_replicas

0 commit comments

Comments
 (0)