Skip to content

Commit 3527e51

Browse files
committed
feat: add aclp clone API and group_by field
1 parent 046476c commit 3527e51

8 files changed

Lines changed: 381 additions & 29 deletions

linode_api4/groups/monitor.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ def create_alert_definition(
235235
description: Optional[str] = None,
236236
scope: Optional[Union[AlertScope, str]] = None,
237237
regions: Optional[list[str]] = None,
238+
group_by: Optional[list[str]] = None,
238239
) -> AlertDefinition:
239240
"""
240241
Create a new alert definition for a given service type.
@@ -270,6 +271,8 @@ def create_alert_definition(
270271
:type scope: Optional[Union[AlertScope, str]]
271272
:param regions: (Optional) Regions to monitor.
272273
:type regions: Optional[list[str]]
274+
:param group_by: (Optional) Aggregates metric data by dimension so that alert conditions are evaluated independently for each dimension value.
275+
:type group_by: Optional[list[str]]
273276
274277
:returns: The newly created :class:`AlertDefinition`.
275278
:rtype: AlertDefinition
@@ -294,6 +297,8 @@ def create_alert_definition(
294297
params["scope"] = scope
295298
if regions is not None:
296299
params["regions"] = regions
300+
if group_by is not None:
301+
params["group_by"] = group_by
297302

298303
# API will validate service_type and return an error if missing
299304
result = self.client.post(
@@ -308,6 +313,96 @@ def create_alert_definition(
308313

309314
return AlertDefinition(self.client, result["id"], service_type, result)
310315

316+
def clone_alert_definition(
317+
self,
318+
service_type: str,
319+
id: int,
320+
label: str,
321+
description: Optional[str] = None,
322+
scope: Optional[Union[AlertScope, str]] = None,
323+
regions: Optional[list[str]] = None,
324+
entity_ids: Optional[list[str]] = None,
325+
severity: Optional[int] = None,
326+
rule_criteria: Optional[dict] = None,
327+
trigger_conditions: Optional[dict] = None,
328+
channel_ids: Optional[list[int]] = None,
329+
group_by: Optional[list[str]] = None,
330+
) -> AlertDefinition:
331+
"""
332+
Clone an existing alert definition for a given service type.
333+
The clone request creates a new alert definition based on the source
334+
definition identified by ``id``.
335+
336+
API URL: POST /monitor/services/{service_type}/alert-definitions/{id}/clone
337+
API Documentation: TODO
338+
339+
:param service_type: Service type for the source alert definition
340+
(e.g. ``"dbaas"``).
341+
:type service_type: str
342+
:param id: Source alert definition identifier.
343+
:type id: int (Alert identifier)
344+
:param label: Human-readable label for the cloned alert definition.
345+
This value is mandatory and must be unique.
346+
:type label: str
347+
:param description: (Optional) Longer description for the cloned alert definition.
348+
:type description: Optional[str]
349+
:param scope: (Optional) Alert scope provided in the clone request.
350+
Scope is inherited from the source alert and is immutable.
351+
:type scope: Optional[Union[AlertScope, str]]
352+
:param regions: (Optional) Regions to monitor.
353+
:type regions: Optional[list[str]]
354+
:param entity_ids: (Optional) Restrict the alert to a subset of entity IDs.
355+
:type entity_ids: Optional[list[str]]
356+
:param severity: (Optional) Severity level for the alert.
357+
:type severity: Optional[int]
358+
:param rule_criteria: (Optional) Rule criteria used to evaluate the alert.
359+
:type rule_criteria: Optional[dict]
360+
:param trigger_conditions: (Optional) Trigger conditions for alert state transitions.
361+
:type trigger_conditions: Optional[dict]
362+
:param channel_ids: (Optional) List of alert channel IDs to notify.
363+
:type channel_ids: Optional[list[int]]
364+
:param group_by: (Optional) Aggregates metric data by dimension so that alert conditions are evaluated independently for each dimension value.
365+
:type group_by: Optional[list[str]]
366+
367+
:returns: The newly created cloned :class:`AlertDefinition`.
368+
:rtype: AlertDefinition
369+
"""
370+
params = {
371+
"label": label,
372+
}
373+
374+
if description is not None:
375+
params["description"] = description
376+
if scope is not None:
377+
params["scope"] = scope
378+
if regions is not None:
379+
params["regions"] = regions
380+
if entity_ids is not None:
381+
params["entity_ids"] = entity_ids
382+
if severity is not None:
383+
params["severity"] = severity
384+
if rule_criteria is not None:
385+
params["rule_criteria"] = rule_criteria
386+
if trigger_conditions is not None:
387+
params["trigger_conditions"] = trigger_conditions
388+
if channel_ids is not None:
389+
params["channel_ids"] = channel_ids
390+
if group_by is not None:
391+
params["group_by"] = group_by
392+
393+
result = self.client.post(
394+
f"/monitor/services/{service_type}/alert-definitions/{id}/clone",
395+
data=params,
396+
)
397+
398+
if "id" not in result:
399+
raise UnexpectedResponseError(
400+
"Unexpected response when cloning alert definition!",
401+
json=result,
402+
)
403+
404+
return AlertDefinition(self.client, result["id"], service_type, result)
405+
311406
def alert_definition_entities(
312407
self,
313408
service_type: str,

linode_api4/objects/monitor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ class AlertDefinition(DerivedBase):
498498
"regions": Property(mutable=True),
499499
"entities": Property(json_object=AlertEntities),
500500
"channel_ids": Property(mutable=True),
501+
"group_by": Property(mutable=True),
501502
}
502503

503504

test/fixtures/monitor_alert-definitions.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
"description": "A test alert for dbaas service",
1010
"scope": "entity",
1111
"regions": [],
12+
"group_by": [
13+
"entity_id"
14+
],
1215
"entities": {
1316
"url": "/monitor/services/dbaas/alert-definitions/12345/entities",
1417
"count": 1,

test/fixtures/monitor_services_dbaas_alert-definitions.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
"description": "A test alert for dbaas service",
1010
"scope": "entity",
1111
"regions": [],
12+
"group_by": [
13+
"entity_id"
14+
],
1215
"entities": {
1316
"url": "/monitor/services/dbaas/alert-definitions/12345/entities",
1417
"count": 1,
@@ -48,8 +51,8 @@
4851
"polling_interval_seconds": 60,
4952
"trigger_occurrences": 3
5053
},
51-
"class": "alert",
52-
"status": "active",
54+
"class": "",
55+
"status": "enabled",
5356
"created": "2024-01-01T00:00:00",
5457
"updated": "2024-01-01T00:00:00",
5558
"updated_by": "tester"

test/fixtures/monitor_services_dbaas_alert-definitions_12345.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
"description": "A test alert for dbaas service",
88
"scope": "entity",
99
"regions": [],
10+
"group_by": [
11+
"entity_id"
12+
],
1013
"entities": {
1114
"url": "/monitor/services/dbaas/alert-definitions/12345/entities",
1215
"count": 1,
@@ -46,8 +49,8 @@
4649
"polling_interval_seconds": 60,
4750
"trigger_occurrences": 3
4851
},
49-
"class": "alert",
50-
"status": "active",
52+
"class": "",
53+
"status": "enabled",
5154
"created": "2024-01-01T00:00:00",
5255
"updated": "2024-01-01T00:00:00",
5356
"updated_by": "tester"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"id": 67891,
3+
"label": "Cloned Alert",
4+
"service_type": "dbaas",
5+
"severity": 1,
6+
"type": "user",
7+
"description": "Cloned from source alert",
8+
"scope": "entity",
9+
"regions": [],
10+
"group_by": [
11+
"entity_id"
12+
],
13+
"entities": {
14+
"url": "/monitor/services/dbaas/alert-definitions/67891/entities",
15+
"count": 1,
16+
"has_more_resources": false
17+
},
18+
"alert_channels": [
19+
{
20+
"id": 10000,
21+
"label": "Read-Write Channel",
22+
"type": "email",
23+
"url": "/monitor/alert-channels/10000"
24+
}
25+
],
26+
"rule_criteria": {
27+
"rules": [
28+
{
29+
"aggregate_function": "avg",
30+
"dimension_filters": [
31+
{
32+
"dimension_label": "node_type",
33+
"label": "Node Type",
34+
"operator": "eq",
35+
"value": "primary"
36+
}
37+
],
38+
"label": "High CPU Usage",
39+
"metric": "cpu_usage",
40+
"operator": "gt",
41+
"threshold": 90,
42+
"unit": "percent"
43+
}
44+
]
45+
},
46+
"trigger_conditions": {
47+
"criteria_condition": "ALL",
48+
"evaluation_period_seconds": 300,
49+
"polling_interval_seconds": 60,
50+
"trigger_occurrences": 3
51+
},
52+
"class": "",
53+
"status": "enabled",
54+
"created": "2024-01-01T00:00:00",
55+
"updated": "2024-01-01T00:00:00",
56+
"updated_by": "tester"
57+
}

0 commit comments

Comments
 (0)