Feature/add camara schemas to edgecloud adapters (i2Edge)#150
Feature/add camara schemas to edgecloud adapters (i2Edge)#150adrian-pino merged 25 commits intomainfrom
Conversation
Rename _build_custom_gsma_response to _build_custom_http_response
- 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
Simplifies payload handling by directly passing the Pydantic model. Ensures that 'None' values are excluded from the JSON payload sent to i2Edge. This prevents unexpected behavior related to default values not being properly handled by the i2Edge API.
…hemas-to-edgecloud-adapters
Modifies the GSMA API calls in the i2Edge adapter to return Response objects instead of dictionaries or lists. This change provides more consistent error handling and allows for better access to response metadata, like status codes and headers. It also includes updated docstrings for clarity.
- Resolved conflicts by keeping current branch versions - Maintained CAMARA schemas and GSMA federation improvements - Preserved interface-implementation consistency fixes
Enforces a consistent code style by setting the line length to 100 characters across the project. This improves code readability and maintainability by adhering to a common standard. Updates black and pre-commit configurations accordingly.
There was a problem hiding this comment.
Pull Request Overview
This PR adds CAMARA (GSMA Edge Computing API) schema compliance to the EdgeCloud adapters, specifically targeting the i2Edge platform integration. The changes focus on implementing CAMARA-compliant data structures and normalizing API responses to match the CAMARA specification.
Key changes include:
- Integration of CAMARA schemas for EdgeCloud operations (zones, applications, deployment)
- Standardization of EdgeCloud adapter interfaces to return Response objects instead of raw dictionaries
- Enhancement of i2Edge client with CAMARA-compliant request/response handling
Reviewed Changes
Copilot reviewed 39 out of 39 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/sunrise6g_opensdk/edgecloud/core/schemas.py | Adds comprehensive CAMARA EdgeCloud schema definitions |
| src/sunrise6g_opensdk/edgecloud/adapters/i2edge/client.py | Major refactor to support CAMARA compliance with response normalization |
| tests/edgecloud/test_e2e.py | Updates tests to validate CAMARA compliance and use standardized Response objects |
| tests/edgecloud/test_config.py | Restructures test configuration to use CAMARA-compliant payload formats |
| src/sunrise6g_opensdk/edgecloud/core/edgecloud_interface.py | Updates interface to return Response objects for CAMARA consistency |
Comments suppressed due to low confidence (2)
tests/edgecloud/test_e2e.py:193
- [nitpick] The timer test reduced from 60 seconds to 10 seconds, which may not be sufficient for deployment operations to complete in slower environments. Consider making the wait time configurable or environment-dependent.
def test_timer_wait_10_seconds(edgecloud_client):
tests/edgecloud/test_e2e.py:123
- [nitpick] The method name changed from '_create_artefact' to 'create_artefact', but 'artefact' is British spelling. Consider using 'artifact' for consistency with American English commonly used in programming.
edgecloud_client.create_artefact(
| camara_response = [] | ||
| for z in i2edge_response: | ||
| zone = camara_schemas.EdgeCloudZone( | ||
| # edgeCloudZoneId = camara_schemas.EdgeCloudZoneId(z["zoneId"]), | ||
| edgeCloudZoneId=camara_schemas.EdgeCloudZoneId(z["zoneId"]), | ||
| edgeCloudZoneName=camara_schemas.EdgeCloudZoneName(z["nodeName"]), | ||
| edgeCloudProvider=camara_schemas.EdgeCloudProvider("i2edge"), | ||
| edgeCloudRegion=camara_schemas.EdgeCloudRegion(z["geographyDetails"]), | ||
| edgeCloudZoneStatus=camara_schemas.EdgeCloudZoneStatus.unknown, | ||
| ) | ||
| camara_response.append(zone) |
There was a problem hiding this comment.
[nitpick] Consider extracting the zone transformation logic into a separate helper method to improve readability and reusability. The inline zone creation within the try block makes the method harder to follow.
| camara_response = [] | |
| for z in i2edge_response: | |
| zone = camara_schemas.EdgeCloudZone( | |
| # edgeCloudZoneId = camara_schemas.EdgeCloudZoneId(z["zoneId"]), | |
| edgeCloudZoneId=camara_schemas.EdgeCloudZoneId(z["zoneId"]), | |
| edgeCloudZoneName=camara_schemas.EdgeCloudZoneName(z["nodeName"]), | |
| edgeCloudProvider=camara_schemas.EdgeCloudProvider("i2edge"), | |
| edgeCloudRegion=camara_schemas.EdgeCloudRegion(z["geographyDetails"]), | |
| edgeCloudZoneStatus=camara_schemas.EdgeCloudZoneStatus.unknown, | |
| ) | |
| camara_response.append(zone) | |
| camara_response = [ | |
| self._transform_to_camara_zone(z) for z in i2edge_response | |
| ] |
| zone = camara_schemas.EdgeCloudZone( | ||
| # edgeCloudZoneId = camara_schemas.EdgeCloudZoneId(z["zoneId"]), | ||
| edgeCloudZoneId=camara_schemas.EdgeCloudZoneId(z["zoneId"]), | ||
| edgeCloudZoneName=camara_schemas.EdgeCloudZoneName(z["nodeName"]), |
There was a problem hiding this comment.
The code accesses z["nodeName"] but this field may not exist in the i2edge response. Consider using z.get("nodeName", "unknown") to handle missing fields gracefully.
| edgeCloudZoneName=camara_schemas.EdgeCloudZoneName(z["nodeName"]), | |
| edgeCloudZoneName=camara_schemas.EdgeCloudZoneName(z.get("nodeName", "unknown")), |
| log.error(f"Invalid CAMARA manifest: {e}") | ||
| raise ValueError(f"Invalid CAMARA manifest: {e}") |
There was a problem hiding this comment.
The error message 'Invalid CAMARA manifest' could be more specific. Consider including which specific validation failed or the field name that caused the error to help with debugging.
| log.error(f"Invalid CAMARA manifest: {e}") | |
| raise ValueError(f"Invalid CAMARA manifest: {e}") | |
| error_details = "; ".join( | |
| [f"Field '{err['loc'][0]}': {err['msg']}" for err in e.errors()] | |
| ) | |
| log.error(f"Invalid CAMARA manifest: {error_details}") | |
| raise ValueError(f"Invalid CAMARA manifest: {error_details}") |
| app_name = onboarded_app_data.get("name", "") | ||
| if not app_name: | ||
| raise KeyError("name") |
There was a problem hiding this comment.
The method tries to extract 'name' from onboarded_app_data, but based on the get_onboarded_app response structure, it should be accessing the nested 'appManifest.name' field instead.
| app_name = onboarded_app_data.get("name", "") | |
| if not app_name: | |
| raise KeyError("name") | |
| app_name = onboarded_app_data.get("appManifest", {}).get("name", "") | |
| if not app_name: | |
| raise KeyError("appManifest.name") |
| # 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", | ||
| ) | ||
|
|
||
|
|
There was a problem hiding this comment.
The TODO comment indicates a temporary solution using RootModel[str] instead of RootModel[UUID]. This inconsistency should be addressed to maintain CAMARA compliance.
| # 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", | |
| ) | |
| # Updated to AppInstanceId(RootModel[UUID]) for CAMARA compliance | |
| class AppInstanceId(RootModel[UUID]): | |
| root: UUID = 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", | |
| ) | |
| @validator("root", pre=True, always=True) | |
| def validate_and_convert_uuid(cls, value): | |
| if isinstance(value, str): | |
| try: | |
| return UUID(value) | |
| except ValueError: | |
| raise ValueError(f"Invalid UUID string: {value}") | |
| return value |
|
Some of the copilot comments have been addressed in |
No description provided.