Example #1
0
def test_jira_getinfo():
    description_txt = "Description stuff goes here like a runbook link."
    rule = {
        'name': 'test alert',
        'jira_account_file': 'jirafile',
        'type': mock_rule(),
        'jira_project': 'testproject',
        'jira_priority': 0,
        'jira_issuetype': 'testtype',
        'jira_server': 'jiraserver',
        'jira_label': 'testlabel',
        'jira_component': 'testcomponent',
        'jira_description': description_txt,
        'jira_watchers': ['testwatcher1', 'testwatcher2'],
        'timestamp_field': '@timestamp',
        'alert_subject': 'Issue {0} occurred at {1}',
        'alert_subject_args': ['test_term', '@timestamp'],
        'rule_file': '/tmp/foo.yaml'
    }

    mock_priority = mock.Mock(id='5')

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []
        alert = JiraAlerter(rule)

    expected_data = {'type': 'jira'}
    actual_data = alert.get_info()
    assert expected_data == actual_data
Example #2
0
def test_jira_auth_token(caplog):
    description_txt = "Test authentication via apitoken"
    rule = {
        'name': 'test alert',
        'jira_account_file': 'jirafile',
        'type': mock_rule(),
        'jira_project': 'testproject',
        'jira_priority': 0,
        'jira_issuetype': 'testtype',
        'jira_server': 'jiraserver',
        'jira_description': description_txt,
        'jira_assignee': 'testuser',
        'timestamp_field': '@timestamp',
        'alert_subject': 'Issue {0} occurred at {1}',
        'alert_subject_args': ['test_term', '@timestamp'],
        'rule_file': '/tmp/foo.yaml'
    }
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {'apikey': 'theapikey'}
        alert = JiraAlerter(rule)
        alert.set_priority
    expected = [
        mock.call('jiraserver', token_auth=('theapikey')),
    ]
    # we only want to test authentication via apikey, the rest we don't care of
    assert mock_jira.mock_calls[:1] == expected
Example #3
0
def test_jira_set_priority(caplog):
    description_txt = "Description stuff goes here like a runbook link."
    rule = {
        'name': 'test alert',
        'jira_account_file': 'jirafile',
        'type': mock_rule(),
        'jira_project': 'testproject',
        'jira_priority': 0,
        'jira_issuetype': 'testtype',
        'jira_server': 'jiraserver',
        'jira_description': description_txt,
        'jira_assignee': 'testuser',
        'timestamp_field': '@timestamp',
        'alert_subject': 'Issue {0} occurred at {1}',
        'alert_subject_args': ['test_term', '@timestamp'],
        'rule_file': '/tmp/foo.yaml'
    }
    with mock.patch('elastalert.alerters.jira.JIRA'), \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        alert = JiraAlerter(rule)
        alert.set_priority

    assert ('elastalert', logging.ERROR,
            'Priority 0 not found. Valid priorities are []'
            ) == caplog.record_tuples[0]
    assert ('elastalert', logging.ERROR,
            'Priority 0 not found. Valid priorities are []'
            ) == caplog.record_tuples[1]
Example #4
0
def test_jira(caplog):
    caplog.set_level(logging.INFO)
    description_txt = "Description stuff goes here like a runbook link."
    rule = {
        'name': 'test alert',
        'jira_account_file': 'jirafile',
        'type': mock_rule(),
        'jira_project': 'testproject',
        'jira_priority': 0,
        'jira_issuetype': 'testtype',
        'jira_server': 'jiraserver',
        'jira_label': 'testlabel',
        'jira_component': 'testcomponent',
        'jira_description': description_txt,
        'jira_watchers': ['testwatcher1', 'testwatcher2'],
        'timestamp_field': '@timestamp',
        'alert_subject': 'Issue {0} occurred at {1}',
        'alert_subject_args': ['test_term', '@timestamp'],
        'rule_file': '/tmp/foo.yaml'
    }

    mock_priority = mock.Mock(id='5')

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []
        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    expected = [
        mock.call('jiraserver', basic_auth=('jirauser', 'jirapassword')),
        mock.call().priorities(),
        mock.call().fields(),
        mock.call().create_issue(
            issuetype={'name': 'testtype'},
            priority={'id': '5'},
            project={'key': 'testproject'},
            labels=['testlabel'],
            components=[{
                'name': 'testcomponent'
            }],
            description=mock.ANY,
            summary='Issue test_value occurred at 2014-10-31T00:00:00',
        ),
        mock.call().add_watcher(mock.ANY, 'testwatcher1'),
        mock.call().add_watcher(mock.ANY, 'testwatcher2'),
    ]

    # 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
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = []
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    expected.insert(3, mock.call().search_issues(mock.ANY))
    assert mock_jira.mock_calls == expected

    # Remove a field if jira_ignore_in_title set
    rule['jira_ignore_in_title'] = 'test_term'
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = []
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    assert 'test_value' not in mock_jira.mock_calls[3][1][0]

    # Issue is still created if search_issues throws an exception
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.side_effect = JIRAError
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    assert mock_jira.mock_calls == expected
    user, level, message = caplog.record_tuples[3]
    assert 'elastalert' in user
    assert logging.ERROR == level
    assert 'Error while searching for Jira ticket using jql' in message

    # Only bump after 3d of inactivity
    rule['jira_bump_after_inactivity'] = 3
    mock_issue = mock.Mock()

    # Check ticket is bumped if it is updated 4 days ago
    mock_issue.fields.updated = str(ts_now() - datetime.timedelta(days=4))
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = [mock_issue]
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])
        # Check add_comment is called
        assert len(mock_jira.mock_calls) == 5
        assert '().add_comment' == mock_jira.mock_calls[4][0]

    # Check ticket is bumped is not bumped if ticket is updated right now
    mock_issue.fields.updated = str(ts_now())
    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value = mock.Mock()
        mock_jira.return_value.search_issues.return_value = [mock_issue]
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = []

        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])
        # Only 4 calls for mock_jira since add_comment is not called
        assert len(mock_jira.mock_calls) == 4

        # Test match resolved values
        rule = {
            'name': 'test alert',
            'jira_account_file': 'jirafile',
            'type': mock_rule(),
            'owner': 'the_owner',
            'jira_project': 'testproject',
            'jira_issuetype': 'testtype',
            'jira_server': 'jiraserver',
            'jira_label': 'testlabel',
            'jira_component': 'testcomponent',
            'jira_description': "DESC",
            'jira_watchers': ['testwatcher1', 'testwatcher2'],
            'timestamp_field': '@timestamp',
            'jira_affected_user': "******",
            'rule_file': '/tmp/foo.yaml'
        }
        mock_issue = mock.Mock()
        mock_issue.fields.updated = str(ts_now() - datetime.timedelta(days=4))
        mock_fields = [{
            'name': 'affected user',
            'id': 'affected_user_id',
            'schema': {
                'type': 'string'
            }
        }]
        with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
                mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
            mock_open.return_value = {
                'user': '******',
                'password': '******'
            }
            mock_jira.return_value = mock.Mock()
            mock_jira.return_value.search_issues.return_value = [mock_issue]
            mock_jira.return_value.fields.return_value = mock_fields
            mock_jira.return_value.priorities.return_value = [mock_priority]
            alert = JiraAlerter(rule)
            alert.alert([{
                'gmail.the_user': '******',
                '@timestamp': '2014-10-31T00:00:00'
            }])
            assert mock_jira.mock_calls[4][2]['affected_user_id'] == "jdoe"
Example #5
0
def test_jira_arbitrary_field_support():
    description_txt = "Description stuff goes here like a runbook link."
    rule = {
        'name':
        'test alert',
        'jira_account_file':
        'jirafile',
        'type':
        mock_rule(),
        'owner':
        'the_owner',
        'jira_project':
        'testproject',
        'jira_issuetype':
        'testtype',
        'jira_server':
        'jiraserver',
        'jira_label':
        'testlabel',
        'jira_component':
        'testcomponent',
        'jira_description':
        description_txt,
        'jira_watchers': ['testwatcher1', 'testwatcher2'],
        'jira_arbitrary_reference_string_field':
        '$owner$',
        'jira_arbitrary_string_field':
        'arbitrary_string_value',
        'jira_arbitrary_string_array_field':
        ['arbitrary_string_value1', 'arbitrary_string_value2'],
        'jira_arbitrary_string_array_field_provided_as_single_value':
        'arbitrary_string_value_in_array_field',
        'jira_arbitrary_number_field':
        1,
        'jira_arbitrary_number_array_field': [2, 3],
        'jira_arbitrary_number_array_field_provided_as_single_value':
        1,
        'jira_arbitrary_complex_field':
        'arbitrary_complex_value',
        'jira_arbitrary_complex_array_field':
        ['arbitrary_complex_value1', 'arbitrary_complex_value2'],
        'jira_arbitrary_complex_array_field_provided_as_single_value':
        'arbitrary_complex_value_in_array_field',
        'timestamp_field':
        '@timestamp',
        'alert_subject':
        'Issue {0} occurred at {1}',
        'alert_subject_args': ['test_term', '@timestamp'],
        'rule_file':
        '/tmp/foo.yaml'
    }

    mock_priority = mock.MagicMock(id='5')

    mock_fields = [
        {
            'name': 'arbitrary reference string field',
            'id': 'arbitrary_reference_string_field',
            'schema': {
                'type': 'string'
            }
        },
        {
            'name': 'arbitrary string field',
            'id': 'arbitrary_string_field',
            'schema': {
                'type': 'string'
            }
        },
        {
            'name': 'arbitrary string array field',
            'id': 'arbitrary_string_array_field',
            'schema': {
                'type': 'array',
                'items': 'string'
            }
        },
        {
            'name': 'arbitrary string array field provided as single value',
            'id': 'arbitrary_string_array_field_provided_as_single_value',
            'schema': {
                'type': 'array',
                'items': 'string'
            }
        },
        {
            'name': 'arbitrary number field',
            'id': 'arbitrary_number_field',
            'schema': {
                'type': 'number'
            }
        },
        {
            'name': 'arbitrary number array field',
            'id': 'arbitrary_number_array_field',
            'schema': {
                'type': 'array',
                'items': 'number'
            }
        },
        {
            'name': 'arbitrary number array field provided as single value',
            'id': 'arbitrary_number_array_field_provided_as_single_value',
            'schema': {
                'type': 'array',
                'items': 'number'
            }
        },
        {
            'name': 'arbitrary complex field',
            'id': 'arbitrary_complex_field',
            'schema': {
                'type': 'ArbitraryType'
            }
        },
        {
            'name': 'arbitrary complex array field',
            'id': 'arbitrary_complex_array_field',
            'schema': {
                'type': 'array',
                'items': 'ArbitraryType'
            }
        },
        {
            'name': 'arbitrary complex array field provided as single value',
            'id': 'arbitrary_complex_array_field_provided_as_single_value',
            'schema': {
                'type': 'array',
                'items': 'ArbitraryType'
            }
        },
    ]

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = mock_fields
        alert = JiraAlerter(rule)
        alert.alert([{
            'test_term': 'test_value',
            '@timestamp': '2014-10-31T00:00:00'
        }])

    expected = [
        mock.call('jiraserver', basic_auth=('jirauser', 'jirapassword')),
        mock.call().priorities(),
        mock.call().fields(),
        mock.call().create_issue(
            issuetype={'name': 'testtype'},
            project={'key': 'testproject'},
            labels=['testlabel'],
            components=[{
                'name': 'testcomponent'
            }],
            description=mock.ANY,
            summary='Issue test_value occurred at 2014-10-31T00:00:00',
            arbitrary_reference_string_field='the_owner',
            arbitrary_string_field='arbitrary_string_value',
            arbitrary_string_array_field=[
                'arbitrary_string_value1', 'arbitrary_string_value2'
            ],
            arbitrary_string_array_field_provided_as_single_value=[
                'arbitrary_string_value_in_array_field'
            ],
            arbitrary_number_field=1,
            arbitrary_number_array_field=[2, 3],
            arbitrary_number_array_field_provided_as_single_value=[1],
            arbitrary_complex_field={'name': 'arbitrary_complex_value'},
            arbitrary_complex_array_field=[{
                'name': 'arbitrary_complex_value1'
            }, {
                'name': 'arbitrary_complex_value2'
            }],
            arbitrary_complex_array_field_provided_as_single_value=[{
                'name':
                'arbitrary_complex_value_in_array_field'
            }],
        ),
        mock.call().add_watcher(mock.ANY, 'testwatcher1'),
        mock.call().add_watcher(mock.ANY, 'testwatcher2'),
    ]

    # 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)

    # Reference an arbitrary string field that is not defined on the Jira server
    rule['jira_nonexistent_field'] = 'nonexistent field value'

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = mock_fields

        with pytest.raises(Exception) as exception:
            alert = JiraAlerter(rule)
            alert.alert([{
                'test_term': 'test_value',
                '@timestamp': '2014-10-31T00:00:00'
            }])
        assert "Could not find a definition for the jira field 'nonexistent field'" in str(
            exception)

    del rule['jira_nonexistent_field']

    # Reference a watcher that does not exist
    rule['jira_watchers'] = 'invalid_watcher'

    with mock.patch('elastalert.alerters.jira.JIRA') as mock_jira, \
            mock.patch('elastalert.alerters.jira.read_yaml') as mock_open:
        mock_open.return_value = {
            'user': '******',
            'password': '******'
        }
        mock_jira.return_value.priorities.return_value = [mock_priority]
        mock_jira.return_value.fields.return_value = mock_fields

        # Cause add_watcher to raise, which most likely means that the user did not exist
        mock_jira.return_value.add_watcher.side_effect = Exception()

        with pytest.raises(Exception) as exception:
            alert = JiraAlerter(rule)
            alert.alert([{
                'test_term': 'test_value',
                '@timestamp': '2014-10-31T00:00:00'
            }])
        assert "Exception encountered when trying to add 'invalid_watcher' as a watcher. Does the user exist?" in str(
            exception)