Skip to content

Commit 9434e39

Browse files
renovate[bot]KOliver94github-actions[bot]
authored
Update dependency django-health-check to v4 (#1598)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Olivér Kecskeméty <kecskemety.oliver@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent fb0dadf commit 9434e39

11 files changed

Lines changed: 123 additions & 57 deletions

File tree

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ ENTRYPOINT ["/app/entrypoint.sh"]
173173

174174
# Set health check
175175
HEALTHCHECK --start-period=20s --interval=30s --retries=5 --timeout=30s \
176-
CMD python manage.py health_check
176+
CMD python manage.py health_check health_check --no-http
177177

178178
# Start the server
179179
CMD ["gunicorn", "--bind=0.0.0.0:8000", "--workers=5", "--threads=2", "core.wsgi"]

backend/.env.sample

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ CORS_ALLOWED_ORIGINS = http://localhost:8000 # Optional. Empty as default. List
99
CSRF_TRUSTED_ORIGINS = https://website.example.com # Optional. Empty as default. A list of trusted origins for unsafe requests. Required if you want to access Django Admin.
1010
DJANGO_ADMIN = True # Optional. Default: True. If True Django's admin panel will be available under /django-admin/
1111
DJANGO_SETTINGS_MODULE = core.settings.production # Optional. Default: core.settings.production. Options: core.settings.{production, staging, debug, test}
12-
HEALTH_CHECK_API = False # Optional. Default: False. Enables /api/v1/health API endpoint for app health check.
1312
HEALTH_CHECK_URL_TOKEN = randomGeneratedToken # Optional. Default: None. If set the health check endpoint will be available only under /api/v1/health/{token}.
1413
# You can use python -c "import secrets; print(secrets.token_urlsafe())" command to generate a token.
1514
LANGUAGE_CODE = hu-hu # Optional. Default: en-us

backend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ EXPOSE 8000
8080

8181
# Set health check
8282
HEALTHCHECK --start-period=30s --interval=5m \
83-
CMD python manage.py health_check
83+
CMD python manage.py health_check health_check --no-http
8484

8585
# Do the migrations and start the server
8686
CMD ["sh", "-c", "python manage.py migrate; gunicorn --bind=0.0.0.0:8000 --workers=5 --threads=2 core.wsgi"]

backend/api/v1/urls.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,6 @@
1414
path("misc/", include(("api.v1.misc.urls", "misc"), namespace="misc")),
1515
]
1616

17-
if settings.HEALTH_CHECK_API_ENABLED:
18-
token = (
19-
f"/{settings.HEALTH_CHECK_URL_TOKEN}"
20-
if hasattr(settings, "HEALTH_CHECK_URL_TOKEN")
21-
and settings.HEALTH_CHECK_URL_TOKEN is not None
22-
else ""
23-
)
24-
urlpatterns += [
25-
path(f"health{token}", include("health_check.urls")),
26-
]
27-
2817
if settings.SPECTACULAR_SERVE_SCHEMA:
2918
from drf_spectacular.views import (
3019
SpectacularAPIView,

backend/common/tests.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
import re
23
from io import StringIO
34

45
from django.conf import settings
@@ -64,24 +65,36 @@ def test_health_check_api_endpoint_works(self):
6465
and settings.HEALTH_CHECK_URL_TOKEN is not None
6566
else ""
6667
)
67-
response = self.client.get(f"/api/v1/health{token}?format=json")
68+
response = self.client.get(f"/health{token}?format=json")
6869
self.assertEqual(response.status_code, status.HTTP_200_OK)
6970
response.data = json.loads(response.content)
70-
self.assertIn("Cache backend: default", response.data)
71-
self.assertIn("DatabaseBackend", response.data)
72-
self.assertIn("DefaultFileStorageHealthCheck", response.data)
73-
self.assertIn("MigrationsHealthCheck", response.data)
74-
self.assertIn("RedisHealthCheck", response.data)
71+
self.assertIn("Cache(alias='default')", response.data)
72+
self.assertIn("Database(alias='default')", response.data)
73+
self.assertIn(
74+
"Mail(backend='django.core.mail.backends.dummy.EmailBackend')",
75+
response.data,
76+
)
77+
self.assertIn("Storage(alias='default')", response.data)
78+
self.assertTrue(
79+
any(
80+
re.search(r"Redis\(host='[^']+', port=6379\)", key)
81+
for key in response.data
82+
)
83+
)
7584

7685
def test_health_check_management_command_works(self):
7786
with StringIO() as out:
78-
call_command("health_check", stdout=out)
79-
self.assertEqual(out.getvalue().count("working"), 5)
80-
self.assertIn("Cache backend: default", out.getvalue())
81-
self.assertIn("DatabaseBackend", out.getvalue())
82-
self.assertIn("DefaultFileStorageHealthCheck", out.getvalue())
83-
self.assertIn("MigrationsHealthCheck", out.getvalue())
84-
self.assertIn("RedisHealthCheck", out.getvalue())
87+
with self.assertRaises(SystemExit) as cm:
88+
call_command("health_check", "health_check", "--no-http", stdout=out)
89+
self.assertEqual(cm.exception.code, 0)
90+
self.assertIn("Cache(alias='default')", out.getvalue())
91+
self.assertIn("Database(alias='default')", out.getvalue())
92+
self.assertIn(
93+
"Mail(backend='django.core.mail.backends.dummy.EmailBackend')",
94+
out.getvalue(),
95+
)
96+
self.assertIn("Storage(alias='default')", out.getvalue())
97+
self.assertRegex(out.getvalue(), r"Redis\(host='[^']+', port=6379\)")
8598

8699
def test_user_profile_avatar_json_validation(self):
87100
self.user.refresh_from_db()

backend/core/settings/base.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from django.core.exceptions import ImproperlyConfigured
2020
from django.core.management.utils import get_random_secret_key
2121
from django.utils.translation import gettext_lazy as _
22+
from redis.asyncio import Redis as RedisClient
2223

2324
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
2425
BACKEND_DIR = os.path.dirname(
@@ -60,6 +61,7 @@
6061
"drf_recaptcha",
6162
"drf_spectacular",
6263
"corsheaders",
64+
"health_check",
6365
"rest_framework_simplejwt.token_blacklist",
6466
"phonenumber_field",
6567
"simple_history",
@@ -322,23 +324,24 @@
322324

323325
# Health check
324326
# https://django-health-check.readthedocs.io/en/stable/
325-
326-
HEALTH_CHECK_API_ENABLED = config("HEALTH_CHECK_API", default=False, cast=bool)
327-
HEALTH_CHECK_URL_TOKEN = config("HEALTH_CHECK_URL_TOKEN", default=None)
328-
INSTALLED_APPS += [
329-
"health_check",
330-
"health_check.db",
331-
"health_check.cache",
332-
"health_check.storage",
333-
"health_check.contrib.migrations",
334-
"health_check.contrib.celery_ping",
335-
"health_check.contrib.redis",
336-
]
337327
try:
338328
REDIS_URL = match("^redis://[a-zA-Z0-9]+:[0-9]+", CACHEOPS_REDIS).group(0)
339329
except AttributeError:
340330
raise ImproperlyConfigured("Cannot extract proper Redis URL from CACHE_REDIS.")
341331

332+
HEALTH_CHECK_URL_TOKEN = config("HEALTH_CHECK_URL_TOKEN", default=None)
333+
HEALTH_CHECK_ENABLED_CHECKS = [
334+
"health_check.Cache",
335+
"health_check.Database",
336+
"health_check.Mail",
337+
"health_check.Storage",
338+
"health_check.contrib.celery.Ping",
339+
(
340+
"health_check.contrib.redis.Redis",
341+
{"client_factory": lambda: RedisClient.from_url(REDIS_URL)},
342+
),
343+
]
344+
342345
# Django REST reCAPTCHA
343346
# https://github.com/llybin/drf-recaptcha
344347

backend/core/settings/test.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
DATABASES["default"].update({"HOST": config("DATABASE_HOST", default="localhost")})
77
CACHEOPS_REDIS = config("CACHE_REDIS", default="redis://localhost:6379/0")
88
CELERY_BROKER_URL = config("CELERY_BROKER", default="redis://localhost:6379/1")
9-
try:
10-
REDIS_URL = match("^redis://[a-zA-Z0-9]+:[0-9]+", CACHEOPS_REDIS).group(0)
11-
except AttributeError:
12-
raise ImproperlyConfigured("Cannot extract proper Redis URL from CACHE_REDIS.")
139

1410
# Use the default Django authentication backend
1511
AUTHENTICATION_BACKENDS += ["django.contrib.auth.backends.ModelBackend"]
@@ -82,12 +78,23 @@
8278
# Random external token
8379
SCH_EVENTS_TOKEN = "123456789abcdef" # nosec
8480

85-
# Enable health check endpoint and remove celery from checks
86-
HEALTH_CHECK_API_ENABLED = True
81+
# Remove celery and update Redis health check to use the local REDIS_URL
8782
try:
88-
INSTALLED_APPS.remove("health_check.contrib.celery_ping")
89-
except ValueError:
90-
pass
83+
REDIS_URL = match("^redis://[a-zA-Z0-9]+:[0-9]+", CACHEOPS_REDIS).group(0)
84+
except AttributeError:
85+
raise ImproperlyConfigured("Cannot extract proper Redis URL from CACHE_REDIS.")
86+
87+
HEALTH_CHECK_ENABLED_CHECKS = [
88+
check
89+
for check in HEALTH_CHECK_ENABLED_CHECKS
90+
if check != "health_check.contrib.celery.Ping"
91+
and not (isinstance(check, tuple) and "Redis" in check[0])
92+
] + [
93+
(
94+
"health_check.contrib.redis.Redis",
95+
{"client_factory": lambda: RedisClient.from_url(REDIS_URL)},
96+
),
97+
]
9198

9299
# Set DRF reCAPTCHA to test mode
93100
DRF_RECAPTCHA_TESTING = True

backend/core/urls.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from django.contrib import admin
1919
from django.urls import include, path, re_path
2020
from django.views.generic import TemplateView
21+
from health_check.views import HealthCheckView
2122

2223
urlpatterns = [
2324
path("api/", include(("api.urls", "api"), namespace="api")),
@@ -27,6 +28,23 @@
2728
re_path(r"", TemplateView.as_view(template_name="index.html")), # React frontend
2829
]
2930

31+
# Django HealthCheck endpoints
32+
token = (
33+
f"/{settings.HEALTH_CHECK_URL_TOKEN}"
34+
if hasattr(settings, "HEALTH_CHECK_URL_TOKEN")
35+
and settings.HEALTH_CHECK_URL_TOKEN is not None
36+
else ""
37+
)
38+
39+
urlpatterns.insert(
40+
0,
41+
path(
42+
f"health{token}",
43+
HealthCheckView.as_view(checks=settings.HEALTH_CHECK_ENABLED_CHECKS),
44+
name="health_check",
45+
),
46+
)
47+
3048
# Enable Django Admin when requested
3149
if settings.DJANGO_ADMIN and "django.contrib.admin" in settings.INSTALLED_APPS:
3250
urlpatterns.insert(0, path("django-admin/", admin.site.urls))

backend/poetry.lock

Lines changed: 39 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dependencies = [
1818
"django-celery-results==2.6.0",
1919
"django-cors-headers==4.9.0",
2020
"django-filter==25.2",
21-
"django-health-check==3.20.8",
21+
"django-health-check[celery,redis]==4.1.2",
2222
"django-phonenumber-field[phonenumbers]==8.4.0",
2323
"django-simple-history==3.11.0",
2424
"drf-recaptcha==4.0.3",
@@ -46,7 +46,6 @@ omit = [
4646
"*/migrations/*",
4747
"*/admin.py",
4848
"*/tests.py",
49-
"common/health_checks.py",
5049
"manage.py",
5150
]
5251
exclude_lines = [

0 commit comments

Comments
 (0)