Adding support to overriding some of the configuration through environment variables.

This commit is contained in:
Mitsuo Takaki
2016-05-19 23:41:20 -07:00
parent 2c01d8eb30
commit a3a91edadc
2 changed files with 34 additions and 28 deletions

View File

@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
import logging
import time
import abc import abc
import cachet_url_monitor.status import cachet_url_monitor.status
import logging import os
import re import re
import requests import requests
import time
from yaml import load from yaml import load
# This is the mandatory fields that must be in the configuration file in this # This is the mandatory fields that must be in the configuration file in this
@@ -41,28 +43,32 @@ class Configuration(object):
""" """
def __init__(self, config_file): def __init__(self, config_file):
# TODO(mtakaki#1|2016-04-28): Accept overriding settings using environment
# variables so we have a more docker-friendly approach.
self.logger = logging.getLogger('cachet_url_monitor.configuration.Configuration') self.logger = logging.getLogger('cachet_url_monitor.configuration.Configuration')
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. # 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.headers = {'X-Cachet-Token': os.environ.get('CACHET_TOKEN') or self.data['cachet']['token']}
(self.data['endpoint']['method'], self.data['endpoint']['url']))
self.expectations = [Expectaction.create(expectation) for expectation self.endpoint_method = os.environ.get('ENDPOINT_METHOD') or self.data['endpoint']['method']
in self.data['endpoint']['expectation']] self.endpoint_url = os.environ.get('ENDPOINT_URL') or self.data['endpoint']['url']
self.endpoint_timeout = os.environ.get('ENDPOINT_TIMEOUT') or self.data['endpoint'].get('timeout')
self.api_url = os.environ.get('CACHET_API_URL') or self.data['cachet']['api_url']
self.component_id = os.environ.get('CACHET_COMPONENT_ID') or self.data['cachet']['component_id']
self.metric_id = os.environ.get('CACHET_METRIC_ID') or self.data['cachet'].get('metric_id')
self.status = self.get_current_status(self.api_url, self.component_id, self.headers)
self.logger.info('Monitoring URL: %s %s' % (self.endpoint_method, self.endpoint_url))
self.expectations = [Expectaction.create(expectation) for expectation in self.data['endpoint']['expectation']]
for expectation in self.expectations: for expectation in self.expectations:
self.logger.info('Registered expectation: %s' % (expectation,)) self.logger.info('Registered expectation: %s' % (expectation,))
def get_current_status(self, component_id): def get_current_status(self, endpoint_url, component_id, headers):
get_status_request = requests.get( get_status_request = requests.get('%s/components/%s' % (endpoint_url, component_id), headers=headers)
'%s/components/%d' % (self.data['cachet']['api_url'], self.data['cachet']['component_id']),
headers=self.headers)
if get_status_request.ok: if get_status_request.ok:
# The component exists. # The component exists.
@@ -112,9 +118,7 @@ class Configuration(object):
self.previous_status = self.status self.previous_status = self.status
try: try:
self.request = requests.request(self.data['endpoint']['method'], self.request = requests.request(self.endpoint_method, self.endpoint_url, timeout=self.endpoint_timeout)
self.data['endpoint']['url'],
timeout=self.data['endpoint']['timeout'])
self.current_timestamp = int(time.time()) self.current_timestamp = int(time.time())
except requests.ConnectionError: except requests.ConnectionError:
self.message = 'The URL is unreachable: %s %s' % ( self.message = 'The URL is unreachable: %s %s' % (
@@ -148,12 +152,9 @@ class Configuration(object):
"""Pushes the status of the component to the cachet server. It will update the component """Pushes the status of the component to the cachet server. It will update the component
status based on the previous call to evaluate(). status based on the previous call to evaluate().
""" """
params = {'id': self.data['cachet']['component_id'], 'status': params = {'id': self.component_id, 'status': self.status}
self.status} component_request = requests.put('%s/components/%d' % (self.api_url, self.component_id), params=params,
component_request = requests.put('%s/components/%d' % headers=self.headers)
(self.data['cachet']['api_url'],
self.data['cachet']['component_id']),
params=params, headers=self.headers)
if component_request.ok: if component_request.ok:
# Successful update # Successful update
self.logger.info('Component update: status [%d]' % (self.status,)) self.logger.info('Component update: status [%d]' % (self.status,))
@@ -167,9 +168,8 @@ class Configuration(object):
It only will send a request if the metric id was set in the configuration. It only will send a request if the metric id was set in the configuration.
""" """
if 'metric_id' in self.data['cachet'] and hasattr(self, 'request'): if 'metric_id' in self.data['cachet'] and hasattr(self, 'request'):
params = {'id': self.data['cachet']['metric_id'], 'value': params = {'id': self.metric_id, 'value': self.request.elapsed.total_seconds(),
self.request.elapsed.total_seconds(), 'timestamp': 'timestamp': self.current_timestamp}
self.current_timestamp}
metrics_request = requests.post('%s/metrics/%d/points' % metrics_request = requests.post('%s/metrics/%d/points' %
(self.data['cachet']['api_url'], (self.data['cachet']['api_url'],
self.data['cachet']['metric_id']), params=params, self.data['cachet']['metric_id']), params=params,

View File

@@ -9,6 +9,7 @@ from requests import ConnectionError, HTTPError, Timeout
sys.modules['requests'] = mock.Mock() sys.modules['requests'] = mock.Mock()
sys.modules['logging'] = mock.Mock() sys.modules['logging'] = mock.Mock()
from cachet_url_monitor.configuration import Configuration from cachet_url_monitor.configuration import Configuration
from test.test_support import EnvironmentVarGuard
class ConfigurationTest(unittest.TestCase): class ConfigurationTest(unittest.TestCase):
@@ -28,6 +29,9 @@ class ConfigurationTest(unittest.TestCase):
sys.modules['requests'].get = get sys.modules['requests'].get = get
self.env = EnvironmentVarGuard()
self.env.set('CACHET_TOKEN', 'token2')
self.configuration = Configuration('config.yml') self.configuration = Configuration('config.yml')
sys.modules['requests'].Timeout = Timeout sys.modules['requests'].Timeout = Timeout
sys.modules['requests'].ConnectionError = ConnectionError sys.modules['requests'].ConnectionError = ConnectionError
@@ -36,6 +40,8 @@ class ConfigurationTest(unittest.TestCase):
def test_init(self): def test_init(self):
assert len(self.configuration.data) == 3 assert len(self.configuration.data) == 3
assert len(self.configuration.expectations) == 3 assert len(self.configuration.expectations) == 3
assert self.configuration.headers == {'X-Cachet-Token': 'token2'}
assert self.configuration.api_url == 'https://demo.cachethq.io/api/v1'
def test_evaluate(self): def test_evaluate(self):
def total_seconds(): def total_seconds():
@@ -120,7 +126,7 @@ class ConfigurationTest(unittest.TestCase):
def put(url, params=None, headers=None): def put(url, params=None, headers=None):
assert url == 'https://demo.cachethq.io/api/v1/components/1' assert url == 'https://demo.cachethq.io/api/v1/components/1'
assert params == {'id': 1, 'status': 1} assert params == {'id': 1, 'status': 1}
assert headers == {'X-Cachet-Token': 'my_token'} assert headers == {'X-Cachet-Token': 'token2'}
response = mock.Mock() response = mock.Mock()
response.status_code = 200 response.status_code = 200
@@ -134,7 +140,7 @@ class ConfigurationTest(unittest.TestCase):
def put(url, params=None, headers=None): def put(url, params=None, headers=None):
assert url == 'https://demo.cachethq.io/api/v1/components/1' assert url == 'https://demo.cachethq.io/api/v1/components/1'
assert params == {'id': 1, 'status': 1} assert params == {'id': 1, 'status': 1}
assert headers == {'X-Cachet-Token': 'my_token'} assert headers == {'X-Cachet-Token': 'token2'}
response = mock.Mock() response = mock.Mock()
response.status_code = 300 response.status_code = 300