From b4f1648edc2438cbd8d9a2fabaa2e37b7f3e4f8a Mon Sep 17 00:00:00 2001 From: Douglas Paz Date: Mon, 9 Jul 2018 12:06:38 -0300 Subject: [PATCH] Add ping endpoint, closes #155 --- bothub/health/__init__.py | 0 bothub/health/apps.py | 5 +++++ bothub/health/checks.py | 23 +++++++++++++++++++++++ bothub/health/tests.py | 1 + bothub/health/views.py | 34 ++++++++++++++++++++++++++++++++++ bothub/urls.py | 2 ++ 6 files changed, 65 insertions(+) create mode 100644 bothub/health/__init__.py create mode 100644 bothub/health/apps.py create mode 100644 bothub/health/checks.py create mode 100644 bothub/health/tests.py create mode 100644 bothub/health/views.py diff --git a/bothub/health/__init__.py b/bothub/health/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bothub/health/apps.py b/bothub/health/apps.py new file mode 100644 index 00000000..ea5593f6 --- /dev/null +++ b/bothub/health/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class HealthConfig(AppConfig): + name = 'health' diff --git a/bothub/health/checks.py b/bothub/health/checks.py new file mode 100644 index 00000000..e3ba2c59 --- /dev/null +++ b/bothub/health/checks.py @@ -0,0 +1,23 @@ +def check_database_connection(**kwargs): + from django.db import connections + from django.db.utils import OperationalError + db_conn = connections['default'] + if not db_conn: + return False + try: + db_conn.cursor() + return True + except OperationalError as e: + return False + + +def check_accessible_api(request, **kwargs): + import requests + HTTP_HOST = request.META.get('HTTP_HOST') + repositories_url = 'http://{}/api/repositories/'.format(HTTP_HOST) + request = requests.get(repositories_url) + try: + request.raise_for_status() + return True + except requests.HTTPError as e: + return False diff --git a/bothub/health/tests.py b/bothub/health/tests.py new file mode 100644 index 00000000..e4defabc --- /dev/null +++ b/bothub/health/tests.py @@ -0,0 +1 @@ +# from django.test import TestCase diff --git a/bothub/health/views.py b/bothub/health/views.py new file mode 100644 index 00000000..3025944a --- /dev/null +++ b/bothub/health/views.py @@ -0,0 +1,34 @@ +from collections import OrderedDict +from functools import reduce + +from django.http import HttpResponse +from rest_framework import status + +from .checks import check_database_connection +from .checks import check_accessible_api + +CHECKS = [ + check_database_connection, + check_accessible_api, +] + + +def ping(request): + checks_status = OrderedDict(map( + lambda check: (check.__name__, check(request=request)), + CHECKS)) + healthy = reduce( + lambda current, status: current and status, + checks_status.values(), + True) + content = '{}\n{}'.format( + 'OK' if healthy else 'something wrong happened', + '\n'.join(map( + lambda x: '{}: {}'.format(*x), + checks_status.items()))) + status_code = status.HTTP_200_OK \ + if healthy else status.HTTP_503_SERVICE_UNAVAILABLE + return HttpResponse( + content=content, + content_type='text/plain', + status=status_code) diff --git a/bothub/urls.py b/bothub/urls.py index bdfd5497..628f309a 100644 --- a/bothub/urls.py +++ b/bothub/urls.py @@ -4,12 +4,14 @@ from rest_framework.documentation import include_docs_urls from bothub.api.routers import router as bothub_api_routers +from bothub.health.views import ping urlpatterns = [ path('api/', include(bothub_api_routers.urls)), path('docs/', include_docs_urls(title='API Documentation')), path('admin/', admin.site.urls), + path('ping/', ping, name='ping'), ] if settings.DEBUG: