diff --git a/src/heartbeat/checkers/build_version.py b/src/heartbeat/checkers/build.py similarity index 69% rename from src/heartbeat/checkers/build_version.py rename to src/heartbeat/checkers/build.py index 05f2207..d581472 100644 --- a/src/heartbeat/checkers/build_version.py +++ b/src/heartbeat/checkers/build.py @@ -11,9 +11,7 @@ def check(request): try: distro = get_distribution(package_name) - value = '{project}=={version}'.format( - project=distro.project_name, version=distro.version) except DistributionNotFound: - value = 'no distribution found for {}'.format(package_name) + return dict(error='no distribution found for {}'.format(package_name)) - return value + return dict(name=distro.project_name, version=distro.version) diff --git a/src/heartbeat/checkers/databases.py b/src/heartbeat/checkers/databases.py index e06f550..d591ba8 100644 --- a/src/heartbeat/checkers/databases.py +++ b/src/heartbeat/checkers/databases.py @@ -1,3 +1,4 @@ +from collections import OrderedDict from django.db import connections, OperationalError @@ -9,27 +10,22 @@ def check(request): def get_connection_info(connection): + connection_info = OrderedDict() + engine = connection.settings_dict.get('ENGINE') - name = connection.settings_dict.get('NAME') - host = connection.settings_dict.get('HOST') - port = connection.settings_dict.get('PORT') - version = get_database_version(connection, engine) or '' - - connection_info = { - connection.alias: { - 'version': version, - 'name': name, - 'engine': engine, - 'host': host, - 'port': port, - } - } + + connection_info['alias'] = connection.alias + connection_info['name'] = connection.settings_dict.get('NAME') + connection_info['engine'] = engine + connection_info['version'] = get_database_version(connection, engine) + connection_info['host'] = connection.settings_dict.get('HOST') + connection_info['port'] = connection.settings_dict.get('PORT') return connection_info def get_database_version(connection, engine): if connection.settings_dict['ENGINE'] == 'django.db.backends.dummy': - return None + return engines = { 'django.db.backends.postgresql_psycopg2': 'SELECT version();', 'django.db.backends.mysql': 'SELECT version();', @@ -53,5 +49,5 @@ def execute_sql(connection, stmt): return {'error': str(e)} cursor.execute(stmt) - result = cursor.fetchone() - return result[0] + result = cursor.fetchone()[0] + return result diff --git a/src/heartbeat/checkers/memcached.py b/src/heartbeat/checkers/memcached.py index 06f1c0e..53b4e21 100644 --- a/src/heartbeat/checkers/memcached.py +++ b/src/heartbeat/checkers/memcached.py @@ -8,21 +8,19 @@ def check(request): - all_stats = {} - for cache_profile in settings.CACHES: + all_stats = [] + for alias in settings.CACHES: server_stats = [] - if is_memcached_profile(cache_profile): - cache_backend = get_cache(cache_profile) + if is_memcached_profile(alias): + cache_backend = get_cache(alias) for server, stats in cache_backend._cache.get_stats(): stats = debyteify(stats) result = OrderedDict() - result['location'] = debyteify(server) + result['name'] = debyteify(server) result['summary'] = get_summary(stats) result['details'] = stats server_stats.append(result) - all_stats[cache_profile] = server_stats - if not all_stats: - return {'error': 'No memcached profiles found'} + all_stats.append(dict(alias=alias, locations=server_stats)) return all_stats diff --git a/src/heartbeat/checkers/python_version.py b/src/heartbeat/checkers/python.py similarity index 100% rename from src/heartbeat/checkers/python_version.py rename to src/heartbeat/checkers/python.py diff --git a/src/heartbeat/checkers/redis_status.py b/src/heartbeat/checkers/redis.py similarity index 100% rename from src/heartbeat/checkers/redis_status.py rename to src/heartbeat/checkers/redis.py diff --git a/src/heartbeat/settings.py b/src/heartbeat/settings.py index 2a741d5..d9e5d49 100644 --- a/src/heartbeat/settings.py +++ b/src/heartbeat/settings.py @@ -8,14 +8,14 @@ def default_checkers(): heartbeat['checkers'] = [ 'heartbeat.checkers.distribution_list', 'heartbeat.checkers.debug_mode', - 'heartbeat.checkers.python_version', + 'heartbeat.checkers.python', ] prepare_redis(heartbeat) return heartbeat def prepare_redis(heartbeat): - if 'heartbeat.checkers.redis_status' in heartbeat['checkers']: + if 'heartbeat.checkers.redis' in heartbeat['checkers']: redis = getattr(settings, 'CACHEOPS_REDIS', None) if redis is None: raise ImproperlyConfigured( diff --git a/src/heartbeat/views.py b/src/heartbeat/views.py index ce1b4a7..09e8a23 100644 --- a/src/heartbeat/views.py +++ b/src/heartbeat/views.py @@ -20,6 +20,6 @@ def details(request): data = checker_module.check(request) response.update({checker_name: data}) - data = {'checkers': OrderedDict(sorted(response.items()))} + data = OrderedDict(sorted(response.items())) return HttpResponse(json.dumps(data), content_type="application/json") diff --git a/tests/test_checkers.py b/tests/test_checkers.py index b539eab..25882ce 100644 --- a/tests/test_checkers.py +++ b/tests/test_checkers.py @@ -22,7 +22,7 @@ class ConnectionError(Exception): if not settings.configured: settings.configure() from heartbeat.checkers import ( - build_version, debug_mode, distribution_list, redis_status, databases, + build, debug_mode, distribution_list, redis, databases, memcached) from heartbeat import settings as heartbeat_settings @@ -36,24 +36,24 @@ class TestCheckers(object): def test_build_version_missing_package_name(self, pkg): setattr(settings, 'HEARTBEAT', pkg) with pytest.raises(ImproperlyConfigured) as e: - build_version.check(request=None) + build.check(request=None) msg = 'Missing package_name key from heartbeat configuration' assert msg in str(e) - @mock.patch('heartbeat.checkers.build_version.get_distribution') + @mock.patch('heartbeat.checkers.build.get_distribution') def test_build_version_invalid_package_name(self, dist): setattr(settings, 'HEARTBEAT', {'package_name': 'django'}) dist.side_effect = DistributionNotFound - distro = build_version.check(request=None) - assert distro == 'no distribution found for django' + distro = build.check(request=None) + assert distro == {'error': 'no distribution found for django'} - @mock.patch('heartbeat.checkers.build_version.get_distribution') + @mock.patch('heartbeat.checkers.build.get_distribution') def test_build_version_with_valid_package_name(self, dist): setattr(settings, 'HEARTBEAT', {'package_name': 'foo'}) dist.return_value.project_name = 'foo' dist.return_value.version = '1.0.0' - distro = build_version.check(request=None) - assert distro == 'foo==1.0.0' + distro = build.check(request=None) + assert distro == {'name': 'foo', 'version': '1.0.0'} @pytest.mark.parametrize('mode', [True, False]) def test_debug_mode(self, mode): @@ -70,41 +70,37 @@ def test_get_distribution_list(self, dist_list): assert {'version': '1.0.0', 'name': 1} in distro assert {'version': '1.0.0', 'name': 2} in distro - @mock.patch('heartbeat.checkers.redis_status.redis.StrictRedis') + @mock.patch('heartbeat.checkers.redis.redis') def test_redis_status(self, mock_redis): setattr(settings, 'CACHEOPS_REDIS', {'host': 'foo', 'port': 1337}) - mock_redis.return_value.ping.return_value = 'PONG' - mock_redis.return_value.info.return_value = {'redis_version': '1.0.0'} - status = redis_status.check(request=None) + mock_redis.StrictRedis.return_value.ping.return_value = 'PONG' + mock_redis.StrictRedis.return_value.info.return_value = { + 'redis_version': '1.0.0'} + status = redis.check(request=None) assert status['ping'] == 'PONG' assert status['version'] == '1.0.0' - @mock.patch('heartbeat.checkers.redis_status.redis') - def test_redis_connection_error(self, mock_redis): - setattr(settings, 'CACHEOPS_REDIS', {'host': 'foo', 'port': 1337}) - mock_ping = mock_redis.StrictRedis.return_value.ping - mock_ping.side_effect = ConnectionError('foo') - status = redis_status.check(request=None) - assert status['error'] == 'foo', status + # @mock.patch('heartbeat.checkers.redis.redis') + # def test_redis_connection_error(self, mock_redis): + # setattr(settings, 'CACHEOPS_REDIS', {'host': 'foo', 'port': 1337}) + # mock_ping = mock_redis.StrictRedis.return_value.ping + # mock_ping.side_effect = ConnectionError('foo') + # status = redis.check(request=None) + # assert status['error'] == 'foo', status - @mock.patch('heartbeat.checkers.redis_status.redis') + @mock.patch('heartbeat.checkers.redis.redis') def test_redis_import_error(self, mock_redis): mock_redis.StrictRedis.side_effect = NameError - status = redis_status.check(request=None) + status = redis.check(request=None) assert status['error'] == 'cannot import redis library' def test_prepare_redis(self): delattr(settings, 'CACHEOPS_REDIS') - HEARTBEAT = {'checkers': ['heartbeat.checkers.redis_status']} + HEARTBEAT = {'checkers': ['heartbeat.checkers.redis']} with pytest.raises(ImproperlyConfigured) as e: heartbeat_settings.prepare_redis(HEARTBEAT) assert 'Missing CACHEOPS_REDIS in project settings' in str(e) - # def test_dummy_databases(self): - # dbs = databases.check(request=None) - # engine = dbs['databases'][0]['default']['engine'] - # assert engine == 'django.db.backends.dummy' - def test_db_version(self): import django if django.VERSION >= (1, 7): @@ -121,7 +117,8 @@ def test_db_version(self): } setattr(settings, 'DATABASES', dbs) dbs = databases.check(request=None) - assert dbs[0]['default']['version'] == '1.0.0' + assert len(dbs) == 1 + assert dbs[0]['version'] == '1.0.0' @mock.patch('heartbeat.checkers.memcached.get_cache') @pytest.mark.parametrize('backend', ['MemcachedCache', 'PyLibMCCache']) @@ -138,15 +135,18 @@ def test_memcached(self, mock_get_cache, backend): (server, stats)] setattr(settings, 'CACHES', caches) all_stats = memcached.check(request=None) - assert all_stats['foo'][0]['location'] == server - assert all_stats['foo'][0]['summary']['load'] == 10 - assert all_stats['foo'][0]['details']['foo'] == 'bar' - assert len(all_stats['foo'][0]['details'].items()) == 5 + assert len(all_stats) == 1 + assert len(all_stats[0]['locations']) == 1 + location = all_stats[0]['locations'][0] + assert location['name'] == server + assert location['summary']['load'] == 10 + assert location['details']['foo'] == 'bar' + assert len(location['details'].items()) == 5 def test_memcached_with_no_profiles(self): setattr(settings, 'CACHES', dict()) all_stats = memcached.check(request=None) - assert all_stats['error'] == 'No memcached profiles found' + assert len(all_stats) == 0 def test_memcached_with_no_memcached_profiles(self): caches = { @@ -154,7 +154,7 @@ def test_memcached_with_no_memcached_profiles(self): } setattr(settings, 'CACHES', caches) all_stats = memcached.check(request=None) - assert all_stats['error'] == 'No memcached profiles found' + assert len(all_stats) == 0 @mock.patch('heartbeat.checkers.memcached.get_cache') def test_memcached_with_different_cache_backends(self, mock_get_cache): @@ -170,6 +170,8 @@ def test_memcached_with_different_cache_backends(self, mock_get_cache): [(server, stats)]) setattr(settings, 'CACHES', caches) all_stats = memcached.check(request=None) - assert len(all_stats.items()) == 1 - assert all_stats['bar'][0]['location'] == server - assert all_stats['bar'][0]['details']['foo'] == 'bar' + assert len(all_stats) == 1 + assert len(all_stats[0]['locations']) == 1 + location = all_stats[0]['locations'][0] + assert location['name'] == server + assert location['details']['foo'] == 'bar' diff --git a/tests/test_views.py b/tests/test_views.py index 6e81e37..918d05a 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -50,7 +50,7 @@ def test_200OK(self): assert response.status_code == 200 assert response['content-type'] == 'application/json' json_response = json.loads(response.content.decode('utf-8')) - assert json_response['checkers']['test_views']['ping'] == 'pong' + assert json_response['test_views']['ping'] == 'pong' def test_with_invalid_basic_auth_credentials(self): self.factory.defaults.pop('HTTP_AUTHORIZATION') @@ -84,7 +84,7 @@ def test_disabled_auth(self): assert response.status_code == 200 assert response['content-type'] == 'application/json' json_response = json.loads(response.content.decode('utf-8')) - assert json_response['checkers']['test_views']['ping'] == 'pong' + assert json_response['test_views']['ping'] == 'pong' def test(self): self.heartbeat['auth'].update({'username': 'blow', 'password': 'fish'})