Skip to content

Commit 51ab8c9

Browse files
Add health check endpoint at /api/healthz (#128)
1 parent 5f14922 commit 51ab8c9

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

api/app.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
bugs_views,
2727
exception_views,
2828
groups_views,
29+
health_check_views,
2930
roles_views,
3031
tags_views,
3132
users_views,
@@ -128,6 +129,9 @@ def create_app(testing: Optional[bool] = False) -> Flask:
128129

129130
@app.before_request
130131
def authenticate_request() -> Optional[ResponseReturnValue]:
132+
# Skip authentication for health check endpoint
133+
if request.path.startswith("/api/healthz"):
134+
return None
131135
return AuthenticationHelpers.authenticate_user(request)
132136

133137
@app.after_request
@@ -202,6 +206,7 @@ def add_headers(response: Response) -> ResponseReturnValue:
202206
warnings.filterwarnings("ignore", message="Only explicitly-declared fields will be included in the Schema Object")
203207

204208
app.register_blueprint(exception_views.bp)
209+
app.register_blueprint(health_check_views.bp)
205210
app.register_blueprint(access_requests_views.bp)
206211
access_requests_views.register_docs()
207212
app.register_blueprint(apps_views.bp)

api/views/health_check_views.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from typing import Any
2+
3+
from flask import Blueprint
4+
from sqlalchemy import text
5+
6+
from api.extensions import db
7+
8+
bp_name = "api-health-check"
9+
bp_url_prefix = "/api/healthz"
10+
bp = Blueprint(bp_name, __name__, url_prefix=bp_url_prefix)
11+
12+
13+
@bp.route("", methods=["GET"])
14+
def health_check() -> Any:
15+
try:
16+
db.session.execute(text("SELECT 1"))
17+
except Exception as e:
18+
return {"status": "error", "error": str(e)}, 500
19+
20+
return {"status": "ok"}, 200

examples/kubernetes/deployment.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,8 @@ spec:
5656
name: access
5757
ports:
5858
- containerPort: 3000
59+
livenessProbe:
60+
httpGet:
61+
path: /api/healthz
62+
port: 3000
5963
serviceAccountName: access

tests/test_health_check.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from flask import Flask, url_for
2+
from flask.testing import FlaskClient
3+
from flask_sqlalchemy import SQLAlchemy
4+
5+
6+
def test_health_check(app: Flask, client: FlaskClient, db: SQLAlchemy) -> None:
7+
# test unauthenticated requests by setting the current user email to "Unauthenticated"
8+
app.config["CURRENT_OKTA_USER_EMAIL"] = "Unauthenticated"
9+
10+
# test 200
11+
health_check_url = url_for("api-health-check.health_check")
12+
rep = client.get(health_check_url)
13+
assert rep.status_code == 200

0 commit comments

Comments
 (0)