From 7710526870319c4c45ea414bfb98c77a980064c3 Mon Sep 17 00:00:00 2001 From: nsano-rururu Date: Sat, 19 Jun 2021 13:44:56 +0900 Subject: [PATCH] Added test code for files in alerters folder --- elastalert/alerters/pagerduty.py | 4 +- tests/alerters/alerta_test.py | 201 +++++++++++++++++++++++++++++- tests/alerters/chatwork_test.py | 11 +- tests/alerters/datadog_test.py | 8 +- tests/alerters/debug_test.py | 54 ++++++++ tests/alerters/dingtalk_test.py | 54 +++++++- tests/alerters/discord_test.py | 10 +- tests/alerters/gitter_test.py | 10 +- tests/alerters/googlechat_test.py | 119 +++++++++++++++++- tests/alerters/httppost_test.py | 10 +- tests/alerters/jira_test.py | 8 +- tests/alerters/line_test.py | 12 +- tests/alerters/mattermost_test.py | 57 ++++++++- tests/alerters/opsgenie_test.py | 121 +++++++++++++----- tests/alerters/pagerduty_test.py | 132 +++++++++++++++++++- tests/alerters/pagertree_test.py | 10 +- tests/alerters/rocketchat_test.py | 10 +- tests/alerters/servicenow_test.py | 10 +- tests/alerters/slack_test.py | 10 +- tests/alerters/teams_test.py | 10 +- tests/alerters/telegram_test.py | 10 +- tests/alerters/victorops_test.py | 10 +- 22 files changed, 778 insertions(+), 103 deletions(-) diff --git a/elastalert/alerters/pagerduty.py b/elastalert/alerters/pagerduty.py index b804b26c..426e9779 100644 --- a/elastalert/alerters/pagerduty.py +++ b/elastalert/alerters/pagerduty.py @@ -103,9 +103,9 @@ def alert(self, matches): if self.pagerduty_event_type == 'trigger': elastalert_logger.info("Trigger sent to PagerDuty") - elif self.pagerduty_event_type == 'resolve': + if self.pagerduty_event_type == 'resolve': elastalert_logger.info("Resolve sent to PagerDuty") - elif self.pagerduty_event_type == 'acknowledge': + if self.pagerduty_event_type == 'acknowledge': elastalert_logger.info("acknowledge sent to PagerDuty") def resolve_formatted_key(self, key, args, matches): diff --git a/tests/alerters/alerta_test.py b/tests/alerters/alerta_test.py index 35cd1758..858a06ba 100644 --- a/tests/alerters/alerta_test.py +++ b/tests/alerters/alerta_test.py @@ -1,5 +1,6 @@ import datetime import json +import logging from unittest import mock import pytest @@ -10,7 +11,8 @@ from elastalert.util import EAException -def test_alerta_no_auth(): +def test_alerta_no_auth(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test Alerta rule!', 'alerta_api_url': 'http://elastalerthost:8080/api/alert', @@ -73,6 +75,7 @@ def test_alerta_no_auth(): ) assert expected_data == json.loads( mock_post_request.call_args_list[0][1]['data']) + assert ('elastalert', logging.INFO, 'Alert sent to Alerta') == caplog.record_tuples[0] def test_alerta_auth(): @@ -616,7 +619,7 @@ def test_alerta_tags(): def test_alerta_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test Alerta rule!', 'alerta_api_url': 'http://elastalerthost:8080/api/alert', @@ -649,8 +652,7 @@ def test_alerta_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting to Alerta: ' in str(ea) def test_alerta_getinfo(): @@ -705,3 +707,194 @@ def test_alerta_required_error(alerta_api_url, expected_data): assert expected_data == actual_data except Exception as ea: assert expected_data in str(ea) + + +@pytest.mark.parametrize('query_key, expected_data', [ + ('hostname', 'Test Alerta rule!.aProbe'), + ('test', 'Test Alerta rule!'), + ('', 'Test Alerta rule!'), +]) +def test_alerta_create_default_title(query_key, expected_data): + rule = { + 'name': 'Test Alerta rule!', + 'alerta_api_url': 'http://elastalerthost:8080/api/alert', + 'timeframe': datetime.timedelta(hours=1), + 'timestamp_field': '@timestamp', + 'type': 'any', + 'alert': 'alerta' + } + if query_key != '': + rule['query_key'] = query_key + + match = [ + { + '@timestamp': '2014-10-10T00:00:00', + 'sender_ip': '1.1.1.1', + 'hostname': 'aProbe' + }, + { + '@timestamp': '2014-10-10T00:00:00', + 'sender_ip': '1.1.1.1', + 'hostname2': 'aProbe' + } + ] + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = AlertaAlerter(rule) + + result = alert.create_default_title(match) + assert expected_data == result + + +def test_alerta_match_timestamp_none(): + rule = { + 'name': 'Test Alerta rule!', + 'alerta_api_url': 'http://elastalerthost:8080/api/alert', + 'timeframe': datetime.timedelta(hours=1), + 'alerta_attributes_keys': ["hostname", "TimestampEvent", "senderIP"], + 'alerta_attributes_values': ["{hostname}", "{logdate}", "{sender_ip}"], + 'alerta_correlate': ["ProbeUP", "ProbeDOWN"], + 'alerta_event': "ProbeUP", + 'alerta_group': "Health", + 'alerta_origin': "ElastAlert 2", + 'alerta_severity': "debug", + 'alerta_text': "Probe {hostname} is UP at {logdate} GMT", + 'alerta_value': "UP", + 'type': 'any', + 'alerta_use_match_timestamp': True, + 'alerta_tags': ['elastalert2'], + 'alert': 'alerta' + } + + match = { + 'sender_ip': '1.1.1.1', + 'hostname': 'aProbe' + } + + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = AlertaAlerter(rule) + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data = { + "origin": "ElastAlert 2", + "resource": "elastalert", + "severity": "debug", + "service": ["elastalert"], + "tags": ['elastalert2'], + "text": "Probe aProbe is UP at GMT", + "value": "UP", + "environment": "Production", + "timeout": 86400, + "correlate": ["ProbeUP", "ProbeDOWN"], + "group": "Health", + "attributes": {"senderIP": "1.1.1.1", "hostname": "aProbe", "TimestampEvent": ""}, + "type": "elastalert", + "event": "ProbeUP" + } + + mock_post_request.assert_called_once_with( + alert.url, + data=mock.ANY, + verify=True, + headers={ + 'content-type': 'application/json'} + ) + + actual_data = json.loads( + mock_post_request.call_args_list[0][1]['data']) + del actual_data['createTime'] + del actual_data['rawData'] + assert expected_data == actual_data + + +def test_alerta_use_match_timestamp(): + rule = { + 'name': 'Test Alerta rule!', + 'alerta_api_url': 'http://elastalerthost:8080/api/alert', + 'timeframe': datetime.timedelta(hours=1), + 'alerta_attributes_keys': ["hostname", "TimestampEvent", "senderIP"], + 'alerta_attributes_values': ["{hostname}", "{logdate}", "{sender_ip}"], + 'alerta_correlate': ["ProbeUP", "ProbeDOWN"], + 'alerta_event': "ProbeUP", + 'alerta_group': "Health", + 'alerta_origin': "ElastAlert 2", + 'alerta_severity': "debug", + 'alerta_text': "Probe {hostname} is UP at {logdate} GMT", + 'alerta_value': "UP", + 'type': 'any', + 'alerta_use_match_timestamp': False, + 'alerta_tags': ['elastalert2'], + 'alert': 'alerta' + } + + match = { + 'sender_ip': '1.1.1.1', + 'hostname': 'aProbe' + } + + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = AlertaAlerter(rule) + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data = { + "origin": "ElastAlert 2", + "resource": "elastalert", + "severity": "debug", + "service": ["elastalert"], + "tags": ['elastalert2'], + "text": "Probe aProbe is UP at GMT", + "value": "UP", + "environment": "Production", + "timeout": 86400, + "correlate": ["ProbeUP", "ProbeDOWN"], + "group": "Health", + "attributes": {"senderIP": "1.1.1.1", "hostname": "aProbe", "TimestampEvent": ""}, + "type": "elastalert", + "event": "ProbeUP" + } + + mock_post_request.assert_called_once_with( + alert.url, + data=mock.ANY, + verify=True, + headers={ + 'content-type': 'application/json'} + ) + + actual_data = json.loads( + mock_post_request.call_args_list[0][1]['data']) + del actual_data['createTime'] + del actual_data['rawData'] + assert expected_data == actual_data + + +def test_get_json_payload_error(): + rule = { + 'name': 'Test Alerta rule!', + 'alerta_api_url': 'http://elastalerthost:8080/api/alert', + 'timeframe': datetime.timedelta(hours=1), + 'timestamp_field': '@timestamp', + 'type': 'any', + 'alert': 'alerta', + 'query_key': 'hostname' + } + match = { + '@timestamp': '2014-10-10T00:00:00', + 'sender_ip': '1.1.1.1', + 'hostname': 'aProbe' + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = AlertaAlerter(rule) + + mock_run = mock.MagicMock(side_effect=Exception) + with mock.patch('json.dumps', mock_run): + + with pytest.raises(Exception) as e: + alert.get_json_payload(match) + + assert 'Error building Alerta request: ' in str(e) diff --git a/tests/alerters/chatwork_test.py b/tests/alerters/chatwork_test.py index cd8945a8..fb0a1e60 100644 --- a/tests/alerters/chatwork_test.py +++ b/tests/alerters/chatwork_test.py @@ -1,3 +1,5 @@ +import logging + from unittest import mock import pytest from requests import RequestException @@ -8,7 +10,8 @@ from elastalert.util import EAException -def test_chatwork(): +def test_chatwork(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test Chatwork Rule', 'type': 'any', @@ -39,6 +42,7 @@ def test_chatwork(): actual_data = mock_post_request.call_args_list[0][1]['params'] assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Alert sent to Chatwork room xxxx2') == caplog.record_tuples[0] def test_chatwork_proxy(): @@ -78,7 +82,7 @@ def test_chatwork_proxy(): def test_chatwork_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test Chatwork Rule', 'type': 'any', @@ -99,8 +103,7 @@ def test_chatwork_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting to Chattwork: . Details: ' in str(ea) def test_chatwork_getinfo(): diff --git a/tests/alerters/datadog_test.py b/tests/alerters/datadog_test.py index e7032585..3e082aa7 100644 --- a/tests/alerters/datadog_test.py +++ b/tests/alerters/datadog_test.py @@ -48,8 +48,8 @@ def test_datadog_alerter(caplog): assert ('elastalert', logging.INFO, 'Alert sent to Datadog') == caplog.record_tuples[0] -def test_datadog_alerterea_exception(): - try: +def test_datadog_ea_exception(): + with pytest.raises(EAException) as ea: rule = { 'name': 'Test Datadog Event Alerter', 'type': 'any', @@ -68,9 +68,7 @@ def test_datadog_alerterea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - assert False - except EAException as ea: - assert 'Error posting event to Datadog:' in str(ea) + assert 'Error posting event to Datadog:' in str(ea) def test_datadog_getinfo(): diff --git a/tests/alerters/debug_test.py b/tests/alerters/debug_test.py index be09cbc2..f35053c9 100644 --- a/tests/alerters/debug_test.py +++ b/tests/alerters/debug_test.py @@ -1,3 +1,5 @@ +import logging + from elastalert.alerters.debug import DebugAlerter from elastalert.loaders import FileRulesLoader @@ -18,3 +20,55 @@ def test_debug_getinfo(): } actual_data = alert.get_info() assert expected_data == actual_data + + +def test_debug_alerter(caplog): + caplog.set_level(logging.INFO) + rule = { + 'name': 'Test Debug Event Alerter', + 'type': 'any', + 'alert': [], + 'timestamp_field': 'timestamp' + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = DebugAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'name': 'debug-test-name' + } + alert.alert([match]) + + excepted1 = 'Alert for Test Debug Event Alerter at None:' + assert ('elastalert', logging.INFO, excepted1) == caplog.record_tuples[0] + + excepted2 = 'Test Debug Event Alerter\n\n@timestamp: 2021-01-01T00:00:00\n' + excepted2 += 'name: debug-test-name\n' + assert ('elastalert', logging.INFO, excepted2) == caplog.record_tuples[1] + + +def test_debug_alerter_querykey(caplog): + caplog.set_level(logging.INFO) + rule = { + 'name': 'Test Debug Event Alerter', + 'type': 'any', + 'alert': [], + 'timestamp_field': 'timestamp', + 'query_key': 'hostname' + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = DebugAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'name': 'debug-test-name', + 'hostname': 'aProbe' + } + alert.alert([match]) + + excepted1 = 'Alert for Test Debug Event Alerter, aProbe at None:' + assert ('elastalert', logging.INFO, excepted1) == caplog.record_tuples[0] + + excepted2 = 'Test Debug Event Alerter\n\n@timestamp: 2021-01-01T00:00:00\n' + excepted2 += 'hostname: aProbe\nname: debug-test-name\n' + assert ('elastalert', logging.INFO, excepted2) == caplog.record_tuples[1] diff --git a/tests/alerters/dingtalk_test.py b/tests/alerters/dingtalk_test.py index b4c1250c..c1a2731f 100644 --- a/tests/alerters/dingtalk_test.py +++ b/tests/alerters/dingtalk_test.py @@ -1,4 +1,5 @@ import json +import logging from unittest import mock import pytest @@ -10,7 +11,8 @@ from elastalert.util import EAException -def test_dingtalk_text(): +def test_dingtalk_text(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test DingTalk Rule', 'type': 'any', @@ -47,6 +49,7 @@ def test_dingtalk_text(): actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Trigger sent to dingtalk') == caplog.record_tuples[0] def test_dingtalk_markdown(): @@ -194,6 +197,50 @@ def test_dingtalk_action_card(): assert expected_data == actual_data +def test_dingtalk_action_card2(): + rule = { + 'name': 'Test DingTalk Rule', + 'type': 'any', + 'dingtalk_access_token': 'xxxxxxx', + 'dingtalk_msgtype': 'action_card', + 'dingtalk_single_title': 'elastalert', + 'dingtalk_single_url': 'http://xxxxx2', + 'alert': [], + 'alert_subject': 'Test DingTalk' + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = DingTalkAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'somefield': 'foobarbaz' + } + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data = { + 'msgtype': 'actionCard', + 'actionCard': { + 'title': 'Test DingTalk', + 'text': 'Test DingTalk Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n' + } + } + + mock_post_request.assert_called_once_with( + 'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxx', + data=mock.ANY, + headers={ + 'Content-Type': 'application/json', + 'Accept': 'application/json;charset=utf-8' + }, + proxies=None, + auth=None + ) + + actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) + assert expected_data == actual_data + + def test_dingtalk_proxy(): rule = { 'name': 'Test DingTalk Rule', @@ -255,7 +302,7 @@ def test_dingtalk_proxy(): def test_dingtalk_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test DingTalk Rule', 'type': 'any', @@ -290,8 +337,7 @@ def test_dingtalk_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting to dingtalk: ' in str(ea) def test_dingtalk_getinfo(): diff --git a/tests/alerters/discord_test.py b/tests/alerters/discord_test.py index 5f7c441d..3d6893c4 100644 --- a/tests/alerters/discord_test.py +++ b/tests/alerters/discord_test.py @@ -1,4 +1,5 @@ import json +import logging from unittest import mock import pytest @@ -10,7 +11,8 @@ from elastalert.util import EAException -def test_discord(): +def test_discord(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test Discord Rule', 'type': 'any', @@ -55,6 +57,7 @@ def test_discord(): actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Alert sent to the webhook http://xxxxxxx') == caplog.record_tuples[0] def test_discord_not_footer(): @@ -185,7 +188,7 @@ def test_discord_description_maxlength(): def test_discord_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test Discord Rule' + ('a' * 2069), 'type': 'any', @@ -205,8 +208,7 @@ def test_discord_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting to Discord: . Details: ' in str(ea) def test_discord_getinfo(): diff --git a/tests/alerters/gitter_test.py b/tests/alerters/gitter_test.py index 40cfb509..efb84a00 100644 --- a/tests/alerters/gitter_test.py +++ b/tests/alerters/gitter_test.py @@ -1,4 +1,5 @@ import json +import logging from unittest import mock import pytest @@ -14,7 +15,8 @@ ('error', 'error'), ('info', 'info') ]) -def test_gitter_msg_level(msg_level, except_msg_level): +def test_gitter_msg_level(msg_level, except_msg_level, caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test Gitter Rule', 'type': 'any', @@ -49,6 +51,7 @@ def test_gitter_msg_level(msg_level, except_msg_level): actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Alert sent to Gitter') == caplog.record_tuples[0] def test_gitter_proxy(): @@ -86,7 +89,7 @@ def test_gitter_proxy(): def test_gitter_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test Gitter Rule', 'type': 'any', @@ -105,8 +108,7 @@ def test_gitter_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting to Gitter: ' in str(ea) def test_gitter_getinfo(): diff --git a/tests/alerters/googlechat_test.py b/tests/alerters/googlechat_test.py index e41808a6..5e998ca2 100644 --- a/tests/alerters/googlechat_test.py +++ b/tests/alerters/googlechat_test.py @@ -1,4 +1,5 @@ import json +import logging from unittest import mock import pytest @@ -9,7 +10,8 @@ from elastalert.util import EAException -def test_google_chat_basic(): +def test_google_chat_basic(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test GoogleChat Rule', 'type': 'any', @@ -38,6 +40,7 @@ def test_google_chat_basic(): actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Alert sent to Google Chat!') == caplog.record_tuples[0] def test_google_chat_card(): @@ -106,7 +109,7 @@ def test_google_chat_card(): def test_google_chat_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test GoogleChat Rule', 'type': 'any', @@ -123,8 +126,7 @@ def test_google_chat_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting to google chat: ' in str(ea) def test_google_chat_getinfo(): @@ -173,3 +175,112 @@ def test_google_chat_required_error(googlechat_webhook_url, expected_data): assert expected_data == actual_data except Exception as ea: assert expected_data in str(ea) + + +def test_ggooglechat_header_title_none(): + rule = { + 'name': 'Test GoogleChat Rule', + 'type': 'any', + 'googlechat_webhook_url': 'http://xxxxxxx', + 'googlechat_format': 'card', + 'googlechat_header_subtitle': 'xxxx2', + 'googlechat_header_image': 'http://xxxx/image.png', + 'googlechat_footer_kibanalink': 'http://xxxxx/kibana', + 'alert': [] + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = GoogleChatAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'somefield': 'foobarbaz' + } + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data = { + 'cards': [{ + 'sections': [ + { + 'widgets': [{ + "textParagraph": { + 'text': 'Test GoogleChat Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n' + } + }] + }, + { + 'widgets': [{ + 'buttons': [{ + 'textButton': { + 'text': 'VISIT KIBANA', + 'onClick': { + 'openLink': { + 'url': rule['googlechat_footer_kibanalink'] + } + } + } + }] + }] + } + ]} + ] + } + + mock_post_request.assert_called_once_with( + rule['googlechat_webhook_url'], + data=mock.ANY, + headers={'content-type': 'application/json'} + ) + + actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) + assert expected_data == actual_data + + +def test_googlechat_footer_kibanalink_none(): + rule = { + 'name': 'Test GoogleChat Rule', + 'type': 'any', + 'googlechat_webhook_url': 'http://xxxxxxx', + 'googlechat_format': 'card', + 'googlechat_header_title': 'xxxx1', + 'googlechat_header_subtitle': 'xxxx2', + 'googlechat_header_image': 'http://xxxx/image.png', + 'alert': [] + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = GoogleChatAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'somefield': 'foobarbaz' + } + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data = { + 'cards': [{ + 'header': { + 'title': rule['googlechat_header_title'], + 'subtitle': rule['googlechat_header_subtitle'], + 'imageUrl': rule['googlechat_header_image'] + }, + 'sections': [ + { + 'widgets': [{ + "textParagraph": { + 'text': 'Test GoogleChat Rule\n\n@timestamp: 2021-01-01T00:00:00\nsomefield: foobarbaz\n' + } + }] + } + ]} + ] + } + + mock_post_request.assert_called_once_with( + rule['googlechat_webhook_url'], + data=mock.ANY, + headers={'content-type': 'application/json'} + ) + + actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) + assert expected_data == actual_data diff --git a/tests/alerters/httppost_test.py b/tests/alerters/httppost_test.py index 5ba4106d..a36050fe 100644 --- a/tests/alerters/httppost_test.py +++ b/tests/alerters/httppost_test.py @@ -1,4 +1,5 @@ import json +import logging from unittest import mock import pytest @@ -9,7 +10,8 @@ from elastalert.util import EAException -def test_http_alerter_with_payload(): +def test_http_alerter_with_payload(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test HTTP Post Alerter With Payload', 'type': 'any', @@ -40,6 +42,7 @@ def test_http_alerter_with_payload(): verify=True ) assert expected_data == json.loads(mock_post_request.call_args_list[0][1]['data']) + assert ('elastalert', logging.INFO, 'HTTP Post alert sent.') == caplog.record_tuples[0] def test_http_alerter_with_payload_all_values(): @@ -264,7 +267,7 @@ def test_http_alerter_post_ca_certs(ca_certs, ignore_ssl_errors, excpet_verify): def test_http_alerter_post_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test HTTP Post Alerter Without Payload', 'type': 'any', @@ -283,8 +286,7 @@ def test_http_alerter_post_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting HTTP Post alert: ' in str(ea) def test_http_getinfo(): diff --git a/tests/alerters/jira_test.py b/tests/alerters/jira_test.py index b38472de..636d5cd3 100644 --- a/tests/alerters/jira_test.py +++ b/tests/alerters/jira_test.py @@ -1,4 +1,5 @@ import datetime +import logging from unittest import mock import pytest @@ -25,7 +26,8 @@ def test_jira_formatted_match_string(ea): assert expected_alert_text_snippet in alert_text -def test_jira(): +def test_jira(caplog): + caplog.set_level(logging.INFO) description_txt = "Description stuff goes here like a runbook link." rule = { 'name': 'test alert', @@ -75,6 +77,10 @@ def test_jira(): # We don't care about additional calls to mock_jira, such as __str__ assert mock_jira.mock_calls[:6] == expected assert mock_jira.mock_calls[3][2]['description'].startswith(description_txt) + user, level, message = caplog.record_tuples[0] + assert 'elastalert' == user + assert logging.INFO == level + assert 'pened Jira ticket: ' in message # Search called if jira_bump_tickets rule['jira_bump_tickets'] = True diff --git a/tests/alerters/line_test.py b/tests/alerters/line_test.py index c01ce701..e30eb551 100644 --- a/tests/alerters/line_test.py +++ b/tests/alerters/line_test.py @@ -1,3 +1,5 @@ +import logging + from unittest import mock import pytest from requests import RequestException @@ -7,7 +9,8 @@ from elastalert.util import EAException -def test_line_notify(): +def test_line_notify(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test LineNotify Rule', 'type': 'any', @@ -39,10 +42,11 @@ def test_line_notify(): actual_data = mock_post_request.call_args_list[0][1]['data'] assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Alert sent to Line Notify') == caplog.record_tuples[0] def test_line_notify_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test LineNotify Rule', 'type': 'any', @@ -59,8 +63,8 @@ def test_line_notify_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + + assert 'Error posting to Line Notify: ' in str(ea) def test_line_getinfo(): diff --git a/tests/alerters/mattermost_test.py b/tests/alerters/mattermost_test.py index 3a32000b..41ad8de1 100644 --- a/tests/alerters/mattermost_test.py +++ b/tests/alerters/mattermost_test.py @@ -1,4 +1,5 @@ import json +import logging from unittest import mock import pytest @@ -9,7 +10,8 @@ from elastalert.util import EAException -def test_mattermost_proxy(): +def test_mattermost_proxy(caplog): + caplog.set_level(logging.INFO) rule = { 'name': 'Test Mattermost Rule', 'type': 'any', @@ -54,6 +56,7 @@ def test_mattermost_proxy(): actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data + assert ('elastalert', logging.INFO, 'Alert sent to Mattermost') == caplog.record_tuples[0] def test_mattermost_alert_text_only(): @@ -751,7 +754,7 @@ def test_mattermost_author_icon(): def test_mattermost_ea_exception(): - try: + with pytest.raises(EAException) as ea: rule = { 'name': 'Test Mattermost Rule', 'type': 'any', @@ -773,8 +776,7 @@ def test_mattermost_ea_exception(): mock_run = mock.MagicMock(side_effect=RequestException) with mock.patch('requests.post', mock_run), pytest.raises(RequestException): alert.alert([match]) - except EAException: - assert True + assert 'Error posting to Mattermost: ' in str(ea) def test_mattermost_get_aggregation_summary_text__maximum_width(): @@ -1093,3 +1095,50 @@ def test_mattermost_kibana_discover_color(): actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) assert expected_data == actual_data + + +def test_mattermost_username_override(): + rule = { + 'name': 'Test Mattermost Rule', + 'type': 'any', + 'alert_text_type': 'alert_text_only', + 'mattermost_webhook_url': 'http://xxxxx', + 'mattermost_msg_pretext': 'aaaaa', + 'mattermost_msg_color': 'danger', + 'mattermost_username_override': 'test user', + 'alert': [], + 'alert_subject': 'Test Mattermost' + } + rules_loader = FileRulesLoader({}) + rules_loader.load_modules(rule) + alert = MattermostAlerter(rule) + match = { + '@timestamp': '2021-01-01T00:00:00', + 'somefield': 'foobarbaz' + } + with mock.patch('requests.post') as mock_post_request: + alert.alert([match]) + + expected_data = { + 'attachments': [ + { + 'fallback': 'Test Mattermost: aaaaa', + 'color': 'danger', + 'title': 'Test Mattermost', + 'pretext': 'aaaaa', + 'fields': [], + 'text': 'Test Mattermost Rule\n\n' + } + ], 'username': 'test user' + } + + mock_post_request.assert_called_once_with( + rule['mattermost_webhook_url'], + data=mock.ANY, + headers={'content-type': 'application/json'}, + verify=True, + proxies=None + ) + + actual_data = json.loads(mock_post_request.call_args_list[0][1]['data']) + assert expected_data == actual_data diff --git a/tests/alerters/opsgenie_test.py b/tests/alerters/opsgenie_test.py index 0547d7e6..a9ceb64b 100644 --- a/tests/alerters/opsgenie_test.py +++ b/tests/alerters/opsgenie_test.py @@ -1,3 +1,5 @@ +import logging + from unittest import mock import pytest from requests import RequestException @@ -8,10 +10,16 @@ from tests.alerts_test import mock_rule -def test_opsgenie_basic(): - rule = {'name': 'testOGalert', 'opsgenie_key': 'ogkey', - 'opsgenie_account': 'genies', 'opsgenie_addr': 'https://api.opsgenie.com/v2/alerts', - 'opsgenie_recipients': ['lytics'], 'type': mock_rule()} +def test_opsgenie_basic(caplog): + caplog.set_level(logging.INFO) + rule = { + 'name': 'testOGalert', + 'opsgenie_key': 'ogkey', + 'opsgenie_account': 'genies', + 'opsgenie_addr': 'https://api.opsgenie.com/v2/alerts', + 'opsgenie_recipients': ['lytics'], + 'type': mock_rule() + } with mock.patch('requests.post') as mock_post: alert = OpsGenieAlerter(rule) @@ -27,14 +35,22 @@ def test_opsgenie_basic(): assert mcal[0][1]['json']['source'] == 'ElastAlert' assert mcal[0][1]['json']['responders'] == [{'username': 'lytics', 'type': 'user'}] assert mcal[0][1]['json']['source'] == 'ElastAlert' + user, level, message = caplog.record_tuples[0] + assert "Error response from https://api.opsgenie.com/v2/alerts \n API Response: