Skip to content

Commit 98ba868

Browse files
committed
resolving review comments
1 parent d2de2ef commit 98ba868

3 files changed

Lines changed: 49 additions & 123 deletions

File tree

linode_api4/groups/monitor.py

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,8 @@ def channel_create(
451451
:rtype: AlertChannel
452452
453453
.. note::
454+
If you need to obtain a single :class:`AlertChannel`, use :meth:`LinodeClient.load`.
455+
Example: ``client.load(AlertChannel, channel_id)``.
454456
For updating an alert channel, use the ``save()`` method on the :class:`AlertChannel` object.
455457
For deleting an alert channel, use the ``delete()`` method directly on the :class:`AlertChannel` object.
456458
"""
@@ -470,27 +472,6 @@ def channel_create(
470472

471473
return AlertChannel(self.client, result["id"], result)
472474

473-
def alert_channel(self, channel_id: int) -> AlertChannel:
474-
"""
475-
Retrieve a specific notification channel definition details by its channel ID.
476-
477-
Returns an :class:`AlertChannel` object for the specified channel ID.
478-
The channel object contains all configuration details for the notification
479-
destination (e.g., email lists, webhooks, etc.).
480-
481-
.. note:: This endpoint is in beta and requires using the v4beta base URL.
482-
483-
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-notification-channel
484-
485-
:param channel_id: The ID of the alert channel to retrieve.
486-
:type channel_id: int
487-
488-
:returns: The requested :class:`AlertChannel` object.
489-
:rtype: AlertChannel
490-
:raises ApiError: if the requested channel could not be loaded.
491-
"""
492-
return self.client.load(AlertChannel, channel_id)
493-
494475
def alert_channel_alerts(self, channel_id: int, *filters) -> PaginatedList:
495476
"""
496477
Retrieve all alerts associated with a specific alert channel.
@@ -499,8 +480,6 @@ def alert_channel_alerts(self, channel_id: int, *filters) -> PaginatedList:
499480
specified alert channel. This allows you to see which alert definitions
500481
are configured to notify this specific channel.
501482
502-
.. note:: This endpoint is in beta and requires using the v4beta base URL.
503-
504483
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-notification-channel-alerts
505484
506485
:param channel_id: The ID of the alert channel to retrieve alerts for.
@@ -512,14 +491,13 @@ def alert_channel_alerts(self, channel_id: int, *filters) -> PaginatedList:
512491
:rtype: PaginatedList[AlertDefinition]
513492
"""
514493
endpoint = f"/monitor/alert-channels/{channel_id}/alerts"
494+
495+
# Build filter dict if filters provided
515496
parsed_filters = None
516497
if filters:
517-
if len(filters) > 1:
518-
parsed_filters = and_(
519-
*filters
520-
).dct # pylint: disable=no-value-for-parameter
521-
else:
522-
parsed_filters = filters[0].dct
498+
parsed_filters = (
499+
and_(*filters).dct if len(filters) > 1 else filters[0].dct
500+
)
523501

524502
response_json = self.client.get(endpoint, filters=parsed_filters)
525503

@@ -529,20 +507,18 @@ def alert_channel_alerts(self, channel_id: int, *filters) -> PaginatedList:
529507
json=response_json,
530508
)
531509

532-
# For each alert definition in the response, extract the service_type
533-
# and use it as the parent_id when creating AlertDefinition objects
534-
result = []
535-
for obj in response_json.get("data", []):
536-
if "id" in obj and "service_type" in obj:
537-
alert = AlertDefinition.make_instance(
538-
obj["id"],
539-
self.client,
540-
parent_id=obj["service_type"],
541-
json=obj,
542-
)
543-
result.append(alert)
544-
545-
# Return paginated list with pagination metadata from response
510+
# Create AlertDefinition objects with proper parent_id (service_type)
511+
result = [
512+
AlertDefinition.make_instance(
513+
obj["id"],
514+
self.client,
515+
parent_id=obj["service_type"],
516+
json=obj,
517+
)
518+
for obj in response_json.get("data", [])
519+
if "id" in obj and "service_type" in obj
520+
]
521+
546522
return PaginatedList(
547523
self.client,
548524
endpoint[1:],

test/integration/models/monitor/test_monitor.py

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -245,25 +245,36 @@ def test_integration_create_get_update_delete_alert_definition(
245245
label = f"{label}-{int(time.time())}"
246246
description = "E2E alert created by SDK integration test"
247247

248-
# Pick an existing alert channel to attach to the definition; skip if none
249-
channels = list(
250-
client.monitor.alert_channels()
251-
) # TODO: create channel instead of relying on pre-existing one
252-
if not channels:
253-
pytest.skip(
254-
"No alert channels available on account for creating alert definitions"
255-
)
248+
# Get valid users to create an alert channel for the alert definition
249+
users = list(client.account.users())
250+
if len(users) == 0:
251+
pytest.skip("No account users available for creating alert channels")
252+
253+
# Use the first user for the alert channel
254+
usernames = [users[0].username]
256255

257256
created = None
257+
created_channel = None
258258

259259
try:
260+
# Create a new alert channel for this test
261+
created_channel = client.monitor.channel_create(
262+
label=f"{get_test_label()}-channel-{int(time.time())}",
263+
channel_type="email",
264+
details=ChannelDetails(
265+
email=EmailDetails(
266+
recipient_type="user",
267+
usernames=usernames,
268+
)
269+
),
270+
)
260271
# Create the alert definition using API-compliant top-level fields
261272
created = client.monitor.create_alert_definition(
262273
service_type=service_type,
263274
label=label,
264275
severity=1,
265276
description=description,
266-
channel_ids=[channels[0].id],
277+
channel_ids=[created_channel.id],
267278
rule_criteria=rule_criteria,
268279
trigger_conditions=trigger_conditions,
269280
)
@@ -293,6 +304,15 @@ def test_integration_create_get_update_delete_alert_definition(
293304
AlertDefinition, created.id, service_type
294305
)
295306
delete_alert.delete()
307+
if created_channel:
308+
# Clean up the created channel
309+
try:
310+
created_channel.delete()
311+
except Exception as e:
312+
# Log but don't fail if cleanup fails
313+
print(
314+
f"Warning: Failed to delete channel {created_channel.id}: {e}"
315+
)
296316

297317

298318
def test_alert_definition_entities(test_linode_client):
@@ -337,8 +357,7 @@ def test_integration_create_get_update_delete_alert_channel(test_linode_client):
337357
working end-to-end against the actual API.
338358
"""
339359
client = test_linode_client
340-
label = get_test_label() + "-e2e-channel"
341-
label = f"{label}-{int(time.time())}"
360+
label = "pythonsdk-alert-channel-test"
342361

343362
created_channel = None
344363

@@ -413,31 +432,6 @@ def test_integration_create_get_update_delete_alert_channel(test_linode_client):
413432
)
414433

415434

416-
def test_integration_alert_channel(test_linode_client):
417-
"""Test retrieving a single alert channel by ID.
418-
419-
This test fetches an existing alert channel and verifies that all
420-
expected properties are populated correctly.
421-
"""
422-
client = test_linode_client
423-
424-
# Get an existing alert channel to test with
425-
channels = list(client.monitor.alert_channels())
426-
if len(channels) == 0:
427-
pytest.skip("No alert channels available on account for testing")
428-
429-
channel_id = channels[0].id
430-
431-
# Test the alert_channel() method
432-
fetched_channel = client.monitor.alert_channel(channel_id)
433-
434-
assert isinstance(fetched_channel, AlertChannel)
435-
assert fetched_channel.id == channel_id
436-
assert fetched_channel.label is not None
437-
assert fetched_channel.channel_type is not None
438-
assert fetched_channel.details is not None
439-
440-
441435
def test_integration_alert_channel_alerts(test_linode_client):
442436
"""Test retrieving alerts associated with a specific alert channel.
443437

test/unit/groups/monitor_api_test.py

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -258,50 +258,6 @@ def test_create_update_delete_alert_channel(self):
258258
assert mock_delete.call_url == channel_url
259259
assert result is True
260260

261-
def test_alert_channel(self):
262-
"""
263-
Test retrieval of a specific alert channel by ID.
264-
Verifies the alert_channel method returns a single AlertChannel object.
265-
"""
266-
channel_id = 123
267-
channel_url = f"/monitor/alert-channels/{channel_id}"
268-
269-
channel_response = {
270-
"id": channel_id,
271-
"label": "alert notification channel",
272-
"type": "user",
273-
"channel_type": "email",
274-
"details": {
275-
"email": {
276-
"usernames": ["admin-user1", "admin-user2"],
277-
"recipient_type": "user",
278-
}
279-
},
280-
"alerts": {
281-
"url": f"{channel_url}/alerts",
282-
"type": "alerts-definitions",
283-
"alert_count": 2,
284-
},
285-
"created": "2024-01-01T00:00:00",
286-
"updated": "2024-01-01T00:00:00",
287-
"created_by": "tester",
288-
"updated_by": "tester",
289-
}
290-
291-
with self.mock_get(channel_response) as mock_get:
292-
channel = self.client.monitor.alert_channel(channel_id=channel_id)
293-
294-
assert mock_get.call_url == channel_url
295-
assert isinstance(channel, AlertChannel)
296-
assert channel.id == channel_id
297-
assert channel.label == "alert notification channel"
298-
assert channel.channel_type == "email"
299-
assert channel.details.email.usernames == [
300-
"admin-user1",
301-
"admin-user2",
302-
]
303-
assert channel.alerts.alert_count == 2
304-
305261
def test_alert_channel_alerts(self):
306262
"""
307263
Test retrieval of alerts associated with a specific alert channel.

0 commit comments

Comments
 (0)