Skip to content

Commit

Permalink
rewrite: check classes and report classes
Browse files Browse the repository at this point in the history
  • Loading branch information
acodeninja committed Feb 15, 2024
1 parent c38b434 commit b049fe6
Show file tree
Hide file tree
Showing 15 changed files with 374 additions and 63 deletions.
Empty file added app/check/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions app/check/check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import Union, List

from app.check.report import CheckReport


class Check:
def execute(self):
raise NotImplemented

@property
def success(self) -> bool:
raise NotImplemented

@property
def report(self) -> Union[CheckReport, List[CheckReport]]:
raise NotImplemented
85 changes: 85 additions & 0 deletions app/check/check_http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from typing import List, Union
from urllib.parse import urlparse, ParseResult

import requests

from app.check.check import Check
from app.check.report import CheckReport


class HTTPCheckInstance:
definition: str
method: str
url: ParseResult
status_code: int
report: CheckReport

def __init__(self, definition: str):
self.definition = definition
self.report = CheckReport()
self.report.summary = definition

def execute(self):
segments = self.definition.split('|')

self.status_code = 200
self.method = 'get'

self.url = urlparse(segments[0])

try:
status = segments[1]
self.status_code = int(status)
except IndexError:
pass
except ValueError:
self.report.success = False
self.report.errors.append(f'expected status code to be integer, got {segments[1]}')
return

try:
method = segments[2]
self.method = method.lower()
except IndexError:
pass

requester = getattr(requests, self.method, None)

if not requester:
self.report.success = False
self.report.errors.append(f'method "{self.method.upper()}" is not a valid HTTP method')
return

try:
r = requester(self.url.geturl())

if r.status_code != self.status_code:
self.report.success = False
self.report.errors.append(
f"expected HTTP Status {self.status_code} but got {r.status_code}")

except ValueError:
self.report.success = False
self.report.errors.append(f'"{self.url.geturl()}" is not a valid URL')
except Exception as e:
self.report.success = False
self.report.errors.append(str(e))


class HTTPCheck(Check):
checks: List[HTTPCheckInstance]

def __init__(self, definition: str):
self.checks = [HTTPCheckInstance(d) for d in definition.split(',')]

def execute(self):
for check in self.checks:
check.execute()

@property
def success(self) -> bool:
return all([c.report.success for c in self.checks])

@property
def report(self) -> Union[CheckReport, List[CheckReport]]:
return [c.report for c in self.checks]
22 changes: 22 additions & 0 deletions app/check/report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import List

import jinja2


class CheckReport:
success: bool
summary: str
errors: List[str]

def __init__(self, success: bool = True, summary: str = '', errors: List[str] = None) -> None:
self.success = success
self.summary = summary
self.errors = errors if errors else []

def render(self) -> str:
env = jinja2.Environment(loader=jinja2.FileSystemLoader("app/views"),
keep_trailing_newline=True)

report_template = env.get_template('report.html')

return report_template.render({'report': self})
62 changes: 13 additions & 49 deletions app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
import os
from datetime import datetime
from typing import Dict, Callable
from urllib.parse import urlparse

import boto3
import redis
import requests
from django.conf import settings
from django.db import connections
from django.http import HttpResponse
from opensearchpy import OpenSearch
from tenacity import retry, stop_after_delay, RetryError, wait_fixed

from celery_worker.tasks import demodjango_task
from .util import render_connection_info, STATUS_SUCCESS, STATUS_FAIL
from .check.check_http import HTTPCheck
from .util import render_connection_info

logger = logging.getLogger("django")

Expand Down Expand Up @@ -77,7 +76,9 @@ def index(request):
f"{settings.ACTIVE_CHECKS if settings.ACTIVE_CHECKS else 'all'}")

return HttpResponse(
"<!doctype html><html><head><title>DemoDjango</title></head><body>"
"<!doctype html><html><head>"
"<title>DemoDjango</title>"
"</head><body>"
f"{''.join(status_check_results)}"
"</body></html>"
)
Expand Down Expand Up @@ -203,48 +204,11 @@ def git_information():


def http_check():
urls = os.environ.get("HTTP_CHECK_URLS", "https://httpstat.us/200|200|GET").split(",")
urls = [u for u in urls if u]

passed = True
message = ""

if not urls:
passed = False
message = ("No urls provided, set HTTP_CHECK_URLS to a comma separated list of "
"URL|STATUS_CODE|METHOD Example: 'http://api.dev.demodjango.internal|200|GET,"
"http://api.dev.demodjango.internal/path|403|POST'")

for url in urls:
segments = url.split("|")
url = segments[0]
url_parsed = urlparse(url)
status = int(segments[1]) if len(segments) > 1 else 200
method = segments[2].lower() if len(segments) > 2 else 'get'
request_success = True

check_message = f"{method.upper()} {url_parsed.hostname}{url_parsed.path} "

requester = getattr(requests, method, None)
if not requester:
check_message += f"invalid HTTP method {method} "
request_success = False

if request_success:
try:
r = requester(url)

if r.status_code != status:
check_message += f"response has status code <code>{r.status_code}</code>, but expected <code>{status}</code> "
passed = False
request_success = False
except Exception as e:
passed = False
request_success = False
check_message += f"{e} "

check_message = f'<span style="color: green">{STATUS_SUCCESS}</span> {check_message}' if request_success else f'<span style="color: red">{STATUS_FAIL}</span> {check_message}'
check_message += "<br>"
message += check_message

return render_connection_info(ALL_CHECKS[HTTP_CONNECTION], passed, message)
urls = os.environ.get("HTTP_CHECK_URLS", "https://httpstat.us/200|200|GET")

check = HTTPCheck(urls)
check.execute()

return render_connection_info(ALL_CHECKS[HTTP_CONNECTION],
check.success,
"".join([c.render() for c in check.report]))
4 changes: 4 additions & 0 deletions app/views/report.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<strong>{{ report.summary }}</strong>
{% for error in report.errors %}
{{ error }}
{% endfor %}
Loading

0 comments on commit b049fe6

Please sign in to comment.