Verifying component status when we initialize to set the initial state. Tests are failing, but checking it in nonetheless.

This commit is contained in:
Mitsuo Takaki
2016-05-18 09:34:58 -07:00
parent 0f53ff8678
commit ca358eab2b
5 changed files with 79 additions and 18 deletions

View File

@@ -25,6 +25,16 @@ class ConfigurationValidationError(Exception):
return repr(self.value) return repr(self.value)
class ComponentNonexistentError(Exception):
"""Exception raised when the component does not exist."""
def __init__(self, component_id):
self.component_id = component_id
def __str__(self):
return repr('Component with id [%d] does not exist.' % (self.component_id,))
class Configuration(object): class Configuration(object):
"""Represents a configuration file, but it also includes the functionality """Represents a configuration file, but it also includes the functionality
of assessing the API and pushing the results to cachet. of assessing the API and pushing the results to cachet.
@@ -37,7 +47,10 @@ class Configuration(object):
self.config_file = config_file self.config_file = config_file
self.data = load(file(self.config_file, 'r')) self.data = load(file(self.config_file, 'r'))
# We need to validate the configuration is correct and then validate the component actually exists.
self.validate() self.validate()
self.headers = {'X-Cachet-Token': self.data['cachet']['token']}
self.status = self.get_current_status(self.data['cachet']['component_id'])
self.logger.info('Monitoring URL: %s %s' % self.logger.info('Monitoring URL: %s %s' %
(self.data['endpoint']['method'], self.data['endpoint']['url'])) (self.data['endpoint']['method'], self.data['endpoint']['url']))
@@ -46,7 +59,16 @@ class Configuration(object):
for expectation in self.expectations: for expectation in self.expectations:
self.logger.info('Registered expectation: %s' % (expectation,)) self.logger.info('Registered expectation: %s' % (expectation,))
self.headers = {'X-Cachet-Token': self.data['cachet']['token']} def get_current_status(self, component_id):
get_status_request = requests.get(
'%s/components/%d' % (self.data['cachet']['api_url'], self.data['cachet']['component_id']),
headers=self.headers)
if get_status_request.ok:
# The component exists.
return get_status_request.json()['data']['status']
else:
raise ComponentNonexistentError(component_id)
def is_create_incident(self): def is_create_incident(self):
"""Will verify if the configuration is set to create incidents or not. """Will verify if the configuration is set to create incidents or not.
@@ -172,7 +194,8 @@ class Configuration(object):
if incident_request.ok: if incident_request.ok:
# Successful metrics upload # Successful metrics upload
self.logger.info( self.logger.info(
'Incident updated: component status [%d], message: "%s"' % (self.status, self.message)) 'Incident updated, API healthy again: component status [%d], message: "%s"' % (
self.status, self.message))
del self.incident_id del self.incident_id
else: else:
self.logger.warning( self.logger.warning(
@@ -253,10 +276,10 @@ class Latency(Expectaction):
return cachet_url_monitor.status.COMPONENT_STATUS_PERFORMANCE_ISSUES return cachet_url_monitor.status.COMPONENT_STATUS_PERFORMANCE_ISSUES
def get_message(self, response): def get_message(self, response):
return 'Latency above threshold: %.4f' % (response.elapsed.total_seconds(),) return 'Latency above threshold: %.4f seconds' % (response.elapsed.total_seconds(),)
def __str__(self): def __str__(self):
return repr('Latency threshold: %.4f' % (self.threshold,)) return repr('Latency threshold: %.4f seconds' % (self.threshold,))
class Regex(Expectaction): class Regex(Expectaction):

View File

@@ -10,6 +10,7 @@ class Agent(object):
"""Monitor agent that will be constantly verifying if the URL is healthy """Monitor agent that will be constantly verifying if the URL is healthy
and updating the component. and updating the component.
""" """
def __init__(self, configuration): def __init__(self, configuration):
self.configuration = configuration self.configuration = configuration
@@ -18,7 +19,6 @@ class Agent(object):
cachet server. cachet server.
""" """
self.configuration.evaluate() self.configuration.evaluate()
self.configuration.push_status()
self.configuration.push_metrics() self.configuration.push_metrics()
def start(self): def start(self):
@@ -26,11 +26,34 @@ class Agent(object):
schedule.every(self.configuration.data['frequency']).seconds.do(self.execute) schedule.every(self.configuration.data['frequency']).seconds.do(self.execute)
class UpdateStatusAgent(Agent):
def __init__(self, configuration):
super(UpdateStatusAgent, self).__init__(configuration)
def execute(self):
super(UpdateStatusAgent, self).execute()
self.configuration.push_status()
class CreateIncidentAgent(Agent):
def __init__(self, configuration):
super(CreateIncidentAgent, self).__init__(configuration)
def execute(self):
super(CreateIncidentAgent, self).execute()
self.configuration.push_incident()
class Scheduler(object): class Scheduler(object):
def __init__(self, config_file): def __init__(self, config_file):
self.logger = logging.getLogger('cachet_url_monitor.scheduler.Scheduler') self.logger = logging.getLogger('cachet_url_monitor.scheduler.Scheduler')
self.configuration = Configuration(config_file) self.configuration = Configuration(config_file)
self.agent = Agent(self.configuration)
if self.configuration.is_create_incident():
self.agent = CreateIncidentAgent(self.configuration)
else:
self.agent = UpdateStatusAgent(self.configuration)
self.stop = False self.stop = False
def start(self): def start(self):

View File

@@ -1,7 +1,7 @@
endpoint: endpoint:
url: http://localhost:8080/swagger url: http://localhost:8080/swagger
method: GET method: GET
timeout: 0.01 timeout: 0.1
expectation: expectation:
- type: HTTP_STATUS - type: HTTP_STATUS
status: 200 status: 200

View File

@@ -42,7 +42,7 @@ class LatencyTest(unittest.TestCase):
elapsed.total_seconds = total_seconds elapsed.total_seconds = total_seconds
assert self.expectation.get_message(request) == ('Latency above ' assert self.expectation.get_message(request) == ('Latency above '
'threshold: 0.1000') 'threshold: 0.1000 seconds')
class HttpStatusTest(unittest.TestCase): class HttpStatusTest(unittest.TestCase):

View File

@@ -1,10 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
import mock
import unittest
import sys import sys
import unittest
import mock
sys.modules['schedule'] = mock.Mock() sys.modules['schedule'] = mock.Mock()
sys.modules['cachet_url_monitor.configuration.Configuration'] = mock.Mock() # sys.modules['cachet_url_monitor.configuration.Configuration'] = mock.Mock()
from cachet_url_monitor.scheduler import Agent,Scheduler sys.modules['requests'] = mock.Mock()
from cachet_url_monitor.scheduler import Agent, Scheduler
class AgentTest(unittest.TestCase): class AgentTest(unittest.TestCase):
@@ -21,7 +24,7 @@ class AgentTest(unittest.TestCase):
self.agent.execute() self.agent.execute()
evaluate.assert_called_once() evaluate.assert_called_once()
push_status.assert_called_once() push_status.assert_not_called()
def test_start(self): def test_start(self):
every = sys.modules['schedule'].every every = sys.modules['schedule'].every
@@ -33,16 +36,28 @@ class AgentTest(unittest.TestCase):
class SchedulerTest(unittest.TestCase): class SchedulerTest(unittest.TestCase):
@mock.patch('cachet_url_monitor.configuration.Configuration.__init__', mock.Mock(return_value=None))
@mock.patch('cachet_url_monitor.configuration.Configuration.is_create_incident', mock.Mock(return_value=False))
def setUp(self): def setUp(self):
self.mock_configuration = sys.modules[('cachet_url_monitor.configuration' def get(url, headers):
'.Configuration')] get_return = mock.Mock()
get_return.ok = True
get_return.json = mock.Mock()
get_return.json.return_value = {'data': {'status': 1}}
return get_return
sys.modules['requests'].get = get
self.scheduler = Scheduler('config.yml') self.scheduler = Scheduler('config.yml')
def test_init(self): def test_init(self):
assert self.scheduler.stop == False assert self.scheduler.stop == False
def test_start(self): @mock.patch('cachet_url_monitor.configuration.Configuration', create=True)
#TODO(mtakaki|2016-05-01): We need a better way of testing this method. def test_start(self, mock_configuration):
# TODO(mtakaki|2016-05-01): We need a better way of testing this method.
# Leaving it as a placeholder. # Leaving it as a placeholder.
mock_configuration.data = {'frequency': 30}
self.scheduler.stop = True self.scheduler.stop = True
self.scheduler.start() self.scheduler.start()