Skip to content

Commit

Permalink
✨ [#1617] added feature to see if connection is alive in service admi…
Browse files Browse the repository at this point in the history
…n list page
  • Loading branch information
bart-maykin committed May 16, 2024
1 parent c4c4ad0 commit 4365497
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 2 deletions.
46 changes: 46 additions & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from django.core.exceptions import ValidationError

import pytest
import requests_mock
from ape_pie import APIClient

from zgw_consumers.client import ServiceConfigAdapter
from zgw_consumers.constants import APITypes, AuthTypes
from zgw_consumers.models import Service
from zgw_consumers.test.factories import ServiceFactory


def test_model_validation_with_oas_fields_enabled_none_provided(settings):
Expand Down Expand Up @@ -76,3 +80,45 @@ def test_model_validation_with_oas_fields_disabled_both_provided(settings):
service.clean()
except ValidationError:
pytest.fail("OAS fields should be ignored")


@pytest.mark.django_db
def test_health_check_indication_service_model_badly_configured(settings):
service = ServiceFactory.create(
api_root="https://example.com/",
api_health_check_endpoint="foo",
auth_type=AuthTypes.zgw,
client_id="my-client-id",
secret="my-secret",
)
adapter = ServiceConfigAdapter(service)
client = APIClient.configure_from(adapter)

with requests_mock.Mocker() as m, client:
m.get(
"https://example.com/foo",
status_code=404,
)
service.refresh_from_db()
assert service.get_health_check_indication == False


@pytest.mark.django_db
def test_health_check_indication_service_model_correctly_configured(settings):
service = ServiceFactory.create(
api_root="https://example.com/",
api_health_check_endpoint="foo",
auth_type=AuthTypes.zgw,
client_id="my-client-id",
secret="my-secret",
)
adapter = ServiceConfigAdapter(service)
client = APIClient.configure_from(adapter)

with requests_mock.Mocker() as m, client:
m.get(
"https://example.com/foo",
status_code=200,
)
service.refresh_from_db()
assert service.get_health_check_indication == True
15 changes: 14 additions & 1 deletion zgw_consumers/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,22 @@

@admin.register(Service)
class ServiceAdmin(admin.ModelAdmin):
list_display = ("label", "api_type", "api_root", "nlx", "auth_type")
list_display = (
"label",
"api_type",
"api_root",
"nlx",
"auth_type",
)
list_filter = ("api_type", "auth_type")
search_fields = ("label", "api_root", "nlx", "uuid")
readonly_fields = [
"get_health_check_indication",
]

@admin.display(description="Health Check", boolean=True)
def get_health_check_indication(self, obj):
return obj.get_health_check_indication

def get_fields(self, request: HttpRequest, obj: models.Model | None = None):
fields = super().get_fields(request, obj=obj)
Expand Down
1 change: 0 additions & 1 deletion zgw_consumers/migrations/0020_service_timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


class Migration(migrations.Migration):

dependencies = [
("zgw_consumers", "0019_alter_service_uuid"),
]
Expand Down
23 changes: 23 additions & 0 deletions zgw_consumers/migrations/0021_service_api_health_check_endpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2 on 2024-05-10 08:58

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("zgw_consumers", "0020_service_timeout"),
]

operations = [
migrations.AddField(
model_name="service",
name="api_health_check_endpoint",
field=models.CharField(
help_text="An optional API endpoint which will be used to check if the API is configured correctly and is currently up or down. This field is only used for in the admin's 'health check' field.",
max_length=255,
blank=True,
verbose_name="health check endpoint",
),
),
]
29 changes: 29 additions & 0 deletions zgw_consumers/models/services.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import logging
import socket
import uuid
from typing import TYPE_CHECKING
Expand All @@ -11,6 +12,7 @@
from django.utils.translation import gettext_lazy as _

from privates.fields import PrivateMediaFileField
from requests.exceptions import ConnectionError, RequestException
from simple_certmanager.models import Certificate
from solo.models import SingletonModel
from typing_extensions import Self, deprecated
Expand All @@ -20,6 +22,8 @@
from ..constants import APITypes, AuthTypes, NLXDirectories
from .abstract import RestAPIService

logger = logging.getLogger(__name__)

if TYPE_CHECKING:
from ..legacy.client import ZGWClient

Expand All @@ -28,6 +32,15 @@ class Service(RestAPIService):
uuid = models.UUIDField(_("UUID"), default=uuid.uuid4)
api_type = models.CharField(_("type"), max_length=20, choices=APITypes.choices)
api_root = models.CharField(_("api root url"), max_length=255, unique=True)
api_health_check_endpoint = models.CharField(
_("health check endpoint"),
help_text=_(
"An optional API endpoint which will be used to check if the API is configured correctly and "
"is currently up or down. This field is only used for in the admin's 'health check' field."
),
max_length=255,
blank=True,
)

# credentials for the API
client_id = models.CharField(max_length=255, blank=True)
Expand Down Expand Up @@ -113,6 +126,22 @@ def clean(self):
{"header_key": _("If header_value is set, header_key must also be set")}
)

@property
def get_health_check_indication(self) -> bool:
from zgw_consumers.client import build_client

try:
client = build_client(self)
if (
client.get(self.api_health_check_endpoint or self.api_root).status_code
== 200
):
return True
except (ConnectionError, RequestException) as e:
logger.exception(self, exc_info=e)

return False

@deprecated(
"The `build_client` method is deprecated and will be removed in the next major release. "
"Instead, use the new `ape_pie.APIClient` or `zgw_consumers.nlx.NLXClient`.",
Expand Down

0 comments on commit 4365497

Please sign in to comment.