<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="5" skipped="7" tests="113" time="925.198" timestamp="2026-07-17T18:28:23.726552+00:00" hostname="maas-group-test-69r5j-e2e-maas-openshift-pod"><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyCRUD" name="test_create_api_key" time="0.112" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyCRUD" name="test_list_api_keys" time="0.142" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyCRUD" name="test_revoke_api_key" time="0.097" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyAuthorization" name="test_admin_manage_other_users_keys" time="0.143" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyAuthorization" name="test_non_admin_cannot_access_other_users_keys" time="0.101" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_own_keys" time="0.261" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_other_user_forbidden" time="0.033" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyBulkOperations" name="test_bulk_revoke_admin_can_revoke_any_user" time="0.094" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_within_expiration_limit" time="0.033" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_at_expiration_limit" time="0.034" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_exceeds_expiration_limit" time="0.031" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_without_expiration" time="0.033" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyExpiration" name="test_create_key_with_short_expiration" time="0.033" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_api_key_model_access_success" time="0.100" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_invalid_api_key_rejected" time="0.031" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_no_auth_header_rejected" time="0.026" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_revoked_api_key_rejected" time="2.135" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyModelInference" name="test_api_key_chat_completions" time="0.043" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_double_revoke_returns_404" time="0.110" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_nonexistent_key_returns_404" time="0.032" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_then_create_new_key_works" time="0.162" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_individual_revoke_multiple_keys" time="0.203" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeyRevocationE2E" name="test_revoke_keys_rejected_at_gateway" time="0.328" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_cronjob_exists_and_configured" time="0.132" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_cleanup_networkpolicy_exists" time="0.125" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_create_ephemeral_key" time="0.113" /><testcase classname="test.e2e.tests.test_api_keys.TestEphemeralKeyCleanup" name="test_trigger_cleanup_preserves_active_keys" time="0.606" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_active_subscription" time="5.464" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_degraded_subscription" time="15.363" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_failed_subscription" time="5.445" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_create_key_for_pending_subscription" time="80.840" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionPhases" name="test_reject_key_for_unreconciled_subscription" time="19.527" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionFilter" name="test_search_filters_by_subscription" time="10.737" /><testcase classname="test.e2e.tests.test_api_keys.TestAPIKeySubscriptionFilter" name="test_search_without_subscription_returns_all" time="0.189" /><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.086" /><testcase classname="test.e2e.tests.test_negative_security.TestHeaderSpoofing" name="test_duplicate_subscription_headers_ignored" time="0.066" /><testcase classname="test.e2e.tests.test_negative_security.TestExpiredKeyRejection" name="test_expired_key_rejected_at_gateway" time="5.069" /><testcase classname="test.e2e.tests.test_negative_security.TestCrossModelAccess" name="test_key_cannot_access_model_outside_subscription" time="0.068" /><testcase classname="test.e2e.tests.test_negative_security.TestAuthPolicyRemoval" name="test_authpolicy_deletion_revokes_access" time="2.977" /><testcase classname="test.e2e.tests.test_negative_security.TestMissingModelRef" name="test_subscription_with_nonexistent_model_ref" time="1.148" /><testcase classname="test.e2e.tests.test_negative_security.TestMissingModelRef" name="test_authpolicy_with_nonexistent_model_ref" time="2.909" /><testcase classname="test.e2e.tests.test_negative_security.TestHeaderAbuse" name="test_special_characters_in_subscription_header" time="0.185" /><testcase classname="test.e2e.tests.test_negative_security.TestWebhookValidation" name="test_subscription_rejected_in_unlabeled_namespace" time="7.184" /><testcase classname="test.e2e.tests.test_negative_security.TestWebhookValidation" name="test_authpolicy_rejected_in_unlabeled_namespace" time="6.908" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_authorized_user_gets_200" time="0.084" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_no_auth_gets_401" time="0.026" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_invalid_token_gets_403" time="0.058" /><testcase classname="test.e2e.tests.test_subscription.TestAuthEnforcement" name="test_wrong_group_gets_403" time="0.032" /><testcase classname="test.e2e.tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_uses_highest_priority_subscription" time="0.337" /><testcase classname="test.e2e.tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_with_explicit_simulator_subscription" time="0.069" /><testcase classname="test.e2e.tests.test_subscription.TestAPIKeySubscriptionBinding" name="test_create_api_key_nonexistent_subscription_errors" time="0.278" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_subscribed_user_gets_200" time="0.039" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_auth_pass_no_subscription_gets_403" time="8.493" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_rate_limit_exhaustion_gets_429" time="23.059" /><testcase classname="test.e2e.tests.test_subscription.TestSubscriptionEnforcement" name="test_models_endpoint_exempt_from_rate_limiting" time="18.015" /><testcase classname="test.e2e.tests.test_subscription.TestMultipleSubscriptionsPerModel" name="test_user_in_one_of_two_subscriptions_gets_200" time="4.414" /><testcase classname="test.e2e.tests.test_subscription.TestMultipleAuthPoliciesPerModel" name="test_two_auth_policies_or_logic" time="10.922" /><testcase classname="test.e2e.tests.test_subscription.TestMultipleAuthPoliciesPerModel" name="test_delete_one_auth_policy_other_still_works" time="12.548" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_delete_subscription_rebuilds_trlp" time="4.559" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_trlp_persists_during_multi_subscription_deletion" time="17.395" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_delete_last_subscription_denies_access" time="4.632" /><testcase classname="test.e2e.tests.test_subscription.TestCascadeDeletion" name="test_unconfigured_model_denied_by_gateway_auth" time="0.527" /><testcase classname="test.e2e.tests.test_subscription.TestOrderingEdgeCases" name="test_subscription_before_auth_policy" time="15.821" /><testcase classname="test.e2e.tests.test_subscription.TestManagedAnnotation" name="test_authpolicy_managed_false_prevents_update" time="4.255"><skipped type="pytest.skip" message="gateway-only mode: per-model AuthPolicy is not created">/workspace/source/test/e2e/tests/test_subscription.py:1056: 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="14.898" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_both_access_and_subscription_gets_200" time="5.817" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_access_but_no_subscription_gets_403" time="9.418" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_with_subscription_but_no_access_gets_403" time="5.829" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_single_subscription_auto_selects" time="11.769" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_multiple_subscriptions_separate_keys_gets_200" time="9.832" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_mint_api_key_denied_for_inaccessible_subscription" time="10.369" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_access_gets_200" time="9.235" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_auth_but_no_subscription_gets_403" time="9.376" /><testcase classname="test.e2e.tests.test_subscription.TestE2ESubscriptionFlow" name="test_e2e_group_based_subscription_but_no_auth_gets_403" time="5.598" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_active_status_with_valid_model" time="5.324" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_failed_status_with_missing_model" time="4.854" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_authpolicy_active_status_with_valid_model" time="4.835" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_authpolicy_failed_status_with_missing_model" time="4.798" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_degraded_status_with_partial_models" time="5.160" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_degraded_trlp_blocks_inference" time="91.684" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_authpolicy_degraded_status_with_partial_models" time="4.813" /><testcase classname="test.e2e.tests.test_subscription.TestStatusReporting" name="test_subscription_status_transitions_on_model_deletion" time="18.579" /><testcase classname="test.e2e.tests.test_subscription.TestDegradedSubscriptionFiltering" name="test_degraded_healthy_model_allows_inference" time="15.250" /><testcase classname="test.e2e.tests.test_subscription.TestDegradedSubscriptionFiltering" name="test_failed_subscription_blocks_inference" time="15.565" /><testcase classname="test.e2e.tests.test_subscription.TestDegradedSubscriptionFiltering" name="test_models_endpoint_with_degraded_subscription_api_key" time="15.306" /><testcase classname="test.e2e.tests.test_subscription.TestDegradedSubscriptionFiltering" name="test_models_endpoint_with_degraded_subscription_kube_token" time="15.314" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_single_subscription_auto_select" time="14.678" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_explicit_subscription_header" time="8.818" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_empty_subscription_header_value" time="4.419" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_models_filtered_by_subscription" time="4.805" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_deduplication_same_model_multiple_refs" time="9.271" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_different_modelrefs_same_model_id" time="130.569"><failure message="AssertionError: Expected to find 'facebook/opt-125m', but got {'publishers/llm/models/facebook/opt-125m'}&#10;assert 'facebook/opt-125m' in {'publishers/llm/models/facebook/opt-125m'}">self = &lt;test_models_endpoint.TestModelsEndpoint object at 0x7fa8ff139310&gt;

    def test_different_modelrefs_same_model_id(self):
        """
        Test 7: Different modelRefs serving same model ID return separate entries.
    
        Uses two DIFFERENT MaaSModelRefs (each listed ONCE) that both serve the
        SAME model ID:
        - MODEL_REF (facebook-opt-125m-simulated) → serves "facebook/opt-125m"
        - PREMIUM_MODEL_REF (premium-simulated-simulated-premium) → serves "facebook/opt-125m"
    
        The API deduplicates by (model ID, URL). Since these are different backend
        services with different URLs, they return as 2 separate entries even though
        they serve the same model ID.
    
        Each entry shows the same model ID but different URL and subscription.
        """
        log.info("Test 7: Different modelRefs same ID should deduplicate (INTENDED behavior)")
    
        sa_name = "e2e-models-diff-refs-sa"
        sa_ns = "default"
        maas_ns = _ns()
        subscription_name = "e2e-diff-refs-subscription"
        auth_policy_name = "e2e-diff-refs-auth"
        api_key = None
    
        try:
            # Create SA
            sa_token = _create_sa_token(sa_name, namespace=sa_ns)
            sa_user = _sa_to_user(sa_name, namespace=sa_ns)
    
            # Create auth policy with both modelRefs
            log.info(f"Creating auth policy with {MODEL_REF} and {PREMIUM_MODEL_REF}")
            auth_policy_cr = {
                "apiVersion": "maas.opendatahub.io/v1alpha1",
                "kind": "MaaSAuthPolicy",
                "metadata": {
                    "name": auth_policy_name,
                    "namespace": maas_ns,
                },
                "spec": {
                    "modelRefs": [
                        {"name": MODEL_REF, "namespace": MODEL_NAMESPACE},
                        {"name": PREMIUM_MODEL_REF, "namespace": MODEL_NAMESPACE},
                    ],
                    "subjects": {
                        "users": [sa_user],
                        "groups": [],
                    },
                },
            }
            subprocess.run(
                ["oc", "apply", "-f", "-"],
                input=json.dumps(auth_policy_cr),
                text=True,
                check=True,
            )
    
            # Create subscription with both modelRefs (each listed ONCE)
            log.info(f"Creating subscription with {MODEL_REF} and {PREMIUM_MODEL_REF}")
            subscription_cr = {
                "apiVersion": "maas.opendatahub.io/v1alpha1",
                "kind": "MaaSSubscription",
                "metadata": {
                    "name": subscription_name,
                    "namespace": maas_ns,
                },
                "spec": {
                    "owner": {
                        "users": [sa_user],
                        "groups": [],
                    },
                    "modelRefs": [
                        {
                            "name": MODEL_REF,
                            "namespace": MODEL_NAMESPACE,
                            "tokenRateLimits": [{"limit": 100, "window": "1m"}],
                        },
                        {
                            "name": PREMIUM_MODEL_REF,
                            "namespace": MODEL_NAMESPACE,
                            "tokenRateLimits": [{"limit": 200, "window": "1m"}],
                        },
                    ],
                },
            }
            subprocess.run(
                ["oc", "apply", "-f", "-"],
                input=json.dumps(subscription_cr),
                text=True,
                check=True,
            )
    
            # Wait for auth and subscription reconciliation before creating API key.
            # Both modelRefs must be governed before /v1/models probes each backend.
            _wait_for_maas_auth_policy_phase(
                auth_policy_name,
                namespace=maas_ns,
                timeout=120,
            )
            _wait_for_maas_subscription_phase(
                subscription_name,
                namespace=maas_ns,
                timeout=120,
                require_model_statuses=True,
            )
            _wait_for_model_ready(MODEL_REF, namespace=MODEL_NAMESPACE)
            _wait_for_model_ready(PREMIUM_MODEL_REF, namespace=MODEL_NAMESPACE)
    
            # Create API key bound to our test subscription
            api_key = _create_api_key(sa_token, name="e2e-diff-refs-test-key", subscription=subscription_name)
    
            _wait_reconcile()
    
            # Query /v1/models. Gateway policy propagation and backend model probes can
            # lag behind CR readiness, so wait until both modelRefs appear.
            log.info(f"Querying /v1/models with subscription: {subscription_name}")
            request_headers = {
                "Authorization": f"Bearer {api_key}",
                "x-maas-subscription": subscription_name,
            }
            deadline = time.time() + 120
            r = None
            models = []
            model_ids = []
            while time.time() &lt; deadline:
                r = _get_models_with_gateway_retry(headers=request_headers)
                if r.status_code == 200:
                    models = r.json().get("data") or []
                    assert isinstance(models, list), "Models should be a list"
                    model_ids = [m["id"] for m in models]
                    urls = [m.get("url") for m in models if m.get("id") == MODEL_NAME and m.get("url")]
                    if len(models) == 2 and len(set(urls)) == 2:
                        break
                    log.info(
                        "Models response not fully propagated yet; "
                        f"got {len(models)} entries: {model_ids}"
                    )
                else:
                    log.info(f"Waiting for /v1/models HTTP 200; got {r.status_code}: {r.text[:200]}")
                time.sleep(5)
    
            assert r is not None, "Expected /v1/models response, got none"
            assert r.status_code == 200, f"Expected 200, got {r.status_code}: {r.text}"
    
            assert isinstance(models, list), "Models should be a list"
    
            # Get model IDs from response
            unique_ids = set(model_ids)
    
            log.info(f"#x1F4CA API Response: {len(models)} total model(s), {len(unique_ids)} unique ID(s)")
            log.info(f"   Model IDs: {model_ids}")
            log.info(f"   Unique IDs: {unique_ids}")
            log.info("   Subscription had: 2 different modelRefs both serving 'facebook/opt-125m'")
    
            # Both modelRefs serve the same model ID
            assert len(unique_ids) == 1, \
                f"Expected only 1 unique model ID (both modelRefs serve {MODEL_NAME}), got {len(unique_ids)}: {unique_ids}"
    
            # Verify it's the expected model ID
            expected_id = MODEL_NAME
&gt;           assert expected_id in unique_ids, \
                f"Expected to find '{expected_id}', but got {unique_ids}"
E               AssertionError: Expected to find 'facebook/opt-125m', but got {'publishers/llm/models/facebook/opt-125m'}
E               assert 'facebook/opt-125m' in {'publishers/llm/models/facebook/opt-125m'}

test/e2e/tests/test_models_endpoint.py:881: AssertionError</failure></testcase><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_multiple_distinct_models_in_subscription" time="16.022"><failure message="AssertionError: Expected to find both distinct models {'test/e2e-distinct-model-2', 'test/e2e-distinct-model'}, but got {'publishers/llm/models/test/e2e-distinct-model', 'publishers/llm/models/test/e2e-distinct-model-2'}&#10;assert {'publishers/...inct-model-2'} == {'test/e2e-di...inct-model-2'}&#10;  &#10;  Extra items in the left set:&#10;  'publishers/llm/models/test/e2e-distinct-model'&#10;  'publishers/llm/models/test/e2e-distinct-model-2'&#10;  Extra items in the right set:&#10;  'test/e2e-distinct-model-2'&#10;  'test/e2e-distinct-model'...&#10;  &#10;  ...Full output truncated (8 lines hidden), use '-vv' to show">self = &lt;test_models_endpoint.TestModelsEndpoint object at 0x7fa8ff12ba60&gt;

    def test_multiple_distinct_models_in_subscription(self):
        """
        Test 8: Multiple distinct models should return exactly 2 entries (1 per unique ID).
    
        Uses pre-deployed models (both known to not have backend duplication issues):
        - DISTINCT_MODEL_REF (simulated-distinct) serving "test/e2e-distinct-model"
        - DISTINCT_MODEL_2_REF (simulated-distinct-2) serving "test/e2e-distinct-model-2"
    
        Creates a subscription with both models. The API should return exactly 2 entries
        (one for each distinct model ID), with no duplicates.
    
        This test validates that when backend models don't have duplication bugs, the
        API correctly returns one entry per distinct model ID.
        """
        log.info("Test 8: Multiple distinct models should return 2 entries")
    
        sa_name = "e2e-models-distinct-sa"
        sa_ns = "default"
        maas_ns = _ns()
        subscription_name = "e2e-distinct-models-subscription"
        auth_policy_name = "e2e-distinct-models-auth"
        api_key = None
    
        try:
            # Create SA
            sa_token = _create_sa_token(sa_name, namespace=sa_ns)
            sa_user = _sa_to_user(sa_name, namespace=sa_ns)
    
            # Create auth policy with both distinct models
            log.info(f"Creating auth policy with {DISTINCT_MODEL_REF} and {DISTINCT_MODEL_2_REF}")
            auth_policy_cr = {
                "apiVersion": "maas.opendatahub.io/v1alpha1",
                "kind": "MaaSAuthPolicy",
                "metadata": {
                    "name": auth_policy_name,
                    "namespace": maas_ns,
                },
                "spec": {
                    "modelRefs": [
                        {"name": DISTINCT_MODEL_REF, "namespace": MODEL_NAMESPACE},
                        {"name": DISTINCT_MODEL_2_REF, "namespace": MODEL_NAMESPACE},
                    ],
                    "subjects": {
                        "users": [sa_user],
                        "groups": [],
                    },
                },
            }
            subprocess.run(
                ["oc", "apply", "-f", "-"],
                input=json.dumps(auth_policy_cr),
                text=True,
                check=True,
            )
    
            # Create subscription with both distinct models
            log.info(f"Creating subscription with {DISTINCT_MODEL_REF} and {DISTINCT_MODEL_2_REF}")
            subscription_cr = {
                "apiVersion": "maas.opendatahub.io/v1alpha1",
                "kind": "MaaSSubscription",
                "metadata": {
                    "name": subscription_name,
                    "namespace": maas_ns,
                },
                "spec": {
                    "owner": {
                        "users": [sa_user],
                        "groups": [],
                    },
                    "modelRefs": [
                        {
                            "name": DISTINCT_MODEL_REF,
                            "namespace": MODEL_NAMESPACE,
                            "tokenRateLimits": [{"limit": 100, "window": "1m"}],
                        },
                        {
                            "name": DISTINCT_MODEL_2_REF,
                            "namespace": MODEL_NAMESPACE,
                            "tokenRateLimits": [{"limit": 100, "window": "1m"}],
                        },
                    ],
                },
            }
            subprocess.run(
                ["oc", "apply", "-f", "-"],
                input=json.dumps(subscription_cr),
                text=True,
                check=True,
            )
    
            # Wait for subscription to reconcile before creating API key
            _wait_for_maas_subscription_phase(subscription_name, namespace=maas_ns)
    
            # Wait for models to become Ready after governance pairing is created
            log.info("Waiting for models to reconcile and become Ready...")
            _wait_for_model_ready(DISTINCT_MODEL_REF, namespace=MODEL_NAMESPACE)
            _wait_for_model_ready(DISTINCT_MODEL_2_REF, namespace=MODEL_NAMESPACE)
    
            # Create API key bound to our test subscription
            api_key = _create_api_key(sa_token, name="e2e-distinct-models-test-key", subscription=subscription_name)
    
            _wait_reconcile()
    
            # Query /v1/models (use retry helper for gateway/Authorino propagation)
            log.info(f"Querying /v1/models with subscription: {subscription_name}")
            r = _request_with_gateway_retry(
                requests.get,
                f"{_maas_api_url()}/v1/models",
                headers={
                    "Authorization": f"Bearer {api_key}",
                    "x-maas-subscription": subscription_name,
                },
            )
    
            assert r.status_code == 200, f"Expected 200, got {r.status_code}: {r.text}"
            data = r.json()
            models = data.get("data") or []
    
            assert isinstance(models, list), "Models should be a list"
    
            # Get model IDs from response
            model_ids = [m["id"] for m in models]
            unique_ids = set(model_ids)
    
            log.info(f"#x1F4CA API Response: {len(models)} total model(s), {len(unique_ids)} unique ID(s)")
            log.info(f"   Model IDs: {model_ids}")
            log.info(f"   Unique IDs: {unique_ids}")
            log.info(f"   Subscription had: 2 modelRefs ({DISTINCT_MODEL_REF}, {DISTINCT_MODEL_2_REF})")
    
            # Verify we got BOTH expected model IDs
            expected_ids = {DISTINCT_MODEL_ID, DISTINCT_MODEL_2_ID}
&gt;           assert unique_ids == expected_ids, \
                f"Expected to find both distinct models {expected_ids}, but got {unique_ids}"
E               AssertionError: Expected to find both distinct models {'test/e2e-distinct-model-2', 'test/e2e-distinct-model'}, but got {'publishers/llm/models/test/e2e-distinct-model', 'publishers/llm/models/test/e2e-distinct-model-2'}
E               assert {'publishers/...inct-model-2'} == {'test/e2e-di...inct-model-2'}
E                 
E                 Extra items in the left set:
E                 'publishers/llm/models/test/e2e-distinct-model'
E                 'publishers/llm/models/test/e2e-distinct-model-2'
E                 Extra items in the right set:
E                 'test/e2e-distinct-model-2'
E                 'test/e2e-distinct-model'...
E                 
E                 ...Full output truncated (8 lines hidden), use '-vv' to show

test/e2e/tests/test_models_endpoint.py:1043: AssertionError</failure></testcase><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_user_token_returns_all_models" time="10.863" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_user_token_with_subscription_header_filters" time="9.191" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_empty_model_list" time="11.265" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_response_schema_matches_openapi" time="4.408" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_model_metadata_preserved" time="4.432" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_scoped_to_subscription" time="9.245" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_with_deleted_subscription_403" time="13.227" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_with_inaccessible_subscription_403" time="9.421" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_invalid_subscription_header_403" time="9.082" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_access_denied_to_subscription_403" time="9.731" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_api_key_ignores_subscription_header" time="16.473" /><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_multiple_api_keys_different_subscriptions" time="16.452"><failure message="AssertionError: Key1 should see test/e2e-distinct-model from e2e-multi-keys-sub1&#10;assert 'test/e2e-distinct-model' in {'publishers/llm/models/test/e2e-distinct-model'}">self = &lt;test_models_endpoint.TestModelsEndpoint object at 0x7fa8ff6e8d30&gt;

    def test_multiple_api_keys_different_subscriptions(self):
        """
        Test: Multiple API keys each bound to different subscriptions.
    
        Creates two API keys from the same user, each explicitly bound to a different
        subscription. Verifies each key returns only its bound subscription's models.
    
        Expected: Each API key returns models only from its bound subscription.
        """
        sa_name = "e2e-multi-keys-sa"
        sa_ns = "default"
        maas_ns = _ns()
        sub1_name = "e2e-multi-keys-sub1"
        sub2_name = "e2e-multi-keys-sub2"
        auth1_name = "e2e-multi-keys-auth1"
        auth2_name = "e2e-multi-keys-auth2"
        api_key1 = None
        api_key2 = None
    
        try:
            # Create SA
            sa_token = _create_sa_token(sa_name, namespace=sa_ns)
            sa_user = _sa_to_user(sa_name, namespace=sa_ns)
    
            # Create two subscriptions with different models
            log.info(f"Creating subscription 1 with {DISTINCT_MODEL_REF}")
            _create_test_auth_policy(auth1_name, DISTINCT_MODEL_REF, users=[sa_user])
            _create_test_subscription(sub1_name, DISTINCT_MODEL_REF, users=[sa_user])
    
            log.info(f"Creating subscription 2 with {DISTINCT_MODEL_2_REF}")
            _create_test_auth_policy(auth2_name, DISTINCT_MODEL_2_REF, users=[sa_user])
            _create_test_subscription(sub2_name, DISTINCT_MODEL_2_REF, users=[sa_user])
    
            # Wait for both subscriptions to reconcile before creating API keys
            _wait_for_maas_subscription_phase(sub1_name, namespace=maas_ns)
            _wait_for_maas_subscription_phase(sub2_name, namespace=maas_ns)
    
            # Create two API keys, each bound to a different subscription
            log.info(f"Creating API key 1 bound to {sub1_name}")
            api_key1_response = _request_with_gateway_retry(
                requests.post,
                f"{_maas_api_url()}/v1/api-keys",
                headers={"Authorization": f"Bearer {sa_token}", "Content-Type": "application/json"},
                json={"name": "key1", "subscription": sub1_name},
            )
            assert api_key1_response.status_code in (200, 201)
            api_key1 = api_key1_response.json().get("key")
            bound_sub1 = api_key1_response.json().get("subscription")
            assert bound_sub1 == sub1_name, f"Key 1 should be bound to {sub1_name}, got {bound_sub1}"
    
            log.info(f"Creating API key 2 bound to {sub2_name}")
            api_key2_response = _request_with_gateway_retry(
                requests.post,
                f"{_maas_api_url()}/v1/api-keys",
                headers={"Authorization": f"Bearer {sa_token}", "Content-Type": "application/json"},
                json={"name": "key2", "subscription": sub2_name},
            )
            assert api_key2_response.status_code in (200, 201)
            api_key2 = api_key2_response.json().get("key")
            bound_sub2 = api_key2_response.json().get("subscription")
            assert bound_sub2 == sub2_name, f"Key 2 should be bound to {sub2_name}, got {bound_sub2}"
    
            _wait_reconcile()
    
            # Test key1 - should return models from sub1 only
            log.info(f"Testing API key 1 (bound to {sub1_name})")
            r1 = _get_models_with_gateway_retry(
                headers={"Authorization": f"Bearer {api_key1}"},
            )
            assert r1.status_code == 200, f"Expected 200 for key1, got {r1.status_code}: {r1.text}"
            models1 = r1.json().get("data") or []
            model_ids1 = {m["id"] for m in models1}
    
&gt;           assert DISTINCT_MODEL_ID in model_ids1, f"Key1 should see {DISTINCT_MODEL_ID} from {sub1_name}"
E           AssertionError: Key1 should see test/e2e-distinct-model from e2e-multi-keys-sub1
E           assert 'test/e2e-distinct-model' in {'publishers/llm/models/test/e2e-distinct-model'}

test/e2e/tests/test_models_endpoint.py:1879: AssertionError</failure></testcase><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_service_account_token_multiple_subs_no_header" time="10.537"><failure message="AssertionError: Should see test/e2e-distinct-model from e2e-sa-multi-no-hdr-sub1 (group access)&#10;assert 'test/e2e-distinct-model' in {'publishers/llm/models/facebook/opt-125m', 'publishers/llm/models/test/e2e-distinct-model', 'publishers/llm/models/test/e2e-distinct-model-2'}">self = &lt;test_models_endpoint.TestModelsEndpoint object at 0x7fa8ff7b4880&gt;

    def test_service_account_token_multiple_subs_no_header(self):
        """
        Test: K8s token with access to multiple subscriptions returns all models (no header).
    
        Creates a service account with access to two subscriptions (via group and user).
        When querying without x-maas-subscription header, should return models from
        all accessible subscriptions.
    
        Expected: HTTP 200 with models from both subscriptions.
        """
        sa_name = "e2e-sa-multi-subs-no-header"
        sa_ns = "default"
        maas_ns = _ns()
        sub1_name = "e2e-sa-multi-no-hdr-sub1"
        sub2_name = "e2e-sa-multi-no-hdr-sub2"
        auth1_name = "e2e-sa-multi-no-hdr-auth1"
        auth2_name = "e2e-sa-multi-no-hdr-auth2"
    
        try:
            # Create SA
            sa_token = _create_sa_token(sa_name, namespace=sa_ns)
            sa_user = _sa_to_user(sa_name, namespace=sa_ns)
    
            # Create two subscriptions with different models
            # Sub1: Access via system:authenticated group
            log.info(f"Creating subscription 1 with {DISTINCT_MODEL_REF} (group: system:authenticated)")
            _create_test_auth_policy(auth1_name, DISTINCT_MODEL_REF, groups=["system:authenticated"])
            _create_test_subscription(sub1_name, DISTINCT_MODEL_REF, groups=["system:authenticated"])
    
            # Sub2: Access via specific user
            log.info(f"Creating subscription 2 with {DISTINCT_MODEL_2_REF} (user: {sa_user})")
            _create_test_auth_policy(auth2_name, DISTINCT_MODEL_2_REF, users=[sa_user])
            _create_test_subscription(sub2_name, DISTINCT_MODEL_2_REF, users=[sa_user])
    
            _wait_for_maas_auth_policy_phase(auth1_name)
            _wait_for_maas_auth_policy_phase(auth2_name)
            _wait_for_maas_subscription_phase(sub1_name)
            _wait_for_maas_subscription_phase(sub2_name)
    
            # Query with K8s token (no header)
            log.info("Querying /v1/models with K8s token (no header) - should return models from both subscriptions")
            r = _request_with_gateway_retry(
                requests.get,
                f"{_maas_api_url()}/v1/models",
                headers={"Authorization": f"Bearer {sa_token}"},
            )
    
            assert r.status_code == 200, f"Expected 200, got {r.status_code}: {r.text}"
            data = r.json()
            models = data.get("data") or []
            model_ids = {m["id"] for m in models}
    
            # Should see models from BOTH subscriptions
&gt;           assert DISTINCT_MODEL_ID in model_ids, \
                f"Should see {DISTINCT_MODEL_ID} from {sub1_name} (group access)"
E               AssertionError: Should see test/e2e-distinct-model from e2e-sa-multi-no-hdr-sub1 (group access)
E               assert 'test/e2e-distinct-model' in {'publishers/llm/models/facebook/opt-125m', 'publishers/llm/models/test/e2e-distinct-model', 'publishers/llm/models/test/e2e-distinct-model-2'}

test/e2e/tests/test_models_endpoint.py:1957: AssertionError</failure></testcase><testcase classname="test.e2e.tests.test_models_endpoint.TestModelsEndpoint" name="test_service_account_token_multiple_subs_with_header" time="12.700"><failure message="AssertionError: Should see test/e2e-distinct-model from e2e-sa-multi-hdr-sub1&#10;assert 'test/e2e-distinct-model' in {'publishers/llm/models/test/e2e-distinct-model'}">self = &lt;test_models_endpoint.TestModelsEndpoint object at 0x7fa8ff7b4730&gt;

    def test_service_account_token_multiple_subs_with_header(self):
        """
        Test: K8s token with access to multiple subscriptions filters by header.
    
        Creates a service account with access to two subscriptions. When querying
        with x-maas-subscription header, should return models from only the specified
        subscription.
    
        Expected: HTTP 200 with models from only the specified subscription.
        """
        sa_name = "e2e-sa-multi-subs-with-header"
        sa_ns = "default"
        maas_ns = _ns()
        sub1_name = "e2e-sa-multi-hdr-sub1"
        sub2_name = "e2e-sa-multi-hdr-sub2"
        auth1_name = "e2e-sa-multi-hdr-auth1"
        auth2_name = "e2e-sa-multi-hdr-auth2"
    
        try:
            # Create SA
            sa_token = _create_sa_token(sa_name, namespace=sa_ns)
            sa_user = _sa_to_user(sa_name, namespace=sa_ns)
    
            # Create two subscriptions with different models
            log.info(f"Creating subscription 1 with {DISTINCT_MODEL_REF}")
            _create_test_auth_policy(auth1_name, DISTINCT_MODEL_REF, users=[sa_user])
            _create_test_subscription(sub1_name, DISTINCT_MODEL_REF, users=[sa_user])
    
            log.info(f"Creating subscription 2 with {DISTINCT_MODEL_2_REF}")
            _create_test_auth_policy(auth2_name, DISTINCT_MODEL_2_REF, users=[sa_user])
            _create_test_subscription(sub2_name, DISTINCT_MODEL_2_REF, users=[sa_user])
    
            _wait_for_maas_auth_policy_phase(auth1_name)
            _wait_for_maas_auth_policy_phase(auth2_name)
            _wait_for_maas_subscription_phase(sub1_name)
            _wait_for_maas_subscription_phase(sub2_name)
    
            # Query with K8s token and header specifying sub1
            log.info(f"Querying /v1/models with K8s token and header: {sub1_name}")
            r1 = _request_with_gateway_retry(
                requests.get,
                f"{_maas_api_url()}/v1/models",
                headers={
                    "Authorization": f"Bearer {sa_token}",
                    "x-maas-subscription": sub1_name,
                },
            )
    
            assert r1.status_code == 200, f"Expected 200, got {r1.status_code}: {r1.text}"
            models1 = r1.json().get("data") or []
            model_ids1 = {m["id"] for m in models1}
    
            # Should see only models from sub1
&gt;           assert DISTINCT_MODEL_ID in model_ids1, f"Should see {DISTINCT_MODEL_ID} from {sub1_name}"
E           AssertionError: Should see test/e2e-distinct-model from e2e-sa-multi-hdr-sub1
E           assert 'test/e2e-distinct-model' in {'publishers/llm/models/test/e2e-distinct-model'}

test/e2e/tests/test_models_endpoint.py:2025: AssertionError</failure></testcase></testsuite></testsuites>