From db43486c866be088a63ecfc4da6372bb49d04188 Mon Sep 17 00:00:00 2001 From: Jim Overholt Date: Mon, 15 Apr 2024 17:02:28 -0700 Subject: [PATCH 1/5] server_info --- catalystwan/api/server_info.py | 39 ++++++++++++++++++++++++++++ catalystwan/endpoints/server_info.py | 12 +++++++++ catalystwan/models/server_info.py | 10 +++++++ 3 files changed, 61 insertions(+) create mode 100644 catalystwan/api/server_info.py create mode 100644 catalystwan/endpoints/server_info.py create mode 100644 catalystwan/models/server_info.py diff --git a/catalystwan/api/server_info.py b/catalystwan/api/server_info.py new file mode 100644 index 00000000..3dccbffa --- /dev/null +++ b/catalystwan/api/server_info.py @@ -0,0 +1,39 @@ +# Copyright 2023 Cisco Systems, Inc. and its affiliates + +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING + +from catalystwan.models.server_info import ServerInfoResponse + +if TYPE_CHECKING: + from catalystwan.session import ManagerSession + +logger = logging.getLogger(__name__) + + +class ServerInfoAPI: + """API methods of Server Info. + + Attributes: + session: logged in API client session + Usage example: + # Create session + session = create_manager_session(...) + # Create device vpn + server_info = session.api.server_info.get() + """ + + def __init__(self, session: ManagerSession): + self.session = session + + def get(self) -> ServerInfoResponse: + """Get server info. + + Args: + Returns: + ServerInfoResponse. + """ + response = self._endpoints.server_info() + return response.dataseq(ServerInfoResponse) diff --git a/catalystwan/endpoints/server_info.py b/catalystwan/endpoints/server_info.py new file mode 100644 index 00000000..39efd577 --- /dev/null +++ b/catalystwan/endpoints/server_info.py @@ -0,0 +1,12 @@ +# Copyright 2024 Cisco Systems, Inc. and its affiliates + +# mypy: disable-error-code="empty-body" + +from catalystwan.endpoints import APIEndpoints, get +from catalystwan.models.server_info import ServerInfoResponse + + +class ServerInfo(APIEndpoints): + @get("server/info") + def get_server_info(self) -> ServerInfoResponse: + ... diff --git a/catalystwan/models/server_info.py b/catalystwan/models/server_info.py new file mode 100644 index 00000000..1c5feec9 --- /dev/null +++ b/catalystwan/models/server_info.py @@ -0,0 +1,10 @@ +# Copyright 2024 Cisco Systems, Inc. and its affiliates + +from pydantic import BaseModel, Field + + +class ServerInfoResponse(BaseModel): + """The response may contain an incorrect spelling "Achitecture".""" + + Architecture: str = Field(..., alias="Achitecture") + Available_processors: int From 76ded6ec29ece50bdb46e76be7290db69014e2e9 Mon Sep 17 00:00:00 2001 From: Jim Overholt Date: Tue, 16 Apr 2024 10:35:19 -0700 Subject: [PATCH 2/5] monitoring --- catalystwan/api/server_info.py | 39 ------------------- catalystwan/endpoints/endpoints_container.py | 2 + .../endpoints/{ => monitoring}/server_info.py | 2 +- .../models/{ => monitoring}/server_info.py | 0 4 files changed, 3 insertions(+), 40 deletions(-) delete mode 100644 catalystwan/api/server_info.py rename catalystwan/endpoints/{ => monitoring}/server_info.py (78%) rename catalystwan/models/{ => monitoring}/server_info.py (100%) diff --git a/catalystwan/api/server_info.py b/catalystwan/api/server_info.py deleted file mode 100644 index 3dccbffa..00000000 --- a/catalystwan/api/server_info.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2023 Cisco Systems, Inc. and its affiliates - -from __future__ import annotations - -import logging -from typing import TYPE_CHECKING - -from catalystwan.models.server_info import ServerInfoResponse - -if TYPE_CHECKING: - from catalystwan.session import ManagerSession - -logger = logging.getLogger(__name__) - - -class ServerInfoAPI: - """API methods of Server Info. - - Attributes: - session: logged in API client session - Usage example: - # Create session - session = create_manager_session(...) - # Create device vpn - server_info = session.api.server_info.get() - """ - - def __init__(self, session: ManagerSession): - self.session = session - - def get(self) -> ServerInfoResponse: - """Get server info. - - Args: - Returns: - ServerInfoResponse. - """ - response = self._endpoints.server_info() - return response.dataseq(ServerInfoResponse) diff --git a/catalystwan/endpoints/endpoints_container.py b/catalystwan/endpoints/endpoints_container.py index c8c53c69..d7a4106e 100644 --- a/catalystwan/endpoints/endpoints_container.py +++ b/catalystwan/endpoints/endpoints_container.py @@ -85,6 +85,7 @@ from catalystwan.endpoints.misc import MiscellaneousEndpoints from catalystwan.endpoints.monitoring_device_details import MonitoringDeviceDetails from catalystwan.endpoints.monitoring_status import MonitoringStatus +from catalystwan.endpoints.monitoring.server_info import ServerInfo from catalystwan.endpoints.real_time_monitoring.reboot_history import RealTimeMonitoringRebootHistory from catalystwan.endpoints.sdavc_cloud_connector import SDAVCCloudConnector from catalystwan.endpoints.tenant_backup_restore import TenantBackupRestore @@ -198,6 +199,7 @@ def __init__(self, session: ManagerSession): self.configuration_software_actions = ConfigurationSoftwareActions(session) self.configuration_disaster_recovery = ConfigurationDisasterRecovery(session) self.monitoring_device_details = MonitoringDeviceDetails(session) + self.monitoring_server_info = ServerInfo(session) self.monitoring_status = MonitoringStatus(session) self.sdavc_cloud_connector = SDAVCCloudConnector(session) self.tenant_backup_restore = TenantBackupRestore(session) diff --git a/catalystwan/endpoints/server_info.py b/catalystwan/endpoints/monitoring/server_info.py similarity index 78% rename from catalystwan/endpoints/server_info.py rename to catalystwan/endpoints/monitoring/server_info.py index 39efd577..cd14ee0b 100644 --- a/catalystwan/endpoints/server_info.py +++ b/catalystwan/endpoints/monitoring/server_info.py @@ -3,7 +3,7 @@ # mypy: disable-error-code="empty-body" from catalystwan.endpoints import APIEndpoints, get -from catalystwan.models.server_info import ServerInfoResponse +from catalystwan.models.monitoring.server_info import ServerInfoResponse class ServerInfo(APIEndpoints): diff --git a/catalystwan/models/server_info.py b/catalystwan/models/monitoring/server_info.py similarity index 100% rename from catalystwan/models/server_info.py rename to catalystwan/models/monitoring/server_info.py From 501ec3c7f586dedc203326fe1c78a0132c26a540 Mon Sep 17 00:00:00 2001 From: Jim Overholt Date: Tue, 16 Apr 2024 12:10:57 -0700 Subject: [PATCH 3/5] monitoring --- catalystwan/api/monitoring_status_api.py | 2 +- catalystwan/api/templates/payloads/tenant/tenant_model.py | 2 +- catalystwan/endpoints/endpoints_container.py | 4 ++-- .../device_details.py} | 0 catalystwan/endpoints/monitoring/server_info.py | 2 +- .../{monitoring_status.py => monitoring/status.py} | 0 catalystwan/models/monitoring/server_info.py | 6 ++++-- catalystwan/tests/test_devices_api.py | 2 +- catalystwan/tests/test_monitoring_status_api.py | 2 +- 9 files changed, 11 insertions(+), 9 deletions(-) rename catalystwan/endpoints/{monitoring_device_details.py => monitoring/device_details.py} (100%) rename catalystwan/endpoints/{monitoring_status.py => monitoring/status.py} (100%) diff --git a/catalystwan/api/monitoring_status_api.py b/catalystwan/api/monitoring_status_api.py index ebc5d111..295ceb68 100644 --- a/catalystwan/api/monitoring_status_api.py +++ b/catalystwan/api/monitoring_status_api.py @@ -5,7 +5,7 @@ import logging from typing import TYPE_CHECKING, List -from catalystwan.endpoints.monitoring_status import MonitoringStatus, Status, UpdateStatus +from catalystwan.endpoints.monitoring.status import MonitoringStatus, Status, UpdateStatus from catalystwan.typed_list import DataSequence logger = logging.getLogger(__name__) diff --git a/catalystwan/api/templates/payloads/tenant/tenant_model.py b/catalystwan/api/templates/payloads/tenant/tenant_model.py index 77454178..37176009 100644 --- a/catalystwan/api/templates/payloads/tenant/tenant_model.py +++ b/catalystwan/api/templates/payloads/tenant/tenant_model.py @@ -8,7 +8,7 @@ from pydantic import BaseModel, ConfigDict from catalystwan.api.templates.feature_template import FeatureTemplate -from catalystwan.endpoints.monitoring_device_details import Tier as TierInfo +from catalystwan.endpoints.monitoring.device_details import Tier as TierInfo from catalystwan.models.tenant import Tenant as TenantInfo if TYPE_CHECKING: diff --git a/catalystwan/endpoints/endpoints_container.py b/catalystwan/endpoints/endpoints_container.py index d7a4106e..99ae32fc 100644 --- a/catalystwan/endpoints/endpoints_container.py +++ b/catalystwan/endpoints/endpoints_container.py @@ -83,9 +83,9 @@ from catalystwan.endpoints.configuration_group import ConfigurationGroup from catalystwan.endpoints.configuration_settings import ConfigurationSettings from catalystwan.endpoints.misc import MiscellaneousEndpoints -from catalystwan.endpoints.monitoring_device_details import MonitoringDeviceDetails -from catalystwan.endpoints.monitoring_status import MonitoringStatus +from catalystwan.endpoints.monitoring.device_details import MonitoringDeviceDetails from catalystwan.endpoints.monitoring.server_info import ServerInfo +from catalystwan.endpoints.monitoring.status import MonitoringStatus from catalystwan.endpoints.real_time_monitoring.reboot_history import RealTimeMonitoringRebootHistory from catalystwan.endpoints.sdavc_cloud_connector import SDAVCCloudConnector from catalystwan.endpoints.tenant_backup_restore import TenantBackupRestore diff --git a/catalystwan/endpoints/monitoring_device_details.py b/catalystwan/endpoints/monitoring/device_details.py similarity index 100% rename from catalystwan/endpoints/monitoring_device_details.py rename to catalystwan/endpoints/monitoring/device_details.py diff --git a/catalystwan/endpoints/monitoring/server_info.py b/catalystwan/endpoints/monitoring/server_info.py index cd14ee0b..a7e0b902 100644 --- a/catalystwan/endpoints/monitoring/server_info.py +++ b/catalystwan/endpoints/monitoring/server_info.py @@ -7,6 +7,6 @@ class ServerInfo(APIEndpoints): - @get("server/info") + @get("/server/info") def get_server_info(self) -> ServerInfoResponse: ... diff --git a/catalystwan/endpoints/monitoring_status.py b/catalystwan/endpoints/monitoring/status.py similarity index 100% rename from catalystwan/endpoints/monitoring_status.py rename to catalystwan/endpoints/monitoring/status.py diff --git a/catalystwan/models/monitoring/server_info.py b/catalystwan/models/monitoring/server_info.py index 1c5feec9..444cf4ab 100644 --- a/catalystwan/models/monitoring/server_info.py +++ b/catalystwan/models/monitoring/server_info.py @@ -6,5 +6,7 @@ class ServerInfoResponse(BaseModel): """The response may contain an incorrect spelling "Achitecture".""" - Architecture: str = Field(..., alias="Achitecture") - Available_processors: int + architecture: str = Field(..., alias="Achitecture") + available_processors: int = Field( + ..., serialization_alias="Available processors", validation_alias="Available processors" + ) diff --git a/catalystwan/tests/test_devices_api.py b/catalystwan/tests/test_devices_api.py index 23fd9d92..aaebfe40 100644 --- a/catalystwan/tests/test_devices_api.py +++ b/catalystwan/tests/test_devices_api.py @@ -10,7 +10,7 @@ from catalystwan.api.basic_api import DevicesAPI, DeviceStateAPI from catalystwan.dataclasses import BfdSessionData, Connection, Device, WanInterface from catalystwan.endpoints.endpoints_container import APIEndpointContainter -from catalystwan.endpoints.monitoring_device_details import DeviceData +from catalystwan.endpoints.monitoring.device_details import DeviceData from catalystwan.endpoints.real_time_monitoring.reboot_history import RebootEntry from catalystwan.exceptions import CatalystwanException from catalystwan.response import ManagerResponse diff --git a/catalystwan/tests/test_monitoring_status_api.py b/catalystwan/tests/test_monitoring_status_api.py index e30cdfe1..c491958b 100644 --- a/catalystwan/tests/test_monitoring_status_api.py +++ b/catalystwan/tests/test_monitoring_status_api.py @@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch from catalystwan.api.monitoring_status_api import MonitoringStatusAPI -from catalystwan.endpoints.monitoring_status import ( +from catalystwan.endpoints.monitoring.status import ( DisabledDeviceListResponse, EnabledIndexDeviceListResponse, Status, From bbf9a1bc348aea6618e026526ab01bcbb149b3fe Mon Sep 17 00:00:00 2001 From: Jim Overholt Date: Tue, 16 Apr 2024 17:16:25 -0700 Subject: [PATCH 4/5] tests --- .../tests/test_monitoring_server_info.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 catalystwan/tests/test_monitoring_server_info.py diff --git a/catalystwan/tests/test_monitoring_server_info.py b/catalystwan/tests/test_monitoring_server_info.py new file mode 100644 index 00000000..deb01ea1 --- /dev/null +++ b/catalystwan/tests/test_monitoring_server_info.py @@ -0,0 +1,26 @@ +# Copyright 2022 Cisco Systems, Inc. and its affiliates + +import unittest +from unittest.mock import MagicMock, patch + +from catalystwan.endpoints.monitoring.server_info import ServerInfo + + +class TestServerInfo(unittest.TestCase): + def test_get_server_info(self): + # Arrange + self.api._endpoints.get_server_info.return_value = self.server_info_response + # Act + result = self.api.get_server_info() + # Assert + assert result == self.server_info_response + + + @patch("catalystwan.session.ManagerSession") + @patch("catalystwan.response.ManagerResponse") + def setUp(self, mock_session, mock_response) -> None: + self.server_info_response = {'Achitecture': 'amd64', 'Available processors': 8} + self.session = mock_session + self.api = ServerInfo(self.session) + self.api._endpoints = MagicMock() + mock_response.json.return_value = self.server_info_response From df24ed6e2fd2679a66e3a7737343c26408f7454d Mon Sep 17 00:00:00 2001 From: Jim Overholt Date: Wed, 17 Apr 2024 10:29:30 -0700 Subject: [PATCH 5/5] unit-test --- .../tests/test_monitoring_server_info.py | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/catalystwan/tests/test_monitoring_server_info.py b/catalystwan/tests/test_monitoring_server_info.py index deb01ea1..6f6d8fbe 100644 --- a/catalystwan/tests/test_monitoring_server_info.py +++ b/catalystwan/tests/test_monitoring_server_info.py @@ -4,23 +4,46 @@ from unittest.mock import MagicMock, patch from catalystwan.endpoints.monitoring.server_info import ServerInfo +from catalystwan.models.monitoring.server_info import ServerInfoResponse class TestServerInfo(unittest.TestCase): - def test_get_server_info(self): + def setUp(self) -> None: + self.mock_server_info_data = { + "Achitecture": "x86_64", + "Available processors": 4, + } # Note the spelling error + + @patch("catalystwan.session.ManagerSession") + def test_get_server_info(self, mock_session): # Arrange - self.api._endpoints.get_server_info.return_value = self.server_info_response + # Create a MagicMock for the response that has a dataobj method + mock_response = MagicMock() + # Set up the mock response's dataobj method to return a ServerInfoResponse + mock_response.dataobj.return_value = ServerInfoResponse(**self.mock_server_info_data) + + # Mock the request method of the ManagerSession to return the mock response + mock_session_instance = mock_session.return_value + mock_session_instance.request.return_value = mock_response + + server_info_api = ServerInfo(mock_session_instance) + # Act - result = self.api.get_server_info() + response = server_info_api.get_server_info() + # Assert - assert result == self.server_info_response + self.assertIsInstance(response, ServerInfoResponse) + self.assertEqual(response.architecture, self.mock_server_info_data["Achitecture"]) + self.assertEqual( + response.available_processors, + self.mock_server_info_data["Available processors"], + ) + self.assertEqual(response.architecture, "x86_64") + self.assertEqual(response.available_processors, 4) + # Ensure the request method was called + mock_session_instance.request.assert_called_once() - @patch("catalystwan.session.ManagerSession") - @patch("catalystwan.response.ManagerResponse") - def setUp(self, mock_session, mock_response) -> None: - self.server_info_response = {'Achitecture': 'amd64', 'Available processors': 8} - self.session = mock_session - self.api = ServerInfo(self.session) - self.api._endpoints = MagicMock() - mock_response.json.return_value = self.server_info_response + +if __name__ == "__main__": + unittest.main()