From 7c386b07f3dabddeeda8fbadbeb250a20cde020c Mon Sep 17 00:00:00 2001 From: Anastasios Pandis Date: Fri, 24 Apr 2026 12:39:39 +0300 Subject: [PATCH] fix: add canonical location-retrieval path and deprecate non-canonical alias --- .../network_functions_controller.py | 5 ++ .../specification/openapi.yaml | 50 ++++++++++++++++++- .../test_network_functions_controller.py | 48 ++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/edge_cloud_management_api/controllers/network_functions_controller.py b/edge_cloud_management_api/controllers/network_functions_controller.py index 87e88ef..3cc95d7 100644 --- a/edge_cloud_management_api/controllers/network_functions_controller.py +++ b/edge_cloud_management_api/controllers/network_functions_controller.py @@ -159,3 +159,8 @@ def retrieve_location(body: dict): jsonify({"error": "An unexpected error occurred", "details": str(e)}), 500, ) + + +def retrieve_location_legacy(body: dict): + """Deprecated legacy alias for location retrieval.""" + return retrieve_location(body) diff --git a/edge_cloud_management_api/specification/openapi.yaml b/edge_cloud_management_api/specification/openapi.yaml index cbfba64..0a0ed1b 100644 --- a/edge_cloud_management_api/specification/openapi.yaml +++ b/edge_cloud_management_api/specification/openapi.yaml @@ -814,7 +814,7 @@ paths: # description: Method not allowed # "404": # description: Session not found - /location/retrieve: + /location-retrieval/v0.5/retrieve: post: tags: - Location Retrieval Functions @@ -863,6 +863,54 @@ paths: $ref: "#/components/responses/500" "503": $ref: "#/components/responses/503" + /location/retrieve: + post: + tags: + - Location Retrieval Functions + summary: Deprecated legacy alias for location retrieval + description: | + Deprecated legacy alias. Use /location-retrieval/v0.5/retrieve. + deprecated: true + operationId: edge_cloud_management_api.controllers.network_functions_controller.retrieve_location_legacy + requestBody: + description: Location retrieval request following CAMARA Device Location API. + content: + application/json: + schema: + $ref: '#/components/schemas/RetrievalLocationRequest' + examples: + PhoneNumberExample: + summary: Retrieve location by phone number + value: + device: + phoneNumber: "+123456789" + maxAge: 60 + Ipv4Example: + summary: Retrieve location by IPv4 address + value: + device: + ipv4Address: + publicAddress: "198.51.100.1" + publicPort: 59765 + maxAge: 120 + maxSurface: 10000 + responses: + "200": + description: Device location retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/LocationResponse' + "400": + $ref: "#/components/responses/400" + "401": + $ref: "#/components/responses/401" + "404": + $ref: "#/components/responses/404" + "500": + $ref: "#/components/responses/500" + "503": + $ref: "#/components/responses/503" /partner: post: tags: diff --git a/tests/unit/controllers/test_network_functions_controller.py b/tests/unit/controllers/test_network_functions_controller.py index 1ad0683..97d8852 100644 --- a/tests/unit/controllers/test_network_functions_controller.py +++ b/tests/unit/controllers/test_network_functions_controller.py @@ -97,3 +97,51 @@ def test_retrieve_location_with_ipv4(mock_factory_class, test_app: Flask): assert result == SAMPLE_LOCATION_RESPONSE mock_client.retrieve_location.assert_called_once_with(ipv4_request) + + +@pytest.mark.unit +@patch("edge_cloud_management_api.controllers.network_functions_controller.PiEdgeAPIClientFactory") +def test_retrieve_location_legacy_success(mock_factory_class, test_app: Flask): + """Legacy route alias returns the same successful response as the canonical route.""" + mock_client = MagicMock() + mock_client.retrieve_location.return_value = SAMPLE_LOCATION_RESPONSE + mock_factory_class.return_value.create_pi_edge_api_client.return_value = mock_client + + with test_app.test_request_context(): + result = network_functions_controller.retrieve_location_legacy(SAMPLE_LOCATION_REQUEST) + + assert result == SAMPLE_LOCATION_RESPONSE + mock_client.retrieve_location.assert_called_once_with(SAMPLE_LOCATION_REQUEST) + + +@pytest.mark.unit +@patch("edge_cloud_management_api.controllers.network_functions_controller.PiEdgeAPIClientFactory") +def test_retrieve_location_legacy_srm_error_is_relayed(mock_factory_class, test_app: Flask): + """Legacy route alias relays SRM errors the same way as the canonical route.""" + error_body = {"error": "Device not found"} + mock_client = MagicMock() + mock_client.retrieve_location.return_value = (error_body, 404) + mock_factory_class.return_value.create_pi_edge_api_client.return_value = mock_client + + with test_app.test_request_context(): + result = network_functions_controller.retrieve_location_legacy(SAMPLE_LOCATION_REQUEST) + + assert result == (error_body, 404) + + +@pytest.mark.unit +@patch("edge_cloud_management_api.controllers.network_functions_controller.PiEdgeAPIClientFactory") +def test_retrieve_location_legacy_connection_error(mock_factory_class, test_app: Flask): + """Legacy route alias preserves canonical connection error behavior.""" + mock_client = MagicMock() + mock_client.retrieve_location.side_effect = ConnectionError("Connection refused") + mock_factory_class.return_value.create_pi_edge_api_client.return_value = mock_client + + with test_app.test_request_context(): + response, status = network_functions_controller.retrieve_location_legacy(SAMPLE_LOCATION_REQUEST) + + assert status == 500 + data = response.get_json() + assert data["error"] == "An unexpected error occurred" + assert "Connection refused" in data["details"] + -- GitLab