Skip to content

Commit 4cd216a

Browse files
SB159threccpre-commit-ci[bot]
authored
test(maas): update subscription tests with new API key changes (#1177)
* test(maas): update subscription tests with new API key changes * test(maas): remove temporary comment from conftest * test(maas): addressed coderabit review * fix: address review comments * fix: address coderabit comment * fix: address coderabit comment * address review comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Thomas Recchiuto <34453570+threcc@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent a41f541 commit 4cd216a

File tree

3 files changed

+90
-10
lines changed

3 files changed

+90
-10
lines changed

tests/model_serving/model_server/maas_billing/maas_subscription/conftest.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Any
33

44
import pytest
5+
import requests
56
from kubernetes.dynamic import DynamicClient
67
from ocp_resources.llm_inference_service import LLMInferenceService
78
from ocp_resources.namespace import Namespace
@@ -10,9 +11,11 @@
1011
from simple_logger.logger import get_logger
1112

1213
from tests.model_serving.model_server.maas_billing.maas_subscription.utils import (
14+
create_api_key,
1315
patch_llmisvc_with_maas_router_and_tiers,
1416
)
1517
from tests.model_serving.model_server.maas_billing.utils import build_maas_headers
18+
from utilities.general import generate_random_name
1619
from utilities.infra import create_inference_token, login_with_user_password
1720
from utilities.llmd_constants import ContainerImages, ModelStorage
1821
from utilities.llmd_utils import create_llmisvc
@@ -255,6 +258,43 @@ def model_url_tinyllama_premium(
255258
return url
256259

257260

261+
@pytest.fixture(scope="class")
262+
def maas_api_key_for_actor(
263+
request_session_http: requests.Session,
264+
base_url: str,
265+
ocp_token_for_actor: str,
266+
maas_controller_enabled_latest: None,
267+
maas_gateway_api: None,
268+
maas_api_gateway_reachable: None,
269+
) -> str:
270+
"""
271+
Create an API key for the current actor (admin/free/premium).
272+
273+
Flow:
274+
- Use OpenShift token (ocp_token_for_actor) to create an API key via MaaS API.
275+
- Use the plaintext API key for gateway inference: Authorization: Bearer <sk-...>.
276+
"""
277+
api_key_name = f"odh-sub-tests-{generate_random_name()}"
278+
279+
_, body = create_api_key(
280+
base_url=base_url,
281+
ocp_user_token=ocp_token_for_actor,
282+
request_session_http=request_session_http,
283+
api_key_name=api_key_name,
284+
request_timeout_seconds=60,
285+
)
286+
287+
return body["key"]
288+
289+
290+
@pytest.fixture(scope="class")
291+
def maas_headers_for_actor_api_key(maas_api_key_for_actor: str) -> dict[str, str]:
292+
"""
293+
Headers for gateway inference using API key (new implementation).
294+
"""
295+
return build_maas_headers(token=maas_api_key_for_actor)
296+
297+
258298
@pytest.fixture(scope="class")
259299
def maas_wrong_group_service_account_token(
260300
maas_api_server_url: str,

tests/model_serving/model_server/maas_billing/maas_subscription/test_multiple_subscriptions_per_model.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class TestMultipleSubscriptionsPerModel:
3535
Validates behavior when multiple subscriptions exist for the same model.
3636
"""
3737

38-
@pytest.mark.sanity
38+
@pytest.mark.smoke
3939
@pytest.mark.parametrize("ocp_token_for_actor", [{"type": "free"}], indirect=True)
4040
def test_user_in_one_of_two_subscriptions_can_access_model(
4141
self,
@@ -44,8 +44,8 @@ def test_user_in_one_of_two_subscriptions_can_access_model(
4444
maas_free_group: str,
4545
maas_model_tinyllama_free,
4646
model_url_tinyllama_free: str,
47-
ocp_token_for_actor: str,
4847
maas_subscription_tinyllama_free,
48+
maas_headers_for_actor_api_key: dict[str, str],
4949
) -> None:
5050
"""
5151
Create a second subscription for a different group the user is NOT in.
@@ -66,10 +66,8 @@ def test_user_in_one_of_two_subscriptions_can_access_model(
6666
) as extra_subscription:
6767
extra_subscription.wait_for_condition(condition="Ready", status="True", timeout=300)
6868

69-
headers = build_maas_headers(token=ocp_token_for_actor)
7069
payload = chat_payload_for_url(model_url=model_url_tinyllama_free)
71-
72-
explicit_headers = dict(headers)
70+
explicit_headers = dict(maas_headers_for_actor_api_key)
7371
explicit_headers[MAAS_SUBSCRIPTION_HEADER] = maas_subscription_tinyllama_free.name
7472

7573
LOGGER.info(
@@ -90,7 +88,7 @@ def test_user_in_one_of_two_subscriptions_can_access_model(
9088
f"{(response.text or '')[:200]}"
9189
)
9290

93-
@pytest.mark.sanity
91+
@pytest.mark.smoke
9492
@pytest.mark.parametrize("ocp_token_for_actor", [{"type": "free"}], indirect=True)
9593
def test_high_priority_subscription_allows_access_when_explicitly_selected(
9694
self,
@@ -99,8 +97,8 @@ def test_high_priority_subscription_allows_access_when_explicitly_selected(
9997
maas_free_group: str,
10098
maas_model_tinyllama_free,
10199
model_url_tinyllama_free: str,
102-
ocp_token_for_actor: str,
103100
maas_subscription_tinyllama_free,
101+
maas_headers_for_actor_api_key: dict[str, str],
104102
) -> None:
105103
"""
106104
Create a second (higher priority) subscription for the same group + model.
@@ -122,10 +120,9 @@ def test_high_priority_subscription_allows_access_when_explicitly_selected(
122120
) as high_tier_subscription:
123121
high_tier_subscription.wait_for_condition(condition="Ready", status="True", timeout=300)
124122

125-
headers = build_maas_headers(token=ocp_token_for_actor)
126123
payload = chat_payload_for_url(model_url=model_url_tinyllama_free)
127124

128-
explicit_headers = dict(headers)
125+
explicit_headers = dict(maas_headers_for_actor_api_key)
129126
explicit_headers[MAAS_SUBSCRIPTION_HEADER] = high_tier_subscription.name
130127

131128
response = poll_expected_status(
@@ -141,7 +138,7 @@ def test_high_priority_subscription_allows_access_when_explicitly_selected(
141138
f"got {response.status_code}: {(response.text or '')[:200]}"
142139
)
143140

144-
@pytest.mark.sanity
141+
@pytest.mark.smoke
145142
def test_service_account_cannot_use_subscription_it_does_not_belong_to(
146143
self,
147144
request_session_http: requests.Session,

tests/model_serving/model_server/maas_billing/maas_subscription/utils.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from ocp_resources.llm_inference_service import LLMInferenceService
1313
from ocp_resources.resource import ResourceEditor
1414
from pytest_testconfig import config as py_config
15+
from requests import Response
1516
from simple_logger.logger import get_logger
1617
from timeout_sampler import TimeoutSampler
1718

@@ -168,3 +169,45 @@ def create_maas_subscription(
168169
teardown=teardown,
169170
wait_for_resource=wait_for_resource,
170171
)
172+
173+
174+
def create_api_key(
175+
base_url: str,
176+
ocp_user_token: str,
177+
request_session_http: requests.Session,
178+
api_key_name: str,
179+
request_timeout_seconds: int = 60,
180+
) -> tuple[Response, dict[str, Any]]:
181+
"""
182+
Create an API key via MaaS API and return (response, parsed_body).
183+
184+
Uses ocp_user_token for auth against maas-api.
185+
Expects plaintext key in body["key"] (sk-...).
186+
"""
187+
api_keys_url = f"{base_url}/v1/api-keys"
188+
189+
response = request_session_http.post(
190+
url=api_keys_url,
191+
headers={
192+
"Authorization": f"Bearer {ocp_user_token}",
193+
"Content-Type": "application/json",
194+
},
195+
json={"name": api_key_name},
196+
timeout=request_timeout_seconds,
197+
)
198+
199+
LOGGER.info(f"create_api_key: url={api_keys_url} status={response.status_code}")
200+
if response.status_code not in (200, 201):
201+
raise AssertionError(f"api-key create failed: status={response.status_code}")
202+
203+
try:
204+
parsed_body: dict[str, Any] = json.loads(response.text)
205+
except json.JSONDecodeError as error:
206+
LOGGER.error(f"Unable to parse API key response from {api_keys_url}; status={response.status_code}")
207+
raise AssertionError("API key creation returned non-JSON response") from error
208+
209+
api_key = parsed_body.get("key", "")
210+
if not isinstance(api_key, str) or not api_key.startswith("sk-"):
211+
raise AssertionError("No plaintext api key returned in MaaS API response")
212+
213+
return response, parsed_body

0 commit comments

Comments
 (0)