Commit e47126f3 authored by Konstantinos Togias's avatar Konstantinos Togias
Browse files

docs: give every E2E check its own direct flow diagram

parent 7d044d58
Loading
Loading
Loading
Loading
Loading
+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
@@ -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)


+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
@@ -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()
+251 −28
Changes for ci/lab/CHECKS.md: 251 added lines, 28 removed lines.
Original line number Diff line number Diff line
@@ -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"]
```
+2 −2
Changes for ci/lab/EXPLAINED.md: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -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.
+3 −3
Changes for ci/lab/README.md: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -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.

@@ -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