Loading ansible/tests/r2_e2e/test_deploy_to_ti.py +2 −2 Changes for ansible/tests/r2_e2e/test_deploy_to_ti.py: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -222,13 +222,13 @@ def test_qod_profile_lifecycle(qod_case,profile_name): @pytest.mark.platform_acceptance def test_qod_unsupported_profile_is_rejected(qod_case): """Reject a profile outside this control path configuration and prove no provider subscription remains.""" """Request a disallowed QoD profile, wait for UNAVAILABLE and verify no provider subscription was created.""" qod_case.verify_refused(qod_case.profile['qod']['unsupported_profile']) @pytest.mark.platform_acceptance def test_qod_backend_refusal_retains_diagnostics(qod_case): """Use a locally allowed profile refused by the NEF and require useful backend diagnostics and cleanup.""" """Request a profile refused by the NEF, wait for UNAVAILABLE and check safe HTTP 400 diagnostics and cleanup.""" qod_case.verify_refused(qod_case.profile['qod']['backend_refusal_profile'],backend=True) Loading ansible/tests/unit/test_report_view.py +12 −0 Changes for ansible/tests/unit/test_report_view.py: 12 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -25,6 +25,18 @@ def test_every_selected_check_has_a_source_explanation_and_documentation_anchor( assert "### " + heading + "\n" in catalog def test_each_catalogue_flow_link_resolves_to_its_own_inline_diagram(): catalog = (ROOT / "ci/lab/CHECKS.md").read_text() for _, _, nodes in (*PHASES, *NETWORK_PHASES): for node in nodes: function = node.split("::")[1].split("[")[0].removeprefix("test_") heading = function.replace("_", " ") section = catalog.split("### " + heading + "\n", 1)[1].split("\n### ", 1)[0] assert "[Flow diagram](#flow-" + function.replace("_", "-") + ")" in section assert "#### Flow " + heading + "\n" in section assert "```mermaid\n" in section def test_actual_cases_keep_failures_skips_time_and_parameter_identity(tmp_path, monkeypatch): monkeypatch.setenv("CI_PROJECT_URL", "https://gitlab.example/oop/ansible") (tmp_path / "health").mkdir() Loading ci/lab/CHECKS.md +251 −28 Changes for ci/lab/CHECKS.md: 251 added lines, 28 removed lines. Original line number Diff line number Diff line Loading @@ -3,156 +3,379 @@ Start with [OpenOP E2E tests, explained](EXPLAINED.md) for the platform and lab overview. Each check below links to its shared flow diagram and source. Several parameter Each check below has its own flow diagram and source link. Several parameter values can run the same check, for example the two login realms or four QoD profiles. Each executed value has its own result in GitLab Tests. The diagrams show test actions and observations. Deployment-related checks use the same running application from a shared fixture; they do not deploy another application for every assertion. Fixtures also perform owned cleanup. ### oeg and fm answer Call public OEG and FM health endpoints and require HTTP 200 from both deployed services. [Flow diagram](EXPLAINED.md#lab-setup) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) [Flow diagram](#flow-oeg-and-fm-answer) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) #### Flow oeg and fm answer ```mermaid flowchart TD A["GET the public OEG health endpoint"] --> B["Require HTTP 200"] B["Require HTTP 200"] --> C["GET the public FM health endpoint"] C["GET the public FM health endpoint"] --> D["Require HTTP 200"] ``` ### keycloak issuer is the public url Discover the configured realm through its public URL and verify the advertised issuer matches it. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) [Flow diagram](#flow-keycloak-issuer-is-the-public-url) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) #### Flow keycloak issuer is the public url ```mermaid flowchart TD A["Select the oop or federation realm"] --> B["GET its public discovery document"] B["GET its public discovery document"] --> C["Require HTTP 200"] C["Require HTTP 200"] --> D["Match the issuer with the expected public realm URL"] ``` ### oeg refuses calls without a valid token Require HTTP 401 for missing or invalid bearer tokens on application and federation routes. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) [Flow diagram](#flow-oeg-refuses-calls-without-a-valid-token) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) #### Flow oeg refuses calls without a valid token ```mermaid flowchart TD A["Call app and federation routes without a token"] --> B["Require HTTP 401"] B["Require HTTP 401"] --> C["Repeat with an invalid token"] C["Repeat with an invalid token"] --> D["Require HTTP 401 again"] ``` ### oeg keeps app apis to app providers Reject the operator role on application routes and let an App Provider reach the application lookup. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) [Flow diagram](#flow-oeg-keeps-app-apis-to-app-providers) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) #### Flow oeg keeps app apis to app providers ```mermaid flowchart TD A["Use operator and App Provider tokens"] --> B["GET an unknown app as operator: require 403"] B["GET an unknown app as operator: require 403"] --> C["GET it as App Provider: require 404 after authorization"] ``` ### oeg keeps federation to operators Require HTTP 403 when an App Provider calls an operator-only federation route. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) [Flow diagram](#flow-oeg-keeps-federation-to-operators) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) #### Flow oeg keeps federation to operators ```mermaid flowchart TD A["Use an App Provider token"] --> B["GET an operator-only federation route"] B["GET an operator-only federation route"] --> C["Require HTTP 403"] ``` ### fm internal api is not public FM serves /internal/* only on its cluster-internal port, never on the EWBI one. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_exposure.py) [Flow diagram](#flow-fm-internal-api-is-not-public) · [Test source](../../ansible/tests/r2_e2e/test_exposure.py) #### Flow fm internal api is not public ```mermaid flowchart TD A["Use the public FM address"] --> B["GET internal identity and partner routes"] B["GET internal identity and partner routes"] --> C["Require HTTP 404 for both"] ``` ### app provider registers reads and deletes an app Onboard an application through OEG, read its stored manifest and list entry, then verify catalogue removal. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) [Flow diagram](#flow-app-provider-registers-reads-and-deletes-an-app) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) #### Flow app provider registers reads and deletes an app ```mermaid flowchart TD A["Fixture registers an owned app through OEG"] --> B["Read its stored manifest and catalogue entry"] B["Read its stored manifest and catalogue entry"] --> C["Delete the app"] C["Delete the app"] --> D["Require 404 and absence from the catalogue list"] ``` ### app provider lists its apps Verify the application registered by this test client appears in its catalogue list. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) [Flow diagram](#flow-app-provider-lists-its-apps) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) #### Flow app provider lists its apps ```mermaid flowchart TD A["Fixture registers an owned app"] --> B["GET the catalogue as that provider"] B["GET the catalogue as that provider"] --> C["Require the owned app ID in the list"] C["Require the owned app ID in the list"] --> D["Fixture removes the app"] ``` ### invalid application is not registered Reject a missing application name or unsupported package and prove no catalogue record was created. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-invalid-application-is-not-registered) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow invalid application is not registered ```mermaid flowchart TD A["Choose missing-name or unsupported QCOW2 manifest"] --> B["POST the app through OEG"] B["POST the app through OEG"] --> C["Require 400 or 501 for the selected case"] C["Require 400 or 501 for the selected case"] --> D["GET the app and catalogue: prove it was not registered"] ``` ### duplicate onboarding preserves the registered application Require HTTP 409 for duplicate onboarding and prove the original application was preserved. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-duplicate-onboarding-preserves-the-registered-application) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow duplicate onboarding preserves the registered application ```mermaid flowchart TD A["Fixture registers the original app"] --> B["POST its ID again with a changed name"] B["POST its ID again with a changed name"] --> C["Require HTTP 409"] C["Require HTTP 409"] --> D["GET the app: require the original name"] ``` ### unknown application cannot be instantiated Reject instantiation of an unknown application and prove no instance was created. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-unknown-application-cannot-be-instantiated) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow unknown application cannot be instantiated ```mermaid flowchart TD A["POST an instance for an unknown app ID"] --> B["Require HTTP 400"] B["Require HTTP 400"] --> C["GET instances filtered by that app"] C["GET instances filtered by that app"] --> D["Require an empty list"] ``` ### unknown instance cannot be terminated Require HTTP 404 for deletion of a nonexistent application instance. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-unknown-instance-cannot-be-terminated) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow unknown instance cannot be terminated ```mermaid flowchart TD A["GET instances for an unknown instance ID"] --> B["Require an empty list"] B["Require an empty list"] --> C["DELETE that unknown instance"] C["DELETE that unknown instance"] --> D["Require HTTP 404"] ``` ### cloud zones match configured workload targets Compare public zone names and unique identities with the workload zones configured in this lab. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-cloud-zones-match-configured-workload-targets) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow cloud zones match configured workload targets ```mermaid flowchart TD A["GET cloud zones through OEG"] --> B["Compare names with the configured workload zones"] B["Compare names with the configured workload zones"] --> C["Require unique IDs, active status and provider fields"] ``` ### progressive oeg request creates a ready workload Instantiate through OEG and independently require the owned Kubernetes Deployment, ready Pod and NodePort Service. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-request-creates-a-ready-workload) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg request creates a ready workload ```mermaid flowchart TD A["Shared fixture onboards and requests instantiation through OEG"] --> B["Observe the owned ready Deployment and Pod"] B["Observe the owned ready Deployment and Pod"] --> C["Observe the owned NodePort Service"] C["Observe the owned NodePort Service"] --> D["Require real Pod and Service identities"] ``` ### progressive workload applies requested resources Compare requested CPU and decimal-MB memory with the actual Kubernetes Deployment and Pod resource requests. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-workload-applies-requested-resources) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive workload applies requested resources ```mermaid flowchart TD A["Use the same deployed container and its requested CPU and memory"] --> B["Read resource requests from Deployment and Pod"] B["Read resource requests from Deployment and Pod"] --> C["Compare Kubernetes quantities with the original request"] ``` ### progressive oeg returns the application instance Poll the public instance until ready and verify its application and zone identities. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-returns-the-application-instance) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg returns the application instance ```mermaid flowchart TD A["Use the same deployed application"] --> B["Poll its public instance until ready"] B["Poll its public instance until ready"] --> C["Verify app and zone identities"] C["Verify app and zone identities"] --> D["Require ready status"] ``` ### progressive oeg returns the observed endpoint Compare the public application endpoint with the actual owned Kubernetes Service and cluster node. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-returns-the-observed-endpoint) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg returns the observed endpoint ```mermaid flowchart TD A["Use the observed owned Service and node"] --> B["Read the endpoint returned by OEG"] B["Read the endpoint returned by OEG"] --> C["Compare host, port and protocol with Kubernetes"] ``` ### progressive endpoint reaches the deployed application Call the returned HTTP endpoint and verify the response identifies the deployed application Pod. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-endpoint-reaches-the-deployed-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive endpoint reaches the deployed application ```mermaid flowchart TD A["Use the endpoint returned by OEG"] --> B["Send an HTTP request to that address"] B["Send an HTTP request to that address"] --> C["Require the expected successful response"] C["Require the expected successful response"] --> D["Match the response with the deployed Pod identity"] ``` ### progressive oeg termination removes the workload Terminate through OEG and verify the public instance and owned Deployment, Pod and Service disappear. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-termination-removes-the-workload) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg termination removes the workload ```mermaid flowchart TD A["Use the same deployed application"] --> B["Request termination through OEG"] B["Request termination through OEG"] --> C["Poll public instance removal"] C["Poll public instance removal"] --> D["Verify the owned Deployment, Pod and Service disappear"] ``` ### qod profile lifecycle Create and read QoD through OEG, inspect the real NEF resource and flow, then verify public and provider deletion. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-qod-profile-lifecycle) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow qod profile lifecycle ```mermaid flowchart TD A["POST QoD with one configured profile"] --> B["Poll the public session to AVAILABLE"] B["Poll the public session to AVAILABLE"] --> C["Inspect NEF profile, device IP, host flow and notification URL"] C["Inspect NEF profile, device IP, host flow and notification URL"] --> D["Fixture deletes the session and verifies public and provider cleanup"] ``` ### qod unsupported profile is rejected Reject a profile outside this control path configuration and prove no provider subscription remains. Request a disallowed QoD profile, wait for UNAVAILABLE and verify no provider subscription was created. [Flow diagram](#flow-qod-unsupported-profile-is-rejected) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow qod unsupported profile is rejected ```mermaid flowchart TD A["POST a profile excluded by SDK configuration"] --> B["Keep the returned session ID"] B["Keep the returned session ID"] --> C["Poll its QoD status to UNAVAILABLE"] C["Poll its QoD status to UNAVAILABLE"] --> D["Require the NEF subscription collection to remain unchanged"] ``` ### qod backend refusal retains diagnostics Use a locally allowed profile refused by the NEF and require useful backend diagnostics and cleanup. Request a profile refused by the NEF, wait for UNAVAILABLE and check safe HTTP 400 diagnostics and cleanup. [Flow diagram](#flow-qod-backend-refusal-retains-diagnostics) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow qod backend refusal retains diagnostics [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) ```mermaid flowchart TD A["POST an SDK-allowed profile unknown to the NEF"] --> B["Poll its QoD status to UNAVAILABLE"] B["Poll its QoD status to UNAVAILABLE"] --> C["Read SRM structured logs: require backend HTTP 400 diagnostics"] C["Read SRM structured logs: require backend HTTP 400 diagnostics"] --> D["Require the NEF subscription collection to remain unchanged"] ``` ### known device returns geographic location Retrieve the simulated device location through OEG and verify geographic coordinates and freshness. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-known-device-returns-geographic-location) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow known device returns geographic location ```mermaid flowchart TD A["Use the simulated device IP"] --> B["POST location retrieval with maxAge 300"] B["POST location retrieval with maxAge 300"] --> C["Require HTTP 200 and a fresh location time"] C["Require HTTP 200 and a fresh location time"] --> D["Check coordinates against the configured CoreSim area"] ``` ### location without device is rejected Require the public missing-identifier error when location retrieval has no device. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-location-without-device-is-rejected) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow location without device is rejected ```mermaid flowchart TD A["POST location retrieval without a device"] --> B["Require HTTP 422"] B["Require HTTP 422"] --> C["Require the MISSING_IDENTIFIER error code"] ``` ### device ti uses the deployed application endpoint Activate device TI through OEG, verify real device/application IPs and notification URL in the NEF, then verify deletion. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-device-ti-uses-the-deployed-application-endpoint) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow device ti uses the deployed application endpoint ```mermaid flowchart TD A["Use the observed endpoint of the shared deployed app"] --> B["POST traffic-influence-devices with device and instance IDs"] B["POST traffic-influence-devices with device and instance IDs"] --> C["Poll the public TI state to active"] C["Poll the public TI state to active"] --> D["Inspect NEF device IP, app IP, host flow and notification URL"] D["Inspect NEF device IP, app IP, host flow and notification URL"] --> E["DELETE TI and verify public and provider removal"] ``` ci/lab/EXPLAINED.md +2 −2 Changes for ci/lab/EXPLAINED.md: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -142,6 +142,6 @@ accuracy. The matrix keeps these limits alongside each result. ## Choose a check or run the lab The [individual check catalogue](CHECKS.md) explains each test and links back to its flow diagram and source. The [operator guide](README.md) contains local The [individual check catalogue](CHECKS.md) explains each test with its own flow diagram and source link. The [operator guide](README.md) contains local commands, profiles and troubleshooting. ci/lab/README.md +3 −3 Changes for ci/lab/README.md: 3 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ New to OpenOP? Read the short [illustrated overview](EXPLAINED.md) and Open release-feature-report in the pipeline for the readable job summary and links to the HTML feature report, Tests tab and exact-source guide. The HTML report links each feature to its actual run and each test to its explanation, shared flow diagram and source. If the server cannot preview HTML artifacts, specific flow diagram and source. If the server cannot preview HTML artifacts, download index.html and open it locally; the job log remains readable in GitLab. The existing Markdown/JSON receipts remain available. Loading Loading @@ -451,8 +451,8 @@ healthy before Nginx resolves their names at startup. The existing verifier still owns qualification. Presentation consumes its actual JSON/JUnit; it never infers a pass from a missing case or a green badge. Documentation stays beside the tests and report links use the exact run commit. Shared flow diagrams explain several related assertions without copying the scenario or adding another execution framework. The overview explains the common journey. Each catalogue check has its own flow diagram without adding another execution framework. - [JUnit reports](https://docs.gitlab.com/ci/testing/unit_test_reports/) put individual cases and their purpose in the native Tests tab. Distinct job Loading Loading
ansible/tests/r2_e2e/test_deploy_to_ti.py +2 −2 Changes for ansible/tests/r2_e2e/test_deploy_to_ti.py: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -222,13 +222,13 @@ def test_qod_profile_lifecycle(qod_case,profile_name): @pytest.mark.platform_acceptance def test_qod_unsupported_profile_is_rejected(qod_case): """Reject a profile outside this control path configuration and prove no provider subscription remains.""" """Request a disallowed QoD profile, wait for UNAVAILABLE and verify no provider subscription was created.""" qod_case.verify_refused(qod_case.profile['qod']['unsupported_profile']) @pytest.mark.platform_acceptance def test_qod_backend_refusal_retains_diagnostics(qod_case): """Use a locally allowed profile refused by the NEF and require useful backend diagnostics and cleanup.""" """Request a profile refused by the NEF, wait for UNAVAILABLE and check safe HTTP 400 diagnostics and cleanup.""" qod_case.verify_refused(qod_case.profile['qod']['backend_refusal_profile'],backend=True) Loading
ansible/tests/unit/test_report_view.py +12 −0 Changes for ansible/tests/unit/test_report_view.py: 12 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -25,6 +25,18 @@ def test_every_selected_check_has_a_source_explanation_and_documentation_anchor( assert "### " + heading + "\n" in catalog def test_each_catalogue_flow_link_resolves_to_its_own_inline_diagram(): catalog = (ROOT / "ci/lab/CHECKS.md").read_text() for _, _, nodes in (*PHASES, *NETWORK_PHASES): for node in nodes: function = node.split("::")[1].split("[")[0].removeprefix("test_") heading = function.replace("_", " ") section = catalog.split("### " + heading + "\n", 1)[1].split("\n### ", 1)[0] assert "[Flow diagram](#flow-" + function.replace("_", "-") + ")" in section assert "#### Flow " + heading + "\n" in section assert "```mermaid\n" in section def test_actual_cases_keep_failures_skips_time_and_parameter_identity(tmp_path, monkeypatch): monkeypatch.setenv("CI_PROJECT_URL", "https://gitlab.example/oop/ansible") (tmp_path / "health").mkdir() Loading
ci/lab/CHECKS.md +251 −28 Changes for ci/lab/CHECKS.md: 251 added lines, 28 removed lines. Original line number Diff line number Diff line Loading @@ -3,156 +3,379 @@ Start with [OpenOP E2E tests, explained](EXPLAINED.md) for the platform and lab overview. Each check below links to its shared flow diagram and source. Several parameter Each check below has its own flow diagram and source link. Several parameter values can run the same check, for example the two login realms or four QoD profiles. Each executed value has its own result in GitLab Tests. The diagrams show test actions and observations. Deployment-related checks use the same running application from a shared fixture; they do not deploy another application for every assertion. Fixtures also perform owned cleanup. ### oeg and fm answer Call public OEG and FM health endpoints and require HTTP 200 from both deployed services. [Flow diagram](EXPLAINED.md#lab-setup) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) [Flow diagram](#flow-oeg-and-fm-answer) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) #### Flow oeg and fm answer ```mermaid flowchart TD A["GET the public OEG health endpoint"] --> B["Require HTTP 200"] B["Require HTTP 200"] --> C["GET the public FM health endpoint"] C["GET the public FM health endpoint"] --> D["Require HTTP 200"] ``` ### keycloak issuer is the public url Discover the configured realm through its public URL and verify the advertised issuer matches it. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) [Flow diagram](#flow-keycloak-issuer-is-the-public-url) · [Test source](../../ansible/tests/r2_e2e/test_platform.py) #### Flow keycloak issuer is the public url ```mermaid flowchart TD A["Select the oop or federation realm"] --> B["GET its public discovery document"] B["GET its public discovery document"] --> C["Require HTTP 200"] C["Require HTTP 200"] --> D["Match the issuer with the expected public realm URL"] ``` ### oeg refuses calls without a valid token Require HTTP 401 for missing or invalid bearer tokens on application and federation routes. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) [Flow diagram](#flow-oeg-refuses-calls-without-a-valid-token) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) #### Flow oeg refuses calls without a valid token ```mermaid flowchart TD A["Call app and federation routes without a token"] --> B["Require HTTP 401"] B["Require HTTP 401"] --> C["Repeat with an invalid token"] C["Repeat with an invalid token"] --> D["Require HTTP 401 again"] ``` ### oeg keeps app apis to app providers Reject the operator role on application routes and let an App Provider reach the application lookup. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) [Flow diagram](#flow-oeg-keeps-app-apis-to-app-providers) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) #### Flow oeg keeps app apis to app providers ```mermaid flowchart TD A["Use operator and App Provider tokens"] --> B["GET an unknown app as operator: require 403"] B["GET an unknown app as operator: require 403"] --> C["GET it as App Provider: require 404 after authorization"] ``` ### oeg keeps federation to operators Require HTTP 403 when an App Provider calls an operator-only federation route. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) [Flow diagram](#flow-oeg-keeps-federation-to-operators) · [Test source](../../ansible/tests/r2_e2e/test_auth.py) #### Flow oeg keeps federation to operators ```mermaid flowchart TD A["Use an App Provider token"] --> B["GET an operator-only federation route"] B["GET an operator-only federation route"] --> C["Require HTTP 403"] ``` ### fm internal api is not public FM serves /internal/* only on its cluster-internal port, never on the EWBI one. [Flow diagram](EXPLAINED.md#login-and-access) · [Test source](../../ansible/tests/r2_e2e/test_exposure.py) [Flow diagram](#flow-fm-internal-api-is-not-public) · [Test source](../../ansible/tests/r2_e2e/test_exposure.py) #### Flow fm internal api is not public ```mermaid flowchart TD A["Use the public FM address"] --> B["GET internal identity and partner routes"] B["GET internal identity and partner routes"] --> C["Require HTTP 404 for both"] ``` ### app provider registers reads and deletes an app Onboard an application through OEG, read its stored manifest and list entry, then verify catalogue removal. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) [Flow diagram](#flow-app-provider-registers-reads-and-deletes-an-app) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) #### Flow app provider registers reads and deletes an app ```mermaid flowchart TD A["Fixture registers an owned app through OEG"] --> B["Read its stored manifest and catalogue entry"] B["Read its stored manifest and catalogue entry"] --> C["Delete the app"] C["Delete the app"] --> D["Require 404 and absence from the catalogue list"] ``` ### app provider lists its apps Verify the application registered by this test client appears in its catalogue list. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) [Flow diagram](#flow-app-provider-lists-its-apps) · [Test source](../../ansible/tests/r2_e2e/test_apps.py) #### Flow app provider lists its apps ```mermaid flowchart TD A["Fixture registers an owned app"] --> B["GET the catalogue as that provider"] B["GET the catalogue as that provider"] --> C["Require the owned app ID in the list"] C["Require the owned app ID in the list"] --> D["Fixture removes the app"] ``` ### invalid application is not registered Reject a missing application name or unsupported package and prove no catalogue record was created. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-invalid-application-is-not-registered) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow invalid application is not registered ```mermaid flowchart TD A["Choose missing-name or unsupported QCOW2 manifest"] --> B["POST the app through OEG"] B["POST the app through OEG"] --> C["Require 400 or 501 for the selected case"] C["Require 400 or 501 for the selected case"] --> D["GET the app and catalogue: prove it was not registered"] ``` ### duplicate onboarding preserves the registered application Require HTTP 409 for duplicate onboarding and prove the original application was preserved. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-duplicate-onboarding-preserves-the-registered-application) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow duplicate onboarding preserves the registered application ```mermaid flowchart TD A["Fixture registers the original app"] --> B["POST its ID again with a changed name"] B["POST its ID again with a changed name"] --> C["Require HTTP 409"] C["Require HTTP 409"] --> D["GET the app: require the original name"] ``` ### unknown application cannot be instantiated Reject instantiation of an unknown application and prove no instance was created. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-unknown-application-cannot-be-instantiated) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow unknown application cannot be instantiated ```mermaid flowchart TD A["POST an instance for an unknown app ID"] --> B["Require HTTP 400"] B["Require HTTP 400"] --> C["GET instances filtered by that app"] C["GET instances filtered by that app"] --> D["Require an empty list"] ``` ### unknown instance cannot be terminated Require HTTP 404 for deletion of a nonexistent application instance. [Flow diagram](EXPLAINED.md#application-catalogue) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) [Flow diagram](#flow-unknown-instance-cannot-be-terminated) · [Test source](../../ansible/tests/r2_e2e/test_release_failures.py) #### Flow unknown instance cannot be terminated ```mermaid flowchart TD A["GET instances for an unknown instance ID"] --> B["Require an empty list"] B["Require an empty list"] --> C["DELETE that unknown instance"] C["DELETE that unknown instance"] --> D["Require HTTP 404"] ``` ### cloud zones match configured workload targets Compare public zone names and unique identities with the workload zones configured in this lab. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-cloud-zones-match-configured-workload-targets) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow cloud zones match configured workload targets ```mermaid flowchart TD A["GET cloud zones through OEG"] --> B["Compare names with the configured workload zones"] B["Compare names with the configured workload zones"] --> C["Require unique IDs, active status and provider fields"] ``` ### progressive oeg request creates a ready workload Instantiate through OEG and independently require the owned Kubernetes Deployment, ready Pod and NodePort Service. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-request-creates-a-ready-workload) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg request creates a ready workload ```mermaid flowchart TD A["Shared fixture onboards and requests instantiation through OEG"] --> B["Observe the owned ready Deployment and Pod"] B["Observe the owned ready Deployment and Pod"] --> C["Observe the owned NodePort Service"] C["Observe the owned NodePort Service"] --> D["Require real Pod and Service identities"] ``` ### progressive workload applies requested resources Compare requested CPU and decimal-MB memory with the actual Kubernetes Deployment and Pod resource requests. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-workload-applies-requested-resources) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive workload applies requested resources ```mermaid flowchart TD A["Use the same deployed container and its requested CPU and memory"] --> B["Read resource requests from Deployment and Pod"] B["Read resource requests from Deployment and Pod"] --> C["Compare Kubernetes quantities with the original request"] ``` ### progressive oeg returns the application instance Poll the public instance until ready and verify its application and zone identities. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-returns-the-application-instance) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg returns the application instance ```mermaid flowchart TD A["Use the same deployed application"] --> B["Poll its public instance until ready"] B["Poll its public instance until ready"] --> C["Verify app and zone identities"] C["Verify app and zone identities"] --> D["Require ready status"] ``` ### progressive oeg returns the observed endpoint Compare the public application endpoint with the actual owned Kubernetes Service and cluster node. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-returns-the-observed-endpoint) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg returns the observed endpoint ```mermaid flowchart TD A["Use the observed owned Service and node"] --> B["Read the endpoint returned by OEG"] B["Read the endpoint returned by OEG"] --> C["Compare host, port and protocol with Kubernetes"] ``` ### progressive endpoint reaches the deployed application Call the returned HTTP endpoint and verify the response identifies the deployed application Pod. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-endpoint-reaches-the-deployed-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive endpoint reaches the deployed application ```mermaid flowchart TD A["Use the endpoint returned by OEG"] --> B["Send an HTTP request to that address"] B["Send an HTTP request to that address"] --> C["Require the expected successful response"] C["Require the expected successful response"] --> D["Match the response with the deployed Pod identity"] ``` ### progressive oeg termination removes the workload Terminate through OEG and verify the public instance and owned Deployment, Pod and Service disappear. [Flow diagram](EXPLAINED.md#starting-an-application) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-progressive-oeg-termination-removes-the-workload) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow progressive oeg termination removes the workload ```mermaid flowchart TD A["Use the same deployed application"] --> B["Request termination through OEG"] B["Request termination through OEG"] --> C["Poll public instance removal"] C["Poll public instance removal"] --> D["Verify the owned Deployment, Pod and Service disappear"] ``` ### qod profile lifecycle Create and read QoD through OEG, inspect the real NEF resource and flow, then verify public and provider deletion. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-qod-profile-lifecycle) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow qod profile lifecycle ```mermaid flowchart TD A["POST QoD with one configured profile"] --> B["Poll the public session to AVAILABLE"] B["Poll the public session to AVAILABLE"] --> C["Inspect NEF profile, device IP, host flow and notification URL"] C["Inspect NEF profile, device IP, host flow and notification URL"] --> D["Fixture deletes the session and verifies public and provider cleanup"] ``` ### qod unsupported profile is rejected Reject a profile outside this control path configuration and prove no provider subscription remains. Request a disallowed QoD profile, wait for UNAVAILABLE and verify no provider subscription was created. [Flow diagram](#flow-qod-unsupported-profile-is-rejected) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow qod unsupported profile is rejected ```mermaid flowchart TD A["POST a profile excluded by SDK configuration"] --> B["Keep the returned session ID"] B["Keep the returned session ID"] --> C["Poll its QoD status to UNAVAILABLE"] C["Poll its QoD status to UNAVAILABLE"] --> D["Require the NEF subscription collection to remain unchanged"] ``` ### qod backend refusal retains diagnostics Use a locally allowed profile refused by the NEF and require useful backend diagnostics and cleanup. Request a profile refused by the NEF, wait for UNAVAILABLE and check safe HTTP 400 diagnostics and cleanup. [Flow diagram](#flow-qod-backend-refusal-retains-diagnostics) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow qod backend refusal retains diagnostics [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) ```mermaid flowchart TD A["POST an SDK-allowed profile unknown to the NEF"] --> B["Poll its QoD status to UNAVAILABLE"] B["Poll its QoD status to UNAVAILABLE"] --> C["Read SRM structured logs: require backend HTTP 400 diagnostics"] C["Read SRM structured logs: require backend HTTP 400 diagnostics"] --> D["Require the NEF subscription collection to remain unchanged"] ``` ### known device returns geographic location Retrieve the simulated device location through OEG and verify geographic coordinates and freshness. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-known-device-returns-geographic-location) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow known device returns geographic location ```mermaid flowchart TD A["Use the simulated device IP"] --> B["POST location retrieval with maxAge 300"] B["POST location retrieval with maxAge 300"] --> C["Require HTTP 200 and a fresh location time"] C["Require HTTP 200 and a fresh location time"] --> D["Check coordinates against the configured CoreSim area"] ``` ### location without device is rejected Require the public missing-identifier error when location retrieval has no device. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-location-without-device-is-rejected) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow location without device is rejected ```mermaid flowchart TD A["POST location retrieval without a device"] --> B["Require HTTP 422"] B["Require HTTP 422"] --> C["Require the MISSING_IDENTIFIER error code"] ``` ### device ti uses the deployed application endpoint Activate device TI through OEG, verify real device/application IPs and notification URL in the NEF, then verify deletion. [Flow diagram](EXPLAINED.md#network-features) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) [Flow diagram](#flow-device-ti-uses-the-deployed-application-endpoint) · [Test source](../../ansible/tests/r2_e2e/test_deploy_to_ti.py) #### Flow device ti uses the deployed application endpoint ```mermaid flowchart TD A["Use the observed endpoint of the shared deployed app"] --> B["POST traffic-influence-devices with device and instance IDs"] B["POST traffic-influence-devices with device and instance IDs"] --> C["Poll the public TI state to active"] C["Poll the public TI state to active"] --> D["Inspect NEF device IP, app IP, host flow and notification URL"] D["Inspect NEF device IP, app IP, host flow and notification URL"] --> E["DELETE TI and verify public and provider removal"] ```
ci/lab/EXPLAINED.md +2 −2 Changes for ci/lab/EXPLAINED.md: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -142,6 +142,6 @@ accuracy. The matrix keeps these limits alongside each result. ## Choose a check or run the lab The [individual check catalogue](CHECKS.md) explains each test and links back to its flow diagram and source. The [operator guide](README.md) contains local The [individual check catalogue](CHECKS.md) explains each test with its own flow diagram and source link. The [operator guide](README.md) contains local commands, profiles and troubleshooting.
ci/lab/README.md +3 −3 Changes for ci/lab/README.md: 3 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -8,7 +8,7 @@ New to OpenOP? Read the short [illustrated overview](EXPLAINED.md) and Open release-feature-report in the pipeline for the readable job summary and links to the HTML feature report, Tests tab and exact-source guide. The HTML report links each feature to its actual run and each test to its explanation, shared flow diagram and source. If the server cannot preview HTML artifacts, specific flow diagram and source. If the server cannot preview HTML artifacts, download index.html and open it locally; the job log remains readable in GitLab. The existing Markdown/JSON receipts remain available. Loading Loading @@ -451,8 +451,8 @@ healthy before Nginx resolves their names at startup. The existing verifier still owns qualification. Presentation consumes its actual JSON/JUnit; it never infers a pass from a missing case or a green badge. Documentation stays beside the tests and report links use the exact run commit. Shared flow diagrams explain several related assertions without copying the scenario or adding another execution framework. The overview explains the common journey. Each catalogue check has its own flow diagram without adding another execution framework. - [JUnit reports](https://docs.gitlab.com/ci/testing/unit_test_reports/) put individual cases and their purpose in the native Tests tab. Distinct job Loading