From 3eb765197d21a2eb934bc699137092ed7ba4e311 Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Fri, 11 Apr 2025 11:49:04 +0530 Subject: [PATCH 01/10] adding monitor APIs --- linode_api4/groups/__init__.py | 1 + linode_api4/groups/monitor.py | 182 ++++++++++++++++++ linode_api4/linode_client.py | 3 + linode_api4/objects/__init__.py | 1 + linode_api4/objects/monitor.py | 106 ++++++++++ test/fixtures/monitor_dashboards.json | 37 ++++ test/fixtures/monitor_dashboards_1.json | 30 +++ test/fixtures/monitor_services.json | 11 ++ test/fixtures/monitor_services_dbaas.json | 11 ++ .../monitor_services_dbaas_dashboards.json | 37 ++++ ...tor_services_dbaas_metric-definitions.json | 55 ++++++ .../monitor_services_dbaas_token.json | 3 + .../models/monitor/test_monitor.py | 122 ++++++++++++ test/unit/objects/monitor_test.py | 101 ++++++++++ 14 files changed, 700 insertions(+) create mode 100644 linode_api4/groups/monitor.py create mode 100644 linode_api4/objects/monitor.py create mode 100644 test/fixtures/monitor_dashboards.json create mode 100644 test/fixtures/monitor_dashboards_1.json create mode 100644 test/fixtures/monitor_services.json create mode 100644 test/fixtures/monitor_services_dbaas.json create mode 100644 test/fixtures/monitor_services_dbaas_dashboards.json create mode 100644 test/fixtures/monitor_services_dbaas_metric-definitions.json create mode 100644 test/fixtures/monitor_services_dbaas_token.json create mode 100644 test/integration/models/monitor/test_monitor.py create mode 100644 test/unit/objects/monitor_test.py diff --git a/linode_api4/groups/__init__.py b/linode_api4/groups/__init__.py index e50eeab66..175a88c5b 100644 --- a/linode_api4/groups/__init__.py +++ b/linode_api4/groups/__init__.py @@ -21,3 +21,4 @@ from .tag import * from .volume import * from .vpc import * +from .monitor import * diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor.py new file mode 100644 index 000000000..8b7a556a5 --- /dev/null +++ b/linode_api4/groups/monitor.py @@ -0,0 +1,182 @@ +from linode_api4.errors import UnexpectedResponseError +from linode_api4.groups import Group +from linode_api4.objects import ( + CreateToken, + DashboardByService, + ServiceDetails, + Dashboard, + MonitorServiceSupported, + MetricDefinition, + DashboardsByID, +) + +class MonitorGroup(Group): + """ + Encapsulates LKE-related methods of the :any:`LinodeClient`. This + should not be instantiated on its own, but should instead be used through + an instance of :any:`LinodeClient`:: + + client = LinodeClient(token) + instances = client.lke.clusters() # use the LKEGroup + + This group contains all features beneath the `/lke` group in the API v4. + """ + + def dashboards(self, *filters): + """ + Returns a list of dashboards on your account. + + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards-all + + :param filters: Any number of filters to apply to this query. + See :doc:`Filtering Collections` + for more details on filtering. + + :returns: A list of Dashboards. + :rtype: PaginatedList of Dashboard + """ + return self.client._get_and_filter(Dashboard, *filters) + + def dashboard_by_ID(self, dashboard_id: int, *filters): + """ + Returns a dashboards on your account based on the ID passed. + + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards-by-id + + :param filters: Any number of filters to apply to this query. + See :doc:`Filtering Collections` + for more details on filtering. + + :returns: A Dashboards. + :rtype: PaginatedList of the Dashboard + """ + result = self.client.get(f"/monitor/dashboards/{dashboard_id}") + + if not "id" in result: + raise UnexpectedResponseError( + "Unexpected response when getting Dashboard!", json=result + ) + return DashboardsByID(self.client, result["id"], result) + + + def dashboard_by_service(self, service_type: str,*filters): + """ + Returns a dashboards on your account based on the service passed. + + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards + + :param filters: Any number of filters to apply to this query. + See :doc:`Filtering Collections` + for more details on filtering. + + :returns: A Dashboards filtered by Service Type. + :rtype: PaginatedList of the Dashboards + """ + + return self.client._get_and_filter( + DashboardByService, + *filters, + endpoint=f"/monitor/services/{service_type}/dashboards", + ) + + + def supported_services(self, *filters): + """ + Returns a list of services supported by ACLP. + + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services + + :param filters: Any number of filters to apply to this query. + See :doc:`Filtering Collections` + for more details on filtering. + + :returns: A list of Supported Services + :rtype: PaginatedList of the Dashboards + """ + + return self.client._get_and_filter(MonitorServiceSupported, *filters) + + def details_by_service(self, service_type: str,*filters): + """ + Returns a details about a particular service. + + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services-for-service-type + + :param filters: Any number of filters to apply to this query. + See :doc:`Filtering Collections` + for more details on filtering. + + :returns: Details about a Supported Services + :rtype: PaginatedList of the Service + """ + return self.client._get_and_filter( + ServiceDetails, + *filters, + endpoint=f"/monitor/services/{service_type}", + ) + + def metric_definitions(self, service_type: str,*filters): + """ + Returns metrics for a specific service type. + + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information + + :param filters: Any number of filters to apply to this query. + See :doc:`Filtering Collections` + for more details on filtering. + + :returns: Returns a List of metrics for a service + :rtype: PaginatedList of metrics + """ + return self.client._get_and_filter( + MetricDefinition, + *filters, + endpoint=f"/monitor/services/{service_type}/metric-definitions", + ) + + def create_token(self, service_type: str, entity_ids: list, *filters): + """ + Returns a JWE Token for a specific service type. + + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token + :param filters: Any number of filters to apply to this query. + See :doc:`Filtering Collections` + for more details on filtering. + + :returns: Returns a token for a service + :rtype: str + """ + + params = {"entity_ids": entity_ids} + + result = self.client.post(f"/monitor/services/{service_type}/token", data=params) + + if "token" not in result: + raise UnexpectedResponseError( + "Unexpected response when creating token!", json=result + ) + return CreateToken(self.client, result["token"], result) + + + + + + + + + + \ No newline at end of file diff --git a/linode_api4/linode_client.py b/linode_api4/linode_client.py index 19e6f3900..ff641e6da 100644 --- a/linode_api4/linode_client.py +++ b/linode_api4/linode_client.py @@ -29,6 +29,7 @@ TagGroup, VolumeGroup, VPCGroup, + MonitorGroup, ) from linode_api4.objects import Image, and_ @@ -201,6 +202,8 @@ def __init__( #: Access methods related to VM placement - See :any:`PlacementAPIGroup` for more information. self.placement = PlacementAPIGroup(self) + self.monitor = MonitorGroup(self) + @property def _user_agent(self): return "{}python-linode_api4/{} {}".format( diff --git a/linode_api4/objects/__init__.py b/linode_api4/objects/__init__.py index b13fac51a..7f1542d2a 100644 --- a/linode_api4/objects/__init__.py +++ b/linode_api4/objects/__init__.py @@ -21,3 +21,4 @@ from .vpc import * from .beta import * from .placement import * +from .monitor import * diff --git a/linode_api4/objects/monitor.py b/linode_api4/objects/monitor.py new file mode 100644 index 000000000..ad2c8124d --- /dev/null +++ b/linode_api4/objects/monitor.py @@ -0,0 +1,106 @@ +from linode_api4.objects import ( + Base, + Property, +) + +class Dashboard(Base): + """ + List dashboards: https://techdocs.akamai.com/linode-api/get-dashboards-all + """ + + api_endpoint = "/monitor/dashboards/" + properties = { + "id": Property(identifier=True), + "created": Property(is_datetime=True), + "label": Property(), + "service_type": Property(), + "type": Property(), + "widgets": Property(mutable=True), + "updated": Property(is_datetime=True), + + } + +class DashboardsByID(Base): + """ + Get a dashboard: https://techdocs.akamai.com/linode-api/reference/get-dashboards-by-id + """ + + + properties = { + "id": Property(identifier=True), + "created": Property(is_datetime=True), + "label": Property(), + "service_type": Property(), + "type": Property(), + "widgets": Property(mutable=True), + "updated": Property(is_datetime=True), + + } + +class DashboardByService(Base): + """ + Get a dashboard: https://techdocs.akamai.com/linode-api/reference/get-dashboards + """ + + properties = { + "id": Property(identifier=True), + "created": Property(is_datetime=True), + "label": Property(), + "service_type": Property(), + "type": Property(), + "widgets": Property(mutable=True), + "updated": Property(is_datetime=True), + + } + + +class MonitorServiceSupported(Base): + + api_endpoint = "/monitor/services/" + id_attribute = "service_type" + properties = { + "service_type": Property(), + "label": Property(mutable=True), + + } + +class ServiceDetails(Base): + """ + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services-for-service-type + """ + id_attribute = "service_type" + properties = { + "label": Property(), + "service_type": Property(), + } + + + +class MetricDefinition(Base): + """ + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information + """ + + id_attribute = "metric" + properties = { + "available_aggregate_functions": Property(), + "dimensions": Property(mutable=True), + "label": Property(), + "is_alertable": Property(), + "metric": Property(), + "metric_type": Property(), + "scrape_interval": Property(), + "unit": Property(), + } + +class CreateToken(Base): + """ + API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token + """ + + properties = { + "token": Property(mutable=True) + } + + + diff --git a/test/fixtures/monitor_dashboards.json b/test/fixtures/monitor_dashboards.json new file mode 100644 index 000000000..42de92b55 --- /dev/null +++ b/test/fixtures/monitor_dashboards.json @@ -0,0 +1,37 @@ +{ + "data": [ + { + "created": "2024-10-10T05:01:58", + "id": 1, + "label": "Resource Usage", + "service_type": "dbaas", + "type": "standard", + "updated": "2024-10-10T05:01:58", + "widgets": [ + { + "aggregate_function": "sum", + "chart_type": "area", + "color": "default", + "label": "CPU Usage", + "metric": "cpu_usage", + "size": 12, + "unit": "%", + "y_label": "cpu_usage" + }, + { + "aggregate_function": "sum", + "chart_type": "area", + "color": "default", + "label": "Disk I/O Write", + "metric": "write_iops", + "size": 6, + "unit": "IOPS", + "y_label": "write_iops" + } + ] + } + ], + "page": 1, + "pages": 1, + "results": 1 + } \ No newline at end of file diff --git a/test/fixtures/monitor_dashboards_1.json b/test/fixtures/monitor_dashboards_1.json new file mode 100644 index 000000000..b78bf3447 --- /dev/null +++ b/test/fixtures/monitor_dashboards_1.json @@ -0,0 +1,30 @@ +{ + "created": "2024-10-10T05:01:58", + "id": 1, + "label": "Resource Usage", + "service_type": "dbaas", + "type": "standard", + "updated": "2024-10-10T05:01:58", + "widgets": [ + { + "aggregate_function": "sum", + "chart_type": "area", + "color": "default", + "label": "CPU Usage", + "metric": "cpu_usage", + "size": 12, + "unit": "%", + "y_label": "cpu_usage" + }, + { + "aggregate_function": "sum", + "chart_type": "area", + "color": "default", + "label": "Available Memory", + "metric": "available_memory", + "size": 6, + "unit": "GB", + "y_label": "available_memory" + } + ] + } \ No newline at end of file diff --git a/test/fixtures/monitor_services.json b/test/fixtures/monitor_services.json new file mode 100644 index 000000000..7a568866c --- /dev/null +++ b/test/fixtures/monitor_services.json @@ -0,0 +1,11 @@ +{ + "data": [ + { + "label": "Databases", + "service_type": "dbaas" + } + ], + "page": 1, + "pages": 1, + "results": 1 + } \ No newline at end of file diff --git a/test/fixtures/monitor_services_dbaas.json b/test/fixtures/monitor_services_dbaas.json new file mode 100644 index 000000000..7a568866c --- /dev/null +++ b/test/fixtures/monitor_services_dbaas.json @@ -0,0 +1,11 @@ +{ + "data": [ + { + "label": "Databases", + "service_type": "dbaas" + } + ], + "page": 1, + "pages": 1, + "results": 1 + } \ No newline at end of file diff --git a/test/fixtures/monitor_services_dbaas_dashboards.json b/test/fixtures/monitor_services_dbaas_dashboards.json new file mode 100644 index 000000000..5fbb7e9db --- /dev/null +++ b/test/fixtures/monitor_services_dbaas_dashboards.json @@ -0,0 +1,37 @@ +{ + "data": [ + { + "created": "2024-10-10T05:01:58", + "id": 1, + "label": "Resource Usage", + "service_type": "dbaas", + "type": "standard", + "updated": "2024-10-10T05:01:58", + "widgets": [ + { + "aggregate_function": "sum", + "chart_type": "area", + "color": "default", + "label": "CPU Usage", + "metric": "cpu_usage", + "size": 12, + "unit": "%", + "y_label": "cpu_usage" + }, + { + "aggregate_function": "sum", + "chart_type": "area", + "color": "default", + "label": "Memory Usage", + "metric": "memory_usage", + "size": 6, + "unit": "%", + "y_label": "memory_usage" + } + ] + } + ], + "page": 1, + "pages": 1, + "results": 1 + } \ No newline at end of file diff --git a/test/fixtures/monitor_services_dbaas_metric-definitions.json b/test/fixtures/monitor_services_dbaas_metric-definitions.json new file mode 100644 index 000000000..c493b23a3 --- /dev/null +++ b/test/fixtures/monitor_services_dbaas_metric-definitions.json @@ -0,0 +1,55 @@ +{ + "data": [ + { + "available_aggregate_functions": [ + "max", + "avg", + "min", + "sum" + ], + "dimensions": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "values": [ + "primary", + "secondary" + ] + } + ], + "is_alertable": true, + "label": "CPU Usage", + "metric": "cpu_usage", + "metric_type": "gauge", + "scrape_interval": "60s", + "unit": "percent" + }, + { + "available_aggregate_functions": [ + "max", + "avg", + "min", + "sum" + ], + "dimensions": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "values": [ + "primary", + "secondary" + ] + } + ], + "is_alertable": true, + "label": "Disk I/O Read", + "metric": "read_iops", + "metric_type": "gauge", + "scrape_interval": "60s", + "unit": "iops" + } + ], + "page": 1, + "pages": 1, + "results": 2 + } \ No newline at end of file diff --git a/test/fixtures/monitor_services_dbaas_token.json b/test/fixtures/monitor_services_dbaas_token.json new file mode 100644 index 000000000..b1aa0d786 --- /dev/null +++ b/test/fixtures/monitor_services_dbaas_token.json @@ -0,0 +1,3 @@ +{ + "token": "abcdefhjigkfghh" +} \ No newline at end of file diff --git a/test/integration/models/monitor/test_monitor.py b/test/integration/models/monitor/test_monitor.py new file mode 100644 index 000000000..fecd68fa4 --- /dev/null +++ b/test/integration/models/monitor/test_monitor.py @@ -0,0 +1,122 @@ +import json + +from linode_api4.objects import ( + MonitorServiceSupported, + Dashboard, + DashboardsByID, + DashboardByService, + ServiceDetails, + MetricDefinition, + CreateToken, +) +from linode_api4 import LinodeClient,MySQLDatabase +import re +import time +from test.integration.helpers import ( + get_test_label, + send_request_when_resource_available, + wait_for_condition, +) + +import pytest + + + +# List all dashboards +def test_get_all_dashboards(test_linode_client): + client = test_linode_client + dashboards = client.monitor.dashboards() + assert isinstance(dashboards[0],Dashboard) + + dashboard_get = dashboards[0] + dashboard_id = dashboard_get.id + get_service_type = dashboard_get.service_type + print(f"printing svc {get_service_type}") + + #Fetch Dashboard by ID + dashboard_by_id = client.monitor.dashboard_by_ID(dashboard_id=dashboard_id) + assert isinstance(dashboard_by_id, DashboardsByID) + assert dashboard_by_id.id == dashboard_id + + #Fetch Dashboard by service_type + dashboards_by_svc = client.monitor.dashboard_by_service(service_type=get_service_type) + assert isinstance(dashboards_by_svc[0], DashboardByService) + assert dashboards_by_svc[0].service_type == get_service_type + +# List supported services +def test_get_supported_services(test_linode_client): + client = test_linode_client + supported_services = client.monitor.supported_services() + assert isinstance(supported_services[0], MonitorServiceSupported) + + get_supported_service = supported_services[0].service_type + + #Get details for a particular service + service_details = client.monitor.details_by_service(service_type=get_supported_service) + assert isinstance(service_details[0],ServiceDetails) + assert service_details[0].service_type == get_supported_service + + #Get Metric definition details for that particular service + metric_definitions = client.monitor.metric_definitions(service_type=get_supported_service) + assert isinstance(metric_definitions[0],MetricDefinition) + +# Test Helpers +def get_db_engine_id(client: LinodeClient, engine: str): + engines = client.database.engines() + engine_id = "" + for e in engines: + if e.engine == engine: + engine_id = e.id + + return str(engine_id) + +@pytest.fixture(scope="session") +def test_create_and_test_db(test_linode_client): + client = test_linode_client + label = get_test_label() + "-sqldb" + region = "us-ord" + engine_id = get_db_engine_id(client, "mysql") + dbtype = "g6-standard-1" + + + db = client.database.mysql_create( + label=label, + region=region, + engine=engine_id, + ltype=dbtype, + cluster_size=None, + ) + + def get_db_status(): + return db.status == "active" + + # TAKES 15-30 MINUTES TO FULLY PROVISION DB + wait_for_condition(60, 2000, get_db_status) + + yield db + send_request_when_resource_available(300, db.delete) + +def test_my_db_functionality(test_linode_client, test_create_and_test_db): + client = test_linode_client + assert test_create_and_test_db.status == "active" + + entity_id = test_create_and_test_db.id + + + # create token for the particular service + token = client.monitor.get_token(service_type="dbaas", entity_ids=[entity_id]) + assert isinstance(token, CreateToken) + assert len(token.token) > 0, "Token should not be empty" + assert hasattr(token, "token"), "Response object has no 'token' attribute" + + + + + + + + + + + + diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_test.py new file mode 100644 index 000000000..1157c93b0 --- /dev/null +++ b/test/unit/objects/monitor_test.py @@ -0,0 +1,101 @@ +from test.unit.base import ClientBaseCase +import datetime + +from linode_api4.objects import CreateToken + +class MonitorSupportedServicesTest(ClientBaseCase): + """ + Tests the methods of MonitorServiceSupported class + """ + + def test_supported_services(self): + """ + Test the services supported by monitor + """ + service = self.client.monitor.supported_services() + self.assertEqual(len(service),1) + self.assertEqual(service[0].label, "Databases") + self.assertEqual(service[0].service_type, "dbaas") + + def test_dashboard_by_ID(self): + """ + Test the dashboard by ID API + """ + dashboard = self.client.monitor.dashboard_by_ID(dashboard_id=1) + self.assertEqual(dashboard.type, "standard") + self.assertEqual(dashboard.created, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual(dashboard.id, 1) + self.assertEqual(dashboard.label, "Resource Usage") + self.assertEqual(dashboard.service_type, "dbaas") + self.assertEqual(dashboard.updated, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual(dashboard.widgets[0].aggregate_function, "sum") + self.assertEqual(dashboard.widgets[0].chart_type, "area") + self.assertEqual(dashboard.widgets[0].color, "default") + self.assertEqual(dashboard.widgets[0].label, "CPU Usage") + self.assertEqual(dashboard.widgets[0].metric, "cpu_usage") + self.assertEqual(dashboard.widgets[0].size, 12) + self.assertEqual(dashboard.widgets[0].unit, "%") + self.assertEqual(dashboard.widgets[0].y_label, "cpu_usage") + + + def test_dashboard_by_service_type(self): + dashboards = self.client.monitor.dashboard_by_service(service_type="dbaas") + self.assertEqual(dashboards[0].type, "standard") + self.assertEqual(dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual(dashboards[0].id, 1) + self.assertEqual(dashboards[0].label, "Resource Usage") + self.assertEqual(dashboards[0].service_type, "dbaas") + self.assertEqual(dashboards[0].updated, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual(dashboards[0].widgets[0].aggregate_function, "sum") + self.assertEqual(dashboards[0].widgets[0].chart_type, "area") + self.assertEqual(dashboards[0].widgets[0].color, "default") + self.assertEqual(dashboards[0].widgets[0].label, "CPU Usage") + self.assertEqual(dashboards[0].widgets[0].metric, "cpu_usage") + self.assertEqual(dashboards[0].widgets[0].size, 12) + self.assertEqual(dashboards[0].widgets[0].unit, "%") + self.assertEqual(dashboards[0].widgets[0].y_label, "cpu_usage") + + def test_get_all_dashboards(self): + dashboards = self.client.monitor.dashboards() + self.assertEqual(dashboards[0].type, "standard") + self.assertEqual(dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual(dashboards[0].id, 1) + self.assertEqual(dashboards[0].label, "Resource Usage") + self.assertEqual(dashboards[0].service_type, "dbaas") + self.assertEqual(dashboards[0].updated, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual(dashboards[0].widgets[0].aggregate_function, "sum") + self.assertEqual(dashboards[0].widgets[0].chart_type, "area") + self.assertEqual(dashboards[0].widgets[0].color, "default") + self.assertEqual(dashboards[0].widgets[0].label, "CPU Usage") + self.assertEqual(dashboards[0].widgets[0].metric, "cpu_usage") + self.assertEqual(dashboards[0].widgets[0].size, 12) + self.assertEqual(dashboards[0].widgets[0].unit, "%") + self.assertEqual(dashboards[0].widgets[0].y_label, "cpu_usage") + + def test_specific_service_details(self): + data = self.client.monitor.details_by_service(service_type="dbaas") + self.assertEqual(data[0].label, "Databases") + self.assertEqual(data[0].service_type, "dbaas") + + def test_metric_definitions(self): + + metrics = self.client.monitor.metric_definitions(service_type="dbaas") + self.assertEqual(metrics[0].available_aggregate_functions, ["max", "avg", "min", "sum"]) + self.assertEqual(metrics[0].is_alertable, True) + self.assertEqual(metrics[0].label, "CPU Usage") + self.assertEqual(metrics[0].metric, "cpu_usage") + self.assertEqual(metrics[0].metric_type, "gauge") + self.assertEqual(metrics[0].scrape_interval, "60s") + self.assertEqual(metrics[0].unit, "percent") + self.assertEqual(metrics[0].dimensions[0].dimension_label, "node_type") + self.assertEqual(metrics[0].dimensions[0].label, "Node Type") + self.assertEqual(metrics[0].dimensions[0].values,["primary", "secondary"]) + + def test_get_token(self): + + with self.mock_post("/monitor/services/dbaas/token") as m: + self.client.monitor.get_token(service_type="dbaas", entity_ids=[189690,188020]) + self.assertEqual(m.return_dct["token"], "abcdefhjigkfghh") + + + From e18ccc9d2a6072beef2874cef2af41ee6776b21c Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Tue, 15 Apr 2025 12:02:47 +0530 Subject: [PATCH 02/10] updating doc --- linode_api4/groups/monitor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor.py index 8b7a556a5..5565fac20 100644 --- a/linode_api4/groups/monitor.py +++ b/linode_api4/groups/monitor.py @@ -12,14 +12,14 @@ class MonitorGroup(Group): """ - Encapsulates LKE-related methods of the :any:`LinodeClient`. This + Encapsulates Monitor-related methods of the :any:`LinodeClient`. This should not be instantiated on its own, but should instead be used through an instance of :any:`LinodeClient`:: client = LinodeClient(token) - instances = client.lke.clusters() # use the LKEGroup + instances = client.monitor.dashboards() # use the LKEGroup - This group contains all features beneath the `/lke` group in the API v4. + This group contains all features beneath the `/monitor` group in the API v4. """ def dashboards(self, *filters): From b181c813d9e0bac0dcd1b8eb03aa1bd19ccb09af Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Thu, 17 Apr 2025 20:36:53 +0530 Subject: [PATCH 03/10] updating tests --- test/integration/models/monitor/test_monitor.py | 2 +- test/unit/objects/monitor_test.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/models/monitor/test_monitor.py b/test/integration/models/monitor/test_monitor.py index fecd68fa4..ce1f94df0 100644 --- a/test/integration/models/monitor/test_monitor.py +++ b/test/integration/models/monitor/test_monitor.py @@ -104,7 +104,7 @@ def test_my_db_functionality(test_linode_client, test_create_and_test_db): # create token for the particular service - token = client.monitor.get_token(service_type="dbaas", entity_ids=[entity_id]) + token = client.monitor.create_token(service_type="dbaas", entity_ids=[entity_id]) assert isinstance(token, CreateToken) assert len(token.token) > 0, "Token should not be empty" assert hasattr(token, "token"), "Response object has no 'token' attribute" diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_test.py index 1157c93b0..54775794c 100644 --- a/test/unit/objects/monitor_test.py +++ b/test/unit/objects/monitor_test.py @@ -91,10 +91,10 @@ def test_metric_definitions(self): self.assertEqual(metrics[0].dimensions[0].label, "Node Type") self.assertEqual(metrics[0].dimensions[0].values,["primary", "secondary"]) - def test_get_token(self): + def create_token(self): with self.mock_post("/monitor/services/dbaas/token") as m: - self.client.monitor.get_token(service_type="dbaas", entity_ids=[189690,188020]) + self.client.monitor.create_token(service_type="dbaas", entity_ids=[189690,188020]) self.assertEqual(m.return_dct["token"], "abcdefhjigkfghh") From d51d300150c50ebc8c129f228ec11a6bfbdddebd Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Mon, 21 Apr 2025 17:19:52 +0530 Subject: [PATCH 04/10] updating lint errors --- linode_api4/groups/monitor.py | 3 +++ linode_api4/objects/monitor.py | 1 + test/integration/models/monitor/test_monitor.py | 7 ++----- test/unit/objects/monitor_test.py | 2 -- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor.py index 5565fac20..8f7b4d0f5 100644 --- a/linode_api4/groups/monitor.py +++ b/linode_api4/groups/monitor.py @@ -10,6 +10,9 @@ DashboardsByID, ) +__all__ = [ + "MonitorGroup", +] class MonitorGroup(Group): """ Encapsulates Monitor-related methods of the :any:`LinodeClient`. This diff --git a/linode_api4/objects/monitor.py b/linode_api4/objects/monitor.py index ad2c8124d..f053e4d54 100644 --- a/linode_api4/objects/monitor.py +++ b/linode_api4/objects/monitor.py @@ -3,6 +3,7 @@ Property, ) +__all__ = ['Dashboard', 'DashboardsByID', 'DashboardByService', 'MonitorServiceSupported', 'ServiceDetails', 'MetricDefinition', 'CreateToken'] class Dashboard(Base): """ List dashboards: https://techdocs.akamai.com/linode-api/get-dashboards-all diff --git a/test/integration/models/monitor/test_monitor.py b/test/integration/models/monitor/test_monitor.py index ce1f94df0..217211e72 100644 --- a/test/integration/models/monitor/test_monitor.py +++ b/test/integration/models/monitor/test_monitor.py @@ -1,5 +1,3 @@ -import json - from linode_api4.objects import ( MonitorServiceSupported, Dashboard, @@ -9,9 +7,8 @@ MetricDefinition, CreateToken, ) -from linode_api4 import LinodeClient,MySQLDatabase -import re -import time +from linode_api4 import LinodeClient + from test.integration.helpers import ( get_test_label, send_request_when_resource_available, diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_test.py index 54775794c..4c27830b5 100644 --- a/test/unit/objects/monitor_test.py +++ b/test/unit/objects/monitor_test.py @@ -1,8 +1,6 @@ from test.unit.base import ClientBaseCase import datetime -from linode_api4.objects import CreateToken - class MonitorSupportedServicesTest(ClientBaseCase): """ Tests the methods of MonitorServiceSupported class From 9084a05120e58d5588fef52e2ce3330d3f60106c Mon Sep 17 00:00:00 2001 From: pmajali Date: Wed, 23 Apr 2025 19:44:53 +0530 Subject: [PATCH 05/10] Updating method name Co-authored-by: Lena Garber <114949949+lgarber-akamai@users.noreply.github.com> --- linode_api4/groups/monitor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor.py index 8f7b4d0f5..d429f40c3 100644 --- a/linode_api4/groups/monitor.py +++ b/linode_api4/groups/monitor.py @@ -66,7 +66,7 @@ def dashboard_by_ID(self, dashboard_id: int, *filters): return DashboardsByID(self.client, result["id"], result) - def dashboard_by_service(self, service_type: str,*filters): + def dashboards_by_service(self, service_type: str, *filters): """ Returns a dashboards on your account based on the service passed. From 69de94021369498c338fac4c900beede1ae376be Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Mon, 28 Apr 2025 22:40:26 +0530 Subject: [PATCH 06/10] updating code with review comments --- linode_api4/groups/monitor.py | 27 +------------------ linode_api4/objects/monitor.py | 18 +------------ .../models/monitor/test_monitor.py | 13 ++++----- test/unit/objects/monitor_test.py | 11 +++++--- 4 files changed, 14 insertions(+), 55 deletions(-) diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor.py index d429f40c3..4f6107e5b 100644 --- a/linode_api4/groups/monitor.py +++ b/linode_api4/groups/monitor.py @@ -7,12 +7,9 @@ Dashboard, MonitorServiceSupported, MetricDefinition, - DashboardsByID, ) -__all__ = [ - "MonitorGroup", -] + class MonitorGroup(Group): """ Encapsulates Monitor-related methods of the :any:`LinodeClient`. This @@ -42,28 +39,6 @@ def dashboards(self, *filters): """ return self.client._get_and_filter(Dashboard, *filters) - def dashboard_by_ID(self, dashboard_id: int, *filters): - """ - Returns a dashboards on your account based on the ID passed. - - .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - - API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards-by-id - - :param filters: Any number of filters to apply to this query. - See :doc:`Filtering Collections` - for more details on filtering. - - :returns: A Dashboards. - :rtype: PaginatedList of the Dashboard - """ - result = self.client.get(f"/monitor/dashboards/{dashboard_id}") - - if not "id" in result: - raise UnexpectedResponseError( - "Unexpected response when getting Dashboard!", json=result - ) - return DashboardsByID(self.client, result["id"], result) def dashboards_by_service(self, service_type: str, *filters): diff --git a/linode_api4/objects/monitor.py b/linode_api4/objects/monitor.py index f053e4d54..93669959c 100644 --- a/linode_api4/objects/monitor.py +++ b/linode_api4/objects/monitor.py @@ -3,13 +3,12 @@ Property, ) -__all__ = ['Dashboard', 'DashboardsByID', 'DashboardByService', 'MonitorServiceSupported', 'ServiceDetails', 'MetricDefinition', 'CreateToken'] class Dashboard(Base): """ List dashboards: https://techdocs.akamai.com/linode-api/get-dashboards-all """ - api_endpoint = "/monitor/dashboards/" + api_endpoint = "/monitor/dashboards/{id}" properties = { "id": Property(identifier=True), "created": Property(is_datetime=True), @@ -21,23 +20,8 @@ class Dashboard(Base): } -class DashboardsByID(Base): - """ - Get a dashboard: https://techdocs.akamai.com/linode-api/reference/get-dashboards-by-id - """ - properties = { - "id": Property(identifier=True), - "created": Property(is_datetime=True), - "label": Property(), - "service_type": Property(), - "type": Property(), - "widgets": Property(mutable=True), - "updated": Property(is_datetime=True), - - } - class DashboardByService(Base): """ Get a dashboard: https://techdocs.akamai.com/linode-api/reference/get-dashboards diff --git a/test/integration/models/monitor/test_monitor.py b/test/integration/models/monitor/test_monitor.py index 217211e72..2899b3b21 100644 --- a/test/integration/models/monitor/test_monitor.py +++ b/test/integration/models/monitor/test_monitor.py @@ -1,7 +1,6 @@ from linode_api4.objects import ( MonitorServiceSupported, Dashboard, - DashboardsByID, DashboardByService, ServiceDetails, MetricDefinition, @@ -26,17 +25,15 @@ def test_get_all_dashboards(test_linode_client): assert isinstance(dashboards[0],Dashboard) dashboard_get = dashboards[0] - dashboard_id = dashboard_get.id get_service_type = dashboard_get.service_type - print(f"printing svc {get_service_type}") #Fetch Dashboard by ID - dashboard_by_id = client.monitor.dashboard_by_ID(dashboard_id=dashboard_id) - assert isinstance(dashboard_by_id, DashboardsByID) - assert dashboard_by_id.id == dashboard_id + dashboard_by_id = client.load(Dashboard, 1) + assert isinstance(dashboard_by_id, Dashboard) + assert dashboard_by_id.id == 1 - #Fetch Dashboard by service_type - dashboards_by_svc = client.monitor.dashboard_by_service(service_type=get_service_type) + # #Fetch Dashboard by service_type + dashboards_by_svc = client.monitor.dashboards_by_service(service_type=get_service_type) assert isinstance(dashboards_by_svc[0], DashboardByService) assert dashboards_by_svc[0].service_type == get_service_type diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_test.py index 4c27830b5..c19c7ba71 100644 --- a/test/unit/objects/monitor_test.py +++ b/test/unit/objects/monitor_test.py @@ -1,7 +1,10 @@ from test.unit.base import ClientBaseCase +from linode_api4.objects import ( + Dashboard, + ) import datetime -class MonitorSupportedServicesTest(ClientBaseCase): +class MonitorTest(ClientBaseCase): """ Tests the methods of MonitorServiceSupported class """ @@ -19,7 +22,7 @@ def test_dashboard_by_ID(self): """ Test the dashboard by ID API """ - dashboard = self.client.monitor.dashboard_by_ID(dashboard_id=1) + dashboard = self.client.load(Dashboard, 1) self.assertEqual(dashboard.type, "standard") self.assertEqual(dashboard.created, datetime.datetime(2024, 10, 10, 5, 1, 58)) self.assertEqual(dashboard.id, 1) @@ -37,7 +40,7 @@ def test_dashboard_by_ID(self): def test_dashboard_by_service_type(self): - dashboards = self.client.monitor.dashboard_by_service(service_type="dbaas") + dashboards = self.client.monitor.dashboards_by_service(service_type="dbaas") self.assertEqual(dashboards[0].type, "standard") self.assertEqual(dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58)) self.assertEqual(dashboards[0].id, 1) @@ -89,7 +92,7 @@ def test_metric_definitions(self): self.assertEqual(metrics[0].dimensions[0].label, "Node Type") self.assertEqual(metrics[0].dimensions[0].values,["primary", "secondary"]) - def create_token(self): + def test_create_token(self): with self.mock_post("/monitor/services/dbaas/token") as m: self.client.monitor.create_token(service_type="dbaas", entity_ids=[189690,188020]) From 7b8348b38b4251fee1a6bdf249dc5e595cb27634 Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Mon, 5 May 2025 09:53:42 +0530 Subject: [PATCH 07/10] sorting imports --- linode_api4/groups/__init__.py | 2 +- linode_api4/groups/monitor.py | 6 +++--- linode_api4/linode_client.py | 2 +- linode_api4/objects/monitor.py | 6 ++---- .../models/monitor/test_monitor.py | 19 +++++++++---------- test/unit/objects/monitor_test.py | 8 ++++---- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/linode_api4/groups/__init__.py b/linode_api4/groups/__init__.py index 175a88c5b..3842042ad 100644 --- a/linode_api4/groups/__init__.py +++ b/linode_api4/groups/__init__.py @@ -10,6 +10,7 @@ from .lke import * from .lke_tier import * from .longview import * +from .monitor import * from .networking import * from .nodebalancer import * from .object_storage import * @@ -21,4 +22,3 @@ from .tag import * from .volume import * from .vpc import * -from .monitor import * diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor.py index 4f6107e5b..14deab161 100644 --- a/linode_api4/groups/monitor.py +++ b/linode_api4/groups/monitor.py @@ -2,11 +2,11 @@ from linode_api4.groups import Group from linode_api4.objects import ( CreateToken, - DashboardByService, - ServiceDetails, Dashboard, - MonitorServiceSupported, + DashboardByService, MetricDefinition, + MonitorServiceSupported, + ServiceDetails, ) diff --git a/linode_api4/linode_client.py b/linode_api4/linode_client.py index ff641e6da..e71f1563e 100644 --- a/linode_api4/linode_client.py +++ b/linode_api4/linode_client.py @@ -19,6 +19,7 @@ LinodeGroup, LKEGroup, LongviewGroup, + MonitorGroup, NetworkingGroup, NodeBalancerGroup, ObjectStorageGroup, @@ -29,7 +30,6 @@ TagGroup, VolumeGroup, VPCGroup, - MonitorGroup, ) from linode_api4.objects import Image, and_ diff --git a/linode_api4/objects/monitor.py b/linode_api4/objects/monitor.py index 93669959c..730310a5f 100644 --- a/linode_api4/objects/monitor.py +++ b/linode_api4/objects/monitor.py @@ -1,7 +1,5 @@ -from linode_api4.objects import ( - Base, - Property, -) +from linode_api4.objects import Base, Property + class Dashboard(Base): """ diff --git a/test/integration/models/monitor/test_monitor.py b/test/integration/models/monitor/test_monitor.py index 2899b3b21..abf4f0f88 100644 --- a/test/integration/models/monitor/test_monitor.py +++ b/test/integration/models/monitor/test_monitor.py @@ -1,13 +1,3 @@ -from linode_api4.objects import ( - MonitorServiceSupported, - Dashboard, - DashboardByService, - ServiceDetails, - MetricDefinition, - CreateToken, -) -from linode_api4 import LinodeClient - from test.integration.helpers import ( get_test_label, send_request_when_resource_available, @@ -16,6 +6,15 @@ import pytest +from linode_api4 import LinodeClient +from linode_api4.objects import ( + CreateToken, + Dashboard, + DashboardByService, + MetricDefinition, + MonitorServiceSupported, + ServiceDetails, +) # List all dashboards diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_test.py index c19c7ba71..3594e61d1 100644 --- a/test/unit/objects/monitor_test.py +++ b/test/unit/objects/monitor_test.py @@ -1,8 +1,8 @@ -from test.unit.base import ClientBaseCase -from linode_api4.objects import ( - Dashboard, - ) import datetime +from test.unit.base import ClientBaseCase + +from linode_api4.objects import Dashboard + class MonitorTest(ClientBaseCase): """ From fe4a6bd0617920acd8823bd0f3f29dfb6eb6a1b1 Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Tue, 6 May 2025 00:27:35 +0530 Subject: [PATCH 08/10] updating with make format changes --- linode_api4/groups/monitor.py | 55 ++++++++----------- linode_api4/objects/monitor.py | 27 ++++----- .../models/monitor/test_monitor.py | 50 ++++++++--------- test/unit/objects/monitor_test.py | 55 ++++++++++++------- 4 files changed, 92 insertions(+), 95 deletions(-) diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor.py index 14deab161..5d0a43c4c 100644 --- a/linode_api4/groups/monitor.py +++ b/linode_api4/groups/monitor.py @@ -24,10 +24,10 @@ class MonitorGroup(Group): def dashboards(self, *filters): """ - Returns a list of dashboards on your account. + Returns a list of dashboards on your account. .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards-all :param filters: Any number of filters to apply to this query. @@ -39,14 +39,12 @@ def dashboards(self, *filters): """ return self.client._get_and_filter(Dashboard, *filters) - - def dashboards_by_service(self, service_type: str, *filters): """ - Returns a dashboards on your account based on the service passed. + Returns a dashboards on your account based on the service passed. .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards :param filters: Any number of filters to apply to this query. @@ -56,20 +54,19 @@ def dashboards_by_service(self, service_type: str, *filters): :returns: A Dashboards filtered by Service Type. :rtype: PaginatedList of the Dashboards """ - + return self.client._get_and_filter( DashboardByService, *filters, endpoint=f"/monitor/services/{service_type}/dashboards", ) - def supported_services(self, *filters): """ - Returns a list of services supported by ACLP. + Returns a list of services supported by ACLP. .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services :param filters: Any number of filters to apply to this query. @@ -82,12 +79,12 @@ def supported_services(self, *filters): return self.client._get_and_filter(MonitorServiceSupported, *filters) - def details_by_service(self, service_type: str,*filters): + def details_by_service(self, service_type: str, *filters): """ - Returns a details about a particular service. + Returns a details about a particular service. .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services-for-service-type :param filters: Any number of filters to apply to this query. @@ -95,20 +92,20 @@ def details_by_service(self, service_type: str,*filters): for more details on filtering. :returns: Details about a Supported Services - :rtype: PaginatedList of the Service + :rtype: PaginatedList of the Service """ return self.client._get_and_filter( ServiceDetails, *filters, endpoint=f"/monitor/services/{service_type}", ) - - def metric_definitions(self, service_type: str,*filters): + + def metric_definitions(self, service_type: str, *filters): """ - Returns metrics for a specific service type. + Returns metrics for a specific service type. .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information :param filters: Any number of filters to apply to this query. @@ -116,20 +113,20 @@ def metric_definitions(self, service_type: str,*filters): for more details on filtering. :returns: Returns a List of metrics for a service - :rtype: PaginatedList of metrics + :rtype: PaginatedList of metrics """ return self.client._get_and_filter( MetricDefinition, *filters, endpoint=f"/monitor/services/{service_type}/metric-definitions", ) - + def create_token(self, service_type: str, entity_ids: list, *filters): """ - Returns a JWE Token for a specific service type. + Returns a JWE Token for a specific service type. .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token :param filters: Any number of filters to apply to this query. See :doc:`Filtering Collections` @@ -141,20 +138,12 @@ def create_token(self, service_type: str, entity_ids: list, *filters): params = {"entity_ids": entity_ids} - result = self.client.post(f"/monitor/services/{service_type}/token", data=params) + result = self.client.post( + f"/monitor/services/{service_type}/token", data=params + ) if "token" not in result: raise UnexpectedResponseError( "Unexpected response when creating token!", json=result ) return CreateToken(self.client, result["token"], result) - - - - - - - - - - \ No newline at end of file diff --git a/linode_api4/objects/monitor.py b/linode_api4/objects/monitor.py index 730310a5f..b67a4b4cb 100644 --- a/linode_api4/objects/monitor.py +++ b/linode_api4/objects/monitor.py @@ -15,11 +15,9 @@ class Dashboard(Base): "type": Property(), "widgets": Property(mutable=True), "updated": Property(is_datetime=True), - } - class DashboardByService(Base): """ Get a dashboard: https://techdocs.akamai.com/linode-api/reference/get-dashboards @@ -33,7 +31,6 @@ class DashboardByService(Base): "type": Property(), "widgets": Property(mutable=True), "updated": Property(is_datetime=True), - } @@ -43,22 +40,22 @@ class MonitorServiceSupported(Base): id_attribute = "service_type" properties = { "service_type": Property(), - "label": Property(mutable=True), - + "label": Property(mutable=True), } + class ServiceDetails(Base): """ API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services-for-service-type """ + id_attribute = "service_type" properties = { - "label": Property(), - "service_type": Property(), + "label": Property(), + "service_type": Property(), } - class MetricDefinition(Base): """ API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information @@ -66,9 +63,9 @@ class MetricDefinition(Base): id_attribute = "metric" properties = { - "available_aggregate_functions": Property(), - "dimensions": Property(mutable=True), - "label": Property(), + "available_aggregate_functions": Property(), + "dimensions": Property(mutable=True), + "label": Property(), "is_alertable": Property(), "metric": Property(), "metric_type": Property(), @@ -76,14 +73,10 @@ class MetricDefinition(Base): "unit": Property(), } + class CreateToken(Base): """ API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token """ - properties = { - "token": Property(mutable=True) - } - - - + properties = {"token": Property(mutable=True)} diff --git a/test/integration/models/monitor/test_monitor.py b/test/integration/models/monitor/test_monitor.py index abf4f0f88..948356639 100644 --- a/test/integration/models/monitor/test_monitor.py +++ b/test/integration/models/monitor/test_monitor.py @@ -21,22 +21,25 @@ def test_get_all_dashboards(test_linode_client): client = test_linode_client dashboards = client.monitor.dashboards() - assert isinstance(dashboards[0],Dashboard) + assert isinstance(dashboards[0], Dashboard) dashboard_get = dashboards[0] get_service_type = dashboard_get.service_type - #Fetch Dashboard by ID + # Fetch Dashboard by ID dashboard_by_id = client.load(Dashboard, 1) assert isinstance(dashboard_by_id, Dashboard) assert dashboard_by_id.id == 1 # #Fetch Dashboard by service_type - dashboards_by_svc = client.monitor.dashboards_by_service(service_type=get_service_type) + dashboards_by_svc = client.monitor.dashboards_by_service( + service_type=get_service_type + ) assert isinstance(dashboards_by_svc[0], DashboardByService) assert dashboards_by_svc[0].service_type == get_service_type -# List supported services + +# List supported services def test_get_supported_services(test_linode_client): client = test_linode_client supported_services = client.monitor.supported_services() @@ -44,14 +47,19 @@ def test_get_supported_services(test_linode_client): get_supported_service = supported_services[0].service_type - #Get details for a particular service - service_details = client.monitor.details_by_service(service_type=get_supported_service) - assert isinstance(service_details[0],ServiceDetails) + # Get details for a particular service + service_details = client.monitor.details_by_service( + service_type=get_supported_service + ) + assert isinstance(service_details[0], ServiceDetails) assert service_details[0].service_type == get_supported_service - #Get Metric definition details for that particular service - metric_definitions = client.monitor.metric_definitions(service_type=get_supported_service) - assert isinstance(metric_definitions[0],MetricDefinition) + # Get Metric definition details for that particular service + metric_definitions = client.monitor.metric_definitions( + service_type=get_supported_service + ) + assert isinstance(metric_definitions[0], MetricDefinition) + # Test Helpers def get_db_engine_id(client: LinodeClient, engine: str): @@ -63,6 +71,7 @@ def get_db_engine_id(client: LinodeClient, engine: str): return str(engine_id) + @pytest.fixture(scope="session") def test_create_and_test_db(test_linode_client): client = test_linode_client @@ -71,7 +80,6 @@ def test_create_and_test_db(test_linode_client): engine_id = get_db_engine_id(client, "mysql") dbtype = "g6-standard-1" - db = client.database.mysql_create( label=label, region=region, @@ -89,27 +97,17 @@ def get_db_status(): yield db send_request_when_resource_available(300, db.delete) + def test_my_db_functionality(test_linode_client, test_create_and_test_db): client = test_linode_client assert test_create_and_test_db.status == "active" - - entity_id = test_create_and_test_db.id + entity_id = test_create_and_test_db.id # create token for the particular service - token = client.monitor.create_token(service_type="dbaas", entity_ids=[entity_id]) + token = client.monitor.create_token( + service_type="dbaas", entity_ids=[entity_id] + ) assert isinstance(token, CreateToken) assert len(token.token) > 0, "Token should not be empty" assert hasattr(token, "token"), "Response object has no 'token' attribute" - - - - - - - - - - - - diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_test.py index 3594e61d1..cb3b5eb27 100644 --- a/test/unit/objects/monitor_test.py +++ b/test/unit/objects/monitor_test.py @@ -14,21 +14,25 @@ def test_supported_services(self): Test the services supported by monitor """ service = self.client.monitor.supported_services() - self.assertEqual(len(service),1) + self.assertEqual(len(service), 1) self.assertEqual(service[0].label, "Databases") self.assertEqual(service[0].service_type, "dbaas") - + def test_dashboard_by_ID(self): """ Test the dashboard by ID API """ dashboard = self.client.load(Dashboard, 1) self.assertEqual(dashboard.type, "standard") - self.assertEqual(dashboard.created, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual( + dashboard.created, datetime.datetime(2024, 10, 10, 5, 1, 58) + ) self.assertEqual(dashboard.id, 1) self.assertEqual(dashboard.label, "Resource Usage") self.assertEqual(dashboard.service_type, "dbaas") - self.assertEqual(dashboard.updated, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual( + dashboard.updated, datetime.datetime(2024, 10, 10, 5, 1, 58) + ) self.assertEqual(dashboard.widgets[0].aggregate_function, "sum") self.assertEqual(dashboard.widgets[0].chart_type, "area") self.assertEqual(dashboard.widgets[0].color, "default") @@ -37,16 +41,21 @@ def test_dashboard_by_ID(self): self.assertEqual(dashboard.widgets[0].size, 12) self.assertEqual(dashboard.widgets[0].unit, "%") self.assertEqual(dashboard.widgets[0].y_label, "cpu_usage") - def test_dashboard_by_service_type(self): - dashboards = self.client.monitor.dashboards_by_service(service_type="dbaas") + dashboards = self.client.monitor.dashboards_by_service( + service_type="dbaas" + ) self.assertEqual(dashboards[0].type, "standard") - self.assertEqual(dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual( + dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58) + ) self.assertEqual(dashboards[0].id, 1) self.assertEqual(dashboards[0].label, "Resource Usage") self.assertEqual(dashboards[0].service_type, "dbaas") - self.assertEqual(dashboards[0].updated, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual( + dashboards[0].updated, datetime.datetime(2024, 10, 10, 5, 1, 58) + ) self.assertEqual(dashboards[0].widgets[0].aggregate_function, "sum") self.assertEqual(dashboards[0].widgets[0].chart_type, "area") self.assertEqual(dashboards[0].widgets[0].color, "default") @@ -55,15 +64,19 @@ def test_dashboard_by_service_type(self): self.assertEqual(dashboards[0].widgets[0].size, 12) self.assertEqual(dashboards[0].widgets[0].unit, "%") self.assertEqual(dashboards[0].widgets[0].y_label, "cpu_usage") - + def test_get_all_dashboards(self): dashboards = self.client.monitor.dashboards() self.assertEqual(dashboards[0].type, "standard") - self.assertEqual(dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual( + dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58) + ) self.assertEqual(dashboards[0].id, 1) self.assertEqual(dashboards[0].label, "Resource Usage") self.assertEqual(dashboards[0].service_type, "dbaas") - self.assertEqual(dashboards[0].updated, datetime.datetime(2024, 10, 10, 5, 1, 58)) + self.assertEqual( + dashboards[0].updated, datetime.datetime(2024, 10, 10, 5, 1, 58) + ) self.assertEqual(dashboards[0].widgets[0].aggregate_function, "sum") self.assertEqual(dashboards[0].widgets[0].chart_type, "area") self.assertEqual(dashboards[0].widgets[0].color, "default") @@ -72,16 +85,19 @@ def test_get_all_dashboards(self): self.assertEqual(dashboards[0].widgets[0].size, 12) self.assertEqual(dashboards[0].widgets[0].unit, "%") self.assertEqual(dashboards[0].widgets[0].y_label, "cpu_usage") - + def test_specific_service_details(self): data = self.client.monitor.details_by_service(service_type="dbaas") self.assertEqual(data[0].label, "Databases") self.assertEqual(data[0].service_type, "dbaas") - + def test_metric_definitions(self): metrics = self.client.monitor.metric_definitions(service_type="dbaas") - self.assertEqual(metrics[0].available_aggregate_functions, ["max", "avg", "min", "sum"]) + self.assertEqual( + metrics[0].available_aggregate_functions, + ["max", "avg", "min", "sum"], + ) self.assertEqual(metrics[0].is_alertable, True) self.assertEqual(metrics[0].label, "CPU Usage") self.assertEqual(metrics[0].metric, "cpu_usage") @@ -90,13 +106,14 @@ def test_metric_definitions(self): self.assertEqual(metrics[0].unit, "percent") self.assertEqual(metrics[0].dimensions[0].dimension_label, "node_type") self.assertEqual(metrics[0].dimensions[0].label, "Node Type") - self.assertEqual(metrics[0].dimensions[0].values,["primary", "secondary"]) + self.assertEqual( + metrics[0].dimensions[0].values, ["primary", "secondary"] + ) def test_create_token(self): with self.mock_post("/monitor/services/dbaas/token") as m: - self.client.monitor.create_token(service_type="dbaas", entity_ids=[189690,188020]) + self.client.monitor.create_token( + service_type="dbaas", entity_ids=[189690, 188020] + ) self.assertEqual(m.return_dct["token"], "abcdefhjigkfghh") - - - From 33e954fe0e03572b1b8f1d9910a8d740aedeacd5 Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Tue, 13 May 2025 01:18:03 +0530 Subject: [PATCH 09/10] updating with review comments --- linode_api4/groups/__init__.py | 2 +- .../groups/{monitor.py => monitor_service.py} | 93 +++++----- linode_api4/linode_client.py | 2 +- linode_api4/objects/__init__.py | 2 +- linode_api4/objects/monitor.py | 82 --------- linode_api4/objects/monitor_service.py | 160 ++++++++++++++++++ .../models/monitor/test_monitor.py | 38 ++--- ...onitor_test.py => monitor_service_test.py} | 18 +- 8 files changed, 245 insertions(+), 152 deletions(-) rename linode_api4/groups/{monitor.py => monitor_service.py} (61%) delete mode 100644 linode_api4/objects/monitor.py create mode 100644 linode_api4/objects/monitor_service.py rename test/unit/objects/{monitor_test.py => monitor_service_test.py} (89%) diff --git a/linode_api4/groups/__init__.py b/linode_api4/groups/__init__.py index 3842042ad..29a8f0c87 100644 --- a/linode_api4/groups/__init__.py +++ b/linode_api4/groups/__init__.py @@ -10,7 +10,7 @@ from .lke import * from .lke_tier import * from .longview import * -from .monitor import * +from .monitor_service import * from .networking import * from .nodebalancer import * from .object_storage import * diff --git a/linode_api4/groups/monitor.py b/linode_api4/groups/monitor_service.py similarity index 61% rename from linode_api4/groups/monitor.py rename to linode_api4/groups/monitor_service.py index 5d0a43c4c..0cf127d39 100644 --- a/linode_api4/groups/monitor.py +++ b/linode_api4/groups/monitor_service.py @@ -1,30 +1,26 @@ from linode_api4.errors import UnexpectedResponseError from linode_api4.groups import Group from linode_api4.objects import ( - CreateToken, - Dashboard, - DashboardByService, - MetricDefinition, - MonitorServiceSupported, - ServiceDetails, + MonitorDashboard, + MonitorMetricsDefinition, + MonitorService, + MonitorServiceToken, ) class MonitorGroup(Group): """ - Encapsulates Monitor-related methods of the :any:`LinodeClient`. This - should not be instantiated on its own, but should instead be used through - an instance of :any:`LinodeClient`:: - - client = LinodeClient(token) - instances = client.monitor.dashboards() # use the LKEGroup + Encapsulates Monitor-related methods of the :any:`LinodeClient`. This group contains all features beneath the `/monitor` group in the API v4. """ - def dashboards(self, *filters): + def list_monitor_dashboards(self, *filters) -> list[MonitorDashboard]: """ - Returns a list of dashboards on your account. + Returns a list of dashboards. + + dashboards = client.monitor_service.list_monitor_dashboards() + dashboard = client.load(Dashboard, 1) .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. @@ -37,34 +33,41 @@ def dashboards(self, *filters): :returns: A list of Dashboards. :rtype: PaginatedList of Dashboard """ - return self.client._get_and_filter(Dashboard, *filters) - def dashboards_by_service(self, service_type: str, *filters): - """ - Returns a dashboards on your account based on the service passed. + return self.client._get_and_filter(MonitorDashboard, *filters) + def list_dashboards_by_service(self, service_type: str, *filters) -> list[MonitorDashboard]: + """ + Returns a list of dashboards for a particular service. + + dashboard_by_service = client.monitor_service.list_dashboards_by_service(service_type="dbaas") + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards + :param service_type: The service type to get dashboards for. + :type service_type: str :param filters: Any number of filters to apply to this query. See :doc:`Filtering Collections` for more details on filtering. - :returns: A Dashboards filtered by Service Type. + :returns: Dashboards filtered by Service Type. :rtype: PaginatedList of the Dashboards """ return self.client._get_and_filter( - DashboardByService, + MonitorDashboard, *filters, endpoint=f"/monitor/services/{service_type}/dashboards", ) - def supported_services(self, *filters): + def list_supported_services(self, *filters) -> list[MonitorService]: """ Returns a list of services supported by ACLP. + supported_services = client.monitor_service.list_supported_services() + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services @@ -74,63 +77,74 @@ def supported_services(self, *filters): for more details on filtering. :returns: A list of Supported Services - :rtype: PaginatedList of the Dashboards + :rtype: PaginatedList of Services """ - return self.client._get_and_filter(MonitorServiceSupported, *filters) + return self.client._get_and_filter(MonitorService, *filters) - def details_by_service(self, service_type: str, *filters): + def list_service_by_type(self, service_type: str, *filters) -> list[MonitorService]: """ - Returns a details about a particular service. + Lists monitor services by a given service_type + service_details = client.monitor_service.list_service_by_type(service_type="dbaas") + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services-for-service-type - + + :param service_type: The service type to get details for. + :type service_type: str :param filters: Any number of filters to apply to this query. See :doc:`Filtering Collections` for more details on filtering. - - :returns: Details about a Supported Services - :rtype: PaginatedList of the Service + + :returns: Lists monitor services by a given service_type + :rtype: PaginatedList of the Services """ return self.client._get_and_filter( - ServiceDetails, + MonitorService, *filters, endpoint=f"/monitor/services/{service_type}", ) - def metric_definitions(self, service_type: str, *filters): + + def list_metric_definitions(self, service_type: str, *filters) -> list[MonitorMetricsDefinition]: """ Returns metrics for a specific service type. + metrics = client.monitor_service.list_metric_definitions(service_type="dbaas") .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information + :param service_type: The service type to get metrics for. + :type service_type: str :param filters: Any number of filters to apply to this query. See :doc:`Filtering Collections` for more details on filtering. - :returns: Returns a List of metrics for a service + :returns: Returns a List of metrics for a service :rtype: PaginatedList of metrics """ return self.client._get_and_filter( - MetricDefinition, + MonitorMetricsDefinition, *filters, endpoint=f"/monitor/services/{service_type}/metric-definitions", ) - def create_token(self, service_type: str, entity_ids: list, *filters): + def create_token(self, service_type: str, entity_ids: list) -> MonitorServiceToken: """ Returns a JWE Token for a specific service type. + token = client.monitor_service.create_token(service_type="dbaas", entity_ids=[1234]) .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token - :param filters: Any number of filters to apply to this query. - See :doc:`Filtering Collections` - for more details on filtering. + + :param service_type: The service type to create token for. + :type service_type: str + :param entity_ids: The list of entity IDs for which the token is valid. + :type entity_ids: list of int :returns: Returns a token for a service :rtype: str @@ -146,4 +160,5 @@ def create_token(self, service_type: str, entity_ids: list, *filters): raise UnexpectedResponseError( "Unexpected response when creating token!", json=result ) - return CreateToken(self.client, result["token"], result) + return MonitorServiceToken(token=result["token"]) + diff --git a/linode_api4/linode_client.py b/linode_api4/linode_client.py index e71f1563e..b0431eb51 100644 --- a/linode_api4/linode_client.py +++ b/linode_api4/linode_client.py @@ -202,7 +202,7 @@ def __init__( #: Access methods related to VM placement - See :any:`PlacementAPIGroup` for more information. self.placement = PlacementAPIGroup(self) - self.monitor = MonitorGroup(self) + self.monitor_service = MonitorGroup(self) @property def _user_agent(self): diff --git a/linode_api4/objects/__init__.py b/linode_api4/objects/__init__.py index 7f1542d2a..3d684b59c 100644 --- a/linode_api4/objects/__init__.py +++ b/linode_api4/objects/__init__.py @@ -21,4 +21,4 @@ from .vpc import * from .beta import * from .placement import * -from .monitor import * +from .monitor_service import * diff --git a/linode_api4/objects/monitor.py b/linode_api4/objects/monitor.py deleted file mode 100644 index b67a4b4cb..000000000 --- a/linode_api4/objects/monitor.py +++ /dev/null @@ -1,82 +0,0 @@ -from linode_api4.objects import Base, Property - - -class Dashboard(Base): - """ - List dashboards: https://techdocs.akamai.com/linode-api/get-dashboards-all - """ - - api_endpoint = "/monitor/dashboards/{id}" - properties = { - "id": Property(identifier=True), - "created": Property(is_datetime=True), - "label": Property(), - "service_type": Property(), - "type": Property(), - "widgets": Property(mutable=True), - "updated": Property(is_datetime=True), - } - - -class DashboardByService(Base): - """ - Get a dashboard: https://techdocs.akamai.com/linode-api/reference/get-dashboards - """ - - properties = { - "id": Property(identifier=True), - "created": Property(is_datetime=True), - "label": Property(), - "service_type": Property(), - "type": Property(), - "widgets": Property(mutable=True), - "updated": Property(is_datetime=True), - } - - -class MonitorServiceSupported(Base): - - api_endpoint = "/monitor/services/" - id_attribute = "service_type" - properties = { - "service_type": Property(), - "label": Property(mutable=True), - } - - -class ServiceDetails(Base): - """ - API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services-for-service-type - """ - - id_attribute = "service_type" - properties = { - "label": Property(), - "service_type": Property(), - } - - -class MetricDefinition(Base): - """ - API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information - """ - - id_attribute = "metric" - properties = { - "available_aggregate_functions": Property(), - "dimensions": Property(mutable=True), - "label": Property(), - "is_alertable": Property(), - "metric": Property(), - "metric_type": Property(), - "scrape_interval": Property(), - "unit": Property(), - } - - -class CreateToken(Base): - """ - API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token - """ - - properties = {"token": Property(mutable=True)} diff --git a/linode_api4/objects/monitor_service.py b/linode_api4/objects/monitor_service.py new file mode 100644 index 000000000..e87da765c --- /dev/null +++ b/linode_api4/objects/monitor_service.py @@ -0,0 +1,160 @@ +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional, Union + +from linode_api4.objects import Base, JSONObject, Property, StrEnum + + +class AggregateFunction(StrEnum): + """ + Enum for supported aggregate functions. + """ + min = "min" + max = "max" + avg = "avg" + sum = "sum" + count = "count" + rate = "rate" + increase = "increase" + last = "last" + +class ChartType(StrEnum): + """ + Enum for supported chart types. + """ + line = "line" + area = "area" + +class ServiceType(StrEnum): + """ + Enum for supported service types. + """ + dbaas = "dbaas" + linode = "linode" + lke = "lke" + vpc = "vpc" + nodebalancer = "nodebalancer" + firewall = "firewall" + object_storage = "object_storage" + aclb = "aclb" + +class MetricType(StrEnum): + """ + Enum for supported metric type + """ + gauge = "gauge" + counter = "counter" + histogram = "histogram" + summary = "summary" + +class MetricUnit(StrEnum): + """ + Enum for supported metric units. + """ + COUNT = "count" + PERCENT = "percent" + BYTE = "byte" + SECOND = "second" + BITS_PER_SECOND = "bits_per_second" + MILLISECOND = "millisecond" + KB = "KB" + MB = "MB" + GB = "GB" + RATE = "rate" + BYTES_PER_SECOND = "bytes_per_second" + PERCENTILE = "percentile" + RATIO = "ratio" + OPS_PER_SECOND = "ops_per_second" + IOPS = "iops" + +class DashboardType(StrEnum): + """ + Enum for supported dashboard types. + """ + standard = "standard" + custom = "custom" + +@dataclass +class DashboardWidget(JSONObject): + """ + Represents a single widget in the widgets list. + """ + metric: str = "" + unit: MetricUnit = "" + label: str = "" + color: str = "" + size: int = 0 + chart_type: ChartType = "" + y_label: str = "" + aggregate_function: AggregateFunction = "" + +@dataclass +class Dimension(JSONObject): + """ + Represents a single dimension in the dimensions list. + """ + dimension_label: Optional[str] = None + label: Optional[str] = None + values: Optional[List[str]] = None + +@dataclass +class MonitorMetricsDefinition(JSONObject): + """ + Represents a single metric definition in the metrics definition list. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information + """ + + metric: str = "" + label: str = "" + metric_type: MetricType = "" + unit: MetricUnit = "" + scrape_interval: int = 0 + is_alertable: bool = False + dimensions: Optional[List[Dimension]] = None + available_aggregate_functions: List[AggregateFunction] = field(default_factory=list) + + +class MonitorDashboard(Base): + """ + Dashboard details. + + List dashboards: https://techdocs.akamai.com/linode-api/get-dashboards-all + """ + + api_endpoint = "/monitor/dashboards/{id}" + properties = { + "id": Property(identifier=True), + "created": Property(is_datetime=True), + "label": Property(), + "service_type": Property(ServiceType), + "type": Property(DashboardType), + "widgets": Property(List[DashboardWidget]), + "updated": Property(is_datetime=True), + } + +class MonitorService(Base): + """ + Represents a single service type. + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services + + """ + + api_endpoint = "/monitor/services/{service_type}" + id_attribute = "service_type" + properties = { + "service_type": Property(ServiceType, identifier=True), + "label": Property(), + } + +@dataclass +class MonitorServiceToken(JSONObject): + """ + A token for the requested service_type. + + API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token + """ + + token: str = "" + + + diff --git a/test/integration/models/monitor/test_monitor.py b/test/integration/models/monitor/test_monitor.py index 948356639..46b521147 100644 --- a/test/integration/models/monitor/test_monitor.py +++ b/test/integration/models/monitor/test_monitor.py @@ -8,57 +8,55 @@ from linode_api4 import LinodeClient from linode_api4.objects import ( - CreateToken, - Dashboard, - DashboardByService, - MetricDefinition, - MonitorServiceSupported, - ServiceDetails, + MonitorDashboard, + MonitorMetricsDefinition, + MonitorService, + MonitorServiceToken, ) # List all dashboards def test_get_all_dashboards(test_linode_client): client = test_linode_client - dashboards = client.monitor.dashboards() - assert isinstance(dashboards[0], Dashboard) + dashboards = client.monitor_service.list_monitor_dashboards() + assert isinstance(dashboards[0], MonitorDashboard) dashboard_get = dashboards[0] get_service_type = dashboard_get.service_type # Fetch Dashboard by ID - dashboard_by_id = client.load(Dashboard, 1) - assert isinstance(dashboard_by_id, Dashboard) + dashboard_by_id = client.load(MonitorDashboard, 1) + assert isinstance(dashboard_by_id, MonitorDashboard) assert dashboard_by_id.id == 1 # #Fetch Dashboard by service_type - dashboards_by_svc = client.monitor.dashboards_by_service( + dashboards_by_svc = client.monitor_service.list_dashboards_by_service( service_type=get_service_type ) - assert isinstance(dashboards_by_svc[0], DashboardByService) + assert isinstance(dashboards_by_svc[0], MonitorDashboard) assert dashboards_by_svc[0].service_type == get_service_type # List supported services def test_get_supported_services(test_linode_client): client = test_linode_client - supported_services = client.monitor.supported_services() - assert isinstance(supported_services[0], MonitorServiceSupported) + supported_services = client.monitor_service.list_supported_services() + assert isinstance(supported_services[0], MonitorService) get_supported_service = supported_services[0].service_type # Get details for a particular service - service_details = client.monitor.details_by_service( + service_details = client.monitor_service.list_service_by_type( service_type=get_supported_service ) - assert isinstance(service_details[0], ServiceDetails) + assert isinstance(service_details[0], MonitorService) assert service_details[0].service_type == get_supported_service # Get Metric definition details for that particular service - metric_definitions = client.monitor.metric_definitions( + metric_definitions = client.monitor_service.list_metric_definitions( service_type=get_supported_service ) - assert isinstance(metric_definitions[0], MetricDefinition) + assert isinstance(metric_definitions[0], MonitorMetricsDefinition) # Test Helpers @@ -105,9 +103,9 @@ def test_my_db_functionality(test_linode_client, test_create_and_test_db): entity_id = test_create_and_test_db.id # create token for the particular service - token = client.monitor.create_token( + token = client.monitor_service.create_token( service_type="dbaas", entity_ids=[entity_id] ) - assert isinstance(token, CreateToken) + assert isinstance(token, MonitorServiceToken) assert len(token.token) > 0, "Token should not be empty" assert hasattr(token, "token"), "Response object has no 'token' attribute" diff --git a/test/unit/objects/monitor_test.py b/test/unit/objects/monitor_service_test.py similarity index 89% rename from test/unit/objects/monitor_test.py rename to test/unit/objects/monitor_service_test.py index cb3b5eb27..023fe1146 100644 --- a/test/unit/objects/monitor_test.py +++ b/test/unit/objects/monitor_service_test.py @@ -1,7 +1,7 @@ import datetime from test.unit.base import ClientBaseCase -from linode_api4.objects import Dashboard +from linode_api4.objects import MonitorDashboard class MonitorTest(ClientBaseCase): @@ -13,7 +13,7 @@ def test_supported_services(self): """ Test the services supported by monitor """ - service = self.client.monitor.supported_services() + service = self.client.monitor_service.list_supported_services() self.assertEqual(len(service), 1) self.assertEqual(service[0].label, "Databases") self.assertEqual(service[0].service_type, "dbaas") @@ -22,7 +22,7 @@ def test_dashboard_by_ID(self): """ Test the dashboard by ID API """ - dashboard = self.client.load(Dashboard, 1) + dashboard = self.client.load(MonitorDashboard, 1) self.assertEqual(dashboard.type, "standard") self.assertEqual( dashboard.created, datetime.datetime(2024, 10, 10, 5, 1, 58) @@ -43,7 +43,7 @@ def test_dashboard_by_ID(self): self.assertEqual(dashboard.widgets[0].y_label, "cpu_usage") def test_dashboard_by_service_type(self): - dashboards = self.client.monitor.dashboards_by_service( + dashboards = self.client.monitor_service.list_dashboards_by_service( service_type="dbaas" ) self.assertEqual(dashboards[0].type, "standard") @@ -66,7 +66,7 @@ def test_dashboard_by_service_type(self): self.assertEqual(dashboards[0].widgets[0].y_label, "cpu_usage") def test_get_all_dashboards(self): - dashboards = self.client.monitor.dashboards() + dashboards = self.client.monitor_service.list_monitor_dashboards() self.assertEqual(dashboards[0].type, "standard") self.assertEqual( dashboards[0].created, datetime.datetime(2024, 10, 10, 5, 1, 58) @@ -87,13 +87,13 @@ def test_get_all_dashboards(self): self.assertEqual(dashboards[0].widgets[0].y_label, "cpu_usage") def test_specific_service_details(self): - data = self.client.monitor.details_by_service(service_type="dbaas") + data = self.client.monitor_service.list_service_by_type(service_type="dbaas") self.assertEqual(data[0].label, "Databases") self.assertEqual(data[0].service_type, "dbaas") def test_metric_definitions(self): - metrics = self.client.monitor.metric_definitions(service_type="dbaas") + metrics = self.client.monitor_service.list_metric_definitions(service_type="dbaas") self.assertEqual( metrics[0].available_aggregate_functions, ["max", "avg", "min", "sum"], @@ -113,7 +113,9 @@ def test_metric_definitions(self): def test_create_token(self): with self.mock_post("/monitor/services/dbaas/token") as m: - self.client.monitor.create_token( + self.client.monitor_service.create_token( service_type="dbaas", entity_ids=[189690, 188020] ) self.assertEqual(m.return_dct["token"], "abcdefhjigkfghh") + + From b386c118e6b198d3b18e5c45da1790f05692b698 Mon Sep 17 00:00:00 2001 From: Priya Majali Date: Tue, 13 May 2025 10:39:26 +0530 Subject: [PATCH 10/10] review updates --- linode_api4/groups/monitor_service.py | 36 ++++++++++++--------- linode_api4/objects/monitor_service.py | 39 ++++++++++++++++------- test/unit/objects/monitor_service_test.py | 10 +++--- 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/linode_api4/groups/monitor_service.py b/linode_api4/groups/monitor_service.py index 0cf127d39..28355efa2 100644 --- a/linode_api4/groups/monitor_service.py +++ b/linode_api4/groups/monitor_service.py @@ -10,7 +10,7 @@ class MonitorGroup(Group): """ - Encapsulates Monitor-related methods of the :any:`LinodeClient`. + Encapsulates Monitor-related methods of the :any:`LinodeClient`. This group contains all features beneath the `/monitor` group in the API v4. """ @@ -36,12 +36,14 @@ def list_monitor_dashboards(self, *filters) -> list[MonitorDashboard]: return self.client._get_and_filter(MonitorDashboard, *filters) - def list_dashboards_by_service(self, service_type: str, *filters) -> list[MonitorDashboard]: + def list_dashboards_by_service( + self, service_type: str, *filters + ) -> list[MonitorDashboard]: """ Returns a list of dashboards for a particular service. - + dashboard_by_service = client.monitor_service.list_dashboards_by_service(service_type="dbaas") - + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. API Documentation: https://techdocs.akamai.com/linode-api/reference/get-dashboards @@ -67,7 +69,7 @@ def list_supported_services(self, *filters) -> list[MonitorService]: Returns a list of services supported by ACLP. supported_services = client.monitor_service.list_supported_services() - + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services @@ -82,22 +84,24 @@ def list_supported_services(self, *filters) -> list[MonitorService]: return self.client._get_and_filter(MonitorService, *filters) - def list_service_by_type(self, service_type: str, *filters) -> list[MonitorService]: + def list_service_by_type( + self, service_type: str, *filters + ) -> list[MonitorService]: """ Lists monitor services by a given service_type service_details = client.monitor_service.list_service_by_type(service_type="dbaas") - + .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services-for-service-type - + :param service_type: The service type to get details for. :type service_type: str :param filters: Any number of filters to apply to this query. See :doc:`Filtering Collections` for more details on filtering. - + :returns: Lists monitor services by a given service_type :rtype: PaginatedList of the Services """ @@ -107,8 +111,9 @@ def list_service_by_type(self, service_type: str, *filters) -> list[MonitorServi endpoint=f"/monitor/services/{service_type}", ) - - def list_metric_definitions(self, service_type: str, *filters) -> list[MonitorMetricsDefinition]: + def list_metric_definitions( + self, service_type: str, *filters + ) -> list[MonitorMetricsDefinition]: """ Returns metrics for a specific service type. @@ -132,7 +137,9 @@ def list_metric_definitions(self, service_type: str, *filters) -> list[MonitorMe endpoint=f"/monitor/services/{service_type}/metric-definitions", ) - def create_token(self, service_type: str, entity_ids: list) -> MonitorServiceToken: + def create_token( + self, service_type: str, entity_ids: list + ) -> MonitorServiceToken: """ Returns a JWE Token for a specific service type. token = client.monitor_service.create_token(service_type="dbaas", entity_ids=[1234]) @@ -140,7 +147,7 @@ def create_token(self, service_type: str, entity_ids: list) -> MonitorServiceTok .. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`. API Documentation: https://techdocs.akamai.com/linode-api/reference/post-get-token - + :param service_type: The service type to create token for. :type service_type: str :param entity_ids: The list of entity IDs for which the token is valid. @@ -161,4 +168,3 @@ def create_token(self, service_type: str, entity_ids: list) -> MonitorServiceTok "Unexpected response when creating token!", json=result ) return MonitorServiceToken(token=result["token"]) - diff --git a/linode_api4/objects/monitor_service.py b/linode_api4/objects/monitor_service.py index e87da765c..14599022b 100644 --- a/linode_api4/objects/monitor_service.py +++ b/linode_api4/objects/monitor_service.py @@ -1,5 +1,5 @@ from dataclasses import dataclass, field -from typing import Any, Dict, List, Optional, Union +from typing import List, Optional from linode_api4.objects import Base, JSONObject, Property, StrEnum @@ -8,6 +8,7 @@ class AggregateFunction(StrEnum): """ Enum for supported aggregate functions. """ + min = "min" max = "max" avg = "avg" @@ -17,17 +18,21 @@ class AggregateFunction(StrEnum): increase = "increase" last = "last" + class ChartType(StrEnum): """ Enum for supported chart types. """ + line = "line" area = "area" + class ServiceType(StrEnum): """ Enum for supported service types. """ + dbaas = "dbaas" linode = "linode" lke = "lke" @@ -37,19 +42,23 @@ class ServiceType(StrEnum): object_storage = "object_storage" aclb = "aclb" + class MetricType(StrEnum): """ Enum for supported metric type """ + gauge = "gauge" counter = "counter" histogram = "histogram" summary = "summary" + class MetricUnit(StrEnum): """ Enum for supported metric units. """ + COUNT = "count" PERCENT = "percent" BYTE = "byte" @@ -66,18 +75,22 @@ class MetricUnit(StrEnum): OPS_PER_SECOND = "ops_per_second" IOPS = "iops" + class DashboardType(StrEnum): """ Enum for supported dashboard types. """ + standard = "standard" custom = "custom" + @dataclass class DashboardWidget(JSONObject): """ Represents a single widget in the widgets list. """ + metric: str = "" unit: MetricUnit = "" label: str = "" @@ -86,21 +99,24 @@ class DashboardWidget(JSONObject): chart_type: ChartType = "" y_label: str = "" aggregate_function: AggregateFunction = "" - + + @dataclass class Dimension(JSONObject): """ Represents a single dimension in the dimensions list. """ + dimension_label: Optional[str] = None label: Optional[str] = None values: Optional[List[str]] = None - + + @dataclass class MonitorMetricsDefinition(JSONObject): """ Represents a single metric definition in the metrics definition list. - + API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-information """ @@ -111,8 +127,10 @@ class MonitorMetricsDefinition(JSONObject): scrape_interval: int = 0 is_alertable: bool = False dimensions: Optional[List[Dimension]] = None - available_aggregate_functions: List[AggregateFunction] = field(default_factory=list) - + available_aggregate_functions: List[AggregateFunction] = field( + default_factory=list + ) + class MonitorDashboard(Base): """ @@ -132,11 +150,12 @@ class MonitorDashboard(Base): "updated": Property(is_datetime=True), } + class MonitorService(Base): """ Represents a single service type. API Documentation: https://techdocs.akamai.com/linode-api/reference/get-monitor-services - + """ api_endpoint = "/monitor/services/{service_type}" @@ -146,7 +165,8 @@ class MonitorService(Base): "label": Property(), } -@dataclass + +@dataclass class MonitorServiceToken(JSONObject): """ A token for the requested service_type. @@ -155,6 +175,3 @@ class MonitorServiceToken(JSONObject): """ token: str = "" - - - diff --git a/test/unit/objects/monitor_service_test.py b/test/unit/objects/monitor_service_test.py index 023fe1146..3e43d99e7 100644 --- a/test/unit/objects/monitor_service_test.py +++ b/test/unit/objects/monitor_service_test.py @@ -87,13 +87,17 @@ def test_get_all_dashboards(self): self.assertEqual(dashboards[0].widgets[0].y_label, "cpu_usage") def test_specific_service_details(self): - data = self.client.monitor_service.list_service_by_type(service_type="dbaas") + data = self.client.monitor_service.list_service_by_type( + service_type="dbaas" + ) self.assertEqual(data[0].label, "Databases") self.assertEqual(data[0].service_type, "dbaas") def test_metric_definitions(self): - metrics = self.client.monitor_service.list_metric_definitions(service_type="dbaas") + metrics = self.client.monitor_service.list_metric_definitions( + service_type="dbaas" + ) self.assertEqual( metrics[0].available_aggregate_functions, ["max", "avg", "min", "sum"], @@ -117,5 +121,3 @@ def test_create_token(self): service_type="dbaas", entity_ids=[189690, 188020] ) self.assertEqual(m.return_dct["token"], "abcdefhjigkfghh") - -