Commit 2dce7a3d authored by Adrian Pino's avatar Adrian Pino
Browse files

enhance EdgeCloud iface, i2Edge client & fix tests for CAMARA compliance

- Reorganize client code with clear CAMARA/GSMA API section separation
- Implement CAMARA-compliant schemas and response formatting for all operations
- Add comprehensive CAMARA validation for application lifecycle operations
- Update test configurations with real i2Edge endpoints and CAMARA payloads
- Enhance error handling and standardize response patterns across adapters
- Remove deprecated utility functions and improve code organization
parent 54afb57f
Loading
Loading
Loading
Loading
+324 −112

File changed.

Preview size limit exceeded, changes collapsed.

+12 −8
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ class EdgeCloudManagementInterface(ABC):
        :param status: Filter by status (active, inactive, unknown).
        :return: List of Edge Cloud Zones.
        """
        # TODO: Evaluate if the CAMARA-input format
        # TODO: Evaluate the CAMARA-return format
        pass

    @abstractmethod
@@ -43,42 +45,43 @@ class EdgeCloudManagementInterface(ABC):
        pass

    @abstractmethod
    def get_all_onboarded_apps(self) -> List[Dict]:
    def get_all_onboarded_apps(self) -> Response:
        """
        Retrieves a list of onboarded applications.

        :return: List of application metadata dictionaries.
        :return: Response with list of application metadata.
        """
        pass

    @abstractmethod
    def get_onboarded_app(self, app_id: str) -> Dict:
    def get_onboarded_app(self, app_id: str) -> Response:
        """
        Retrieves information of a specific onboarded application.

        :param app_id: Unique identifier of the application.
        :return: Dictionary with application details.
        :return: Response with application details.
        """
        pass

    @abstractmethod
    def delete_onboarded_app(self, app_id: str) -> None:
    def delete_onboarded_app(self, app_id: str) -> Response:
        """
        Deletes an application onboarded from the Edge Cloud Provider.

        :param app_id: Unique identifier of the application.
        :return: Response confirming deletion.
        """
        pass

    @abstractmethod
    def deploy_app(self, app_id: str, app_zones: List[Dict]) -> Dict:
    def deploy_app(self, app_id: str, app_zones: List[Dict]) -> Response:
        """
        Requests the instantiation of an application instance.

        :param app_id: Unique identifier of the application.
        :param app_zones: List of Edge Cloud Zones where the app should be
        instantiated.
        :return: Dictionary with instance details.
        :return: Response with instance details.
        """
        pass

@@ -100,11 +103,12 @@ class EdgeCloudManagementInterface(ABC):
        pass

    @abstractmethod
    def undeploy_app(self, app_instance_id: str) -> None:
    def undeploy_app(self, app_instance_id: str) -> Response:
        """
        Terminates a specific application instance.

        :param app_instance_id: Unique identifier of the application instance.
        :return: Response confirming termination.
        """
        pass

+4 −2
Original line number Diff line number Diff line
@@ -19,8 +19,10 @@ class AppId(RootModel[UUID]):
    )


class AppInstanceId(RootModel[UUID]):
    root: UUID = Field(
# TODO: Update to AppInstanceId(RootModel[UUID])
# As a temporary solution RootModel[str] will be used until i2Edge get's updated
class AppInstanceId(RootModel[str]):
    root: str = Field(
        ...,
        description="A globally unique identifier associated with a running\ninstance of an application.\nEdge Cloud Platform generates this identifier when the\ninstantiation in the Edge Cloud Zone is successful.\n",
    )
+0 −17
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@
#   - César Cajas (cesar.cajas@i2cat.net)
##
import json
from uuid import NAMESPACE_DNS, UUID, uuid5

from requests import Response

@@ -16,22 +15,6 @@ from sunrise6g_opensdk import logger
log = logger.get_logger(__name__)


def ensure_valid_uuid(value: str) -> str:
    """
    Return the original value if it's a valid UUID,
    or generate a deterministic UUIDv5 from the input string otherwise.
    """
    try:
        UUID(value)
        return value
    except ValueError:
        generated = str(uuid5(NAMESPACE_DNS, value))
        log.warning(
            f"[WARNING] Invalid UUID '{value}' – using generated UUIDv5: {generated}"
        )
    return generated


def build_custom_http_response(
    status_code: int,
    content: str | bytes | dict | list,
+53 −27
Original line number Diff line number Diff line
CONFIG = {
    "i2edge": {
        "ZONE_ID": "Omega",
        # Basic identifiers
        "ZONE_ID": "f0662bfe-1d90-5f59-a759-c755b3b69b93",
        "APP_ID": "9c9143f0-f44f-49df-939e-1e8b891ba8f5",
        # Artefact-related fields (non-CAMARA endpoints)
        "ARTEFACT_ID": "9c9143f0-f44f-49df-939e-1e8b891ba8f5",
        "ARTEFACT_NAME": "i2edgechart",
        "REPO_NAME": "github-cesar",
        "REPO_TYPE": "PUBLICREPO",
        "REPO_URL": "https://cesarcajas.github.io/helm-charts-examples/",
        # CAMARA onboard_app payload
        "APP_ONBOARD_MANIFEST": {
            "appId": "9c9143f0-f44f-49df-939e-1e8b891ba8f5",
            "appId": "9c9143f0-f44f-49df-939e-1e8b891ba8f5",  # Optional to CAMARA
            "name": "i2edge_app_SDK",
            "version": "1.0.0",
            "appProvider": "i2CAT_DEV",
@@ -46,20 +50,22 @@ CONFIG = {
                }
            ],
        },
        "APP_ID": "9c9143f0-f44f-49df-939e-1e8b891ba8f5",
        "APP_ZONES": [
        # CAMARA deploy_app payload
        "APP_DEPLOY_PAYLOAD": {
            "appId": "9c9143f0-f44f-49df-939e-1e8b891ba8f5",
            "appZones": [
                {
                "kubernetesClusterRef": "not-used",
                    "EdgeCloudZone": {
                    "edgeCloudZoneId": "Omega",
                    "edgeCloudZoneName": "not-used",
                    "edgeCloudZoneStatus": "not-used",
                    "edgeCloudProvider": "not-used",
                    "edgeCloudRegion": "not-used",
                },
                        "edgeCloudZoneId": "f0662bfe-1d90-5f59-a759-c755b3b69b93",
                        "edgeCloudZoneName": "i2edge-zone-1",
                        "edgeCloudZoneStatus": "active",
                        "edgeCloudProvider": "i2CAT",
                        "edgeCloudRegion": "Europe-West",
                    }
                }
            ],
        },
    },
    "aeros": {
        "ZONE_ID": "urn:ngsi-ld:Domain:NCSRD",
        "ARTEFACT_ID": "aeros-app-2",
@@ -108,23 +114,43 @@ CONFIG = {
            ],
        },
        "APP_ID": "aeros-app-2",
        "APP_ZONES": [
        # CAMARA deploy_app payload
        "APP_DEPLOY_PAYLOAD": {
            "appId": "aeros-app-2",
            "appZones": [
                {
                "kubernetesClusterRef": "not-used",
                    "EdgeCloudZone": {
                        "edgeCloudZoneId": "urn:ngsi-ld:Domain:NCSRD",
                    "edgeCloudZoneName": "not-used",
                    "edgeCloudZoneStatus": "not-used",
                    "edgeCloudProvider": "not-used",
                    "edgeCloudRegion": "not-used",
                },
                        "edgeCloudZoneName": "aeros-zone-1",
                        "edgeCloudZoneStatus": "active",
                        "edgeCloudProvider": "NCSRD",
                        "edgeCloudRegion": "Europe-South",
                    }
                }
            ],
        },
    },
    "kubernetes": {
        "K8S_ONBOARDED_APP_NAME": "nginx",
        "K8S_APP_ID": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "APP_ID": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "ZONE_ID": "b2a1b33d-f382-47de-b555-2d32155eb74c",
        # CAMARA deploy_app payload
        "APP_DEPLOY_PAYLOAD": {
            "appId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "appZones": [
                {
                    "EdgeCloudZone": {
                        "edgeCloudZoneId": "b2a1b33d-f382-47de-b555-2d32155eb74c",
                        "edgeCloudZoneName": "k8s-zone-1",
                        "edgeCloudZoneStatus": "active",
                        "edgeCloudProvider": "kubernetes",
                        "edgeCloudRegion": "Local",
                    }
                }
            ],
        },
        # Legacy K8S_DEPLOY_PAYLOAD for backward compatibility (if needed)
        "K8S_DEPLOY_PAYLOAD": {
            "appId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
            "name": "nginx-test",
Loading