Commit aff3f81f authored by vpitsilis's avatar vpitsilis
Browse files

Edge-Application management initial

parent 8bbf5647
Loading
Loading
Loading
Loading
+204 −40
Original line number Diff line number Diff line
@@ -5,10 +5,14 @@
#   - Vasilis Pitsilis (vpitsilis@dat.demokritos.gr, vpitsilis@iit.demokritos.gr)
#   - Andreas Sakellaropoulos (asakellaropoulos@iit.demokritos.gr)
##
import uuid
from typing import Any, Dict, List, Optional

import yaml

from sunrise6g_opensdk.edgecloud.clients.aeros import config
from sunrise6g_opensdk.edgecloud.clients.aeros.continuum_client import ContinuumClient
from sunrise6g_opensdk.edgecloud.clients.errors import EdgeCloudPlatformError
from sunrise6g_opensdk.edgecloud.core.edgecloud_interface import (
    EdgeCloudManagementInterface,
)
@@ -24,6 +28,8 @@ class EdgeApplicationManager(EdgeCloudManagementInterface):
    def __init__(self, base_url: str, **kwargs):
        self.base_url = base_url
        self.logger = setup_logger(__name__, is_debug=True, file_name=config.LOG_FILE)
        self._app_store: Dict[str, Dict] = {}
        self._deployed_services: Dict[str, List[str]] = {}

        # Overwrite config values if provided via kwargs
        if "aerOS_API_URL" in kwargs:
@@ -42,39 +48,169 @@ class EdgeApplicationManager(EdgeCloudManagementInterface):

    def onboard_app(self, app_manifest: Dict) -> Dict:
        # HLO-FE POST with TOSCA and app_id (service_id)
        service_id = app_manifest.get("serviceId")
        tosca_str = app_manifest.get("tosca")
        aeros_client = ContinuumClient(self.base_url)
        onboard_response = aeros_client.onboard_service(
            service_id=service_id, tosca_str=tosca_str
        # service_id = app_manifest.get("serviceId")
        # tosca_str = app_manifest.get("tosca")
        # aeros_client = ContinuumClient(self.base_url)
        # onboard_response = aeros_client.onboard_service(
        #     service_id=service_id, tosca_str=tosca_str
        # )
        app_id = app_manifest.get("appId")
        if not app_id:
            raise EdgeCloudPlatformError("Missing 'appId' in app manifest")

        if app_id in self._app_store:
            raise EdgeCloudPlatformError(
                f"Application with id '{app_id}' already exists"
            )
        return {"appId": onboard_response["serviceId"]}

        self._app_store[app_id] = app_manifest
        self.logger.debug("Onboarded application with id: %s", app_id)
        return {"appId": app_id}

    def get_all_onboarded_apps(self) -> List[Dict]:
        aeros_client = ContinuumClient(self.base_url)
        ngsild_params = "type=Service&format=simplified"
        aeros_apps = aeros_client.query_entities(ngsild_params)
        return [
            {"appId": service["id"], "name": service["name"]} for service in aeros_apps
        ]
        # return [{"appId": "1234-5678", "name": "TestApp"}]
        # aeros_client = ContinuumClient(self.base_url)
        # ngsild_params = "type=Service&format=simplified"
        # aeros_apps = aeros_client.query_entities(ngsild_params)
        # return [
        #     {"appId": service["id"], "name": service["name"]} for service in aeros_apps
        # ]
        return list(self._app_store.values())

    def get_onboarded_app(self, app_id: str) -> Dict:
        aeros_client = ContinuumClient(self.base_url)
        ngsild_params = "format=simplified"
        aeros_app = aeros_client.query_entity(app_id, ngsild_params)
        return {"appId": aeros_app["id"], "name": aeros_app["name"]}
        # aeros_client = ContinuumClient(self.base_url)
        # ngsild_params = "format=simplified"
        # aeros_app = aeros_client.query_entity(app_id, ngsild_params)
        # return {"appId": aeros_app["id"], "name": aeros_app["name"]}
        if app_id not in self._app_store:
            raise EdgeCloudPlatformError(
                f"Application with id '{app_id}' does not exist"
            )
        return self._app_store[app_id]

    def delete_onboarded_app(self, app_id: str) -> None:
        print(f"Deleting application: {app_id}")
        if app_id not in self._app_store:
            raise EdgeCloudPlatformError(
                f"Application with id '{app_id}' does not exist"
            )
        del self._app_store[app_id]
        # TBD: Purge from continuum (make all ngsil-ld calls for servieId connected entities)
        # Should check if undeployed first

    def _generate_service_id(self, app_id: str) -> str:
        return f"ur n:ngsi-ld:Service:{app_id}-{uuid.uuid4().hex[:4]}"

    def _generate_tosca_yaml_dict(
        self, app_manifest: Dict, app_zones: List[Dict]
    ) -> Dict:
        component = app_manifest.get("componentSpec", [{}])[0]
        component_name = component.get("componentName", "application")

        image_path = app_manifest.get("appRepo", {}).get("imagePath", "")
        # Extract image_file
        image_file = image_path.split("/")[-1]
        # Extract repository_url
        if "/" in image_path:
            repository_url = "/".join(image_path.split("/")[:-1])
        else:
            repository_url = "docker_hub"
        zone_id = (
            app_zones[0].get("EdgeCloudZone", {}).get("edgeCloudZoneId", "default-zone")
        )
        ports = {}
        for iface in component.get("networkInterfaces", []):
            interface_id = iface.get("interfaceId", "default")
            protocol = iface.get("protocol", "TCP").lower()
            port = iface.get("port", 8080)
            ports[interface_id] = {
                "properties": {"protocol": [protocol], "source": port}
            }
        expose_ports = any(
            iface.get("visibilityType") == "VISIBILITY_EXTERNAL"
            for iface in component.get("networkInterfaces", [])
        )

        yaml_dict = {
            "tosca_definitions_version": "tosca_simple_yaml_1_3",
            "description": f"TOSCA for {app_manifest.get('name', 'application')}",
            "node_templates": {
                component_name: {
                    "type": "tosca.nodes.Container.Application",
                    "requirements": [
                        {
                            "network": {
                                "properties": {
                                    "ports": ports,
                                    "exposePorts": expose_ports,
                                }
                            }
                        },
                        {"host": {"node_filter": {"properties": {"id": zone_id}}}},
                    ],
                    "artifacts": {
                        "application_image": {
                            "file": image_file,
                            "type": "tosca.artifacts.Deployment.Image.Container.Docker",
                            "repository": repository_url,
                        }
                    },
                    "interfaces": {
                        "Standard": {
                            "create": {
                                "implementation": "application_image",
                                "inputs": {"cliArgs": [], "envVars": []},
                            }
                        }
                    },
                }
            },
        }

        return yaml_dict

    def deploy_app(self, app_id: str, app_zones: List[Dict]) -> Dict:
        # HLO-FE PUT with app_id (service_id)
        # aeros_client = ContinuumClient(self.base_url)
        # deploy_response = aeros_client.deploy_service(app_id)
        # return {"deploy_name": deploy_response["serviceId"]}
        # 1. Get app CAMARA manifest
        app_manifest = self._app_store.get(app_id)
        if not app_manifest:
            raise EdgeCloudPlatformError(
                f"Application with id '{app_id}' does not exist"
            )

        # 2. Generate unique service ID
        service_id = self._generate_service_id(app_id)
        # Dev test
        # service_id = "service-my-id"

        # yaml_dict = {
        #     "serviceId": service_id,
        #     "tosca": app_manifest.get("tosca", "")
        # }

        # 5. Convert dict to YAML string
        yaml_dict = self._generate_tosca_yaml_dict(app_manifest, app_zones)
        tosca_yaml = yaml.dump(yaml_dict, sort_keys=False)
        print("Generated TOSCA YAML:")
        print(tosca_yaml)
        response = {"serviceId": service_id}  # Mocked response
        # 6. Instantiate client and call onboard_service
        aeros_client = ContinuumClient(self.base_url)
        deploy_response = aeros_client.deploy_service(app_id)
        return {"appInstanceId": deploy_response["serviceId"]}
        response = aeros_client.onboard_service(service_id, tosca_yaml)

        if "serviceId" not in response:
            raise EdgeCloudPlatformError(
                "Invalid response from onboard_service: missing 'serviceId'"
            )

        # 7. Track deployment
        if app_id not in self._deployed_services:
            self._deployed_services[app_id] = []
        self._deployed_services[app_id].append(service_id)

        # 8. Return expected format
        return {"appInstanceId": response["serviceId"]}

    def get_all_deployed_apps(
        self,
@@ -82,22 +218,27 @@ class EdgeApplicationManager(EdgeCloudManagementInterface):
        app_instance_id: Optional[str] = None,
        region: Optional[str] = None,
    ) -> List[Dict]:
        # FIXME: Get services in deployed state
        aeros_client = ContinuumClient(self.base_url)
        ngsild_params = 'type=Service&format=simplified&q=actionType=="DEPLOYED"'
        if app_id:
            ngsild_params += f'&q=service=="{app_id}"'
        aeros_apps = aeros_client.query_entities(ngsild_params)
        return [
            {
                "appInstanceId": service["id"],
                "status":
                # scomponent["serviceComponentStatus"].split(":")[-1].lower()
                service["actionType"],
            }
            for service in aeros_apps
        ]
        # return [{"appInstanceId": "abcd-efgh", "status": "ready"}]
        # # FIXME: Get services in deployed state
        # aeros_client = ContinuumClient(self.base_url)
        # ngsild_params = 'type=Service&format=simplified&q=actionType=="DEPLOYED"'
        # if app_id:
        #     ngsild_params += f'&q=service=="{app_id}"'
        # aeros_apps = aeros_client.query_entities(ngsild_params)
        # return [
        #     {
        #         "appInstanceId": service["id"],
        #         "status":
        #         # scomponent["serviceComponentStatus"].split(":")[-1].lower()
        #         service["actionType"],
        #     }
        #     for service in aeros_apps
        # ]
        # # return [{"appInstanceId": "abcd-efgh", "status": "ready"}]
        deployed = []
        for stored_app_id, instance_ids in self._deployed_services.items():
            for instance_id in instance_ids:
                deployed.append({"appId": stored_app_id, "appInstanceId": instance_id})
        return deployed

    # def get_all_deployed_apps(self,
    #                           app_id: Optional[str] = None,
@@ -118,9 +259,31 @@ class EdgeApplicationManager(EdgeCloudManagementInterface):
    #     # return [{"appInstanceId": "abcd-efgh", "status": "ready"}]

    def undeploy_app(self, app_instance_id: str) -> None:
        # HLO-FE DELETE with app_id (service_id)
        # 1. Locate app_id corresponding to this instance
        found_app_id = None
        for app_id, instances in self._deployed_services.items():
            if app_instance_id in instances:
                found_app_id = app_id
                break

        if not found_app_id:
            raise EdgeCloudPlatformError(
                f"No deployed app instance with ID '{app_instance_id}' found"
            )

        # 2. Call the external undeploy_service
        aeros_client = ContinuumClient(self.base_url)
        _ = aeros_client.undeploy_service(app_instance_id)
        try:
            aeros_client.undeploy_service(app_instance_id)
        except Exception as e:
            raise EdgeCloudPlatformError(
                f"Failed to undeploy app instance '{app_instance_id}': {str(e)}"
            )

        # 3. Clean up internal tracking
        self._deployed_services[found_app_id].remove(app_instance_id)
        if not self._deployed_services[found_app_id]:
            del self._deployed_services[found_app_id]

    def get_edge_cloud_zones(
        self, region: Optional[str] = None, status: Optional[str] = None
@@ -130,8 +293,9 @@ class EdgeApplicationManager(EdgeCloudManagementInterface):
        aeros_domains = aeros_client.query_entities(ngsild_params)
        return [
            {
                "edgeCloudZoneId": domain["id"],
                "zoneId": domain["id"],
                "status": domain["domainStatus"].split(":")[-1].lower(),
                "geographyDetails": "NOT_USED",
            }
            for domain in aeros_domains
        ]
+0 −1
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@ from typing import Optional, Union
from uuid import UUID

from src.edgecloud import logger

from sunrise6g_opensdk.edgecloud.api.routers.lcm.schemas import RequiredResources
from sunrise6g_opensdk.edgecloud.core import utils as core_utils

+4 −4
Original line number Diff line number Diff line
@@ -13,11 +13,11 @@ EDGE_CLOUD_TEST_CASES = [
    {
        "edgecloud": {
            "client_name": "aeros",
            "base_url": "http://test-aeros.url",
            "base_url": "https://ncsrd-mvp-domain.aeros-project.eu",
            # Additional parameters for aerOS client:
            "aerOS_API_URL": "http://fake.api.url",
            "aerOS_ACCESS_TOKEN": "fake-access",
            "aerOS_HLO_TOKEN": "fake-hlo",
            "aerOS_API_URL": "https://ncsrd-mvp-domain.aeros-project.eu",
            "aerOS_ACCESS_TOKEN": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJzaTcxSzNkUm11UFIxY2RhT2daNVFtbGpUVlR6U3JQM0cyYlZNdEVDeUVjIn0.eyJleHAiOjE4MTcwMzUwMTksImlhdCI6MTczMDcyMTQxOSwianRpIjoiODk2ODhlODktNTRmOS00MzFhLTliZTUtOTQ5MmMxYjE0NDZiIiwiaXNzIjoiaHR0cHM6Ly9rZXljbG9hay5jZi1tdnAtZG9tYWluLmFlcm9zLXByb2plY3QuZXUvYXV0aC9yZWFsbXMva2V5Y2xvYWNrLW9wZW5sZGFwIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImE5ZWY0ZTFiLTg5NTgtNGZkYS1hODQ5LTJlNjdlZmY3NjkzMyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFlcm9zLXRlc3QiLCJzZXNzaW9uX3N0YXRlIjoiOGM2MTJjMDYtYTE5MS00MjBmLTlmNTItZGU5OWZiYzJkODI3IiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJDbG91ZEZlcnJvRG9tYWluIiwiZGVmYXVsdC1yb2xlcy1rZXljbG9hY2stb3BlbmxkYXAiLCJvZmZsaW5lX2FjY2VzcyIsIklvVCBzZXJ2aWNlIGRlcGxveWVyIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiI4YzYxMmMwNi1hMTkxLTQyMGYtOWY1Mi1kZTk5ZmJjMmQ4MjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJJb1Qgc2VydmljZSBkZXBsb3llciAxIERlcGxveWVyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiaW90c2VydmljZWRlcGxveWVyMSIsImdpdmVuX25hbWUiOiJJb1Qgc2VydmljZSBkZXBsb3llciAxIiwiZmFtaWx5X25hbWUiOiJEZXBsb3llciJ9.XXM3HYVntCrSOsyJIKg-ATsqMigyQZhLMaeZtl9GqYPuISXfYl3AV0Hcs5w3n55J_-NOdlFnZdJgHlpEdB9LvxegagI4ZteoEZC72og9OdmzFV1ud4jPTrhGm7rbjCXs7bF-sGwGCKrLIs53PZPQiRcm1KxfN4RhBy3sL0Ff79QHkgvTbag-DQMrh5Y_NrTifrMrZ0i8JZD8AsRrHoi5zs7N2PXQ0zNv3n1dxxlWBKd46cWh3kutqNgTNV-s7YTde1FCSthKMcQLxe284qdFWAYlctzU5y4zLe-3VPxU7fH16jD7yAazTYdGVy4U0B5fPn_087ABjEf0oZmt40nuug",
            "aerOS_HLO_TOKEN": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJzaTcxSzNkUm11UFIxY2RhT2daNVFtbGpUVlR6U3JQM0cyYlZNdEVDeUVjIn0.eyJleHAiOjE4MTcwMzUwMTksImlhdCI6MTczMDcyMTQxOSwianRpIjoiODk2ODhlODktNTRmOS00MzFhLTliZTUtOTQ5MmMxYjE0NDZiIiwiaXNzIjoiaHR0cHM6Ly9rZXljbG9hay5jZi1tdnAtZG9tYWluLmFlcm9zLXByb2plY3QuZXUvYXV0aC9yZWFsbXMva2V5Y2xvYWNrLW9wZW5sZGFwIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImE5ZWY0ZTFiLTg5NTgtNGZkYS1hODQ5LTJlNjdlZmY3NjkzMyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFlcm9zLXRlc3QiLCJzZXNzaW9uX3N0YXRlIjoiOGM2MTJjMDYtYTE5MS00MjBmLTlmNTItZGU5OWZiYzJkODI3IiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJDbG91ZEZlcnJvRG9tYWluIiwiZGVmYXVsdC1yb2xlcy1rZXljbG9hY2stb3BlbmxkYXAiLCJvZmZsaW5lX2FjY2VzcyIsIklvVCBzZXJ2aWNlIGRlcGxveWVyIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJzaWQiOiI4YzYxMmMwNi1hMTkxLTQyMGYtOWY1Mi1kZTk5ZmJjMmQ4MjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJJb1Qgc2VydmljZSBkZXBsb3llciAxIERlcGxveWVyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiaW90c2VydmljZWRlcGxveWVyMSIsImdpdmVuX25hbWUiOiJJb1Qgc2VydmljZSBkZXBsb3llciAxIiwiZmFtaWx5X25hbWUiOiJEZXBsb3llciJ9.XXM3HYVntCrSOsyJIKg-ATsqMigyQZhLMaeZtl9GqYPuISXfYl3AV0Hcs5w3n55J_-NOdlFnZdJgHlpEdB9LvxegagI4ZteoEZC72og9OdmzFV1ud4jPTrhGm7rbjCXs7bF-sGwGCKrLIs53PZPQiRcm1KxfN4RhBy3sL0Ff79QHkgvTbag-DQMrh5Y_NrTifrMrZ0i8JZD8AsRrHoi5zs7N2PXQ0zNv3n1dxxlWBKd46cWh3kutqNgTNV-s7YTde1FCSthKMcQLxe284qdFWAYlctzU5y4zLe-3VPxU7fH16jD7yAazTYdGVy4U0B5fPn_087ABjEf0oZmt40nuug",
        }
    },
    # Uncomment once piedge import issues are fixed
+100 −7
Original line number Diff line number Diff line
@@ -20,10 +20,10 @@ the EdgeCloud Platform integration across different clients.
# i2Edge variables
######################
# EdgeCloud Zone
ZONE_ID = "Omega"
ZONE_ID = "urn:ngsi-ld:Domain:NCSRD"

# Artefact
ARTEFACT_ID = "i2edgechart-id-2"
ARTEFACT_ID = "aeros-id-1"
ARTEFACT_NAME = "i2edgechart"
REPO_NAME = "github-cesar"
REPO_TYPE = "PUBLICREPO"
@@ -32,13 +32,13 @@ REPO_URL = "https://cesarcajas.github.io/helm-charts-examples/"
# Onboarding: CAMARA /app payload (only mandatory fields)
APP_ONBOARD_MANIFEST = {
    "appId": ARTEFACT_ID,
    "name": "i2edge-app-SDK",
    "name": "aeros-SDK",
    "version": "1.0.0",
    "appProvider": "i2CAT",
    "appProvider": "ncsrd",
    "packageType": "CONTAINER",
    "appRepo": {
        "type": "PUBLICREPO",
        "imagePath": "https://example.com/my-app-image:1.0.0",
        "imagePath": "https://example.com/nginx:latest",
    },
    "requiredResources": {
        "infraKind": "kubernetes",
@@ -58,7 +58,7 @@ APP_ONBOARD_MANIFEST = {
    },
    "componentSpec": [
        {
            "componentName": "my-component",
            "componentName": "aeros-comp",
            "networkInterfaces": [
                {
                    "interfaceId": "eth0",
@@ -94,4 +94,97 @@ APP_ZONES = [
######################
# aerOS variables
######################
# TODO
AEROS_APP_ID = "urn:ngsi-ld:Service:sunriseapp2"
AEROS_TOSCA_DESCRIPTOR = {
    "serviceId": AEROS_APP_ID,
    "tosca": """
  tosca_definitions_version: tosca_simple_yaml_1_3
  description: TOSCA for network performance
  node_templates:
    influxdb:
      type: tosca.nodes.Container.Application
      requirements:
        - network:
            properties:
              ports:
                fastapi:
                  properties:
                    protocol: [tcp]
                    source: 8086
              exposePorts: true
        - host:
            node_filter:
              properties:
                id: "urn:ngsi-ld:InfrastructureElement:NCSRD:cebf2bd4d0ba"
      artifacts:
        influxdb-image:
          file: p4lik4ri/influxdb
          type: tosca.artifacts.Deployment.Image.Container.Docker
          repository: docker_hub
      interfaces:
        Standard:
          create:
            implementation: influxdb-image
            inputs:
              envVars:
                - INFLUXDB_BUCKET: some-bucket
                - INFLUXDB_ORG: NCSRD
                - INFLUXDB_USER: vpitsilis
                - INFLUXDB_USER_PASSWORD: mypassword
  """,
}

AEROS_ZONE_ID = "urn:ngsi-ld:Domain:NCSRD"

AEROS_TOSCA_DESCRIPTOR_2 = """
tosca_definitions_version: tosca_simple_yaml_1_3
description: A test service for testing TOSCA generation
node_templates:
  auto-component:
    artifacts:
      nginx-image:
        file: nginx
        type: tosca.artifacts.Deployment.Image.Container.Docker
        repository: docker_hub
    interfaces:
      Standard:
        create:
          implementation: application_image
          inputs:
            cliArgs: []
            envVars: []
    requirements:
    - network:
        properties:
          ports:
            port1:
              properties:
                protocol:
                - tcp
                source: 80
            port2:
              properties:
                protocol:
                - tcp
                source: 443
          exposePorts: false
    - host:
        node_filter:
          capabilities:
          - host:
              properties:
                cpu_arch:
                  equal: x64
                realtime:
                  equal: false
                cpu_usage:
                  less_or_equal: '0.4'
                mem_size:
                  greater_or_equal: '1'
                energy_efficiency:
                  greater_or_equal: '10'
                green:
                  greater_or_equal: '10'
          properties: null
    type: tosca.nodes.Container.Application
"""
+41 −46
Original line number Diff line number Diff line
@@ -30,20 +30,12 @@ import pytest

from sunrise6g_opensdk.common.sdk import Sdk as sdkclient
from sunrise6g_opensdk.edgecloud.clients.errors import EdgeCloudPlatformError
from sunrise6g_opensdk.edgecloud.clients.i2edge.client import (
    EdgeApplicationManager as I2EdgeClient,
)
from tests.edgecloud.test_cases import test_cases
from tests.edgecloud.test_config import (
from tests.edgecloud.test_config import (  # ARTEFACT_ID,; ARTEFACT_NAME,; REPO_NAME,; REPO_TYPE,; REPO_URL,; ZONE_ID,
    AEROS_ZONE_ID,
    APP_ID,
    APP_ONBOARD_MANIFEST,
    APP_ZONES,
    ARTEFACT_ID,
    ARTEFACT_NAME,
    REPO_NAME,
    REPO_TYPE,
    REPO_URL,
    ZONE_ID,
)


@@ -72,7 +64,7 @@ def test_get_edge_cloud_zones(edgecloud_client):


@pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
def test_get_edge_cloud_zones_details(edgecloud_client, zone_id=ZONE_ID):
def test_get_edge_cloud_zones_details(edgecloud_client, zone_id=AEROS_ZONE_ID):
    """
    Test that get_edge_cloud_zone_details returns valid responses for each client.
    Since each client has different response formats, we only verify basic success criteria.
@@ -94,22 +86,22 @@ def test_get_edge_cloud_zones_details(edgecloud_client, zone_id=ZONE_ID):
        pytest.fail(f"Missing expected key in response: {e}")


@pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
def test_create_artefact(edgecloud_client):
    if isinstance(edgecloud_client, I2EdgeClient):
        try:
            edgecloud_client._create_artefact(
                artefact_id=ARTEFACT_ID,
                artefact_name=ARTEFACT_NAME,
                repo_name=REPO_NAME,
                repo_type=REPO_TYPE,
                repo_url=REPO_URL,
                password=None,
                token=None,
                user_name=None,
            )
        except EdgeCloudPlatformError as e:
            pytest.fail(f"Artefact creation failed unexpectedly: {e}")
# @pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
# def test_create_artefact(edgecloud_client):
#     if isinstance(edgecloud_client, I2EdgeClient):
#         try:
#             edgecloud_client._create_artefact(
#                 artefact_id=ARTEFACT_ID,
#                 artefact_name=ARTEFACT_NAME,
#                 repo_name=REPO_NAME,
#                 repo_type=REPO_TYPE,
#                 repo_url=REPO_URL,
#                 password=None,
#                 token=None,
#                 user_name=None,
#             )
#         except EdgeCloudPlatformError as e:
#             pytest.fail(f"Artefact creation failed unexpectedly: {e}")


@pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
@@ -120,14 +112,18 @@ def test_onboard_app(edgecloud_client):
        pytest.fail(f"App onboarding failed unexpectedly: {e}")


# @pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
# def test_timer_wait_15_seconds(edgecloud_client):
#     time.sleep(15)


@pytest.fixture(scope="module")
def app_instance_id(edgecloud_client):
    try:
        output = edgecloud_client.deploy_app(APP_ID, APP_ZONES)
        deployed_app = {"appInstanceId": output["deploy_name"]}
        assert "appInstanceId" in deployed_app
        assert deployed_app["appInstanceId"] is not None
        yield deployed_app["appInstanceId"]
        assert "appInstanceId" in output
        assert output["appInstanceId"] is not None
        yield output["appInstanceId"]
    finally:
        pass

@@ -150,18 +146,17 @@ def test_undeploy_app(edgecloud_client, app_instance_id):
        pytest.fail(f"App undeployment failed unexpectedly: {e}")


@pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
def test_delete_onboarded_app(edgecloud_client):
    try:
        edgecloud_client.delete_onboarded_app(app_id=APP_ONBOARD_MANIFEST["appId"])
    except EdgeCloudPlatformError as e:
        pytest.fail(f"App onboarding deletion failed unexpectedly: {e}")


@pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
def test_delete_artefact(edgecloud_client):
    if isinstance(edgecloud_client, I2EdgeClient):
        try:
            edgecloud_client._delete_artefact(artefact_id=ARTEFACT_ID)
        except EdgeCloudPlatformError as e:
            pytest.fail(f"Artefact deletion failed unexpectedly: {e}")
# @pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
# def test_delete_onboarded_app(edgecloud_client):
#     try:
#         edgecloud_client.delete_onboarded_app(app_id=APP_ONBOARD_MANIFEST["appId"])
#     except EdgeCloudPlatformError as e:
#         pytest.fail(f"App onboarding deletion failed unexpectedly: {e}")

# @pytest.mark.parametrize("edgecloud_client", test_cases, ids=id_func, indirect=True)
# def test_delete_artefact(edgecloud_client):
#     if isinstance(edgecloud_client, I2EdgeClient):
#         try:
#             edgecloud_client._delete_artefact(artefact_id=ARTEFACT_ID)
#         except EdgeCloudPlatformError as e:
#             pytest.fail(f"Artefact deletion failed unexpectedly: {e}")