Skip to content

Commit 3abea8f

Browse files
committed
feat: Add provider list smoke test within evalhub
modified: tests/model_explainability/evalhub/test_evalhub_health.py modified: tests/model_explainability/evalhub/utils.py Signed-off-by: Karishma Punwatkar <kpunwatk@redhat.com> modified: tests/model_explainability/evalhub/conftest.py modified: tests/model_explainability/evalhub/constants.py modified: tests/model_explainability/evalhub/test_evalhub_health.py modified: tests/model_explainability/evalhub/utils.py modified: tests/model_explainability/evalhub/conftest.py modified: tests/model_explainability/evalhub/constants.py modified: tests/model_explainability/evalhub/test_evalhub_health.py modified: tests/model_explainability/evalhub/utils.py
1 parent 2690541 commit 3abea8f

File tree

4 files changed

+102
-4
lines changed

4 files changed

+102
-4
lines changed

tests/model_explainability/evalhub/conftest.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
from kubernetes.dynamic import DynamicClient
66
from ocp_resources.deployment import Deployment
77
from ocp_resources.namespace import Namespace
8+
from ocp_resources.role_binding import RoleBinding
89
from ocp_resources.route import Route
10+
from ocp_resources.service_account import ServiceAccount
911
from simple_logger.logger import get_logger
1012

13+
from tests.model_explainability.evalhub.constants import EVALHUB_PROVIDERS_ACCESS_CLUSTER_ROLE
1114
from utilities.certificates_utils import create_ca_bundle_file
1215
from utilities.constants import Timeout
1316
from utilities.resources.evalhub import EvalHub
@@ -67,3 +70,37 @@ def evalhub_ca_bundle_file(
6770
) -> str:
6871
"""Create a CA bundle file for verifying the EvalHub route TLS certificate."""
6972
return create_ca_bundle_file(client=admin_client)
73+
74+
75+
@pytest.fixture(scope="class")
76+
def evalhub_scoped_sa(
77+
admin_client: DynamicClient,
78+
model_namespace: Namespace,
79+
evalhub_deployment: Deployment,
80+
) -> Generator[ServiceAccount, Any, Any]:
81+
"""ServiceAccount with providers access in the test namespace."""
82+
with ServiceAccount(
83+
client=admin_client,
84+
name="evalhub-test-user",
85+
namespace=model_namespace.name,
86+
) as sa:
87+
yield sa
88+
89+
90+
@pytest.fixture(scope="class")
91+
def evalhub_providers_role_binding(
92+
admin_client: DynamicClient,
93+
model_namespace: Namespace,
94+
evalhub_scoped_sa: ServiceAccount,
95+
) -> Generator[RoleBinding, Any, Any]:
96+
"""RoleBinding granting the scoped SA providers access via the ClusterRole."""
97+
with RoleBinding(
98+
client=admin_client,
99+
name="evalhub-test-providers-access",
100+
namespace=model_namespace.name,
101+
role_ref_kind="ClusterRole",
102+
role_ref_name=EVALHUB_PROVIDERS_ACCESS_CLUSTER_ROLE,
103+
subjects_kind="ServiceAccount",
104+
subjects_name=evalhub_scoped_sa.name,
105+
) as rb:
106+
yield rb

tests/model_explainability/evalhub/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@
1212
EVALHUB_API_VERSION: str = "v1alpha1"
1313
EVALHUB_KIND: str = "EvalHub"
1414
EVALHUB_PLURAL: str = "evalhubs"
15+
16+
# RBAC ClusterRole names (must match operator config/rbac/evalhub/ YAML files)
17+
EVALHUB_PROVIDERS_ACCESS_CLUSTER_ROLE: str = "trustyai-service-operator-evalhub-providers-access"

tests/model_explainability/evalhub/test_evalhub_health.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import pytest
22
from ocp_resources.route import Route
33

4-
from tests.model_explainability.evalhub.utils import validate_evalhub_health
4+
from tests.model_explainability.evalhub.utils import validate_evalhub_health, validate_evalhub_providers
55

66

77
@pytest.mark.parametrize(
88
"model_namespace",
99
[
1010
pytest.param(
11-
{"name": "test-evalhub-health"},
11+
{"name": "test-evalhub-health-providers"},
1212
),
1313
],
1414
indirect=True,
1515
)
1616
@pytest.mark.smoke
1717
@pytest.mark.model_explainability
18-
class TestEvalHubHealth:
19-
"""Tests for basic EvalHub service health and availability."""
18+
class TestEvalHub:
19+
"""Tests for basic EvalHub service health and providers."""
2020

2121
def test_evalhub_health_endpoint(
2222
self,
@@ -30,3 +30,19 @@ def test_evalhub_health_endpoint(
3030
token=current_client_token,
3131
ca_bundle_file=evalhub_ca_bundle_file,
3232
)
33+
34+
def test_evalhub_providers_list(
35+
self,
36+
current_client_token: str,
37+
evalhub_ca_bundle_file: str,
38+
evalhub_route: Route,
39+
model_namespace,
40+
) -> None:
41+
"""Test that the evaluations providers endpoint returns a non-empty list."""
42+
43+
validate_evalhub_providers(
44+
host=evalhub_route.host,
45+
token=current_client_token,
46+
ca_bundle_file=evalhub_ca_bundle_file,
47+
tenant=model_namespace.name,
48+
)

tests/model_explainability/evalhub/utils.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,30 @@
44
from tests.model_explainability.evalhub.constants import (
55
EVALHUB_HEALTH_PATH,
66
EVALHUB_HEALTH_STATUS_HEALTHY,
7+
EVALHUB_PROVIDERS_PATH,
78
)
89
from utilities.guardrails import get_auth_headers
910

1011
LOGGER = get_logger(name=__name__)
1112

13+
TENANT_HEADER: str = "X-Tenant"
14+
15+
16+
def _build_headers(token: str, tenant: str | None = None) -> dict[str, str]:
17+
"""Build request headers with auth and optional tenant.
18+
19+
Args:
20+
token: Bearer token for authentication.
21+
tenant: Namespace for the X-Tenant header. Omitted if None.
22+
23+
Returns:
24+
Headers dict.
25+
"""
26+
headers = get_auth_headers(token=token)
27+
if tenant is not None:
28+
headers[TENANT_HEADER] = tenant
29+
return headers
30+
1231

1332
def validate_evalhub_health(
1433
host: str,
@@ -45,3 +64,26 @@ def validate_evalhub_health(
4564
f"Expected status '{EVALHUB_HEALTH_STATUS_HEALTHY}', got '{data['status']}'"
4665
)
4766
assert "timestamp" in data, "Health response missing 'timestamp' field"
67+
68+
69+
def validate_evalhub_providers(
70+
host: str,
71+
token: str,
72+
ca_bundle_file: str,
73+
tenant: str | None = None,
74+
) -> dict:
75+
"""Smoke test for the EvalHub providers endpoint."""
76+
url = f"https://{host}{EVALHUB_PROVIDERS_PATH}"
77+
78+
response = requests.get(
79+
url=url,
80+
headers=_build_headers(token=token, tenant=tenant),
81+
verify=ca_bundle_file,
82+
timeout=10,
83+
)
84+
response.raise_for_status()
85+
86+
data = response.json()
87+
assert data.get("items"), f"Smoke test failed: Providers list is empty for tenant {tenant}"
88+
89+
return data

0 commit comments

Comments
 (0)