2018-04-15 00:27:37 +00:00
|
|
|
from datetime import datetime
|
|
|
|
from unittest.mock import patch
|
|
|
|
|
2018-04-10 00:07:32 +00:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
from minitor.main import InvalidMonitorException
|
|
|
|
from minitor.main import MinitorAlert
|
|
|
|
from minitor.main import Monitor
|
|
|
|
from minitor.main import validate_monitor_settings
|
|
|
|
|
|
|
|
|
|
|
|
class TestMonitor(object):
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def monitor(self):
|
|
|
|
return Monitor({
|
2018-04-10 18:06:42 +00:00
|
|
|
'name': 'Sample Monitor',
|
2018-04-10 00:07:32 +00:00
|
|
|
'command': ['echo', 'foo'],
|
2018-04-15 00:27:37 +00:00
|
|
|
'alert_down': ['log'],
|
|
|
|
'alert_up': ['log'],
|
|
|
|
'check_interval': 1,
|
|
|
|
'alert_after': 1,
|
|
|
|
'alert_every': 1,
|
2018-04-10 00:07:32 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('settings', [
|
|
|
|
{'alert_after': 0},
|
|
|
|
{'alert_every': 0},
|
|
|
|
{'check_interval': 0},
|
|
|
|
{'alert_after': 'invalid'},
|
|
|
|
{'alert_every': 'invalid'},
|
|
|
|
{'check_interval': 'invalid'},
|
|
|
|
])
|
|
|
|
def test_monitor_invalid_configuration(self, settings):
|
|
|
|
with pytest.raises(InvalidMonitorException):
|
|
|
|
validate_monitor_settings(settings)
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
'alert_after',
|
|
|
|
[1, 20],
|
|
|
|
ids=lambda arg: 'alert_after({})'.format(arg),
|
|
|
|
)
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
'alert_every',
|
|
|
|
[-1, 1, 2, 1440],
|
|
|
|
ids=lambda arg: 'alert_every({})'.format(arg),
|
|
|
|
)
|
|
|
|
def test_monitor_alert_after(self, monitor, alert_after, alert_every):
|
|
|
|
monitor.alert_after = alert_after
|
|
|
|
monitor.alert_every = alert_every
|
|
|
|
|
|
|
|
# fail a bunch of times before the final failure
|
|
|
|
for _ in range(alert_after - 1):
|
|
|
|
monitor.failure()
|
|
|
|
|
|
|
|
# this time should raise an alert
|
|
|
|
with pytest.raises(MinitorAlert):
|
|
|
|
monitor.failure()
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
'alert_after',
|
|
|
|
[1, 20],
|
|
|
|
ids=lambda arg: 'alert_after({})'.format(arg),
|
|
|
|
)
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
'alert_every',
|
|
|
|
[1, 2, 1440],
|
|
|
|
ids=lambda arg: 'alert_every({})'.format(arg),
|
|
|
|
)
|
|
|
|
def test_monitor_alert_every(self, monitor, alert_after, alert_every):
|
|
|
|
monitor.alert_after = alert_after
|
|
|
|
monitor.alert_every = alert_every
|
|
|
|
|
|
|
|
# fail a bunch of times before the final failure
|
|
|
|
for _ in range(alert_after - 1):
|
|
|
|
monitor.failure()
|
|
|
|
|
|
|
|
# this time should raise an alert
|
|
|
|
with pytest.raises(MinitorAlert):
|
|
|
|
monitor.failure()
|
|
|
|
|
|
|
|
# fail a bunch more times until the next alert
|
|
|
|
for _ in range(alert_every - 1):
|
|
|
|
monitor.failure()
|
|
|
|
|
|
|
|
# this failure should alert now
|
|
|
|
with pytest.raises(MinitorAlert):
|
|
|
|
monitor.failure()
|
|
|
|
|
|
|
|
def test_monitor_alert_every_exponential(self, monitor):
|
|
|
|
monitor.alert_after = 1
|
|
|
|
monitor.alert_every = -1
|
|
|
|
|
|
|
|
failure_count = 16
|
|
|
|
expect_failures_on = {1, 2, 4, 8, 16}
|
|
|
|
|
|
|
|
for i in range(failure_count):
|
|
|
|
if i + 1 in expect_failures_on:
|
|
|
|
with pytest.raises(MinitorAlert):
|
|
|
|
monitor.failure()
|
|
|
|
else:
|
|
|
|
monitor.failure()
|
2018-04-15 00:27:37 +00:00
|
|
|
|
|
|
|
@pytest.mark.parametrize('last_check', [None, datetime(2018, 4, 10)])
|
|
|
|
def test_monitor_should_check(self, monitor, last_check):
|
|
|
|
monitor.last_check = last_check
|
|
|
|
assert monitor.should_check()
|
|
|
|
|
|
|
|
def test_monitor_check_fail(self, monitor):
|
2018-04-19 00:05:33 +00:00
|
|
|
assert monitor.last_output is None
|
2018-04-15 00:27:37 +00:00
|
|
|
with patch.object(monitor, 'failure') as mock_failure:
|
|
|
|
monitor.command = ['ls', '--not-real']
|
|
|
|
assert not monitor.check()
|
|
|
|
mock_failure.assert_called_once()
|
2018-04-19 00:05:33 +00:00
|
|
|
assert monitor.last_output is not None
|
2018-04-15 00:27:37 +00:00
|
|
|
|
|
|
|
def test_monitor_check_success(self, monitor):
|
2018-04-19 00:05:33 +00:00
|
|
|
assert monitor.last_output is None
|
2018-04-15 00:27:37 +00:00
|
|
|
with patch.object(monitor, 'success') as mock_success:
|
|
|
|
assert monitor.check()
|
|
|
|
mock_success.assert_called_once()
|
2018-04-19 00:05:33 +00:00
|
|
|
assert monitor.last_output is not None
|
2018-04-15 00:27:37 +00:00
|
|
|
|
|
|
|
@pytest.mark.parametrize('failure_count', [0, 1])
|
|
|
|
def test_monitor_success(self, monitor, failure_count):
|
|
|
|
monitor.alert_count = 0
|
|
|
|
monitor.total_failure_count = failure_count
|
|
|
|
assert monitor.last_success is None
|
|
|
|
|
|
|
|
monitor.success()
|
|
|
|
|
|
|
|
assert monitor.alert_count == 0
|
|
|
|
assert monitor.last_success is not None
|
|
|
|
assert monitor.total_failure_count == 0
|
|
|
|
|
|
|
|
def test_monitor_success_back_up(self, monitor):
|
|
|
|
monitor.total_failure_count = 1
|
|
|
|
monitor.alert_count = 1
|
|
|
|
|
|
|
|
with pytest.raises(MinitorAlert):
|
|
|
|
monitor.success()
|
|
|
|
|
|
|
|
assert monitor.alert_count == 0
|
|
|
|
assert monitor.last_success is not None
|
|
|
|
assert monitor.total_failure_count == 0
|