Add KUMA monitoring UI

This commit is contained in:
“Naeel”
2026-08-26 13:55:47 +03:00
parent 4e05eeffe1
commit 8a15e705cd
2 changed files with 26 additions and 15 deletions
+3 -1
View File
@@ -125,7 +125,7 @@ WHITELIST_TIMEOUT=10
## Версионирование ## Версионирование
Версия KUMA установлена в `0.0.1`. В дальнейшем увеличивается только третья позиция: `0.0.*`. Версия KUMA установлена в `0.0.2`. В дальнейшем увеличивается только третья позиция: `0.0.*`.
## SMTP-алерты ## SMTP-алерты
@@ -141,3 +141,5 @@ SMTP_SUBJECT_PREFIX=[KUMA]
``` ```
Для сортировки почты добавлен префикс темы `[KUMA]`. `SMTP_FROM` остаётся реальным адресом SMTP-аккаунта; несуществующий адрес отправителя не используется. Для сортировки почты добавлен префикс темы `[KUMA]`. `SMTP_FROM` остаётся реальным адресом SMTP-аккаунта; несуществующий адрес отправителя не используется.
Добавлен UI на `/` для ручной проверки whitelist и отправки алерта. Whitelist URL предустановлен: `https://whitelist.nodejsk8s.services.ngcloud.ru/v2/app`.
+23 -14
View File
@@ -4,11 +4,11 @@ import smtplib
import ssl import ssl
from email.message import EmailMessage from email.message import EmailMessage
from flask import Flask, jsonify from flask import Flask, jsonify, request
import requests import requests
app = Flask(__name__) app = Flask(__name__)
VERSION = "0.0.1" VERSION = "0.0.2"
WHITELIST_URL = os.getenv( WHITELIST_URL = os.getenv(
"WHITELIST_URL", "WHITELIST_URL",
"https://whitelist.nodejsk8s.services.ngcloud.ru/v2/app", "https://whitelist.nodejsk8s.services.ngcloud.ru/v2/app",
@@ -26,13 +26,14 @@ def mariadb_configuration():
} }
def check_whitelist(): def check_whitelist(url=None):
url = url or WHITELIST_URL
headers = {} headers = {}
token = os.getenv("WHITELIST_TOKEN") token = os.getenv("WHITELIST_TOKEN")
if token: if token:
headers["Authorization"] = f"Bearer {token}" headers["Authorization"] = f"Bearer {token}"
response = requests.get( response = requests.get(
WHITELIST_URL, url,
headers=headers, headers=headers,
allow_redirects=False, allow_redirects=False,
timeout=int(os.getenv("WHITELIST_TIMEOUT", "10")), timeout=int(os.getenv("WHITELIST_TIMEOUT", "10")),
@@ -40,7 +41,7 @@ def check_whitelist():
content_type = response.headers.get("Content-Type", "") content_type = response.headers.get("Content-Type", "")
body = response.json() if "json" in content_type else response.text body = response.json() if "json" in content_type else response.text
return { return {
"url": WHITELIST_URL, "url": url,
"status": response.status_code, "status": response.status_code,
"location": response.headers.get("Location"), "location": response.headers.get("Location"),
"body": body, "body": body,
@@ -66,13 +67,20 @@ def send_alert(subject, body):
@app.get("/") @app.get("/")
def index(): def index():
return jsonify({ return """<!doctype html>
"service": "kuma", <html lang="ru"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
"version": VERSION, <title>KUMA</title><style>
"state": "stateless", body{font-family:system-ui,sans-serif;max-width:760px;margin:40px auto;padding:0 20px;color:#172033;background:#f4f7fb}
"target": "https://whitelist.nodejsk8s.services.ngcloud.ru/", main{background:#fff;border:1px solid #dbe3ef;border-radius:12px;padding:24px;box-shadow:0 8px 24px #17203312}
"mariadb": mariadb_configuration(), h1{margin-top:0}label{display:block;margin:14px 0 6px;font-weight:600}input,textarea{width:100%;padding:10px;border:1px solid #bcc8d8;border-radius:6px;box-sizing:border-box}button{margin-top:18px;padding:10px 16px;border:0;border-radius:6px;background:#1769d1;color:white;cursor:pointer}button+button{margin-left:8px;background:#53657d}pre{white-space:pre-wrap;background:#f0f4f8;padding:14px;border-radius:6px;margin-top:20px;min-height:60px}
}) </style></head><body><main><h1>KUMA</h1><p>Мониторинг whitelist и почтовые алерты. Версия __VERSION__.</p>
<label for="url">Whitelist URL</label><input id="url" value="__URL__">
<button onclick="check()">Проверить whitelist</button><button onclick="alertNow()">Отправить алерт</button><pre id="result">Готово к проверке</pre>
</main><script>
const result=document.getElementById('result');
async function check(){result.textContent='Проверка...';const r=await fetch('/check?url='+encodeURIComponent(document.getElementById('url').value));result.textContent=JSON.stringify(await r.json(),null,2)}
async function alertNow(){result.textContent='Отправка...';const r=await fetch('/alert',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url:document.getElementById('url').value})});result.textContent=JSON.stringify(await r.json(),null,2)}
</script></body></html>""".replace("__VERSION__", VERSION).replace("__URL__", WHITELIST_URL)
@app.get("/health") @app.get("/health")
@@ -83,7 +91,8 @@ def health():
@app.get("/check") @app.get("/check")
def check(): def check():
try: try:
result = check_whitelist() url = request.args.get("url")
result = check_whitelist(url)
return jsonify({"ok": 200 <= result["status"] < 300, **result}) return jsonify({"ok": 200 <= result["status"] < 300, **result})
except requests.RequestException as exc: except requests.RequestException as exc:
return jsonify({"ok": False, "url": WHITELIST_URL, "error": str(exc)}), 502 return jsonify({"ok": False, "url": WHITELIST_URL, "error": str(exc)}), 502
@@ -91,7 +100,7 @@ def check():
@app.post("/alert") @app.post("/alert")
def alert(): def alert():
payload = requests.get(WHITELIST_URL, timeout=10).text payload = requests.get(request.json.get("url", WHITELIST_URL), timeout=10).text
try: try:
send_alert("KUMA whitelist alert", payload) send_alert("KUMA whitelist alert", payload)
return jsonify({"ok": True, "sent": True}) return jsonify({"ok": True, "sent": True})