<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="5" skipped="7" tests="91" time="1056.189" timestamp="2026-07-27T19:26:09.817441+00:00" hostname="maas-group-test-m5x2w-e2e-maas-openshift-pod"><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyCRUD" name="test_create_api_key" time="0.100" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyCRUD" name="test_list_api_keys" time="0.141" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyCRUD" name="test_revoke_api_key" time="0.090" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyAuthorization" name="test_admin_manage_other_users_keys" time="0.125" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyAuthorization" name="test_non_admin_cannot_access_other_users_keys" time="0.087" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_own_keys" time="0.236" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_other_user_forbidden" time="0.029" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_admin_can_revoke_any_user" time="0.092" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_within_expiration_limit" time="0.030" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_at_expiration_limit" time="0.028" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_exceeds_expiration_limit" time="0.029" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_without_expiration" time="0.030" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_with_short_expiration" time="0.035" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_api_key_model_access_success" time="0.097" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_invalid_api_key_rejected" time="0.025" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_no_auth_header_rejected" time="0.023" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_revoked_api_key_rejected" time="2.122" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_api_key_chat_completions" time="0.032" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_double_revoke_returns_404" time="0.098" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_nonexistent_key_returns_404" time="0.030" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_then_create_new_key_works" time="0.154" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_individual_revoke_multiple_keys" time="0.184" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_keys_rejected_at_gateway" time="0.295" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_cronjob_exists_and_configured" time="0.110" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_cleanup_networkpolicy_exists" time="0.109" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_create_ephemeral_key" time="0.097" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_trigger_cleanup_preserves_active_keys" time="0.448" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_active_subscription" time="5.330" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_degraded_subscription" time="15.149" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_failed_subscription" time="5.329" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_pending_subscription" time="85.134" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_reject_key_for_unreconciled_subscription" time="18.481" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionFilter" name="test_search_filters_by_subscription" time="15.594" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionFilter" name="test_search_without_subscription_returns_all" time="0.182" /><testcase classname="test.e2e.tests.test_namespace_scoping.TestMaaSAPIWatchNamespace" name="test_subscription_in_subscription_namespace_visible_to_api" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:212: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="test.e2e.tests.test_namespace_scoping.TestMaaSAPIWatchNamespace" name="test_subscription_in_another_namespace_not_visible_to_api" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:245: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="test.e2e.tests.test_namespace_scoping.TestMaaSControllerWatchNamespace" name="test_authpolicy_and_subscription_in_maas_subscription_namespace" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:283: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="test.e2e.tests.test_namespace_scoping.TestMaaSControllerWatchNamespace" name="test_authpolicy_and_subscription_in_another_namespace" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:320: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="test.e2e.tests.test_namespace_scoping.TestModelRef" name="test_auth_policy_model_ref" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:377: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="test.e2e.tests.test_namespace_scoping.TestModelRef" name="test_subscription_model_ref" time="0.000"><skipped type="pytest.skip" message="test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true">/workspace/source/test/e2e/tests/test_namespace_scoping.py:453: test_namespace_scoping validates single-tenant dormant mode; skipped when ENABLE_TENANT_NAMESPACE_DISCOVERY=true</skipped></testcase><testcase classname="test.e2e.tests.test_negative_security.TestHeaderSpoofing" name="test_injected_identity_headers_ignored" time="0.080" /><testcase classname="test.e2e.tests.test_negative_security.TestHeaderSpoofing" name="test_duplicate_subscription_headers_ignored" time="0.065" /><testcase classname="test.e2e.tests.test_negative_security.TestExpiredKeyRejection" name="test_expired_key_rejected_at_gateway" time="5.063" /><testcase classname="test.e2e.tests.test_negative_security.TestCrossModelAccess" name="test_key_cannot_access_model_outside_subscription" time="0.058" /><testcase classname="test.e2e.tests.test_negative_security.TestAuthPolicyRemoval" name="test_authpolicy_deletion_revokes_access" time="0.840" /><testcase classname="test.e2e.tests.test_negative_security.TestMissingModelRef" name="test_subscription_with_nonexistent_model_ref" time="1.109" /><testcase classname="test.e2e.tests.test_negative_security.TestMissingModelRef" name="test_authpolicy_with_nonexistent_model_ref" time="3.623" /><testcase classname="test.e2e.tests.test_negative_security.TestHeaderAbuse" name="test_special_characters_in_subscription_header" time="0.178" /><testcase classname="test.e2e.tests.test_negative_security.TestWebhookValidation" name="test_subscription_rejected_in_unlabeled_namespace" time="7.782" /><testcase classname="test.e2e.tests.test_negative_security.TestWebhookValidation" name="test_authpolicy_rejected_in_unlabeled_namespace" time="6.604" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_authorized_user_gets_200" time="0.080" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_no_auth_gets_401" time="0.023" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_invalid_token_gets_403" time="0.048" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_wrong_group_gets_403" time="0.030" /><testcase classname="test.e2e.tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_uses_highest_priority_subscription" time="0.317" /><testcase classname="test.e2e.tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_with_explicit_simulator_subscription" time="0.065" /><testcase classname="test.e2e.tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_nonexistent_subscription_errors" time="0.246" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_subscribed_user_gets_200" time="0.037" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_auth_pass_no_subscription_gets_403" time="8.445" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_rate_limit_exhaustion_gets_429" time="16.759" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_models_endpoint_exempt_from_rate_limiting" time="14.754" /><testcase classname="test.e2e.tests.test_subscription.TestMultipleSubscriptionsPerModel" name="test_user_in_one_of_two_subscriptions_gets_200" time="4.427" /><testcase classname="test.e2e.tests.test_subscription.TestMultipleAuthPoliciesPerModel" name="test_two_auth_policies_or_logic" time="8.792" /><testcase classname="test.e2e.tests.test_subscription.TestMultipleAuthPoliciesPerModel" name="test_delete_one_auth_policy_other_still_works" time="12.529" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_delete_subscription_rebuilds_trlp" time="4.541" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_trlp_persists_during_multi_subscription_deletion" time="18.183" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_delete_last_subscription_denies_access" time="4.631" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_unconfigured_model_denied_by_gateway_auth" time="0.482" /><testcase classname="test.e2e.tests.test_subscription.TestOrderingEdgeCases" name="test_subscription_before_auth_policy" time="13.709" /><testcase classname="test.e2e.tests.test_subscription.TestManagedAnnotation" name="test_authpolicy_managed_false_prevents_update" time="4.235"><skipped type="pytest.skip" message="gateway-only mode: per-model AuthPolicy is not created">/workspace/source/test/e2e/tests/test_subscription.py:1054: gateway-only mode: per-model AuthPolicy is not created</skipped></testcase><testcase classname="test.e2e.tests.test_subscription.TestManagedAnnotation" name="test_trlp_managed_false_prevents_update" time="13.993" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_both_access_and_subscription_gets_200" time="5.776" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_access_but_no_subscription_gets_403" time="9.284" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_subscription_but_no_access_gets_403" time="5.690" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_single_subscription_auto_selects" time="36.147" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_multiple_subscriptions_separate_keys_gets_200" time="9.535" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_mint_api_key_denied_for_inaccessible_subscription" time="9.854" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_access_gets_200" time="9.167" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_auth_but_no_subscription_gets_403" time="9.336" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_subscription_but_no_auth_gets_403" time="5.424" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_active_status_with_valid_model" time="5.263" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_failed_status_with_missing_model" time="4.820" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_authpolicy_active_status_with_valid_model" time="4.804" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_authpolicy_failed_status_with_missing_model" time="4.807" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_degraded_status_with_partial_models" time="5.149" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_degraded_trlp_blocks_inference" time="192.332" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_authpolicy_degraded_status_with_partial_models" time="197.300"><failure message="subprocess.TimeoutExpired: Command '['oc', 'delete', 'sa', 'e2e-status-degraded-auth-sa', '-n', 'llm', '--ignore-not-found']' timed out after 30 seconds">self = &lt;test_subscription.TestStatusReporting object at 0x7f276e591580&gt;

    def test_authpolicy_degraded_status_with_partial_models(self):
        """
        Test: MaaSAuthPolicy shows Degraded phase when some models are valid, some missing.
    
        Creates an auth policy with one valid and one missing model ref and verifies:
        - Phase is "Degraded"
        - authPolicies contains entry for the valid model (ready=true)
        """
        ns = _ns()
        auth_name = "e2e-status-degraded-auth"
        sa_name = "e2e-status-degraded-auth-sa"
        missing_model = "nonexistent-model-auth-partial"
    
        try:
            _create_sa_token(sa_name, namespace=MODEL_NAMESPACE)
            sa_user = _sa_to_user(sa_name, namespace=MODEL_NAMESPACE)
    
            # Create auth policy with both valid and missing models
            _create_test_auth_policy(auth_name, [MODEL_REF, missing_model], users=[sa_user])
    
            # Wait for auth policy to reach Degraded phase with polling
&gt;           cr = _wait_for_maas_auth_policy_phase(auth_name, "Degraded", timeout=60)

test/e2e/tests/test_subscription.py:2077: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
test/e2e/tests/test_helper.py:952: in _wait_for_maas_auth_policy_phase
    cr = _get_cr("maasauthpolicy", name, namespace)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

kind = 'maasauthpolicy', name = 'e2e-status-degraded-auth'
namespace = 'models-as-a-service'

    def _get_cr(kind, name, namespace=None):
        """Get a CR as dict, or None if not found. Retries on transient errors.
    
        Returns None only when the resource genuinely does not exist (server NotFound).
        Raises RuntimeError for other failures (RBAC, missing CRD, transport errors
        that persist after retries) so callers can distinguish infrastructure issues
        from true absence.
        """
        namespace = namespace or _ns()
        max_retries = 3
        retry_delay = 2
    
        for attempt in range(max_retries):
            result = subprocess.run(["oc", "get", kind, name, "-n", namespace, "-o", "json"], capture_output=True, text=True)
    
            if result.returncode == 0:
                return json.loads(result.stdout)
    
            if attempt &lt; max_retries - 1 and _is_transient_kubectl_error(result.stderr):
                log.warning(
                    f"Transient kubectl error getting {kind}/{name} (attempt {attempt + 1}/{max_retries}): {result.stderr.strip()}"
                )
                time.sleep(retry_delay * (attempt + 1))
                continue
    
            # Terminal failure — distinguish not-found from other errors
            if _is_not_found_error(result.stderr):
                return None
    
            log.error(
                f"Failed to get {kind}/{name} in namespace '{namespace}' after {attempt + 1} attempts. "
                f"Last error: {result.stderr.strip()}"
            )
&gt;           raise RuntimeError(
                f"Failed to get {kind}/{name} in namespace '{namespace}': {result.stderr.strip()}"
            )
E           RuntimeError: Failed to get maasauthpolicy/e2e-status-degraded-auth in namespace 'models-as-a-service': Unable to connect to the server: net/http: TLS handshake timeout

test/e2e/tests/test_helper.py:390: RuntimeError

During handling of the above exception, another exception occurred:

self = &lt;test_subscription.TestStatusReporting object at 0x7f276e591580&gt;

    def test_authpolicy_degraded_status_with_partial_models(self):
        """
        Test: MaaSAuthPolicy shows Degraded phase when some models are valid, some missing.
    
        Creates an auth policy with one valid and one missing model ref and verifies:
        - Phase is "Degraded"
        - authPolicies contains entry for the valid model (ready=true)
        """
        ns = _ns()
        auth_name = "e2e-status-degraded-auth"
        sa_name = "e2e-status-degraded-auth-sa"
        missing_model = "nonexistent-model-auth-partial"
    
        try:
            _create_sa_token(sa_name, namespace=MODEL_NAMESPACE)
            sa_user = _sa_to_user(sa_name, namespace=MODEL_NAMESPACE)
    
            # Create auth policy with both valid and missing models
            _create_test_auth_policy(auth_name, [MODEL_REF, missing_model], users=[sa_user])
    
            # Wait for auth policy to reach Degraded phase with polling
            cr = _wait_for_maas_auth_policy_phase(auth_name, "Degraded", timeout=60)
    
            status = cr.get("status", {})
            auth_policies = status.get("authPolicies", [])
    
            log.info(f"AuthPolicy status: phase={status.get('phase')}, authPolicies={auth_policies}")
    
            # Should have at least one entry for the valid model
            if len(auth_policies) &gt; 0:
                ready_count = sum(1 for ap in auth_policies if ap.get("ready") is True)
                log.info(f"Found {ready_count} ready authPolicies out of {len(auth_policies)}")
    
            log.info("✅ MaaSAuthPolicy Degraded status verified")
    
        finally:
            _delete_cr("maasauthpolicy", auth_name, namespace=ns)
&gt;           _delete_sa(sa_name, namespace=MODEL_NAMESPACE)

test/e2e/tests/test_subscription.py:2093: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
test/e2e/tests/test_helper.py:193: in _delete_sa
    result = subprocess.run(
/usr/lib64/python3.9/subprocess.py:507: in run
    stdout, stderr = process.communicate(input, timeout=timeout)
/usr/lib64/python3.9/subprocess.py:1134: in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
/usr/lib64/python3.9/subprocess.py:1996: in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;Popen: returncode: -9 args: ['oc', 'delete', 'sa', 'e2e-status-degraded-aut...&gt;
endtime = 50142.542046008, orig_timeout = 30, stdout_seq = [], stderr_seq = []
skip_check_and_raise = False

    def _check_timeout(self, endtime, orig_timeout, stdout_seq, stderr_seq,
                       skip_check_and_raise=False):
        """Convenience for checking if a timeout has expired."""
        if endtime is None:
            return
        if skip_check_and_raise or _time() &gt; endtime:
&gt;           raise TimeoutExpired(
                    self.args, orig_timeout,
                    output=b''.join(stdout_seq) if stdout_seq else None,
                    stderr=b''.join(stderr_seq) if stderr_seq else None)
E           subprocess.TimeoutExpired: Command '['oc', 'delete', 'sa', 'e2e-status-degraded-auth-sa', '-n', 'llm', '--ignore-not-found']' timed out after 30 seconds

/usr/lib64/python3.9/subprocess.py:1178: TimeoutExpired</failure></testcase><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_status_transitions_on_model_deletion" time="54.533"><failure message="RuntimeError: Failed to create SA e2e-status-transition-sa: error: failed to create serviceaccount: Post &quot;https://ac9d8d277b501404e83ccf4bfd66001c-f4cdb3420478dd37.elb.us-east-1.amazonaws.com:6443/api/v1/namespaces/llm/serviceaccounts?fieldManager=kubectl-create&amp;fieldValidation=Ignore&quot;: net/http: TLS handshake timeout">self = &lt;test_subscription.TestStatusReporting object at 0x7f276e5918e0&gt;

    def test_subscription_status_transitions_on_model_deletion(self):
        """
        Test: MaaSSubscription transitions from Active to Degraded/Failed when model is deleted.
    
        Creates a subscription with a temporary model, verifies Active status,
        then deletes the model and verifies status transitions appropriately.
        """
        ns = _ns()
        subscription_name = "e2e-status-transition-sub"
        auth_name = "e2e-status-transition-auth"
        model_name = "e2e-temp-model-status"
        sa_name = "e2e-status-transition-sa"
    
        try:
&gt;           _create_sa_token(sa_name, namespace=MODEL_NAMESPACE)

test/e2e/tests/test_subscription.py:2110: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

sa_name = 'e2e-status-transition-sa', namespace = 'llm', duration = '10m'

    def _create_sa_token(sa_name, namespace=None, duration="10m"):
        namespace = namespace or _ns()
        sa_result = subprocess.run(
            ["oc", "create", "sa", sa_name, "-n", namespace], capture_output=True, text=True
        )
        if sa_result.returncode != 0 and "already exists" not in sa_result.stderr:
&gt;           raise RuntimeError(f"Failed to create SA {sa_name}: {sa_result.stderr}")
E           RuntimeError: Failed to create SA e2e-status-transition-sa: error: failed to create serviceaccount: Post "https://ac9d8d277b501404e83ccf4bfd66001c-f4cdb3420478dd37.elb.us-east-1.amazonaws.com:6443/api/v1/namespaces/llm/serviceaccounts?fieldManager=kubectl-create&amp;fieldValidation=Ignore": net/http: TLS handshake timeout

test/e2e/tests/test_helper.py:179: RuntimeError</failure></testcase><testcase classname="test.e2e.tests.test_subscription.TestDegradedSubscriptionFiltering" name="test_degraded_healthy_model_allows_inference" time="44.448"><failure message="RuntimeError: Failed to create SA e2e-degraded-healthy-inf-sa: error: failed to create serviceaccount: Post &quot;https://ac9d8d277b501404e83ccf4bfd66001c-f4cdb3420478dd37.elb.us-east-1.amazonaws.com:6443/api/v1/namespaces/llm/serviceaccounts?fieldManager=kubectl-create&amp;fieldValidation=Ignore&quot;: net/http: TLS handshake timeout">self = &lt;test_subscription.TestDegradedSubscriptionFiltering object at 0x7f276e0a5370&gt;

    def test_degraded_healthy_model_allows_inference(self):
        """
        Test: Inference to healthy model in Degraded subscription succeeds.
    
        Setup:
        1. Create subscription with 1 valid + 1 missing model
        2. Controller sets phase=Degraded, modelRefStatuses shows mixed health
    
        Verify:
        - Subscription is Degraded with one ready=true, one ready=false
        - Inference to the valid model succeeds (200)
        """
        ns = _ns()
        subscription_name = "e2e-degraded-healthy-inf"
        auth_name = "e2e-degraded-healthy-inf-auth"
        sa_name = "e2e-degraded-healthy-inf-sa"
        missing_model = "nonexistent-model-inf"
    
        try:
&gt;           oc_token = _create_sa_token(sa_name, namespace=MODEL_NAMESPACE)

test/e2e/tests/test_subscription.py:2203: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

sa_name = 'e2e-degraded-healthy-inf-sa', namespace = 'llm', duration = '10m'

    def _create_sa_token(sa_name, namespace=None, duration="10m"):
        namespace = namespace or _ns()
        sa_result = subprocess.run(
            ["oc", "create", "sa", sa_name, "-n", namespace], capture_output=True, text=True
        )
        if sa_result.returncode != 0 and "already exists" not in sa_result.stderr:
&gt;           raise RuntimeError(f"Failed to create SA {sa_name}: {sa_result.stderr}")
E           RuntimeError: Failed to create SA e2e-degraded-healthy-inf-sa: error: failed to create serviceaccount: Post "https://ac9d8d277b501404e83ccf4bfd66001c-f4cdb3420478dd37.elb.us-east-1.amazonaws.com:6443/api/v1/namespaces/llm/serviceaccounts?fieldManager=kubectl-create&amp;fieldValidation=Ignore": net/http: TLS handshake timeout

test/e2e/tests/test_helper.py:179: RuntimeError</failure></testcase><testcase classname="test.e2e.tests.test_subscription.TestDegradedSubscriptionFiltering" name="test_failed_subscription_blocks_inference" time="43.377"><failure message="RuntimeError: Failed to create SA e2e-failed-sub-inf-sa: error: failed to create serviceaccount: Post &quot;https://ac9d8d277b501404e83ccf4bfd66001c-f4cdb3420478dd37.elb.us-east-1.amazonaws.com:6443/api/v1/namespaces/llm/serviceaccounts?fieldManager=kubectl-create&amp;fieldValidation=Ignore&quot;: net/http: TLS handshake timeout">self = &lt;test_subscription.TestDegradedSubscriptionFiltering object at 0x7f276e0a56a0&gt;

    def test_failed_subscription_blocks_inference(self):
        """
        Test: Failed subscription blocks inference via OPA rule.
    
        Setup:
        1. Create subscription with valid model (starts Active)
        2. Create API key
        3. Manually patch subscription to Failed phase
        4. Verify inference is rejected by OPA (403)
    
        Note: We use manual patching because naturally creating a Failed subscription
        requires only invalid models, which don't have routes (404 before OPA runs).
        """
        ns = _ns()
        subscription_name = "e2e-failed-sub-inf"
        auth_name = "e2e-failed-sub-inf-auth"
        sa_name = "e2e-failed-sub-inf-sa"
    
        try:
&gt;           oc_token = _create_sa_token(sa_name, namespace=MODEL_NAMESPACE)

test/e2e/tests/test_subscription.py:2282: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

sa_name = 'e2e-failed-sub-inf-sa', namespace = 'llm', duration = '10m'

    def _create_sa_token(sa_name, namespace=None, duration="10m"):
        namespace = namespace or _ns()
        sa_result = subprocess.run(
            ["oc", "create", "sa", sa_name, "-n", namespace], capture_output=True, text=True
        )
        if sa_result.returncode != 0 and "already exists" not in sa_result.stderr:
&gt;           raise RuntimeError(f"Failed to create SA {sa_name}: {sa_result.stderr}")
E           RuntimeError: Failed to create SA e2e-failed-sub-inf-sa: error: failed to create serviceaccount: Post "https://ac9d8d277b501404e83ccf4bfd66001c-f4cdb3420478dd37.elb.us-east-1.amazonaws.com:6443/api/v1/namespaces/llm/serviceaccounts?fieldManager=kubectl-create&amp;fieldValidation=Ignore": net/http: TLS handshake timeout

test/e2e/tests/test_helper.py:179: RuntimeError</failure></testcase><testcase classname="test.e2e.tests.test_subscription.TestDegradedSubscriptionFiltering" name="test_models_endpoint_with_degraded_subscription_api_key" time="95.396"><failure message="subprocess.TimeoutExpired: Command '['oc', 'delete', 'sa', 'e2e-degraded-models-apikey-sa', '-n', 'llm', '--ignore-not-found']' timed out after 30 seconds">self = &lt;test_subscription.TestDegradedSubscriptionFiltering object at 0x7f276e0a5f40&gt;

    def test_models_endpoint_with_degraded_subscription_api_key(self):
        """
        Test: /v1/models with API key bound to Degraded subscription.
    
        Verify behavior when querying models list with a Degraded subscription.
        Current implementation may succeed (showing valid models) or fail depending
        on selector implementation.
        """
        ns = _ns()
        subscription_name = "e2e-degraded-models-apikey"
        auth_name = "e2e-degraded-models-apikey-auth"
        sa_name = "e2e-degraded-models-apikey-sa"
        missing_model = "nonexistent-model-apikey"
    
        try:
&gt;           oc_token = _create_sa_token(sa_name, namespace=MODEL_NAMESPACE)

test/e2e/tests/test_subscription.py:2393: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

sa_name = 'e2e-degraded-models-apikey-sa', namespace = 'llm', duration = '10m'

    def _create_sa_token(sa_name, namespace=None, duration="10m"):
        namespace = namespace or _ns()
        sa_result = subprocess.run(
            ["oc", "create", "sa", sa_name, "-n", namespace], capture_output=True, text=True
        )
        if sa_result.returncode != 0 and "already exists" not in sa_result.stderr:
&gt;           raise RuntimeError(f"Failed to create SA {sa_name}: {sa_result.stderr}")
E           RuntimeError: Failed to create SA e2e-degraded-models-apikey-sa: error: failed to create serviceaccount: Post "https://ac9d8d277b501404e83ccf4bfd66001c-f4cdb3420478dd37.elb.us-east-1.amazonaws.com:6443/api/v1/namespaces/llm/serviceaccounts?fieldManager=kubectl-create&amp;fieldValidation=Ignore": net/http: TLS handshake timeout

test/e2e/tests/test_helper.py:179: RuntimeError

During handling of the above exception, another exception occurred:

self = &lt;test_subscription.TestDegradedSubscriptionFiltering object at 0x7f276e0a5f40&gt;

    def test_models_endpoint_with_degraded_subscription_api_key(self):
        """
        Test: /v1/models with API key bound to Degraded subscription.
    
        Verify behavior when querying models list with a Degraded subscription.
        Current implementation may succeed (showing valid models) or fail depending
        on selector implementation.
        """
        ns = _ns()
        subscription_name = "e2e-degraded-models-apikey"
        auth_name = "e2e-degraded-models-apikey-auth"
        sa_name = "e2e-degraded-models-apikey-sa"
        missing_model = "nonexistent-model-apikey"
    
        try:
            oc_token = _create_sa_token(sa_name, namespace=MODEL_NAMESPACE)
            sa_user = _sa_to_user(sa_name, namespace=MODEL_NAMESPACE)
    
            # Create auth policy
            _create_test_auth_policy(auth_name, MODEL_REF, users=[sa_user])
    
            # Create subscription
            _create_test_subscription(
                subscription_name,
                [MODEL_REF, missing_model],
                users=[sa_user]
            )
    
            _wait_reconcile(seconds=10)
    
            # Verify Degraded
            cr = _get_cr("maassubscription", subscription_name, namespace=ns)
            phase = cr.get("status", {}).get("phase")
            assert phase == "Degraded", f"Expected Degraded, got {phase}"
    
            # Create API key
            # oc_token already set from _create_sa_token above
            api_key = _create_api_key(
                oc_token,
                name="degraded-models",
                subscription=subscription_name
            )
    
            # Call /v1/models
            url = f"{_maas_api_url()}/v1/models"
            headers = {
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json"
            }
    
            log.info(f"GET {url} with API key")
            r = _request_with_gateway_retry(requests.get, url, headers=headers)
    
            log.info(f"Response: {r.status_code}")
    
            # Should succeed - API key can list models from Degraded subscription
            assert r.status_code == 200, \
                f"Expected 200 for /v1/models with Degraded subscription API key, got {r.status_code}: {r.text[:500]}"
    
            data = r.json()
            models = data.get("data", [])
            log.info(f"✅ /v1/models succeeded, returned {len(models)} models")
    
            # Gateway-only behavior may filter degraded subscriptions from /v1/models.
            # Validate success response shape rather than requiring model visibility.
            assert isinstance(models, list), "Expected /v1/models data to be a list"
    
        finally:
            _delete_cr("maassubscription", subscription_name, namespace=ns)
            _delete_cr("maasauthpolicy", auth_name, namespace=ns)
&gt;           _delete_sa(sa_name, namespace=MODEL_NAMESPACE)

test/e2e/tests/test_subscription.py:2448: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
test/e2e/tests/test_helper.py:193: in _delete_sa
    result = subprocess.run(
/usr/lib64/python3.9/subprocess.py:507: in run
    stdout, stderr = process.communicate(input, timeout=timeout)
/usr/lib64/python3.9/subprocess.py:1134: in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
/usr/lib64/python3.9/subprocess.py:1996: in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;Popen: returncode: -9 args: ['oc', 'delete', 'sa', 'e2e-degraded-models-api...&gt;
endtime = 50380.587204748, orig_timeout = 30, stdout_seq = [], stderr_seq = []
skip_check_and_raise = False

    def _check_timeout(self, endtime, orig_timeout, stdout_seq, stderr_seq,
                       skip_check_and_raise=False):
        """Convenience for checking if a timeout has expired."""
        if endtime is None:
            return
        if skip_check_and_raise or _time() &gt; endtime:
&gt;           raise TimeoutExpired(
                    self.args, orig_timeout,
                    output=b''.join(stdout_seq) if stdout_seq else None,
                    stderr=b''.join(stderr_seq) if stderr_seq else None)
E           subprocess.TimeoutExpired: Command '['oc', 'delete', 'sa', 'e2e-degraded-models-apikey-sa', '-n', 'llm', '--ignore-not-found']' timed out after 30 seconds

/usr/lib64/python3.9/subprocess.py:1178: TimeoutExpired</failure></testcase></testsuite></testsuites>