Merge pull request #21494 from thatch45/arthurlogilab-uptime

Merge #21478
This commit is contained in:
Thomas S Hatch 2015-03-10 11:18:59 -06:00
commit 2b1eab60d1
3 changed files with 274 additions and 0 deletions

116
salt/modules/uptime.py Normal file
View File

@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
'''
Wrapper around uptime API
=========================
'''
import requests
import logging
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__)
def create(name, **params):
'''Create a check on a given URL.
Additional parameters can be used and are passed to API (for
example interval, maxTime, etc). See the documentation
https://github.com/fzaninotto/uptime for a full list of the
parameters.
CLI Example:
.. code-block:: bash
salt '*' uptime.create http://example.org
'''
if check_exists(name):
msg = 'Trying to create check that already exists : {0}'.format(name)
log.error(msg)
raise CommandExecutionError(msg)
application_url = _get_application_url()
log.debug('[uptime] trying PUT request')
params.update(url=name)
req = requests.put('{0}/api/checks'.format(application_url), data=params)
if not req.ok:
raise CommandExecutionError(
'request to uptime failed : {0}'.format(req.reason)
)
log.debug('[uptime] PUT request successfull')
return req.json()['_id']
def delete(name):
'''
Delete a check on a given URL
CLI Example:
.. code-block:: bash
salt '*' uptime.delete http://example.org
'''
if not check_exists(name):
msg = "Trying to delete check that doesn't exists : {0}".format(name)
log.error(msg)
raise CommandExecutionError(msg)
application_url = _get_application_url()
log.debug('[uptime] trying DELETE request')
jcontent = requests.get('{0}/api/checks'.format(application_url)).json()
url_id = [x['_id'] for x in jcontent if x['url'] == name][0]
req = requests.delete('{0}/api/checks/{1}'.format(application_url, url_id))
if not req.ok:
raise CommandExecutionError(
'request to uptime failed : {0}'.format(req.reason)
)
log.debug('[uptime] DELETE request successfull')
return True
def _get_application_url():
'''
Helper function to get application url from pillar
'''
application_url = __salt__['pillar.get']('uptime:application_url')
if application_url is None:
log.error('Could not load {0} pillar'.format('uptime:application_url'))
msg = '{0} pillar is required for authentication'
raise CommandExecutionError(
msg.format('uptime:application_url')
)
return application_url
def checks_list():
'''
List URL checked by uptime
CLI Example:
.. code-block:: bash
salt '*' uptime.checks_list
'''
application_url = _get_application_url()
log.debug('[uptime] get checks')
jcontent = requests.get('{0}/api/checks'.format(application_url)).json()
return [x['url'] for x in jcontent]
def check_exists(name):
'''
Check if a given URL is in being monitored by uptime
CLI Example:
.. code-block:: bash
salt '*' uptime.check_exists http://example.org
'''
if name in checks_list():
log.debug('[uptime] found {0} in checks'.format(name))
return True
return False

65
salt/states/uptime.py Normal file
View File

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
'''Monitor Web Server with Uptime
==============================
`Uptime <https://github.com/fzaninotto/uptime>`_ is an open source
remote monitoring application using Node.js, MongoDB, and Twitter
Bootstrap.
.. warning::
This state module is beta. It might be changed later to include
more or less automation.
.. note::
This state module requires a pillar to specify the location of
your uptime install
.. code-block:: yaml
uptime:
url: "http://uptime-url.example.org"
Example:
.. code-block:: yaml
url:
uptime.monitored
url/sitemap.xml:
uptime.monitored:
- polling: 600 # every hour
'''
def monitored(name, **params):
'''
Makes sure an URL is monitored by uptime. Checks if URL is already
monitored, and if not, adds it.
'''
ret = {'name': name, 'changes': {}, 'result': None, 'comment': ''}
if __salt__['uptime.check_exists'](name=name):
ret['result'] = True
ret['comment'] = 'URL {0} is already monitored'.format(name)
ret['changes'] = {}
return ret
if not __opts__['test']:
url_monitored = __salt__['uptime.create'](name, **params)
if url_monitored:
ret['result'] = True
msg = 'Successfully added the URL {0} to uptime'
ret['comment'] = msg.format(name)
ret['changes'] = {'url_monitored': url_monitored}
else:
ret['result'] = False
ret['comment'] = 'Failed to add {0} to uptime'.format(name)
ret['changes'] = {}
else:
msg = 'URL {0} is going to be added to uptime'
ret.update(result=None,
comment=msg.format(name))
return ret

View File

@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
# Import python libs
from __future__ import absolute_import, print_function
# Import Salt Testing libs
from salttesting import skipIf, TestCase
from salttesting.helpers import ensure_in_syspath
from salttesting.mock import NO_MOCK, NO_MOCK_REASON, Mock, patch
ensure_in_syspath('../../')
ensure_in_syspath('../../../')
# Import salt libs
from salt.exceptions import CommandExecutionError
from salt.modules import uptime
uptime.__grains__ = None # in order to stub it w/patch below
uptime.__salt__ = None # in order to stub it w/patch below
if NO_MOCK is False:
SALT_STUB = {
'pillar.get': Mock(return_value='http://localhost:5000'),
'requests.put': Mock(),
}
else:
SALT_STUB = {}
class RequestMock(Mock):
''' Request Mock'''
def get(self, *args, **kwargs):
return RequestResponseMock()
def put(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
return RequestPutResponseMock()
def delete(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
return RequestResponseMock()
class RequestResponseMock(Mock):
def json(self):
return [{'url': 'http://example.org',
'_id': 1234}, ]
class RequestPutResponseMock(Mock):
ok = True
def json(self):
return {'_id': 4321}
REQUEST_MOCK = RequestMock()
@skipIf(NO_MOCK, NO_MOCK_REASON)
@patch.multiple(uptime,
requests=REQUEST_MOCK,
__salt__=SALT_STUB)
class UptimeTestCase(TestCase):
''' UptimeTestCase'''
def test_checks_list(self):
ret = uptime.checks_list()
self.assertListEqual(ret, ['http://example.org'])
def test_checks_exists(self):
self.assertTrue(uptime.check_exists('http://example.org') is True)
def test_checks_create(self):
self.assertRaises(CommandExecutionError, uptime.create,
'http://example.org')
self.assertEqual(4321, uptime.create('http://example.com'))
self.assertEqual(('http://localhost:5000/api/checks',),
REQUEST_MOCK.args)
def test_checks_delete(self):
self.assertRaises(CommandExecutionError, uptime.delete,
'http://example.com')
self.assertTrue(uptime.delete('http://example.org') is True)
self.assertEqual(('http://localhost:5000/api/checks/1234',),
REQUEST_MOCK.args)
if __name__ == '__main__':
from integration import run_tests
run_tests(UptimeTestCase, needs_daemon=False)