Skip to content

Commit 9e99b43

Browse files
committed
feat: add ACLP list entities method
Add entities envelope in AlertDefinition. Add list entities GET API method. Add tests.
1 parent c9e18a5 commit 9e99b43

File tree

8 files changed

+259
-9
lines changed

8 files changed

+259
-9
lines changed

linode_api4/groups/monitor.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from linode_api4.objects import (
77
AlertChannel,
88
AlertDefinition,
9+
AlertDefinitionEntity,
910
MonitorDashboard,
1011
MonitorMetricsDefinition,
1112
MonitorService,
@@ -219,6 +220,8 @@ def create_alert_definition(
219220
channel_ids: list[int],
220221
rule_criteria: dict,
221222
trigger_conditions: dict,
223+
scope: Optional[str] = None,
224+
regions: Optional[list[str]] = None,
222225
entity_ids: Optional[list[str]] = None,
223226
description: Optional[str] = None,
224227
) -> AlertDefinition:
@@ -248,6 +251,10 @@ def create_alert_definition(
248251
:param trigger_conditions: Trigger conditions that define when
249252
the alert should transition state.
250253
:type trigger_conditions: dict
254+
:param scope: (Optional) Alert scope (for example: `account`, `entity`, or `region`). Defaults to `entity`.
255+
:type scope: Optional[str]
256+
:param regions: (Optional) Regions to monitor.
257+
:type regions: Optional[list[str]]
251258
:param entity_ids: (Optional) Restrict the alert to a subset of entity IDs.
252259
:type entity_ids: Optional[list[str]]
253260
:param description: (Optional) Longer description for the alert definition.
@@ -267,6 +274,10 @@ def create_alert_definition(
267274
"rule_criteria": rule_criteria,
268275
"trigger_conditions": trigger_conditions,
269276
}
277+
if scope is not None:
278+
params["scope"] = scope
279+
if regions is not None:
280+
params["regions"] = regions
270281
if description is not None:
271282
params["description"] = description
272283
if entity_ids is not None:
@@ -284,3 +295,38 @@ def create_alert_definition(
284295
)
285296

286297
return AlertDefinition(self.client, result["id"], service_type, result)
298+
299+
def alert_definition_entities(
300+
self,
301+
service_type: str,
302+
id: int,
303+
*filters,
304+
) -> PaginatedList:
305+
"""
306+
List entities associated with a specific alert definition.
307+
308+
This endpoint supports pagination fields (`page`, `page_size`) in the API.
309+
310+
.. note:: This endpoint is in beta and requires using the v4beta base URL.
311+
312+
API Documentation: <todo: add link to techdocs>
313+
314+
:param service_type: Service type for the alert definition (e.g. `dbaas`).
315+
:type service_type: str
316+
:param id: Alert definition identifier.
317+
:type id: int
318+
:param filters: Optional filter expressions to apply to the collection.
319+
See :doc:`Filtering Collections</linode_api4/objects/filtering>`.
320+
321+
:returns: A paginated list of entities associated with the alert definition.
322+
:rtype: PaginatedList[AlertDefinitionEntity]
323+
"""
324+
325+
endpoint = (
326+
f"/monitor/services/{service_type}/alert-definitions/{id}/entities"
327+
)
328+
return self.client._get_and_filter(
329+
AlertDefinitionEntity,
330+
*filters,
331+
endpoint=endpoint,
332+
)

linode_api4/objects/monitor.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
"Alert",
1111
"AlertChannel",
1212
"AlertDefinition",
13+
"AlertDefinitionEntity",
14+
"AlertEntities",
15+
"AlertScope",
1316
"AlertType",
1417
"Alerts",
1518
"MonitorDashboard",
@@ -387,6 +390,43 @@ class AlertType(StrEnum):
387390
user = "user"
388391

389392

393+
class AlertScope(StrEnum):
394+
"""
395+
Scope values supported for alert definitions.
396+
"""
397+
398+
entity = "entity"
399+
region = "region"
400+
account = "account"
401+
402+
403+
@dataclass
404+
class AlertEntities(JSONObject):
405+
"""
406+
Represents entity metadata for an alert definition.
407+
408+
For entity scoped alerts, `entities` envelope contains the URL to list entities,
409+
a count, and a has_more_resources flag.
410+
For region/account scoped alerts, the `entities` are returned as an empty object.
411+
"""
412+
413+
url: str = ""
414+
count: int = 0
415+
has_more_resources: bool = False
416+
417+
418+
@dataclass
419+
class AlertDefinitionEntity(JSONObject):
420+
"""
421+
Represents an entity associated with an alert definition.
422+
"""
423+
424+
id: str = ""
425+
label: str = ""
426+
url: str = ""
427+
type: str = ""
428+
429+
390430
class AlertDefinition(DerivedBase):
391431
"""
392432
Represents an alert definition for a monitor service.
@@ -406,17 +446,24 @@ class AlertDefinition(DerivedBase):
406446
"severity": Property(mutable=True),
407447
"type": Property(mutable=True),
408448
"status": Property(mutable=True),
409-
"has_more_resources": Property(mutable=True),
449+
"scope": Property(AlertScope),
450+
"regions": Property(mutable=True),
451+
"has_more_resources": Property(
452+
mutable=True
453+
), # Deprecated; use entities.has_more_resources
454+
"entities": Property(json_object=AlertEntities),
410455
"rule_criteria": Property(mutable=True, json_object=RuleCriteria),
411456
"trigger_conditions": Property(
412457
mutable=True, json_object=TriggerConditions
413458
),
414-
"alert_channels": Property(mutable=True, json_object=Alerts),
459+
"alert_channels": Property(mutable=True, json_object=Alert),
415460
"created": Property(is_datetime=True),
416461
"updated": Property(is_datetime=True),
417462
"updated_by": Property(),
418463
"created_by": Property(),
419-
"entity_ids": Property(mutable=True),
464+
"entity_ids": Property(
465+
mutable=True
466+
), # Deprecated; use entities.url to fetch associated entities
420467
"description": Property(mutable=True),
421468
"service_class": Property(alias_of="class"),
422469
}

test/fixtures/monitor_alert-definitions.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,26 @@
77
"severity": 1,
88
"type": "user",
99
"description": "A test alert for dbaas service",
10+
"scope": "entity",
11+
"regions": [],
1012
"entity_ids": ["13217"],
11-
"alert_channels": [],
13+
"entities": {
14+
"url": "/monitor/services/dbaas/alert-definitions/12345/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+
],
1226
"has_more_resources": false,
1327
"rule_criteria": null,
1428
"trigger_conditions": null,
1529
"class": "alert",
16-
"notification_groups": [],
1730
"status": "active",
1831
"created": "2024-01-01T00:00:00",
1932
"updated": "2024-01-01T00:00:00",

test/fixtures/monitor_services_dbaas_alert-definitions.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,24 @@
77
"severity": 1,
88
"type": "user",
99
"description": "A test alert for dbaas service",
10+
"scope": "entity",
11+
"regions": [],
1012
"entity_ids": [
1113
"13217"
1214
],
13-
"alert_channels": [],
15+
"entities": {
16+
"url": "/monitor/services/dbaas/alert-definitions/12345/entities",
17+
"count": 1,
18+
"has_more_resources": false
19+
},
20+
"alert_channels": [
21+
{
22+
"id": 10000,
23+
"label": "Read-Write Channel",
24+
"type": "email",
25+
"url": "/monitor/alert-channels/10000"
26+
}
27+
],
1428
"has_more_resources": false,
1529
"rule_criteria": {
1630
"rules": [
@@ -39,7 +53,6 @@
3953
"trigger_occurrences": 3
4054
},
4155
"class": "alert",
42-
"notification_groups": [],
4356
"status": "active",
4457
"created": "2024-01-01T00:00:00",
4558
"updated": "2024-01-01T00:00:00",

test/fixtures/monitor_services_dbaas_alert-definitions_12345.json

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,24 @@
55
"severity": 1,
66
"type": "user",
77
"description": "A test alert for dbaas service",
8+
"scope": "entity",
9+
"regions": [],
810
"entity_ids": [
911
"13217"
1012
],
11-
"alert_channels": [],
13+
"entities": {
14+
"url": "/monitor/services/dbaas/alert-definitions/12345/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+
],
1226
"has_more_resources": false,
1327
"rule_criteria": {
1428
"rules": [
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"data": [
3+
{
4+
"id": "1",
5+
"label": "mydatabase-1",
6+
"url": "/v4/databases/mysql/instances/1",
7+
"type": "dbaas"
8+
},
9+
{
10+
"id": "2",
11+
"label": "mydatabase-2",
12+
"url": "/v4/databases/mysql/instances/2",
13+
"type": "dbaas"
14+
},
15+
{
16+
"id": "3",
17+
"label": "mydatabase-3",
18+
"url": "/v4/databases/mysql/instances/3",
19+
"type": "dbaas"
20+
}
21+
],
22+
"page": 1,
23+
"pages": 1,
24+
"results": 3
25+
}

test/integration/models/monitor/test_monitor.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77

88
import pytest
99

10-
from linode_api4 import LinodeClient
10+
from linode_api4 import LinodeClient, PaginatedList
1111
from linode_api4.objects import (
1212
AlertDefinition,
13+
AlertDefinitionEntity,
1314
ApiError,
1415
MonitorDashboard,
1516
MonitorMetricsDefinition,
@@ -275,3 +276,35 @@ def wait_for_alert_ready(alert_id, service_type: str):
275276
AlertDefinition, created.id, service_type
276277
)
277278
delete_alert.delete()
279+
280+
281+
def test_alert_definition_entities(test_linode_client):
282+
"""Test listing entities associated with an alert definition.
283+
284+
This test first retrieves alert definitions for a service type, then lists entities for the first alert definition.
285+
It asserts that the returned entities have expected fields.
286+
"""
287+
pytest.skip("reason: list alert_definition_entities API is not yet live")
288+
client = test_linode_client
289+
service_type = "dbaas"
290+
291+
alert_definitions = client.monitor.alert_definitions(
292+
service_type=service_type
293+
)
294+
295+
if len(alert_definitions) == 0:
296+
pytest.skip("No alert definitions available for dbaas service type")
297+
298+
alert_def = alert_definitions[0]
299+
entities = client.monitor.alert_definition_entities(
300+
service_type, alert_def.id
301+
)
302+
303+
assert isinstance(entities, PaginatedList)
304+
if len(entities) > 0:
305+
entity = entities[0]
306+
assert isinstance(entity, AlertDefinitionEntity)
307+
assert entity.id
308+
assert entity.label
309+
assert entity.url
310+
assert entity.type == service_type

0 commit comments

Comments
 (0)