Skip to content

Commit 6167bc3

Browse files
authored
Merge branch 'main' into custom_ns
2 parents 20e2a51 + 2dbe408 commit 6167bc3

22 files changed

Lines changed: 295 additions & 168 deletions

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ repos:
1919
- id: check-toml
2020

2121
- repo: https://github.com/PyCQA/flake8
22-
rev: "7.1.2"
22+
rev: "7.2.0"
2323
hooks:
2424
- id: flake8
2525
args: [--config=.flake8, '--ignore=FCN001,W503']

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ Please follow the [Getting Started Guide](docs/GETTING_STARTED.md) on how to run
1010

1111
## Contribute to opendatahub-tests
1212
Please follow the [Contributing Guide](docs/CONTRIBUTING.md) and the [Developer guide](docs/DEVELOPER_GUIDE.md)
13+
14+
15+
## GitHub workflows
16+
Please follow the [GitHub workflows Guide](docs/GITHUB_WORKFLOWS.md) for more information.
File renamed without changes.

tests/model_serving/model_server/components/kserve_dsc_deployment_mode/conftest.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,6 @@
1717
)
1818
from utilities.constants import ModelAndFormat
1919
from utilities.inference_utils import create_isvc
20-
from utilities.jira import is_jira_open
21-
22-
23-
@pytest.fixture(scope="class")
24-
def skip_if_serverless_annotation_bug_present(
25-
admin_client: DynamicClient,
26-
) -> None:
27-
jira_id = "RHOAIENG-19654"
28-
29-
if is_jira_open(jira_id=jira_id, admin_client=admin_client):
30-
pytest.skip(reason=f"Bug {jira_id} is not fixed")
3120

3221

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

tests/model_serving/model_server/components/kserve_dsc_deployment_mode/test_kserve_dsc_default_deployment_mode.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
class TestKServeDSCServerlessDefaultDeploymentMode:
4646
def test_isvc_contains_serverless_deployment_mode(
4747
self,
48-
skip_if_serverless_annotation_bug_present,
4948
default_deployment_mode_in_dsc,
5049
ovms_inference_service,
5150
):
@@ -75,7 +74,6 @@ def test_kserve_dsc_serverless_default_deployment_mode(
7574
)
7675
def test_isvc_on_dsc_default_deployment_mode_change_to_raw(
7776
self,
78-
skip_if_serverless_annotation_bug_present,
7977
patched_default_deployment_mode_in_dsc,
8078
ovms_inference_service,
8179
):
@@ -93,7 +91,6 @@ def test_isvc_on_dsc_default_deployment_mode_change_to_raw(
9391
)
9492
def test_restarted_pod_is_serverless(
9593
self,
96-
skip_if_serverless_annotation_bug_present,
9794
patched_default_deployment_mode_in_dsc,
9895
restarted_inference_pod,
9996
):

tests/model_serving/model_server/conftest.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,39 @@ def ovms_kserve_inference_service(
358358
if max_replicas := request.param.get("max-replicas"):
359359
isvc_kwargs["max_replicas"] = max_replicas
360360

361+
if scale_metric := request.param.get("scale-metric"):
362+
isvc_kwargs["scale_metric"] = scale_metric
363+
364+
if scale_target := request.param.get("scale-target"):
365+
isvc_kwargs["scale_target"] = scale_target
366+
361367
with create_isvc(**isvc_kwargs) as isvc:
362368
yield isvc
363369

364370

371+
@pytest.fixture(scope="class")
372+
def ovms_raw_inference_service(
373+
request: FixtureRequest,
374+
admin_client: DynamicClient,
375+
model_namespace: Namespace,
376+
openvino_kserve_serving_runtime: ServingRuntime,
377+
ci_endpoint_s3_secret: Secret,
378+
) -> Generator[InferenceService, Any, Any]:
379+
with create_isvc(
380+
client=admin_client,
381+
name=f"{request.param['name']}-raw",
382+
namespace=model_namespace.name,
383+
external_route=True,
384+
runtime=openvino_kserve_serving_runtime.name,
385+
storage_path=request.param["model-dir"],
386+
storage_key=ci_endpoint_s3_secret.name,
387+
model_format=ModelAndFormat.OPENVINO_IR,
388+
deployment_mode=KServeDeploymentType.RAW_DEPLOYMENT,
389+
model_version=request.param["model-version"],
390+
) as isvc:
391+
yield isvc
392+
393+
365394
@pytest.fixture(scope="class")
366395
def http_s3_tensorflow_model_mesh_inference_service(
367396
request: FixtureRequest,

tests/model_serving/model_server/model_car/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212

1313

1414
@pytest.fixture(scope="class")
15-
def model_car_tgis_inference_service(
15+
def model_car_serverless_inference_service(
1616
request: FixtureRequest,
1717
admin_client: DynamicClient,
1818
model_namespace: Namespace,
1919
serving_runtime_from_template: ServingRuntime,
2020
) -> Generator[InferenceService, Any, Any]:
2121
with create_isvc(
2222
client=admin_client,
23-
name="tgis-model-car",
23+
name="serverless-model-car",
2424
namespace=model_namespace.name,
2525
runtime=serving_runtime_from_template.name,
2626
storage_uri=request.param["storage-uri"],

tests/model_serving/model_server/model_car/test_oci_image.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,26 @@
22

33
from tests.model_serving.model_server.utils import verify_inference_response
44
from utilities.infra import get_pods_by_isvc_label
5-
from utilities.constants import ModelName, Protocols
5+
from utilities.constants import ModelFormat, ModelName, Protocols, RuntimeTemplates
66
from utilities.inference_utils import Inference
7-
from utilities.manifests.tgis_grpc import TGIS_INFERENCE_CONFIG
7+
from utilities.manifests.onnx import ONNX_INFERENCE_CONFIG
88

99
pytestmark = pytest.mark.serverless
1010

1111

1212
@pytest.mark.parametrize(
13-
"model_namespace, serving_runtime_from_template, model_car_tgis_inference_service",
13+
"model_namespace, serving_runtime_from_template, model_car_serverless_inference_service",
1414
[
1515
pytest.param(
16-
{"name": "tgsi-model-car"},
16+
{"name": f"{ModelFormat.OPENVINO}-model-car"},
1717
{
18-
"name": "tgis-runtime",
19-
"template-name": "tgis-grpc-serving-template",
18+
"name": f"{ModelName.MNIST}-runtime",
19+
"template-name": RuntimeTemplates.OVMS_KSERVE,
2020
"multi-model": False,
2121
},
2222
{
23-
"storage-uri": "oci://quay.io/mwaykole/test@sha256:c526a1a3697253eb09adc65da6efaf7f36150205c3a51ab8d13b92b6a3af9c1c" # noqa: E501
23+
# Using mnist-8-1 model from OCI image
24+
"storage-uri": "oci://quay.io/mwaykole/test@sha256:8a3217bcfa2cc5fa3d07496cff8b234acdf2c9725dd307dc0a80401f55e1a11c" # noqa: E501
2425
},
2526
)
2627
],
@@ -29,11 +30,11 @@
2930
class TestKserveModelCar:
3031
@pytest.mark.smoke
3132
@pytest.mark.jira("RHOAIENG-13465")
32-
def test_model_car_no_restarts(self, model_car_tgis_inference_service):
33+
def test_model_car_no_restarts(self, model_car_serverless_inference_service):
3334
"""Verify that model pod doesn't restart"""
3435
pod = get_pods_by_isvc_label(
35-
client=model_car_tgis_inference_service.client,
36-
isvc=model_car_tgis_inference_service,
36+
client=model_car_serverless_inference_service.client,
37+
isvc=model_car_serverless_inference_service,
3738
)[0]
3839
restarted_containers = [
3940
container.name for container in pod.instance.status.containerStatuses if container.restartCount > 1
@@ -42,13 +43,12 @@ def test_model_car_no_restarts(self, model_car_tgis_inference_service):
4243

4344
@pytest.mark.smoke
4445
@pytest.mark.jira("RHOAIENG-12306")
45-
def test_model_car_using_rest(self, model_car_tgis_inference_service):
46+
def test_model_car_using_rest(self, model_car_serverless_inference_service):
4647
"""Verify model query with token using REST"""
4748
verify_inference_response(
48-
inference_service=model_car_tgis_inference_service,
49-
inference_config=TGIS_INFERENCE_CONFIG,
50-
inference_type=Inference.ALL_TOKENS,
51-
protocol=Protocols.GRPC,
52-
model_name=ModelName.FLAN_T5_SMALL_HF,
49+
inference_service=model_car_serverless_inference_service,
50+
inference_config=ONNX_INFERENCE_CONFIG,
51+
inference_type=Inference.INFER,
52+
protocol=Protocols.HTTPS,
5353
use_default_query=True,
5454
)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import pytest
2+
3+
from tests.model_serving.model_server.utils import verify_inference_response
4+
from tests.model_serving.model_server.raw_deployment.utils import assert_ingress_status_changed
5+
from utilities.constants import ModelFormat, ModelVersion, Protocols, RunTimeConfigs
6+
from utilities.inference_utils import Inference
7+
from utilities.manifests.onnx import ONNX_INFERENCE_CONFIG
8+
9+
10+
pytestmark = [pytest.mark.rawdeployment, pytest.mark.usefixtures("valid_aws_config")]
11+
12+
13+
@pytest.mark.parametrize(
14+
"model_namespace, openvino_kserve_serving_runtime, ovms_raw_inference_service",
15+
[
16+
pytest.param(
17+
{"name": "kserve-raw-route-reconciliation"},
18+
RunTimeConfigs.ONNX_OPSET13_RUNTIME_CONFIG,
19+
{"name": ModelFormat.ONNX, "model-version": ModelVersion.OPSET13, "model-dir": "test-dir"},
20+
)
21+
],
22+
indirect=True,
23+
)
24+
class TestONNXRawRouteReconciliation:
25+
"""Test suite for Validating reconciliation"""
26+
27+
@pytest.mark.smoke
28+
def test_raw_onnx_rout_reconciliation(self, admin_client, ovms_raw_inference_service):
29+
"""
30+
Verify that the KServe Raw ONNX model can be queried using REST
31+
and ensure that the model rout reconciliation works correctly .
32+
"""
33+
# Initial inference validation
34+
verify_inference_response(
35+
inference_service=ovms_raw_inference_service,
36+
inference_config=ONNX_INFERENCE_CONFIG,
37+
inference_type=Inference.INFER,
38+
protocol=Protocols.HTTPS,
39+
use_default_query=True,
40+
)
41+
42+
def test_route_value_before_and_after_deletion(self, admin_client, ovms_raw_inference_service):
43+
# Validate ingress status before and after route deletion
44+
assert_ingress_status_changed(admin_client=admin_client, inference_service=ovms_raw_inference_service)
45+
46+
def test_model_works_after_route_is_recreated(self, ovms_raw_inference_service):
47+
# Final inference validation after route update
48+
verify_inference_response(
49+
inference_service=ovms_raw_inference_service,
50+
inference_config=ONNX_INFERENCE_CONFIG,
51+
inference_type=Inference.INFER,
52+
protocol=Protocols.HTTPS,
53+
use_default_query=True,
54+
)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from kubernetes.dynamic import DynamicClient
2+
from kubernetes.dynamic.exceptions import ResourceNotFoundError
3+
from ocp_resources.inference_service import InferenceService
4+
from utilities.constants import Timeout
5+
from utilities.infra import get_model_route
6+
7+
8+
def assert_ingress_status_changed(admin_client: DynamicClient, inference_service: InferenceService) -> None:
9+
"""
10+
Validates that the ingress status changes correctly after route deletion.
11+
12+
Args:
13+
admin_client (DynamicClient): The administrative client used to manage the model route.
14+
inference_service (InferenceService): The inference service whose route status is being checked.
15+
16+
Raises:
17+
ResourceNotFoundError: If the route does not exist before or after deletion.
18+
AssertionError: If any of the validation checks fail.
19+
20+
Returns:
21+
None
22+
"""
23+
route = get_model_route(admin_client, inference_service)
24+
if not route.exists:
25+
raise ResourceNotFoundError("Route before deletion not found: No active route is currently available.")
26+
27+
initial_status = route.instance.status["ingress"][0]["conditions"][0]
28+
initial_host = route.host
29+
initial_transition_time = initial_status["lastTransitionTime"]
30+
initial_status_value = initial_status["status"]
31+
32+
route.delete(wait=True, timeout=Timeout.TIMEOUT_1MIN)
33+
34+
if not route.exists:
35+
raise ResourceNotFoundError("Route after deletion not found: No active route is currently available.")
36+
37+
updated_status = route.instance.status["ingress"][0]["conditions"][0]
38+
updated_host = route.host
39+
updated_transition_time = updated_status["lastTransitionTime"]
40+
updated_status_value = updated_status["status"]
41+
42+
# Collect failures instead of stopping at the first failed assertion
43+
failures = []
44+
45+
if updated_host != initial_host:
46+
failures.append(f"Host mismatch: before={initial_host}, after={updated_host}")
47+
48+
if updated_transition_time == initial_transition_time:
49+
failures.append(
50+
f"Transition time did not change: before={initial_transition_time}, after={updated_transition_time}"
51+
)
52+
53+
if updated_status_value != "True":
54+
failures.append(f"Updated ingress status incorrect: expected=True, actual={updated_status_value}")
55+
56+
if initial_status_value != "True":
57+
failures.append(f"Initial ingress status incorrect: expected=True, actual={initial_status_value}")
58+
59+
# Assert all failures at once
60+
assert not failures, "Ingress status validation failed:\n" + "\n".join(failures)

0 commit comments

Comments
 (0)