-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add health_check django command (#217)
- Loading branch information
Showing
8 changed files
with
178 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import sys | ||
|
||
from django.core.management.base import BaseCommand | ||
|
||
from health_check.mixins import CheckMixin | ||
|
||
|
||
class Command(CheckMixin, BaseCommand): | ||
help = "Run health checks and exit 0 if everything went well." | ||
|
||
def handle(self, *args, **options): | ||
# perform all checks | ||
errors = self.errors | ||
|
||
for plugin in self.plugins: | ||
style_func = self.style.SUCCESS if not plugin.errors else self.style.ERROR | ||
self.stdout.write( | ||
"{:<24} ... {}\n".format( | ||
plugin.identifier(), | ||
style_func(plugin.pretty_status()) | ||
) | ||
) | ||
|
||
if errors: | ||
sys.exit(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import copy | ||
|
||
from concurrent.futures import ThreadPoolExecutor | ||
|
||
from health_check.conf import HEALTH_CHECK | ||
from health_check.exceptions import ServiceWarning | ||
from health_check.plugins import plugin_dir | ||
|
||
|
||
class CheckMixin: | ||
_errors = None | ||
_plugins = None | ||
|
||
@property | ||
def errors(self): | ||
if not self._errors: | ||
self._errors = self.run_check() | ||
return self._errors | ||
|
||
@property | ||
def plugins(self): | ||
if not self._plugins: | ||
self._plugins = sorted(( | ||
plugin_class(**copy.deepcopy(options)) | ||
for plugin_class, options in plugin_dir._registry | ||
), key=lambda plugin: plugin.identifier()) | ||
return self._plugins | ||
|
||
def run_check(self): | ||
errors = [] | ||
|
||
def _run(plugin): | ||
plugin.run_check() | ||
try: | ||
return plugin | ||
finally: | ||
from django.db import connection | ||
connection.close() | ||
|
||
with ThreadPoolExecutor(max_workers=len(self.plugins) or 1) as executor: | ||
for plugin in executor.map(_run, self.plugins): | ||
if plugin.critical_service: | ||
if not HEALTH_CHECK['WARNINGS_AS_ERRORS']: | ||
errors.extend( | ||
e for e in plugin.errors | ||
if not isinstance(e, ServiceWarning) | ||
) | ||
else: | ||
errors.extend(plugin.errors) | ||
|
||
return errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from io import StringIO | ||
|
||
import pytest | ||
|
||
from health_check.backends import BaseHealthCheckBackend | ||
from health_check.plugins import plugin_dir | ||
|
||
from django.core.management import call_command | ||
|
||
|
||
class FailPlugin(BaseHealthCheckBackend): | ||
def check_status(self): | ||
self.add_error('Oops') | ||
|
||
|
||
class OkPlugin(BaseHealthCheckBackend): | ||
def check_status(self): | ||
pass | ||
|
||
|
||
class TestCommand: | ||
@pytest.yield_fixture(autouse=True) | ||
def setup(self): | ||
plugin_dir.reset() | ||
plugin_dir.register(FailPlugin) | ||
plugin_dir.register(OkPlugin) | ||
yield | ||
plugin_dir.reset() | ||
|
||
def test_command(self): | ||
stdout = StringIO() | ||
with pytest.raises(SystemExit): | ||
call_command("health_check", stdout=stdout) | ||
stdout.seek(0) | ||
assert stdout.read() == ( | ||
"FailPlugin ... unknown error: Oops\n" | ||
"OkPlugin ... working\n" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import pytest | ||
|
||
from health_check.backends import BaseHealthCheckBackend | ||
from health_check.mixins import CheckMixin | ||
from health_check.plugins import plugin_dir | ||
|
||
|
||
class FailPlugin(BaseHealthCheckBackend): | ||
def check_status(self): | ||
self.add_error('Oops') | ||
|
||
|
||
class OkPlugin(BaseHealthCheckBackend): | ||
def check_status(self): | ||
pass | ||
|
||
|
||
class Checker(CheckMixin): | ||
pass | ||
|
||
|
||
class TestCheckMixin: | ||
@pytest.yield_fixture(autouse=True) | ||
def setup(self): | ||
plugin_dir.reset() | ||
plugin_dir.register(FailPlugin) | ||
plugin_dir.register(OkPlugin) | ||
yield | ||
plugin_dir.reset() | ||
|
||
def test_plugins(self): | ||
assert len(Checker().plugins) == 2 | ||
|
||
def test_errors(self): | ||
assert len(Checker().errors) == 1 | ||
|
||
def test_run_check(self): | ||
assert len(Checker().run_check()) == 1 |