From df997e0b964e33551138c7545f59f1fe70362f92 Mon Sep 17 00:00:00 2001 From: DlondonoD Date: Wed, 5 Aug 2026 16:51:32 +0200 Subject: [PATCH 1/6] Redesign GET /edge-cloud-zones and remove GET /clusters per issue #73 Per issue #73's analysis of both list endpoints against the CAMARA Design Guide (including the pagination guide at Commonalities/documentation/CAMARA-API-Design-Guide.md#41-pagination): Fix (mandatory per issue): - ClusterInfo.provider renamed to edgeCloudProvider, now referencing EdgeCloudProvider instead of the incorrect AppProvider (Application Provider != Edge Cloud Provider running the cluster). - Removed 500/503 from the endpoint, and restricted 400/403 to only INVALID_ARGUMENT/PERMISSION_DENIED via new local Generic400/403 response objects, per the rationale already applied for issue #72 (5xx not documented by default; OUT_OF_RANGE/INVALID_TOKEN_CONTEXT irrelevant to this API). Consider (adopted): - Combined GET /clusters into GET /edge-cloud-zones: removed the standalone /clusters path, getClusters operation, its dedicated security scope and the now-unused 'Cluster' tag. EdgeCloudZone gains an optional 'clusters' array (ClusterInfo items, without the redundant edgeCloudZoneId/edgeCloudRegion fields already provided by the enclosing zone), populated when the zone has Kubernetes clusters available. - Added pagination support per the Commonalities pagination guide: page/perPage query params (ref'd from CAMARA_common.yaml), x-total-count/x-total-pages/link response headers, and a new EdgeCloudZoneList response schema (replacing the bare EdgeCloudZones array) wrapping items + the common Pagination object. - Added a new CountryCode schema (ISO 3166-1 alpha-2) and countryCode query parameter, replacing the previous edge-cloud-provider-specific 'region' filter with a standardized, interoperable one. EdgeCloudZone gains a required 'countryCode' property; the existing free-text edgeCloudRegion field is kept as provider-specific descriptive info. - Added an edgeCloudProvider query parameter to filter zones by provider. - Removed the 'default: unknown' from the status query parameter (now defined inline instead of -ing EdgeCloudZoneStatus, whose default remains appropriate for the response object) so omitting the filter returns zones of any status instead of defaulting to 'unknown' only. Updated getEdgeCloudZones.feature accordingly (new schema references, countryCode/edgeCloudProvider/pagination scenarios, removed the region-filter scenario, added a no-default-status scenario and a 400 invalid-page scenario) and deleted getClusters.feature, since the operation no longer exists. Fixes #73 --- .../edge-application-management.yaml | 246 ++++++++++-------- ...application-management-getClusters.feature | 94 ------- ...ation-management-getEdgeCloudZones.feature | 74 +++++- 3 files changed, 202 insertions(+), 212 deletions(-) delete mode 100644 code/Test_definitions/edge-application-management-getClusters.feature diff --git a/code/API_definitions/edge-application-management.yaml b/code/API_definitions/edge-application-management.yaml index 12f7b10..4753376 100644 --- a/code/API_definitions/edge-application-management.yaml +++ b/code/API_definitions/edge-application-management.yaml @@ -87,9 +87,10 @@ info: removing all associated instances. __Edge Cloud information__ - * __getEdgeCloudZones__ List of the operators Edge Cloud Zones and their - status, ordering the results by location and filtering by status - (active/inactive/unknown) + * __getEdgeCloudZones__ Paginated list of the operators Edge Cloud Zones, + including their status, geographical country code and, when applicable, + the Kubernetes clusters available within each zone. Results can be + filtered by country code, status and Edge Cloud Provider. @@ -201,8 +202,6 @@ tags: description: Application and Application Instance Lice Cycle Management - name: Edge Cloud description: Edge Cloud Zones Availability - - name: Cluster - description: Kubernetes Cluster information - name: App Instance CALLBACK Operation description: Operations for handling application instance callback notifications - name: App Deployment CALLBACK Operation @@ -994,69 +993,6 @@ paths: "503": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - /clusters: - get: - security: - - openId: - - edge-application-management:clusters:read - tags: - - Cluster - summary: | - Retrieve a list of the available clusters filtered by the optional - query parameters. - description: | - List available cluster information - operationId: getClusters - parameters: - - $ref: "#/components/parameters/x-correlator" - - name: region - description: | - Human readable name of the geographical Edge Cloud Region of - the Cluster. Defined by the Edge Cloud Provider. - in: query - required: false - schema: - $ref: "#/components/schemas/EdgeCloudRegion" - - name: clusterRef - description: | - A globally unique identifier for the Cluster. - in: query - required: false - schema: - $ref: "#/components/schemas/KubernetesClusterRef" - - name: edgeCloudZoneId - description: | - Edge Cloud Zone identifier. - in: query - required: false - schema: - $ref: "#/components/schemas/EdgeCloudZoneId" - responses: - "200": - description: | - Successful response, returning the cluster's information. - Returns an empty list if no clusters were found or none match - the specified query parameters. - headers: - x-correlator: - $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" - content: - application/json: - schema: - type: array - maxItems: 100 - items: - $ref: "#/components/schemas/ClusterInfo" - "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" - "401": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" - "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" - "500": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" - "503": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" /edge-cloud-zones: get: security: @@ -1064,50 +1000,70 @@ paths: - edge-application-management:edge-cloud-zones:read tags: - Edge Cloud - summary: Retrieve a list of the provider's Edge Cloud Zones and their status + summary: Retrieve a paginated list of the provider's Edge Cloud Zones description: | - List of the provider's Edge Cloud Zones and their - status, ordering the results by location and filtering by - status (active/inactive/unknown) + List of the provider's Edge Cloud Zones, including their status and, + when applicable, the Kubernetes clusters available within each zone. + Results can be filtered by country code, status and Edge Cloud + Provider, and are returned as a paginated collection. operationId: getEdgeCloudZones parameters: - $ref: "#/components/parameters/x-correlator" - - name: region + - $ref: "../common/CAMARA_common.yaml#/components/parameters/page" + - $ref: "../common/CAMARA_common.yaml#/components/parameters/perPage" + - name: countryCode description: | - Human readable name of the geographical Edge Cloud Region of - the Edge Cloud. Defined by the Edge Cloud Provider. + ISO 3166-1 alpha-2 country code to filter Edge Cloud Zones by + their geographical location, independent of any Edge Cloud + Provider-specific region naming. in: query required: false schema: - $ref: "#/components/schemas/EdgeCloudRegion" + $ref: "#/components/schemas/CountryCode" + - name: edgeCloudProvider + description: | + Human readable name of the Edge Cloud Provider to filter Edge + Cloud Zones by. + in: query + required: false + schema: + $ref: "#/components/schemas/EdgeCloudProvider" - name: status - description: Human readable status of the Edge Cloud Zone + description: | + Status of the Edge Cloud Zone to filter by. If omitted, Edge + Cloud Zones are returned regardless of their status. in: query required: false schema: - $ref: "#/components/schemas/EdgeCloudZoneStatus" + type: string + enum: + - active + - inactive + - unknown responses: "200": description: | - Successful response, returning the - Available Edge Cloud Zones. + Successful response, returning a paginated list of the Edge + Cloud Zones matching the specified query parameters. headers: x-correlator: $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + x-total-count: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-total-count" + x-total-pages: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-total-pages" + link: + $ref: "../common/CAMARA_common.yaml#/components/headers/link" content: application/json: schema: - $ref: "#/components/schemas/EdgeCloudZones" + $ref: "#/components/schemas/EdgeCloudZoneList" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" - "500": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" - "503": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" + $ref: "#/components/responses/Generic403" components: securitySchemes: openId: @@ -1130,6 +1086,58 @@ components: schema: $ref: "#/components/schemas/XCorrelator" + responses: + Generic400: + description: Bad Request + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "../common/CAMARA_common.yaml#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 400 + code: + enum: + - INVALID_ARGUMENT + examples: + GENERIC_400_INVALID_ARGUMENT: + description: Invalid Argument. Generic Syntax Exception + value: + status: 400 + code: INVALID_ARGUMENT + message: Client specified an invalid argument, request body or query param. + Generic403: + description: Forbidden + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "../common/CAMARA_common.yaml#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 403 + code: + enum: + - PERMISSION_DENIED + examples: + GENERIC_403_PERMISSION_DENIED: + description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security + value: + status: 403 + code: PERMISSION_DENIED + message: Client does not have sufficient permissions to perform this action. + callbacks: onAppInstanceStatusChange: "{$request.body#/subscriptionRequest/sink}": @@ -1718,26 +1726,24 @@ components: ClusterInfo: type: object - description: Kubernetes cluster information + description: | + Kubernetes cluster information. Returned nested within the Edge + Cloud Zone it belongs to, so identifiers already provided by the + enclosing Edge Cloud Zone (zone id, region) are not repeated here. required: - name - - provider + - edgeCloudProvider - clusterRef - - edgeCloudZoneId properties: name: type: string maxLength: 64 description: | - Name of the Cluster, scoped to the Provider - provider: - $ref: "#/components/schemas/AppProvider" + Name of the Cluster, scoped to the Edge Cloud Provider + edgeCloudProvider: + $ref: "#/components/schemas/EdgeCloudProvider" clusterRef: $ref: "#/components/schemas/KubernetesClusterRef" - edgeCloudZoneId: - $ref: "#/components/schemas/EdgeCloudZoneId" - edgeCloudRegion: - $ref: "#/components/schemas/EdgeCloudRegion" version: type: string maxLength: 64 @@ -1751,6 +1757,17 @@ components: $ref: "#/components/schemas/KubernetesNodePool" minItems: 1 + CountryCode: + type: string + pattern: ^[A-Z]{2}$ + minLength: 2 + maxLength: 2 + description: | + ISO 3166-1 alpha-2 country code representing the geographical + location of the Edge Cloud Zone, independent of any Edge Cloud + Provider-specific region naming. + example: "GB" + EdgeCloudProvider: type: string maxLength: 64 @@ -1763,15 +1780,22 @@ components: Human readable name of the geographical Edge Cloud Region of the Edge Cloud. Defined by the Edge Cloud Provider. - EdgeCloudZones: - type: array - items: - $ref: "#/components/schemas/EdgeCloudZone" - minItems: 1 - maxItems: 100 + EdgeCloudZoneList: + type: object description: | - A collection of Edge Cloud Zones where the Application Provider can - instantiate an Application Instance. + A paginated collection of Edge Cloud Zones where the Application + Provider can instantiate an Application Instance. + required: + - items + - pagination + properties: + items: + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/EdgeCloudZone" + pagination: + $ref: "../common/CAMARA_common.yaml#/components/schemas/Pagination" EdgeCloudZoneId: type: string @@ -1795,6 +1819,7 @@ components: - edgeCloudZoneId - edgeCloudZoneName - edgeCloudProvider + - countryCode properties: edgeCloudZoneId: $ref: "#/components/schemas/EdgeCloudZoneId" @@ -1806,6 +1831,17 @@ components: $ref: "#/components/schemas/EdgeCloudProvider" edgeCloudRegion: $ref: "#/components/schemas/EdgeCloudRegion" + countryCode: + $ref: "#/components/schemas/CountryCode" + clusters: + description: | + Kubernetes clusters available within this Edge Cloud Zone, when + applicable. Omitted or empty if the Edge Cloud Provider does not + offer Kubernetes clusters in this zone. + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/ClusterInfo" EdgeCloudZoneName: type: string diff --git a/code/Test_definitions/edge-application-management-getClusters.feature b/code/Test_definitions/edge-application-management-getClusters.feature deleted file mode 100644 index 7b6f57d..0000000 --- a/code/Test_definitions/edge-application-management-getClusters.feature +++ /dev/null @@ -1,94 +0,0 @@ -Feature: CAMARA Edge Application Management API, vwip - Operation getClusters - # Input to be provided by the implementation to the tester - # - # Implementation indications: - # * apiRoot: API root of the server URL - # - # Testing assets: - # * An available cluster to get information - # - # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml - Background: Common getClusters setup - Given an environment at "apiRoot" - And the resource "/edge-application-management/vwip/clusters" - And the header "Content-Type" is set to "application/json" - And the header "Authorization" is set to a valid access token - And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" - # Success scenarios - #/clusters GET 200 - @eam_getClusters_01_generic_success_scenario - Scenario: Get information of existing clusters - Given There are at least one cluster available - When the request "getClusters" is sent - Then the response status code is 200 - And the response header "Content-Type" is "application/json" - And the response header "x-correlator" has same value as the request header "x-correlator" - And A list of clusters is returned - And the response body complies with the OAS schema at "/components/schemas/ClusterInfo" - #/clusters GET 200 filtered by region - @eam_getClusters_02_generic_success_scenario_filtered_by_region - Scenario: Get information of existing clusters with optional parameters ("region") - Given There are at least one cluster available - And the request query parameter "$.region" is set to a valid region - When the request "getClusters" is sent - Then the response status code is 200 - And the response header "Content-Type" is "application/json" - And the response header "x-correlator" has same value as the request header "x-correlator" - And information of clusters of "$.region" is returned - And the response body complies with the OAS schema at "/components/schemas/ClusterInfo" - #/clusters GET 200 filtered by edgeCloudZoneId - @eam_getClusters_03_generic_success_scenario_filtered_by_edgeCloudZone - Scenario: Get information of existing clusters with optional parameters ("edgeCloudZoneId") - Given There are at least one cluster available - And the request query parameter "$.edgeCloudZoneId" is set to a valid edgeCloudZoneId - When the request "getClusters" is sent - Then the response status code is 200 - And the response header "Content-Type" is "application/json" - And the response header "x-correlator" has same value as the request header "x-correlator" - And information of clusters of "$.edgeCloudZoneId" is returned - And the response body complies with the OAS schema at "/components/schemas/ClusterInfo" - #/clusters GET 200 filtered by clusterRef - @eam_getClusters_04_generic_success_scenario_filtered_by_clusterRef - Scenario: Get information of existing clusters with optional parameters ("clusterRef") - Given There are at least one cluster available - And the request query parameter "$.clusterRef" is set to a valid clusterRef - When the request "getClusters" is sent - Then the response status code is 200 - And the response header "Content-Type" is "application/json" - And the response header "x-correlator" has same value as the request header "x-correlator" - And information of clusters of "$.edgeCloudZoneId" is returned - And the response body complies with the OAS schema at "/components/schemas/ClusterInfo" - #Errors - #/clusters GET 404 - @eam_getClusters_404.1_not_found - Scenario: Get information of existing clusters with invalid optional parameters ("region") - Given the request query parameter "$.region" is set to an invalid region - When the request "getClusters" is sent - Then the response status code is 404 - And the response header "x-correlator" has same value as the request header "x-correlator" - And the response header "Content-Type" is "application/json" - And the response property "$.status" is 404 - And the response property "$.code" is "NOT_FOUND" - And the response property "$.message" contains a user friendly text - # Error 401 - @eam_getClusters_401.1_missing_access_token - Scenario: Missing access token - Given the header "Authorization" is not included - When the request "getClusters" is sent - Then the response status code is 401 - And the response header "x-correlator" has same value as the request header "x-correlator" - And the response header "Content-Type" is "application/json" - And the response property "$.status" is 401 - And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text - # Errors 403 - @eam_getClusters_403.1_missing_access_token_scope - Scenario: Missing access token scope - Given the header "Authorization" is set to an access token that does not include the required scope - When the request "getClusters" is sent - Then the response status code is 403 - And the response header "x-correlator" has same value as the request header "x-correlator" - And the response header "Content-Type" is "application/json" - And the response property "$.status" is 403 - And the response property "$.code" is "PERMISSION_DENIED" - And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature b/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature index 6da9841..f4e6dfd 100644 --- a/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature +++ b/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature @@ -5,7 +5,8 @@ Feature: CAMARA Edge Application Management API, vwip - Operation getEdgeCloudZo # * apiRoot: API root of the server URL # # Testing assets: - # * An available edge Cloud Zones to get information + # * An available edge Cloud Zones to get information, at least one of which + # has Kubernetes clusters available # # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml Background: Common getEdgeCloudZones setup @@ -17,28 +18,41 @@ Feature: CAMARA Edge Application Management API, vwip - Operation getEdgeCloudZo # Success scenarios #/edge-cloud-zones GET 200 @eam_getEdgeCloudZones_01_generic_success_scenario - Scenario: Get information of existing edge cloud zones + Scenario: Get a paginated list of existing edge cloud zones Given There are at least one Edge Cloud Zones available When the request "getEdgeCloudZones" is sent Then the response status code is 200 And the response header "Content-Type" is "application/json" And the response header "x-correlator" has same value as the request header "x-correlator" - And A list of Edge Cloud Zones is returned - And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZones" - #/edge-cloud-zones GET 200 filtered by region - @eam_getEdgeCloudZones_02_generic_success_scenario_filtered_by_region - Scenario: Get information of existing Edge Cloud Zones with optional parameters ("region") + And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" + And the response property "$.items" is a list of Edge Cloud Zones + And the response property "$.pagination" is present and complies with the OAS schema at "/components/schemas/Pagination" + And any Edge Cloud Zone with Kubernetes clusters includes them in the "$.items[].clusters" property + #/edge-cloud-zones GET 200 filtered by countryCode + @eam_getEdgeCloudZones_02_success_scenario_filtered_by_countryCode + Scenario: Get information of existing Edge Cloud Zones with optional parameter ("countryCode") Given There are at least one Edge Cloud Zones available - And the request query parameter "$.region" is set to a valid region + And the request query parameter "$.countryCode" is set to a valid ISO 3166-1 alpha-2 country code When the request "getEdgeCloudZones" is sent Then the response status code is 200 And the response header "Content-Type" is "application/json" And the response header "x-correlator" has same value as the request header "x-correlator" - And information of Edge Cloud Zones of "$.region" is returned - And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZones" + And information of Edge Cloud Zones with "$.countryCode" is returned + And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" + #/edge-cloud-zones GET 200 filtered by edgeCloudProvider + @eam_getEdgeCloudZones_03_success_scenario_filtered_by_edgeCloudProvider + Scenario: Get information of existing Edge Cloud Zones with optional parameter ("edgeCloudProvider") + Given There are at least one Edge Cloud Zones available + And the request query parameter "$.edgeCloudProvider" is set to a valid Edge Cloud Provider name + When the request "getEdgeCloudZones" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And information of Edge Cloud Zones of "$.edgeCloudProvider" is returned + And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" #/edge-cloud-zones GET 200 filtered by status - @eam_getEdgeCloudZones_03_generic_success_scenario_filtered_by_status - Scenario: Get information of existing Edge Cloud Zones with optional parameters ("status") + @eam_getEdgeCloudZones_04_success_scenario_filtered_by_status + Scenario: Get information of existing Edge Cloud Zones with optional parameter ("status") Given There are at least one Edge Cloud Zones available And the request query parameter "$.status" is set to a valid status When the request "getEdgeCloudZones" is sent @@ -46,7 +60,41 @@ Feature: CAMARA Edge Application Management API, vwip - Operation getEdgeCloudZo And the response header "Content-Type" is "application/json" And the response header "x-correlator" has same value as the request header "x-correlator" And information of Edge Cloud Zones of "$.status" is returned - And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZones" + And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" + #/edge-cloud-zones GET 200 no status filter returns zones regardless of status + @eam_getEdgeCloudZones_05_success_scenario_no_status_filter + Scenario: Get existing Edge Cloud Zones without the optional parameter ("status") + Given there are Edge Cloud Zones available with different statuses + When the request "getEdgeCloudZones" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And Edge Cloud Zones with any status are returned + And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" + #/edge-cloud-zones GET 200 paginated by page and perPage + @eam_getEdgeCloudZones_06_success_scenario_paginated + Scenario: Get a specific page of existing Edge Cloud Zones with optional parameters ("page", "perPage") + Given there are more Edge Cloud Zones available than the requested "perPage" value + And the request query parameter "$.page" is set to a valid page number + And the request query parameter "$.perPage" is set to a valid perPage value + When the request "getEdgeCloudZones" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response property "$.pagination.page" has the value provided for "$.page" + And the response property "$.pagination.perPage" has the value provided for "$.perPage" + And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" + # Error 400 + @eam_getEdgeCloudZones_400.1_invalid_page + Scenario: Invalid pagination parameter ("page") + Given the request query parameter "$.page" is set to an invalid page number + When the request "getEdgeCloudZones" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text # Error 401 @eam_getEdgeCloudZones_401.1_missing_access_token Scenario: Missing access token From f0dbe25562a06e749995575a25c33e2b700f6404 Mon Sep 17 00:00:00 2001 From: DlondonoD Date: Wed, 5 Aug 2026 17:13:48 +0200 Subject: [PATCH 2/6] Avoid generic 'items' name and restore edgeCloudRegion filtering Per the Commonalities pagination guide, the 'items' array name in the paginated response schema is API-specific, not mandatory - renamed EdgeCloudZoneList.items to edgeCloudZones for clarity in this API's context. Updated the .feature file's property references accordingly. Also restored the ability to filter by edgeCloudRegion, lost when 'region' was replaced by the new standardized countryCode filter. The EdgeCloudZone schema still exposes edgeCloudRegion as a provider-specific descriptive field, so it makes sense to keep it filterable alongside countryCode: countryCode for provider-independent results, edgeCloudRegion when finer, provider-specific granularity is needed. Added the corresponding query parameter, operation/API description updates, and a getEdgeCloudZones.feature scenario. --- .../edge-application-management.yaml | 22 ++++++++++++++----- ...ation-management-getEdgeCloudZones.feature | 21 +++++++++++++----- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/code/API_definitions/edge-application-management.yaml b/code/API_definitions/edge-application-management.yaml index 4753376..227f951 100644 --- a/code/API_definitions/edge-application-management.yaml +++ b/code/API_definitions/edge-application-management.yaml @@ -90,7 +90,8 @@ info: * __getEdgeCloudZones__ Paginated list of the operators Edge Cloud Zones, including their status, geographical country code and, when applicable, the Kubernetes clusters available within each zone. Results can be - filtered by country code, status and Edge Cloud Provider. + filtered by country code, Edge Cloud Provider, Edge Cloud + Provider-specific region and status. @@ -1004,8 +1005,9 @@ paths: description: | List of the provider's Edge Cloud Zones, including their status and, when applicable, the Kubernetes clusters available within each zone. - Results can be filtered by country code, status and Edge Cloud - Provider, and are returned as a paginated collection. + Results can be filtered by country code, Edge Cloud Provider, + Edge Cloud Provider-specific region and status, and are returned as + a paginated collection. operationId: getEdgeCloudZones parameters: - $ref: "#/components/parameters/x-correlator" @@ -1028,6 +1030,16 @@ paths: required: false schema: $ref: "#/components/schemas/EdgeCloudProvider" + - name: edgeCloudRegion + description: | + Edge Cloud Provider-specific geographical region name to filter + Edge Cloud Zones by. Since this value is not standardized across + Edge Cloud Providers, prefer filtering by countryCode when + provider-independent results are needed. + in: query + required: false + schema: + $ref: "#/components/schemas/EdgeCloudRegion" - name: status description: | Status of the Edge Cloud Zone to filter by. If omitted, Edge @@ -1786,10 +1798,10 @@ components: A paginated collection of Edge Cloud Zones where the Application Provider can instantiate an Application Instance. required: - - items + - edgeCloudZones - pagination properties: - items: + edgeCloudZones: type: array maxItems: 100 items: diff --git a/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature b/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature index f4e6dfd..909689e 100644 --- a/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature +++ b/code/Test_definitions/edge-application-management-getEdgeCloudZones.feature @@ -25,9 +25,9 @@ Feature: CAMARA Edge Application Management API, vwip - Operation getEdgeCloudZo And the response header "Content-Type" is "application/json" And the response header "x-correlator" has same value as the request header "x-correlator" And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" - And the response property "$.items" is a list of Edge Cloud Zones + And the response property "$.edgeCloudZones" is a list of Edge Cloud Zones And the response property "$.pagination" is present and complies with the OAS schema at "/components/schemas/Pagination" - And any Edge Cloud Zone with Kubernetes clusters includes them in the "$.items[].clusters" property + And any Edge Cloud Zone with Kubernetes clusters includes them in the "$.edgeCloudZones[].clusters" property #/edge-cloud-zones GET 200 filtered by countryCode @eam_getEdgeCloudZones_02_success_scenario_filtered_by_countryCode Scenario: Get information of existing Edge Cloud Zones with optional parameter ("countryCode") @@ -50,8 +50,19 @@ Feature: CAMARA Edge Application Management API, vwip - Operation getEdgeCloudZo And the response header "x-correlator" has same value as the request header "x-correlator" And information of Edge Cloud Zones of "$.edgeCloudProvider" is returned And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" + #/edge-cloud-zones GET 200 filtered by edgeCloudRegion + @eam_getEdgeCloudZones_04_success_scenario_filtered_by_edgeCloudRegion + Scenario: Get information of existing Edge Cloud Zones with optional parameter ("edgeCloudRegion") + Given There are at least one Edge Cloud Zones available + And the request query parameter "$.edgeCloudRegion" is set to a valid Edge Cloud Provider-specific region name + When the request "getEdgeCloudZones" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And information of Edge Cloud Zones of "$.edgeCloudRegion" is returned + And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" #/edge-cloud-zones GET 200 filtered by status - @eam_getEdgeCloudZones_04_success_scenario_filtered_by_status + @eam_getEdgeCloudZones_05_success_scenario_filtered_by_status Scenario: Get information of existing Edge Cloud Zones with optional parameter ("status") Given There are at least one Edge Cloud Zones available And the request query parameter "$.status" is set to a valid status @@ -62,7 +73,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation getEdgeCloudZo And information of Edge Cloud Zones of "$.status" is returned And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" #/edge-cloud-zones GET 200 no status filter returns zones regardless of status - @eam_getEdgeCloudZones_05_success_scenario_no_status_filter + @eam_getEdgeCloudZones_06_success_scenario_no_status_filter Scenario: Get existing Edge Cloud Zones without the optional parameter ("status") Given there are Edge Cloud Zones available with different statuses When the request "getEdgeCloudZones" is sent @@ -72,7 +83,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation getEdgeCloudZo And Edge Cloud Zones with any status are returned And the response body complies with the OAS schema at "/components/schemas/EdgeCloudZoneList" #/edge-cloud-zones GET 200 paginated by page and perPage - @eam_getEdgeCloudZones_06_success_scenario_paginated + @eam_getEdgeCloudZones_07_success_scenario_paginated Scenario: Get a specific page of existing Edge Cloud Zones with optional parameters ("page", "perPage") Given there are more Edge Cloud Zones available than the requested "perPage" value And the request query parameter "$.page" is set to a valid page number From a9583a1d0114f97a7951a57cc88ec2e0bbb6f661 Mon Sep 17 00:00:00 2001 From: DlondonoD Date: Fri, 7 Aug 2026 10:40:46 +0200 Subject: [PATCH 3/6] Replace ambiguous PATCH /deployments/{id} with explicit action endpoints (#74) The PATCH-based updateAppDeployment operation obscured the actual API design requirement (adding/removing specific Edge Cloud Zones and Kubernetes clusters from an existing deployment) by treating it as a generic database entry update: - Ambiguous behavior around array replacement vs merging for edgeCloudZones/kubernetesClusterRefs, needing an explanatory note that JSON Merge Patch replaces rather than merges arrays - itself a sign PATCH wasn't intuitive here. - Functionality creep: PATCH incidentally allowed updating appDeploymentName, which was never a stated design requirement. Removed the patch: operation on /deployments/{appDeploymentId} and replaced it with four explicit, unambiguous action endpoints, as suggested in the issue: - POST /deployments/{appDeploymentId}/addEdgeCloudZone - POST /deployments/{appDeploymentId}/removeEdgeCloudZone - POST /deployments/{appDeploymentId}/addKubernetesCluster - POST /deployments/{appDeploymentId}/removeKubernetesCluster Each takes a single-field request body (edgeCloudZoneId or kubernetesClusterRef) and returns the updated AppDeploymentInfo on 200, with 409 ALREADY_EXISTS for add operations targeting an already-present zone/cluster and 404 NOT_FOUND for remove operations targeting one not present in the deployment. appDeploymentName is no longer updatable through any operation, removing the functionality creep entirely. Replaced updateAppDeployment.feature with one .feature file per new operation, and updated the API description's Quick Start section. Fixes #74 --- .../edge-application-management.yaml | 309 +++++++++++++----- ...ation-management-addEdgeCloudZone.feature} | 73 +++-- ...on-management-addKubernetesCluster.feature | 100 ++++++ ...ion-management-removeEdgeCloudZone.feature | 99 ++++++ ...management-removeKubernetesCluster.feature | 98 ++++++ 5 files changed, 579 insertions(+), 100 deletions(-) rename code/Test_definitions/{edge-application-management-updateAppDeployment.feature => edge-application-management-addEdgeCloudZone.feature} (54%) create mode 100644 code/Test_definitions/edge-application-management-addKubernetesCluster.feature create mode 100644 code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature create mode 100644 code/Test_definitions/edge-application-management-removeKubernetesCluster.feature diff --git a/code/API_definitions/edge-application-management.yaml b/code/API_definitions/edge-application-management.yaml index 227f951..9a8056f 100644 --- a/code/API_definitions/edge-application-management.yaml +++ b/code/API_definitions/edge-application-management.yaml @@ -83,6 +83,11 @@ info: deployment. * __getAppDeployments__ - Retrieves a list of deployments for a given application. + * __addEdgeCloudZone__ / __removeEdgeCloudZone__ - Extend or reduce an + existing application deployment by adding or removing a specific Edge + Cloud Zone. + * __addKubernetesCluster__ / __removeKubernetesCluster__ - Add or remove + a specific Kubernetes cluster used by an existing application deployment. * __deleteAppDeployment__ - Terminates a specific application deployment, removing all associated instances. @@ -863,104 +868,187 @@ paths: $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - patch: + + /deployments/{appDeploymentId}/addEdgeCloudZone: + post: security: - openId: - edge-application-management:deployments:update tags: - Application - summary: Update an Application Deployment + summary: Add an Edge Cloud Zone to an Application Deployment description: | - Update the configuration or properties of an existing application deployment - using JSON Merge Patch semantics (RFC 7396). Only the fields provided in the - request body will be updated. Fields not included in the request will remain unchanged. - - IMPORTANT: When updating array fields (like edgeCloudZones or kubernetesClusterRefs), - JSON Merge Patch will REPLACE the entire array, not merge or append to it. - - This operation may include changing the deployment name, target Edge Cloud Zones, or other updatable fields. - operationId: updateAppDeployment + Extend an existing application deployment to an additional Edge + Cloud Zone, instantiating the application there. + operationId: addEdgeCloudZone parameters: - $ref: "#/components/parameters/x-correlator" - name: appDeploymentId in: path description: | - Identifier of the specific application deployment to be updated. + Identifier of the specific application deployment to be + extended. required: true schema: $ref: "#/components/schemas/AppDeploymentId" requestBody: description: | - The fields to update for the application deployment using JSON Merge Patch (RFC 7396). - Only the fields included in the request will be updated; omitted fields remain unchanged. - - NOTE: When updating array fields (edgeCloudZones, kubernetesClusterRefs), the entire array - will be REPLACED, not merged. To modify an array, you must include the complete array - with all desired elements in your request. + The Edge Cloud Zone to add to the application deployment. required: true content: - application/merge-patch+json: + application/json: schema: type: object + required: + - edgeCloudZoneId properties: - appDeploymentName: - $ref: "#/components/schemas/AppDeploymentName" - edgeCloudZones: - type: array - maxItems: 100 - items: - $ref: "#/components/schemas/EdgeCloudZoneId" - kubernetesClusterRefs: - type: array - maxItems: 100 - items: - $ref: "#/components/schemas/KubernetesClusterRef" - examples: - updateDeploymentName: - summary: Update only the deployment name - description: | - This example shows how to update only the deployment name. - Other fields will remain unchanged. - value: - appDeploymentName: "my_updated_deployment" - updateMultipleFields: - summary: Update multiple fields simultaneously - description: | - This example shows how to update both the deployment name - and Edge Cloud Zones in a single request. Remember that both - array fields will be completely replaced with the new values. - value: - appDeploymentName: "production_deployment" - edgeCloudZones: - - "123e4567-e89b-12d3-a456-426614174000" - - "123e4567-e89b-12d3-a456-426614174001" - kubernetesClusterRefs: - - "642f6105-7015-4af1-a4d1-e1ecb8437abc" - - "642f6105-7015-4af1-a4d1-e1ecb8437def" - arrayReplacementExample: - summary: Example of array replacement behavior - description: | - This example demonstrates how arrays are completely replaced in JSON Merge Patch. - - If the current deployment has: - - edgeCloudZones: ["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001", "123e4567-e89b-12d3-a456-426614174002"] - - kubernetesClusterRefs: ["642f6105-7015-4af1-a4d1-e1ecb8437abc", "642f6105-7015-4af1-a4d1-e1ecb8437def"] - - And the user sends this patch: - - edgeCloudZones: ["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174003"] + edgeCloudZoneId: + $ref: "#/components/schemas/EdgeCloudZoneId" + responses: + "200": + description: Edge Cloud Zone added successfully + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/AppDeploymentInfo" + "400": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + "401": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" + "403": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + "404": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + "409": + description: Conflict + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorInfo" + example: + status: 409 + code: ALREADY_EXISTS + message: "Edge Cloud Zone already part of the deployment" + "500": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" + "503": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - The result will be: - - edgeCloudZones: ["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174003"] (completely replaced) - - kubernetesClusterRefs: ["642f6105-7015-4af1-a4d1-e1ecb8437abc", "642f6105-7015-4af1-a4d1-e1ecb8437def"] (unchanged, as it wasn't in the patch) + /deployments/{appDeploymentId}/removeEdgeCloudZone: + post: + security: + - openId: + - edge-application-management:deployments:update + tags: + - Application + summary: Remove an Edge Cloud Zone from an Application Deployment + description: | + Terminate the application instance in the given Edge Cloud Zone and + remove it from the deployment. + operationId: removeEdgeCloudZone + parameters: + - $ref: "#/components/parameters/x-correlator" + - name: appDeploymentId + in: path + description: | + Identifier of the specific application deployment to be + reduced. + required: true + schema: + $ref: "#/components/schemas/AppDeploymentId" + requestBody: + description: | + The Edge Cloud Zone to remove from the application deployment. + required: true + content: + application/json: + schema: + type: object + required: + - edgeCloudZoneId + properties: + edgeCloudZoneId: + $ref: "#/components/schemas/EdgeCloudZoneId" + responses: + "200": + description: Edge Cloud Zone removed successfully + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/AppDeploymentInfo" + "400": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + "401": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" + "403": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + "404": + description: | + The application deployment, or the given Edge Cloud Zone within + it, was not found. + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorInfo" + example: + status: 404 + code: NOT_FOUND + message: "Edge Cloud Zone not found in the deployment" + "500": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" + "503": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - To add a single zone while keeping existing ones, ALL zones must be included in the request. - value: - edgeCloudZones: - - "123e4567-e89b-12d3-a456-426614174000" - - "123e4567-e89b-12d3-a456-426614174003" + /deployments/{appDeploymentId}/addKubernetesCluster: + post: + security: + - openId: + - edge-application-management:deployments:update + tags: + - Application + summary: Add a Kubernetes cluster to an Application Deployment + description: | + Add a specific Kubernetes cluster, within an Edge Cloud Zone already + part of the deployment, to be used by the application deployment. + operationId: addKubernetesCluster + parameters: + - $ref: "#/components/parameters/x-correlator" + - name: appDeploymentId + in: path + description: | + Identifier of the specific application deployment to be + extended. + required: true + schema: + $ref: "#/components/schemas/AppDeploymentId" + requestBody: + description: | + The Kubernetes cluster to add to the application deployment. + required: true + content: + application/json: + schema: + type: object + required: + - kubernetesClusterRef + properties: + kubernetesClusterRef: + $ref: "#/components/schemas/KubernetesClusterRef" responses: "200": - description: Application deployment updated successfully + description: Kubernetes cluster added successfully headers: x-correlator: $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" @@ -987,8 +1075,79 @@ paths: $ref: "#/components/schemas/ErrorInfo" example: status: 409 - code: ABORTED - message: "Update conflict" + code: ALREADY_EXISTS + message: "Kubernetes cluster already part of the deployment" + "500": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" + "503": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" + + /deployments/{appDeploymentId}/removeKubernetesCluster: + post: + security: + - openId: + - edge-application-management:deployments:update + tags: + - Application + summary: Remove a Kubernetes cluster from an Application Deployment + description: | + Stop using the given Kubernetes cluster for the application + deployment. + operationId: removeKubernetesCluster + parameters: + - $ref: "#/components/parameters/x-correlator" + - name: appDeploymentId + in: path + description: | + Identifier of the specific application deployment to be + reduced. + required: true + schema: + $ref: "#/components/schemas/AppDeploymentId" + requestBody: + description: | + The Kubernetes cluster to remove from the application deployment. + required: true + content: + application/json: + schema: + type: object + required: + - kubernetesClusterRef + properties: + kubernetesClusterRef: + $ref: "#/components/schemas/KubernetesClusterRef" + responses: + "200": + description: Kubernetes cluster removed successfully + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/AppDeploymentInfo" + "400": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + "401": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" + "403": + $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + "404": + description: | + The application deployment, or the given Kubernetes cluster + within it, was not found. + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorInfo" + example: + status: 404 + code: NOT_FOUND + message: "Kubernetes cluster not found in the deployment" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": diff --git a/code/Test_definitions/edge-application-management-updateAppDeployment.feature b/code/Test_definitions/edge-application-management-addEdgeCloudZone.feature similarity index 54% rename from code/Test_definitions/edge-application-management-updateAppDeployment.feature rename to code/Test_definitions/edge-application-management-addEdgeCloudZone.feature index f75ebc3..55a7a8a 100644 --- a/code/Test_definitions/edge-application-management-updateAppDeployment.feature +++ b/code/Test_definitions/edge-application-management-addEdgeCloudZone.feature @@ -1,4 +1,4 @@ -Feature: CAMARA Edge Application Management API, vwip - Operation updateAppDeployment +Feature: CAMARA Edge Application Management API, vwip - Operation addEdgeCloudZone # Input to be provided by the implementation to the tester # # Implementation indications: @@ -7,46 +7,69 @@ Feature: CAMARA Edge Application Management API, vwip - Operation updateAppDeplo # Testing assets: # * An appId of a submitted application and the values used in the submitApp operation. # * A deployment instantiated by createAppDeployment operation. + # * An additional edgeCloudZoneId not yet part of the deployment. # # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml - Background: Common updateAppDeployment setup + Background: Common addEdgeCloudZone setup Given an environment at "apiRoot" - And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/addEdgeCloudZone" And the header "Content-Type" is set to "application/json" And the header "Authorization" is set to a valid access token And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" # Properties not explicitly overwritten in the Scenarios can take any values compliant with the schema And the request body is set by default to a request body compliant with the request body schema for this operation # Success scenarios - @eam_updateAppDeployment_01_generic_success_scenario - Scenario: Update a running instance of an application within an Edge Cloud Zone with mandatory parameter ("appDeploymentId") - Given there are application instances running + @eam_addEdgeCloudZone_01_generic_success_scenario + Scenario: Add an Edge Cloud Zone to an existing deployment with mandatory parameters + Given there is a deployment created by operation createAppDeployment And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID - And the body property "$.appDeploymentName" is set to a valid name - When the request "updateAppDeployment" is sent + And the request body property "$.edgeCloudZoneId" is set to a valid edge zone id not yet part of the deployment + When the request "addEdgeCloudZone" is sent Then the response status code is 200 And the response header "Content-Type" is "application/json" And the response header "x-correlator" has same value as the request header "x-correlator" And the response body complies with the OAS schema at "/components/schemas/AppDeploymentInfo" + And the response property "$.edgeCloudZones" contains the value provided for "$.edgeCloudZoneId" + # Error scenarios # Error 409 - @eam_updateAppDeployment_409.1_aborted - Scenario: Error response for a concurrent update conflict - Given there is a concurrent update in progress for the deployment + @eam_addEdgeCloudZone_409.1_already_exists + Scenario: Add an Edge Cloud Zone already part of the deployment + Given there is a deployment created by operation createAppDeployment And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID - When the request "updateAppDeployment" is sent + And the request body property "$.edgeCloudZoneId" is set to an edge zone id already part of the deployment + When the request "addEdgeCloudZone" is sent Then the response status code is 409 - And the response header "x-correlator" has same value as the request header "x-correlator" And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" And the response property "$.status" is 409 - And the response property "$.code" is "ABORTED" + And the response property "$.code" is "ALREADY_EXISTS" + And the response property "$.message" contains a user friendly text + # Error 400 + @eam_addEdgeCloudZone_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the request body schema for this operation + When the request "addEdgeCloudZone" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + @eam_addEdgeCloudZone_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "addEdgeCloudZone" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" And the response property "$.message" contains a user friendly text - # Errors # Error 404 - @eam_updateAppDeployment_404.1_invalid_parameter - Scenario: Update a running instance of an application within an Edge Cloud Zone with mandatory, and non-existing, parameter ("appDeploymentId") - Given there are application instances running - And the path parameter "$.appDeploymentId" is set to an invalid application instance ID - When the request "updateAppDeployment" is sent + @eam_addEdgeCloudZone_404.1_invalid_parameter + Scenario: Add an Edge Cloud Zone to a non-existing deployment + Given the request path parameter "$.appDeploymentId" is set to an invalid application deployment ID + When the request "addEdgeCloudZone" is sent Then the response status code is 404 And the response header "x-correlator" has same value as the request header "x-correlator" And the response header "Content-Type" is "application/json" @@ -54,21 +77,21 @@ Feature: CAMARA Edge Application Management API, vwip - Operation updateAppDeplo And the response property "$.code" is "NOT_FOUND" And the response property "$.message" contains a user friendly text # Error 401 - @eam_updateAppDeployment_401.1_missing_access_token + @eam_addEdgeCloudZone_401.1_missing_access_token Scenario: Missing access token Given the header "Authorization" is not included - When the request "updateAppDeployment" is sent + When the request "addEdgeCloudZone" is sent Then the response status code is 401 And the response header "x-correlator" has same value as the request header "x-correlator" And the response header "Content-Type" is "application/json" And the response property "$.status" is 401 And the response property "$.code" is "UNAUTHENTICATED" And the response property "$.message" contains a user friendly text - # Error 403 - @eam_updateAppDeployment_403.1_missing_access_token_scope + # Errors 403 + @eam_addEdgeCloudZone_403.1_missing_access_token_scope Scenario: Missing access token scope Given the header "Authorization" is set to an access token that does not include the required scope - When the request "updateAppDeployment" is sent + When the request "addEdgeCloudZone" is sent Then the response status code is 403 And the response header "x-correlator" has same value as the request header "x-correlator" And the response header "Content-Type" is "application/json" diff --git a/code/Test_definitions/edge-application-management-addKubernetesCluster.feature b/code/Test_definitions/edge-application-management-addKubernetesCluster.feature new file mode 100644 index 0000000..8ac18c0 --- /dev/null +++ b/code/Test_definitions/edge-application-management-addKubernetesCluster.feature @@ -0,0 +1,100 @@ +Feature: CAMARA Edge Application Management API, vwip - Operation addKubernetesCluster + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * An appId of a submitted application and the values used in the submitApp operation. + # * A deployment instantiated by createAppDeployment operation. + # * An additional kubernetesClusterRef, within an Edge Cloud Zone already part of the + # deployment, not yet used by the deployment. + # + # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml + Background: Common addKubernetesCluster setup + Given an environment at "apiRoot" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/addKubernetesCluster" + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" + # Properties not explicitly overwritten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the request body schema for this operation + # Success scenarios + @eam_addKubernetesCluster_01_generic_success_scenario + Scenario: Add a Kubernetes cluster to an existing deployment with mandatory parameters + Given there is a deployment created by operation createAppDeployment + And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID + And the request body property "$.kubernetesClusterRef" is set to a valid kubernetes cluster not yet part of the deployment + When the request "addKubernetesCluster" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response body complies with the OAS schema at "/components/schemas/AppDeploymentInfo" + # Error scenarios + # Error 409 + @eam_addKubernetesCluster_409.1_already_exists + Scenario: Add a Kubernetes cluster already part of the deployment + Given there is a deployment created by operation createAppDeployment + And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID + And the request body property "$.kubernetesClusterRef" is set to a kubernetes cluster already part of the deployment + When the request "addKubernetesCluster" is sent + Then the response status code is 409 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response property "$.status" is 409 + And the response property "$.code" is "ALREADY_EXISTS" + And the response property "$.message" contains a user friendly text + # Error 400 + @eam_addKubernetesCluster_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the request body schema for this operation + When the request "addKubernetesCluster" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + @eam_addKubernetesCluster_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "addKubernetesCluster" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + # Error 404 + @eam_addKubernetesCluster_404.1_invalid_parameter + Scenario: Add a Kubernetes cluster to a non-existing deployment + Given the request path parameter "$.appDeploymentId" is set to an invalid application deployment ID + When the request "addKubernetesCluster" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text + # Error 401 + @eam_addKubernetesCluster_401.1_missing_access_token + Scenario: Missing access token + Given the header "Authorization" is not included + When the request "addKubernetesCluster" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + # Errors 403 + @eam_addKubernetesCluster_403.1_missing_access_token_scope + Scenario: Missing access token scope + Given the header "Authorization" is set to an access token that does not include the required scope + When the request "addKubernetesCluster" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature b/code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature new file mode 100644 index 0000000..37aad09 --- /dev/null +++ b/code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature @@ -0,0 +1,99 @@ +Feature: CAMARA Edge Application Management API, vwip - Operation removeEdgeCloudZone + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * An appId of a submitted application and the values used in the submitApp operation. + # * A deployment instantiated by createAppDeployment operation, with at least one + # edgeCloudZoneId that can be removed. + # + # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml + Background: Common removeEdgeCloudZone setup + Given an environment at "apiRoot" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/removeEdgeCloudZone" + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" + # Properties not explicitly overwritten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the request body schema for this operation + # Success scenarios + @eam_removeEdgeCloudZone_01_generic_success_scenario + Scenario: Remove an Edge Cloud Zone from an existing deployment with mandatory parameters + Given there is a deployment created by operation createAppDeployment + And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID + And the request body property "$.edgeCloudZoneId" is set to an edge zone id part of the deployment + When the request "removeEdgeCloudZone" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response body complies with the OAS schema at "/components/schemas/AppDeploymentInfo" + And the response property "$.edgeCloudZones" does not contain the value provided for "$.edgeCloudZoneId" + # Error scenarios + # Error 400 + @eam_removeEdgeCloudZone_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the request body schema for this operation + When the request "removeEdgeCloudZone" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + @eam_removeEdgeCloudZone_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "removeEdgeCloudZone" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + # Error 404 + @eam_removeEdgeCloudZone_404.1_invalid_deployment + Scenario: Remove an Edge Cloud Zone from a non-existing deployment + Given the request path parameter "$.appDeploymentId" is set to an invalid application deployment ID + When the request "removeEdgeCloudZone" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text + @eam_removeEdgeCloudZone_404.2_zone_not_in_deployment + Scenario: Remove an Edge Cloud Zone not part of the deployment + Given there is a deployment created by operation createAppDeployment + And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID + And the request body property "$.edgeCloudZoneId" is set to a valid edge zone id not part of the deployment + When the request "removeEdgeCloudZone" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text + # Error 401 + @eam_removeEdgeCloudZone_401.1_missing_access_token + Scenario: Missing access token + Given the header "Authorization" is not included + When the request "removeEdgeCloudZone" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + # Errors 403 + @eam_removeEdgeCloudZone_403.1_missing_access_token_scope + Scenario: Missing access token scope + Given the header "Authorization" is set to an access token that does not include the required scope + When the request "removeEdgeCloudZone" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature b/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature new file mode 100644 index 0000000..718dc24 --- /dev/null +++ b/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature @@ -0,0 +1,98 @@ +Feature: CAMARA Edge Application Management API, vwip - Operation removeKubernetesCluster + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * An appId of a submitted application and the values used in the submitApp operation. + # * A deployment instantiated by createAppDeployment operation, with at least one + # kubernetesClusterRef that can be removed. + # + # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml + Background: Common removeKubernetesCluster setup + Given an environment at "apiRoot" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/removeKubernetesCluster" + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" + # Properties not explicitly overwritten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the request body schema for this operation + # Success scenarios + @eam_removeKubernetesCluster_01_generic_success_scenario + Scenario: Remove a Kubernetes cluster from an existing deployment with mandatory parameters + Given there is a deployment created by operation createAppDeployment + And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID + And the request body property "$.kubernetesClusterRef" is set to a kubernetes cluster part of the deployment + When the request "removeKubernetesCluster" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response body complies with the OAS schema at "/components/schemas/AppDeploymentInfo" + # Error scenarios + # Error 400 + @eam_removeKubernetesCluster_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the request body schema for this operation + When the request "removeKubernetesCluster" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + @eam_removeKubernetesCluster_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "removeKubernetesCluster" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + # Error 404 + @eam_removeKubernetesCluster_404.1_invalid_deployment + Scenario: Remove a Kubernetes cluster from a non-existing deployment + Given the request path parameter "$.appDeploymentId" is set to an invalid application deployment ID + When the request "removeKubernetesCluster" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text + @eam_removeKubernetesCluster_404.2_cluster_not_in_deployment + Scenario: Remove a Kubernetes cluster not part of the deployment + Given there is a deployment created by operation createAppDeployment + And the request path parameter "$.appDeploymentId" is set to a valid application deployment ID + And the request body property "$.kubernetesClusterRef" is set to a valid kubernetes cluster not part of the deployment + When the request "removeKubernetesCluster" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text + # Error 401 + @eam_removeKubernetesCluster_401.1_missing_access_token + Scenario: Missing access token + Given the header "Authorization" is not included + When the request "removeKubernetesCluster" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + # Errors 403 + @eam_removeKubernetesCluster_403.1_missing_access_token_scope + Scenario: Missing access token scope + Given the header "Authorization" is set to an access token that does not include the required scope + When the request "removeKubernetesCluster" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" + And the response property "$.message" contains a user friendly text From 76749d537d8ad1c72f6c3d5d3cc3db90c7d905ce Mon Sep 17 00:00:00 2001 From: DlondonoD Date: Fri, 7 Aug 2026 12:03:47 +0200 Subject: [PATCH 4/6] Expose kubernetesClusterRefs on AppDeploymentInfo addKubernetesCluster and removeKubernetesCluster returned AppDeploymentInfo without any way to verify their effect in the response, unlike addEdgeCloudZone/removeEdgeCloudZone which can be checked against the edgeCloudZones array. Added an optional kubernetesClusterRefs array property (not required, since a deployment may not use any specific Kubernetes cluster) mirroring the one already accepted by createAppDeployment's request body. Updated addKubernetesCluster.feature and removeKubernetesCluster.feature success scenarios to assert the cluster is present/absent in the response accordingly. --- code/API_definitions/edge-application-management.yaml | 8 ++++++++ ...ge-application-management-addKubernetesCluster.feature | 1 + ...application-management-removeKubernetesCluster.feature | 1 + 3 files changed, 10 insertions(+) diff --git a/code/API_definitions/edge-application-management.yaml b/code/API_definitions/edge-application-management.yaml index 9a8056f..c860006 100644 --- a/code/API_definitions/edge-application-management.yaml +++ b/code/API_definitions/edge-application-management.yaml @@ -1633,6 +1633,14 @@ components: maxItems: 100 items: $ref: "#/components/schemas/AppInstanceId" + kubernetesClusterRefs: + description: | + List of Kubernetes clusters used by this deployment, when + applicable. + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/KubernetesClusterRef" AppInstanceInfo: description: Information about the application instance. diff --git a/code/Test_definitions/edge-application-management-addKubernetesCluster.feature b/code/Test_definitions/edge-application-management-addKubernetesCluster.feature index 8ac18c0..713816e 100644 --- a/code/Test_definitions/edge-application-management-addKubernetesCluster.feature +++ b/code/Test_definitions/edge-application-management-addKubernetesCluster.feature @@ -30,6 +30,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation addKubernetesC And the response header "Content-Type" is "application/json" And the response header "x-correlator" has same value as the request header "x-correlator" And the response body complies with the OAS schema at "/components/schemas/AppDeploymentInfo" + And the response property "$.kubernetesClusterRefs" contains the value provided for "$.kubernetesClusterRef" # Error scenarios # Error 409 @eam_addKubernetesCluster_409.1_already_exists diff --git a/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature b/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature index 718dc24..e042763 100644 --- a/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature +++ b/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature @@ -29,6 +29,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation removeKubernet And the response header "Content-Type" is "application/json" And the response header "x-correlator" has same value as the request header "x-correlator" And the response body complies with the OAS schema at "/components/schemas/AppDeploymentInfo" + And the response property "$.kubernetesClusterRefs" does not contain the value provided for "$.kubernetesClusterRef" # Error scenarios # Error 400 @eam_removeKubernetesCluster_400.1_schema_not_compliant From 98b189b7142fa15d10771060f203b44fd29d9d46 Mon Sep 17 00:00:00 2001 From: DlondonoD Date: Tue, 11 Aug 2026 15:14:22 +0200 Subject: [PATCH 5/6] Fix CAMARA validation errors from Actions run 31171204936 (PR #80) - [S-008] x4: the 4 new deployment action paths introduced in a9583a1 used camelCase path segments (addEdgeCloudZone, removeEdgeCloudZone, addKubernetesCluster, removeKubernetesCluster), violating the mandatory kebab-case path convention. Renamed to add-edge-cloud-zone, remove-edge-cloud-zone, add-kubernetes-cluster and remove-kubernetes-cluster respectively, consistent with the rest of the spec's paths (/app-instances, /edge-cloud-zones, etc.). operationIds are unaffected (S-008 only applies to paths). Updated the 4 corresponding .feature files' Background resource to match. - [S-011]: EdgeCloudZoneList.edgeCloudZones (introduced in f0dbe25) was missing a description. Added one. The remaining 10 [S-313] findings (1 warning + 9 notices) are pre-existing free-form/implementation-dependent string fields already covered by the rationale documented for issue #46/#65 (names, versions, opaque strings); no action needed. --- code/API_definitions/edge-application-management.yaml | 11 +++++++---- ...ge-application-management-addEdgeCloudZone.feature | 2 +- ...pplication-management-addKubernetesCluster.feature | 2 +- ...application-management-removeEdgeCloudZone.feature | 2 +- ...ication-management-removeKubernetesCluster.feature | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/code/API_definitions/edge-application-management.yaml b/code/API_definitions/edge-application-management.yaml index c860006..399261f 100644 --- a/code/API_definitions/edge-application-management.yaml +++ b/code/API_definitions/edge-application-management.yaml @@ -869,7 +869,7 @@ paths: "503": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - /deployments/{appDeploymentId}/addEdgeCloudZone: + /deployments/{appDeploymentId}/add-edge-cloud-zone: post: security: - openId: @@ -940,7 +940,7 @@ paths: "503": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - /deployments/{appDeploymentId}/removeEdgeCloudZone: + /deployments/{appDeploymentId}/remove-edge-cloud-zone: post: security: - openId: @@ -1011,7 +1011,7 @@ paths: "503": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - /deployments/{appDeploymentId}/addKubernetesCluster: + /deployments/{appDeploymentId}/add-kubernetes-cluster: post: security: - openId: @@ -1082,7 +1082,7 @@ paths: "503": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic503" - /deployments/{appDeploymentId}/removeKubernetesCluster: + /deployments/{appDeploymentId}/remove-kubernetes-cluster: post: security: - openId: @@ -1969,6 +1969,9 @@ components: - pagination properties: edgeCloudZones: + description: | + The Edge Cloud Zones matching the specified query parameters, + for the requested page. type: array maxItems: 100 items: diff --git a/code/Test_definitions/edge-application-management-addEdgeCloudZone.feature b/code/Test_definitions/edge-application-management-addEdgeCloudZone.feature index 55a7a8a..9b29baa 100644 --- a/code/Test_definitions/edge-application-management-addEdgeCloudZone.feature +++ b/code/Test_definitions/edge-application-management-addEdgeCloudZone.feature @@ -12,7 +12,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation addEdgeCloudZo # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml Background: Common addEdgeCloudZone setup Given an environment at "apiRoot" - And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/addEdgeCloudZone" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/add-edge-cloud-zone" And the header "Content-Type" is set to "application/json" And the header "Authorization" is set to a valid access token And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" diff --git a/code/Test_definitions/edge-application-management-addKubernetesCluster.feature b/code/Test_definitions/edge-application-management-addKubernetesCluster.feature index 713816e..1a58e05 100644 --- a/code/Test_definitions/edge-application-management-addKubernetesCluster.feature +++ b/code/Test_definitions/edge-application-management-addKubernetesCluster.feature @@ -13,7 +13,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation addKubernetesC # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml Background: Common addKubernetesCluster setup Given an environment at "apiRoot" - And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/addKubernetesCluster" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/add-kubernetes-cluster" And the header "Content-Type" is set to "application/json" And the header "Authorization" is set to a valid access token And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" diff --git a/code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature b/code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature index 37aad09..eef4df5 100644 --- a/code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature +++ b/code/Test_definitions/edge-application-management-removeEdgeCloudZone.feature @@ -12,7 +12,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation removeEdgeClou # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml Background: Common removeEdgeCloudZone setup Given an environment at "apiRoot" - And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/removeEdgeCloudZone" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/remove-edge-cloud-zone" And the header "Content-Type" is set to "application/json" And the header "Authorization" is set to a valid access token And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" diff --git a/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature b/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature index e042763..3e03b59 100644 --- a/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature +++ b/code/Test_definitions/edge-application-management-removeKubernetesCluster.feature @@ -12,7 +12,7 @@ Feature: CAMARA Edge Application Management API, vwip - Operation removeKubernet # References to OAS spec schemas refer to schemas specified in edge-application-management.yaml Background: Common removeKubernetesCluster setup Given an environment at "apiRoot" - And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/removeKubernetesCluster" + And the resource "/edge-application-management/vwip/deployments/{appDeploymentId}/remove-kubernetes-cluster" And the header "Content-Type" is set to "application/json" And the header "Authorization" is set to a valid access token And the header "x-correlator" complies with the schema at "#/components/schemas/XCorrelator" From 7bdd53791c7109afe06af3e537c072feac11f00e Mon Sep 17 00:00:00 2001 From: DlondonoD Date: Tue, 11 Aug 2026 15:26:28 +0200 Subject: [PATCH 6/6] Fix P-040 bundling name collision on Generic400/403 (Actions run 31495351424, PR #80) The Generic400/403 response objects introduced locally for #72 (restricting the documented error codes, e.g. dropping OUT_OF_RANGE and INVALID_TOKEN_CONTEXT) never made it past the fix/issue-72 branch into fix/issue-73/74/75, which were branched from main instead. Only the redesigned getEdgeCloudZones operation (added in fix/issue-73) ended up referencing the local Generic400/403, while every other operation still $ref'd the common ones - two different-content components sharing the same name in the same bundled document, which the validator flags as a P-040 collision. Consistently applied the #72 fix repo-wide instead: - Added a local Generic404 (NOT_FOUND only, dropping IDENTIFIER_NOT_FOUND per the same #72 rationale), which was missing. - Replaced all remaining external $ref's to CAMARA_common.yaml's Generic400/403/404 - including the two notification callbacks - with the local ones, so each name now resolves to exactly one component throughout the bundled document. Generic401 is untouched, since no local override exists for it and no collision was ever reported. --- .../edge-application-management.yaml | 113 +++++++++++------- 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/code/API_definitions/edge-application-management.yaml b/code/API_definitions/edge-application-management.yaml index 399261f..db2e9e3 100644 --- a/code/API_definitions/edge-application-management.yaml +++ b/code/API_definitions/edge-application-management.yaml @@ -248,11 +248,11 @@ paths: schema: $ref: "#/components/schemas/SubmittedApp" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "409": description: Conflict headers: @@ -297,11 +297,11 @@ paths: items: $ref: "#/components/schemas/AppManifestInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -341,13 +341,13 @@ paths: schema: $ref: "#/components/schemas/AppManifestInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -385,13 +385,13 @@ paths: x-correlator: $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "409": description: Conflict headers: @@ -468,11 +468,11 @@ paths: schema: $ref: "#/components/schemas/AppInstanceInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "409": description: Conflict headers: @@ -541,11 +541,11 @@ paths: items: $ref: "#/components/schemas/AppInstanceInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -584,13 +584,13 @@ paths: schema: $ref: "#/components/schemas/AppInstanceInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -630,13 +630,13 @@ paths: x-correlator: $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -709,11 +709,11 @@ paths: appDeploymentId: $ref: "#/components/schemas/AppDeploymentId" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "409": description: Conflict headers: @@ -774,11 +774,11 @@ paths: items: $ref: "#/components/schemas/AppDeploymentInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -817,13 +817,13 @@ paths: schema: $ref: "#/components/schemas/AppDeploymentInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -857,13 +857,13 @@ paths: x-correlator: $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "500": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic500" "503": @@ -915,13 +915,13 @@ paths: schema: $ref: "#/components/schemas/AppDeploymentInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "409": description: Conflict headers: @@ -986,11 +986,11 @@ paths: schema: $ref: "#/components/schemas/AppDeploymentInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": description: | The application deployment, or the given Edge Cloud Zone within @@ -1057,13 +1057,13 @@ paths: schema: $ref: "#/components/schemas/AppDeploymentInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic404" + $ref: "#/components/responses/Generic404" "409": description: Conflict headers: @@ -1128,11 +1128,11 @@ paths: schema: $ref: "#/components/schemas/AppDeploymentInfo" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "404": description: | The application deployment, or the given Kubernetes cluster @@ -1308,6 +1308,31 @@ components: status: 403 code: PERMISSION_DENIED message: Client does not have sufficient permissions to perform this action. + Generic404: + description: Not found + headers: + x-correlator: + $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "../common/CAMARA_common.yaml#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 404 + code: + enum: + - NOT_FOUND + examples: + GENERIC_404_NOT_FOUND: + description: Resource is not found + value: + status: 404 + code: NOT_FOUND + message: The specified resource is not found. callbacks: onAppInstanceStatusChange: @@ -1343,11 +1368,11 @@ components: x-correlator: $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "410": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic410" "429": @@ -1385,11 +1410,11 @@ components: x-correlator: $ref: "../common/CAMARA_common.yaml#/components/headers/x-correlator" "400": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic400" + $ref: "#/components/responses/Generic400" "401": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic401" "403": - $ref: "../common/CAMARA_common.yaml#/components/responses/Generic403" + $ref: "#/components/responses/Generic403" "410": $ref: "../common/CAMARA_common.yaml#/components/responses/Generic410" "429":