generic response checking method and get_check

This commit is contained in:
Andrew Herrington
2021-12-10 19:48:28 -06:00
parent 95ab6d45f2
commit 557f4e4477
4 changed files with 68 additions and 12 deletions

View File

@@ -12,9 +12,10 @@ from urllib.parse import urljoin
from urllib.parse import urlparse from urllib.parse import urlparse
from weakref import finalize from weakref import finalize
from httpx import Client from httpx import Client, Response
from healthchecks_io.schemas import checks from healthchecks_io.schemas import checks
from .exceptions import HCAPIAuthError, HCAPIError, CheckNotFoundError
class AbstractClient(ABC): class AbstractClient(ABC):
@@ -79,6 +80,31 @@ class AbstractClient(ABC):
""" """
return self._client.is_closed return self._client.is_closed
@staticmethod
def check_response(response: Response) -> Response:
"""Checks a healthchecks.io response.
Args:
response (Response): a response from the healthchecks.io api
Raises:
HCAPIAuthError: Raised when status_code == 401 or 403
HCAPIError: Raised when status_code is 5xx
Returns:
Response: the passed in response object
"""
if response.status_code == 401 or response.status_code == 403:
raise HCAPIAuthError("Auth failure when getting checks")
if str(response.status_code).startswith("5"):
raise HCAPIError(
f"Error when reaching out to HC API at {response.request.url}. "
f"Status Code {response.status_code}. Response {response.text}"
)
return response
@staticmethod @staticmethod
def _add_url_params(url: str, params: Dict[str, str], replace: bool = True): def _add_url_params(url: str, params: Dict[str, str], replace: bool = True):
"""Add GET params to provided URL being aware of existing. """Add GET params to provided URL being aware of existing.

View File

@@ -6,7 +6,7 @@ from typing import Optional
from httpx import AsyncClient as HTTPXAsyncClient from httpx import AsyncClient as HTTPXAsyncClient
from ._abstract import AbstractClient from ._abstract import AbstractClient
from .exceptions import HCAPIAuthError from .exceptions import HCAPIAuthError, CheckNotFoundError
from .exceptions import HCAPIError from .exceptions import HCAPIError
from healthchecks_io import VERSION from healthchecks_io import VERSION
from healthchecks_io.schemas import checks from healthchecks_io.schemas import checks
@@ -69,18 +69,31 @@ class AsyncClient(AbstractClient):
request_url, {"tag": tag}, replace=False request_url, {"tag": tag}, replace=False
) )
response = await self._client.get(request_url) response = self.check_response(await self._client.get(request_url))
if response.status_code == 401:
raise HCAPIAuthError("Auth failure when getting checks")
if response.status_code != 200:
raise HCAPIError(
f"Error when reaching out to HC API at {request_url}. "
f"Status Code {response.status_code}. Response {response.text}"
)
return [ return [
checks.Check.from_api_result(check_data) checks.Check.from_api_result(check_data)
for check_data in response.json()["checks"] for check_data in response.json()["checks"]
] ]
async def get_check(self, check_id: str) -> checks.Check:
"""Get a single check by id.
check_id can either be a check uuid if using a read/write api key
or a unique key if using a read only api key.
Args:
check_id (str): check's uuid or unique id
Returns:
checks.Check: the check
Raises:
CheckNotFoundError: when no check with check_id is found
"""
request_url = self._get_api_request_url(f"checks/{check_id}")
response = self.check_response(await self._client.get(request_url))
if response.status_code == 404:
raise CheckNotFoundError(f"{check_id} not found at {request_url}")
return checks.Check.from_api_result(response.json())

View File

@@ -11,3 +11,8 @@ class HCAPIAuthError(HCAPIError):
"""Thrown when we fail to auth to the Healthchecks api.""" """Thrown when we fail to auth to the Healthchecks api."""
... ...
class CheckNotFoundError(HCAPIError):
"""Thrown when getting a check returns a 404."""
...

View File

@@ -74,3 +74,15 @@ def test_finalizer_closes(test_async_client):
assert not test_async_client.is_closed assert not test_async_client.is_closed
test_async_client._finalizer_method() test_async_client._finalizer_method()
assert test_async_client.is_closed assert test_async_client.is_closed
@pytest.mark.asyncio
@pytest.mark.respx
async def test_get_check_200(fake_check_api_result, respx_mock, test_async_client):
assert test_async_client._client is not None
checks_url = urljoin(test_async_client._api_url, "checks/test")
respx_mock.get(checks_url).mock(
return_value=Response(status_code=200, json=fake_check_api_result)
)
check = await test_async_client.get_check(check_id="test")
assert check.name == fake_check_api_result["name"]