-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix errors in webex alert destination. Add formatting support for QUE…
…RY_RESULT_TABLE. (#7296) * prevent text values in payload being detected as 'set' on send. Webex send ERROR:: Object of type set is not JSON serializable Signed-off-by: Matt Nelson <[email protected]> * add support for formatted QUERY_RESULT_TABLE in webex card Signed-off-by: Matt Nelson <[email protected]> * don't try to send to blank destinations Signed-off-by: Matt Nelson <[email protected]> * fix handling of the encoded QUERY_RESULTS_TABLE text Signed-off-by: Matt Nelson <[email protected]> * re-sort imports for ruff Signed-off-by: Matt Nelson <[email protected]> * change formatter to black Signed-off-by: Matt Nelson <[email protected]> * Add additional tests for Webex notification handling ensure blank entries are handled for room IDs and person emails. ensure that the API is not called when no valid destinations are provided. ensure proper attachment formatting for alerts containing 2D arrays. Signed-off-by: Matt Nelson <[email protected]> * Add test for Webex notification with 1D array handling This commit introduces a new test case to verify that the Webex notification function correctly handles a 1D array input in the alert body. The test ensures that the expected payload is constructed properly and that the requests.post method is called with the correct parameters. Signed-off-by: Matt Nelson <[email protected]> --------- Signed-off-by: Matt Nelson <[email protected]>
- Loading branch information
Showing
2 changed files
with
290 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -261,37 +261,139 @@ def test_webex_notify_calls_requests_post(): | |
alert.name = "Test Alert" | ||
alert.custom_subject = "Test custom subject" | ||
alert.custom_body = "Test custom body" | ||
alert.render_template = mock.Mock(return_value={"Rendered": "template"}) | ||
|
||
query = mock.Mock() | ||
query.id = 1 | ||
|
||
user = mock.Mock() | ||
app = mock.Mock() | ||
host = "https://localhost:5000" | ||
options = { | ||
"webex_bot_token": "abcd", | ||
"to_room_ids": "1234,5678", | ||
"to_person_emails": "[email protected],[email protected]", | ||
} | ||
metadata = {"Scheduled": False} | ||
|
||
new_state = Alert.TRIGGERED_STATE | ||
destination = Webex(options) | ||
|
||
with mock.patch("redash.destinations.webex.requests.post") as mock_post: | ||
mock_response = mock.Mock() | ||
mock_response.status_code = 200 | ||
mock_post.return_value = mock_response | ||
|
||
destination.notify(alert, query, user, new_state, app, host, metadata, options) | ||
|
||
query_link = f"{host}/queries/{query.id}" | ||
alert_link = f"{host}/alerts/{alert.id}" | ||
|
||
expected_attachments = Webex.formatted_attachments_template( | ||
alert.custom_subject, alert.custom_body, query_link, alert_link | ||
) | ||
|
||
expected_payload_room = { | ||
"markdown": alert.custom_subject + "\n" + alert.custom_body, | ||
"attachments": expected_attachments, | ||
"roomId": "1234", | ||
} | ||
|
||
expected_payload_email = { | ||
"markdown": alert.custom_subject + "\n" + alert.custom_body, | ||
"attachments": expected_attachments, | ||
"toPersonEmail": "[email protected]", | ||
} | ||
|
||
# Check that requests.post was called for both roomId and toPersonEmail destinations | ||
mock_post.assert_any_call( | ||
destination.api_base_url, | ||
json=expected_payload_room, | ||
headers={"Authorization": "Bearer abcd"}, | ||
timeout=5.0, | ||
) | ||
|
||
mock_post.assert_any_call( | ||
destination.api_base_url, | ||
json=expected_payload_email, | ||
headers={"Authorization": "Bearer abcd"}, | ||
timeout=5.0, | ||
) | ||
|
||
assert mock_response.status_code == 200 | ||
|
||
|
||
def test_webex_notify_handles_blank_entries(): | ||
alert = mock.Mock(spec_set=["id", "name", "custom_subject", "custom_body", "render_template"]) | ||
alert.id = 1 | ||
alert.name = "Test Alert" | ||
alert.custom_subject = "Test custom subject" | ||
alert.custom_body = "Test custom body" | ||
alert.render_template = mock.Mock(return_value={"Rendered": "template"}) | ||
|
||
query = mock.Mock() | ||
query.id = 1 | ||
|
||
user = mock.Mock() | ||
app = mock.Mock() | ||
host = "https://localhost:5000" | ||
options = { | ||
"webex_bot_token": "abcd", | ||
"to_room_ids": "", | ||
"to_person_emails": "", | ||
} | ||
metadata = {"Scheduled": False} | ||
|
||
new_state = Alert.TRIGGERED_STATE | ||
destination = Webex(options) | ||
|
||
with mock.patch("redash.destinations.webex.requests.post") as mock_post: | ||
destination.notify(alert, query, user, new_state, app, host, metadata, options) | ||
|
||
# Ensure no API calls are made when destinations are blank | ||
mock_post.assert_not_called() | ||
|
||
|
||
def test_webex_notify_handles_2d_array(): | ||
alert = mock.Mock(spec_set=["id", "name", "custom_subject", "custom_body", "render_template"]) | ||
alert.id = 1 | ||
alert.name = "Test Alert" | ||
alert.custom_subject = "Test custom subject" | ||
alert.custom_body = "Test custom body with table [['Col1', 'Col2'], ['Val1', 'Val2']]" | ||
alert.render_template = mock.Mock(return_value={"Rendered": "template"}) | ||
|
||
query = mock.Mock() | ||
query.id = 1 | ||
|
||
user = mock.Mock() | ||
app = mock.Mock() | ||
host = "https://localhost:5000" | ||
options = {"webex_bot_token": "abcd", "to_room_ids": "1234"} | ||
options = { | ||
"webex_bot_token": "abcd", | ||
"to_room_ids": "1234", | ||
} | ||
metadata = {"Scheduled": False} | ||
|
||
new_state = Alert.TRIGGERED_STATE | ||
destination = Webex(options) | ||
|
||
with mock.patch("redash.destinations.webex.requests.post") as mock_post: | ||
mock_response = mock.Mock() | ||
mock_response.status_code = 204 | ||
mock_response.status_code = 200 | ||
mock_post.return_value = mock_response | ||
|
||
destination.notify(alert, query, user, new_state, app, host, metadata, options) | ||
|
||
query_link = f"{host}/queries/{query.id}" | ||
alert_link = f"{host}/alerts/{alert.id}" | ||
|
||
formatted_attachments = Webex.formatted_attachments_template( | ||
expected_attachments = Webex.formatted_attachments_template( | ||
alert.custom_subject, alert.custom_body, query_link, alert_link | ||
) | ||
|
||
expected_payload = { | ||
"markdown": alert.custom_subject + "\n" + alert.custom_body, | ||
"attachments": formatted_attachments, | ||
"attachments": expected_attachments, | ||
"roomId": "1234", | ||
} | ||
|
||
|
@@ -302,7 +404,60 @@ def test_webex_notify_calls_requests_post(): | |
timeout=5.0, | ||
) | ||
|
||
assert mock_response.status_code == 204 | ||
assert mock_response.status_code == 200 | ||
|
||
|
||
def test_webex_notify_handles_1d_array(): | ||
alert = mock.Mock(spec_set=["id", "name", "custom_subject", "custom_body", "render_template"]) | ||
alert.id = 1 | ||
alert.name = "Test Alert" | ||
alert.custom_subject = "Test custom subject" | ||
alert.custom_body = "Test custom body with 1D array, however unlikely ['Col1', 'Col2']" | ||
alert.render_template = mock.Mock(return_value={"Rendered": "template"}) | ||
|
||
query = mock.Mock() | ||
query.id = 1 | ||
|
||
user = mock.Mock() | ||
app = mock.Mock() | ||
host = "https://localhost:5000" | ||
options = { | ||
"webex_bot_token": "abcd", | ||
"to_room_ids": "1234", | ||
} | ||
metadata = {"Scheduled": False} | ||
|
||
new_state = Alert.TRIGGERED_STATE | ||
destination = Webex(options) | ||
|
||
with mock.patch("redash.destinations.webex.requests.post") as mock_post: | ||
mock_response = mock.Mock() | ||
mock_response.status_code = 200 | ||
mock_post.return_value = mock_response | ||
|
||
destination.notify(alert, query, user, new_state, app, host, metadata, options) | ||
|
||
query_link = f"{host}/queries/{query.id}" | ||
alert_link = f"{host}/alerts/{alert.id}" | ||
|
||
expected_attachments = Webex.formatted_attachments_template( | ||
alert.custom_subject, alert.custom_body, query_link, alert_link | ||
) | ||
|
||
expected_payload = { | ||
"markdown": alert.custom_subject + "\n" + alert.custom_body, | ||
"attachments": expected_attachments, | ||
"roomId": "1234", | ||
} | ||
|
||
mock_post.assert_called_once_with( | ||
destination.api_base_url, | ||
json=expected_payload, | ||
headers={"Authorization": "Bearer abcd"}, | ||
timeout=5.0, | ||
) | ||
|
||
assert mock_response.status_code == 200 | ||
|
||
|
||
def test_datadog_notify_calls_requests_post(): | ||
|