Commit 42e8ec14 authored by Javier Velázquez's avatar Javier Velázquez
Browse files

Merge branch 'feat/46-tid-fix-telemetry-endpoints-obtaining-none-templates' into 'develop'

Resolve "(TID) Fix telemetry endpoints obtaining none templates"

See merge request !49
parents 9c2e9efc 14e0321b
Loading
Loading
Loading
Loading
Loading
+9 −2
Changes for src/api/handlers/restconf_handler.py: 9 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -1038,9 +1038,16 @@ class RestconfHandler:
        if not existing_slice:
            raise ValueError(f"There is no slice with id '{slice_id}' registered")

        template_id = safe_get(
            existing_slice, ["network-slice-services", "slice-service", slice_id, "slo-sle-template"]
        # slice-service is a list after normalize_libyang_data, so look the slice up by id
        slice_list = safe_get(existing_slice, ["network-slice-services", "slice-service"]) or []
        slice_item = next(
            (item for item in slice_list if isinstance(item, dict) and item.get("id") == slice_id), None
        )
        template_id = slice_item.get("slo-sle-template") if slice_item else None
        if not template_id:
            raise ValueError(f"Slice '{slice_id}' has no SLO/SLE template assigned")

        logger.debug("Using SLO/SLE template '%s' for slice '%s'", template_id, slice_id)
        slo_sle_template = self.get_slo_sle_templates(template_id)[0]
        slo_sle_template = safe_get(
            slo_sle_template, ["network-slice-services", "slo-sle-templates", "slo-sle-template"]
+34 −5
Changes for src/tests/test_api.py: 34 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -514,9 +514,14 @@ class TestTelemetryStreams:
            res, code = api.get_telemetry("nonexistent-slice")
            assert code == 404

        # More than 2 SDPs error
        # Malformed slice data without a template -> 404
        with patch("src.api.main.get_data_store", return_value=[1, 2, 3]):
            res, code = api.get_telemetry("slice-many-sdps")
            res, code = api.get_telemetry("slice-malformed")
            assert code == 404

        # Unexpected datastore error -> 500
        with patch("src.api.main.get_data_store", side_effect=RuntimeError("sysrepo down")):
            res, code = api.get_telemetry("slice-error")
            assert code == 500

    def test_get_telemetry_history(self, controller_with_mocked_db):
@@ -1332,9 +1337,9 @@ class TestApiRequestedMethodsCoverage:
        api = Api(controller_with_mocked_db)

        # Single slice telemetry success
        existing_slice = {"network-slice-services": {"slice-service": {"s1": {"slo-sle-template": "tmpl-1"}}}}
        existing_slice = {"network-slice-services": {"slice-service": [{"id": "s1", "slo-sle-template": "tmpl-1"}]}}
        tmpl_data = [
            {"network-slice-services": {"slo-sle-templates": {"slo-sle-template": {"tmpl-1": {"id": "tmpl-1"}}}}}
            {"network-slice-services": {"slo-sle-templates": {"slo-sle-template": [{"id": "tmpl-1"}]}}}
        ]
        with (
            patch("src.api.main.get_data_store", return_value=existing_slice),
@@ -1350,8 +1355,14 @@ class TestApiRequestedMethodsCoverage:
            res_no_slice, code_no_slice = api.get_telemetry("s1")
            assert code_no_slice == 404

        # Single slice telemetry - slice without template -> 404
        no_tmpl_slice = {"network-slice-services": {"slice-service": [{"id": "s1"}]}}
        with patch("src.api.main.get_data_store", return_value=no_tmpl_slice):
            _, code_unassigned = api.get_telemetry("s1")
            assert code_unassigned == 404

        # Single slice telemetry - template not found -> 404
        empty_tmpl_data = [{"network-slice-services": {"slo-sle-templates": {"slo-sle-template": {}}}}]
        empty_tmpl_data = [{"network-slice-services": {"slo-sle-templates": {"slo-sle-template": []}}}]
        with (
            patch("src.api.main.get_data_store", return_value=existing_slice),
            patch.object(api, "get_slo_sle_templates", return_value=empty_tmpl_data),
@@ -1372,6 +1383,24 @@ class TestApiRequestedMethodsCoverage:
            assert code_all == 200
            assert "s1" in res_all

    def test_get_single_slice_telemetry_uses_slice_template(self, controller_with_mocked_db):
        """The slice's own template is used, not the first one stored in sysrepo."""
        api = Api(controller_with_mocked_db)
        existing_slice = {"network-slice-services": {"slice-service": [{"id": "s1", "slo-sle-template": "gold"}]}}
        gold = {"id": "gold", "slo-policy": {"metric-bound": [{"metric-type": "two-way-delay-maximum", "bound": 5}]}}
        gold_data = {"network-slice-services": {"slo-sle-templates": {"slo-sle-template": [gold]}}}

        with (
            patch("src.api.main.get_data_store", return_value=existing_slice),
            patch.object(api, "get_slo_sle_templates", return_value=(gold_data, 200)) as mock_templates,
            patch.object(api.slice_service, "monitoring", return_value={"ok": True}) as mock_monitoring,
        ):
            _, code = api.get_telemetry("s1")

        assert code == 200
        mock_templates.assert_called_once_with("gold")
        mock_monitoring.assert_called_once_with("s1", gold)

    def test_sync_stream_and_streams_coverage(self, controller_with_mocked_db):
        api = Api(controller_with_mocked_db)