From 56ade45717a5cdb1371200f39de2d67f19e95914 Mon Sep 17 00:00:00 2001 From: jenriordan Date: Tue, 31 Dec 2024 11:38:55 +0000 Subject: [PATCH 1/3] initial commit --- django_app/healthcheck/checks/s3.py | 18 +++++++++++------- django_app/healthcheck/views.py | 6 +++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/django_app/healthcheck/checks/s3.py b/django_app/healthcheck/checks/s3.py index f43e671a..be0be227 100644 --- a/django_app/healthcheck/checks/s3.py +++ b/django_app/healthcheck/checks/s3.py @@ -1,18 +1,22 @@ +import boto3 import sentry_sdk -from core.document_storage import PermanentDocumentStorage, TemporaryDocumentStorage +from django.conf import settings def s3_check() -> bool: """ - Performs a check on the S3 connection + Check if the S3 bucket exists and ensure the app can access it. + https://boto3.amazonaws.com/v1/documentation/api/1.35.9/reference/services/s3/client/head_bucket.html """ - temporary_document_bucket = TemporaryDocumentStorage().bucket - permanent_document_bucket = PermanentDocumentStorage().bucket + client = boto3.client("s3") + + bucket_names = [settings.TEMPORARY_S3_BUCKET_NAME, settings.PERMANENT_S3_BUCKET_NAME] try: - assert temporary_document_bucket.creation_date - assert permanent_document_bucket.creation_date - return True + for bucket_name in bucket_names: + client.head_bucket(Bucket=bucket_name) except Exception as e: sentry_sdk.capture_exception(e) return False + + return True diff --git a/django_app/healthcheck/views.py b/django_app/healthcheck/views.py index 92b5e701..f83ccf10 100644 --- a/django_app/healthcheck/views.py +++ b/django_app/healthcheck/views.py @@ -4,7 +4,7 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render from django.views.generic import View -from healthcheck.checks import db_check +from healthcheck.checks import db_check, s3_check class HealthCheckView(View): @@ -20,8 +20,8 @@ def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResp start = time.time() is_db_good = db_check() - # is_s3_good = s3_check() - all_good = is_db_good and True + is_s3_good = s3_check() + all_good = is_db_good and is_s3_good end = time.time() time_taken = round(end - start, 3) From 1447c714993229f21d1e40a069a0c3188d113aea Mon Sep 17 00:00:00 2001 From: jenriordan Date: Tue, 31 Dec 2024 12:17:05 +0000 Subject: [PATCH 2/3] add unit tests --- .../test_unit/test_healthcheck/test_views.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/test_unit/test_healthcheck/test_views.py diff --git a/tests/test_unit/test_healthcheck/test_views.py b/tests/test_unit/test_healthcheck/test_views.py new file mode 100644 index 00000000..9e57974c --- /dev/null +++ b/tests/test_unit/test_healthcheck/test_views.py @@ -0,0 +1,30 @@ +from unittest.mock import patch + +import pytest +from django.urls import reverse + +from tests.helpers import get_response_content + + +@pytest.fixture(autouse=True) +def setup(): + """Need to fix the Sites context processor as healthcheck views don't have a site.""" + with patch("core.sites.context_processors.sites", return_value={}): + yield + + +@patch("healthcheck.checks.s3.boto3") +def test_successful_healthcheck(mock_s3_client, al_client): + mock_s3_client.head_bucket.return_value = {"test": True} + response = al_client.get(reverse("healthcheck:healthcheck_ping")) + content = get_response_content(response) + assert "OK" in content + assert response.status_code == 200 + + +@patch("healthcheck.views.db_check", return_value=False) +def test_db_broken_healthcheck(mock_db_check, al_client): + response = al_client.get(reverse("healthcheck:healthcheck_ping")) + content = get_response_content(response) + assert "FAIL" in content + assert response.status_code == 200 From 9e683bcb987c2ed8f87228dc1a652d968875ebd3 Mon Sep 17 00:00:00 2001 From: jenriordan Date: Tue, 31 Dec 2024 12:31:58 +0000 Subject: [PATCH 3/3] add missed test --- tests/test_unit/test_healthcheck/test_views.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_unit/test_healthcheck/test_views.py b/tests/test_unit/test_healthcheck/test_views.py index 9e57974c..33134abf 100644 --- a/tests/test_unit/test_healthcheck/test_views.py +++ b/tests/test_unit/test_healthcheck/test_views.py @@ -22,6 +22,14 @@ def test_successful_healthcheck(mock_s3_client, al_client): assert response.status_code == 200 +@patch("healthcheck.views.s3_check", return_value=False) +def test_s3_broken_healthcheck(mock_s3_check, al_client): + response = al_client.get(reverse("healthcheck:healthcheck_ping")) + content = get_response_content(response) + assert "FAIL" in content + assert response.status_code == 200 + + @patch("healthcheck.views.db_check", return_value=False) def test_db_broken_healthcheck(mock_db_check, al_client): response = al_client.get(reverse("healthcheck:healthcheck_ping"))