Commit 6f1a3527 authored by Konstantinos Togias's avatar Konstantinos Togias
Browse files

test: use supported Kubernetes resources in SDK acceptance

parent 46c2b84a
Loading
Loading
Loading
Loading
+22 −5
Changes for ansible/tests/r2_e2e/SDK_ACCEPTANCE.md: 22 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -24,11 +24,13 @@ of this run. No existing test is marked xfail or weakened.
   Compute `sdk.sha256` from the independently reviewed wheel:

   ```sh
   python tests/r2_e2e/sdk_artifact.py /disk/artifacts/openop_tfsdk-1.1.1-py3-none-any.whl
   python tests/r2_e2e/sdk_artifact.py /disk/artifacts/openop_tfsdk-2.0.0rc3-py3-none-any.whl
   ```

   The same script runs read-only in the selected SRM pod. Python/chart contents
   and package version must match; version 1.1.1 alone cannot identify a commit.
   and package version must match; the version alone cannot identify a commit.
   Replace all three SDK fields with the selected candidate; the command shows
   the published rc3 filename as an example, not the final release candidate.
   Record the reviewed source SHA alongside the wheel fingerprint. The test
   verifies both SRM/OEG running image digests before creating a test client.

@@ -59,9 +61,9 @@ Cleanup uses public OEG deletion, only for this run's application/instances/TI,
then removes that client. Cleanup failures are reported alongside the test
failure, and no namespace, platform release or unrelated resource is deleted.

The current SDK baseline returns no endpoints, so this assertion is expected
to fail once a compatible lab is available. That is not a live failure already
reproduced by this change. Capture the red baseline before changing the SDK.
The release SDK can return NodePort endpoints. This scenario still requires
a compatible SRM/OEG image set, explicit control-path configuration and a real
lab run; offline success does not qualify the selected live candidate.

## Complete the TI checkpoint separately

@@ -114,3 +116,18 @@ JUnit and a qualification receipt record the selected checkpoint, source SHA,
SDK wheel checksum and running SRM/OEG image digests. No credentials or complete
settings/profile are exported as CI artifacts. A passing endpoints checkpoint
cannot substitute for Traffic Influence or other release acceptance scenarios.


## Public container request

Catalogue and SDK acceptance use the same container manifest builder. The
public Kubernetes shape is requiredResources.infraKind=kubernetes with
isStandalone=false and applicationResources.cpuPool containing integer numCPU,
memory in MB and the required topology. Canonical SDK values such as100m belong
at the SDK boundary, not in this public request.

The default is one CPU core and256MB. An optional resource_requests profile
object can select {"cpu":2,"memory_mb":257}; CPU must be an integer1–256 and
memory_mb an integer1–16384. Invalid values fail during profile loading, before
creating lab clients. This bounded repair fixes request construction; observing
applied Deployment/Pod resources belongs to the next cumulative checkpoint.
+34 −0
Changes for ansible/tests/r2_e2e/app_manifest.py: 34 added lines, 0 removed lines.
Original line number Diff line number Diff line
"""The supported Release 2 container shape shared by catalogue and workload tests."""

import secrets
from uuid import uuid4


def validated_resource_requests(profile):
    requested = profile.get("resource_requests", {"cpu": 1, "memory_mb": 256})
    if (not isinstance(requested, dict) or set(requested) != {"cpu", "memory_mb"}
            or type(requested.get("cpu")) is not int or not 1 <= requested["cpu"] <= 256
            or type(requested.get("memory_mb")) is not int or not 1 <= requested["memory_mb"] <= 16384):
        raise ValueError("resource_requests requires integer CPU cores1–256 and memory_mb1–16384 for Kubernetes cpuPool")
    return requested


def container_manifest(image="nginx:1.27-alpine", *, app_id=None, name=None, cpu=1, memory_mb=256):
    return {
        "appId": app_id or str(uuid4()),
        "name": name or f"e2e_web_{secrets.token_hex(3)}",
        "appProvider": "e2e_app_provider",
        "version": "1.0.0",
        "packageType": "CONTAINER",
        "appRepo": {"type": "PUBLICREPO", "imagePath": image},
        "requiredResources": {
            "infraKind": "kubernetes", "isStandalone": False,
            "applicationResources": {"cpuPool": {
                "numCPU": cpu, "memory": memory_mb,
                "topology": {"minNumberOfNodes": 1, "minNodeCpu": 1, "minNodeMemory": 256},
            }},
        },
        "componentSpec": [{"componentName": "web", "networkInterfaces": [
            {"interfaceId": "http", "protocol": "TCP", "port": 80,
             "visibilityType": "VISIBILITY_EXTERNAL"}]}],
    }
+3 −3
Changes for ansible/tests/r2_e2e/profiles/deploy_to_ti.example.json: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -19,9 +19,9 @@
    "image_digest": "sha256:REPLACE_WITH_REVIEWED_OEG_IMAGE_DIGEST"
  },
  "sdk": {
    "revision": "c748ee15857eead260d933f75f59516e5698f929",
    "version": "2.0.0rc2",
    "sha256": "d5dfd568b89e8368217cb5094f9a48c1170c97aed87fd01f388b119409125eb9"
    "revision": "REPLACE_WITH_REVIEWED_SDK_SOURCE_SHA",
    "version": "REPLACE_WITH_REVIEWED_CANDIDATE_VERSION",
    "sha256": "REPLACE_WITH_REVIEWED_SDK_CONTENT_FINGERPRINT"
  },
  "ti": {
    "application_wide_supported": false,
+7 −22
Changes for ansible/tests/r2_e2e/sdk_scenario.py: 7 added lines, 22 removed lines.
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ import time
from urllib.parse import urlparse
from uuid import uuid4

from app_manifest import container_manifest, validated_resource_requests


def load_profile(path, checkpoint):
    profile = json.loads(Path(path).read_text())
@@ -39,6 +41,7 @@ def load_profile(path, checkpoint):
        or not 1 <= profile["timeout_seconds"] <= 900
    ):
        raise ValueError("timeout_seconds must be between 1 and 900")
    validated_resource_requests(profile)
    if checkpoint == "ti":
        ti = profile["ti"]
        if ti["application_wide_supported"] is not True:
@@ -229,28 +232,10 @@ class Scenario:
        active = [z for z in zones.json() if z["edgeCloudZoneStatus"] == "active"]
        assert len(active) == 1, "The dedicated lab must expose exactly one active local zone"
        self.zone_id = active[0]["edgeCloudZoneId"]
        manifest = {
            "appId": self.app_id,
            "name": self.name,
            "appProvider": "sdk_e2e_provider",
            "version": "1.0.0",
            "packageType": "CONTAINER",
            "appRepo": {"type": "PUBLICREPO", "imagePath": self.profile["application_image"]},
            "requiredResources": {"infraKind": "container", "numCPU": "100m", "memory": 128},
            "componentSpec": [
                {
                    "componentName": "web",
                    "networkInterfaces": [
                        {
                            "interfaceId": "http",
                            "protocol": "TCP",
                            "port": 80,
                            "visibilityType": "VISIBILITY_EXTERNAL",
                        }
                    ],
                }
            ],
        }
        manifest = container_manifest(
            self.profile["application_image"], app_id=self.app_id, name=self.name,
            **validated_resource_requests(self.profile)
        )
        # A unique caller-supplied ID permits bounded cleanup after a lost response.
        self.registered = True
        response = self.call("POST", self.apps, json=manifest)
+1 −21
Changes for ansible/tests/r2_e2e/test_apps.py: 1 added line, 21 removed lines.
Original line number Diff line number Diff line
"""App Providers register applications at OEG, which keeps them in SRM's catalog."""

import secrets

import pytest

from app_manifest import container_manifest as _manifest
from conftest import http

APPS = "/edge-application-management/v0.1alpha1/apps"


def _manifest():
    return {
        "name": f"e2e_nginx_{secrets.token_hex(3)}",
        "appProvider": "e2e_app_provider",
        "version": "1.0.0",
        "packageType": "CONTAINER",
        "appRepo": {"type": "PUBLICREPO", "imagePath": "nginx:1.27-alpine"},
        "requiredResources": {
            "infraKind": "kubernetes", "isStandalone": False,
            "applicationResources": {"cpuPool": {
                "numCPU": 1, "memory": 256,
                "topology": {"minNumberOfNodes": 1, "minNodeCpu": 1, "minNodeMemory": 256},
            }},
        },
        "componentSpec": [{"componentName": "web", "networkInterfaces": [
            {"interfaceId": "http", "protocol": "TCP", "port": 80,
             "visibilityType": "VISIBILITY_EXTERNAL"}]}],
    }


@pytest.fixture
def registered_app(operators, callers):
Loading