Add URL health checks from config
This commit is contained in:
@@ -28,4 +28,6 @@ docker:
|
||||
tg-admin-bot: "tg-admin-bot"
|
||||
# Explicit list used by legacy modules
|
||||
containers:
|
||||
tg-admin-bot: "tg-admin-bot"
|
||||
tg-admin-bot:
|
||||
name: "tg-admin-bot"
|
||||
url: "http://127.0.0.1:8080/health"
|
||||
|
||||
@@ -17,7 +17,7 @@ async def help_cmd(msg: Message):
|
||||
"🐳 Docker — управление контейнерами\n"
|
||||
"📦 Backup — restic бэкапы\n"
|
||||
"🧉 Artifacts — критичные образы (Clonezilla, NAND)\n"
|
||||
"⚙️ System — диски, безопасность, reboot\n\n"
|
||||
"⚙️ System — диски, безопасность, URL, reboot\n\n"
|
||||
"Inline-кнопки используются для выбора контейнеров.",
|
||||
reply_markup=menu_kb,
|
||||
parse_mode="Markdown",
|
||||
|
||||
@@ -4,6 +4,9 @@ from app import dp
|
||||
from auth import is_admin_msg
|
||||
from keyboards import system_kb
|
||||
from system_checks import security, disks
|
||||
from app import cfg
|
||||
from services.http_checks import get_url_checks, check_url
|
||||
import asyncio
|
||||
|
||||
|
||||
@dp.message(F.text == "💽 Disks")
|
||||
@@ -16,3 +19,34 @@ async def sd(msg: Message):
|
||||
async def sec(msg: Message):
|
||||
if is_admin_msg(msg):
|
||||
await msg.answer(security(), reply_markup=system_kb)
|
||||
|
||||
|
||||
@dp.message(F.text == "🌐 URLs")
|
||||
async def urls(msg: Message):
|
||||
if not is_admin_msg(msg):
|
||||
return
|
||||
|
||||
checks = list(get_url_checks(cfg))
|
||||
if not checks:
|
||||
await msg.answer("⚠️ Нет URL для проверки", reply_markup=system_kb)
|
||||
return
|
||||
|
||||
await msg.answer("⏳ Проверяю URL…", reply_markup=system_kb)
|
||||
|
||||
async def worker():
|
||||
tasks = [asyncio.to_thread(check_url, url) for _, url in checks]
|
||||
results = await asyncio.gather(*tasks)
|
||||
|
||||
lines = ["🌐 URLs\n"]
|
||||
for (alias, url), (ok, status, ms, err) in zip(checks, results):
|
||||
if ok:
|
||||
lines.append(f"🟢 {alias}: {status} ({ms}ms)")
|
||||
elif status is not None:
|
||||
lines.append(f"🔴 {alias}: {status} ({ms}ms)")
|
||||
else:
|
||||
reason = err or "error"
|
||||
lines.append(f"🔴 {alias}: {reason} ({ms}ms)")
|
||||
|
||||
await msg.answer("\n".join(lines), reply_markup=system_kb)
|
||||
|
||||
asyncio.create_task(worker())
|
||||
|
||||
@@ -49,6 +49,7 @@ artifacts_kb = ReplyKeyboardMarkup(
|
||||
system_kb = ReplyKeyboardMarkup(
|
||||
keyboard=[
|
||||
[KeyboardButton(text="💽 Disks"), KeyboardButton(text="🔐 Security")],
|
||||
[KeyboardButton(text="🌐 URLs")],
|
||||
[KeyboardButton(text="🔄 Reboot")],
|
||||
[KeyboardButton(text="⬅️ Назад")],
|
||||
],
|
||||
|
||||
38
services/http_checks.py
Normal file
38
services/http_checks.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import time
|
||||
from typing import Iterable, Tuple
|
||||
from urllib.error import HTTPError, URLError
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
|
||||
def get_url_checks(cfg) -> Iterable[Tuple[str, str]]:
|
||||
docker_cfg = cfg.get("docker", {})
|
||||
containers = docker_cfg.get("containers", {})
|
||||
for alias, value in containers.items():
|
||||
if isinstance(value, str):
|
||||
continue
|
||||
if isinstance(value, dict):
|
||||
url = value.get("url")
|
||||
if url:
|
||||
yield alias, url
|
||||
|
||||
|
||||
def check_url(url: str, timeout: int = 5) -> Tuple[bool, int | None, int | None, str | None]:
|
||||
start = time.time()
|
||||
req = Request(url, headers={"User-Agent": "tg-admin-bot"})
|
||||
try:
|
||||
with urlopen(req, timeout=timeout) as resp:
|
||||
status = int(resp.status)
|
||||
except HTTPError as e:
|
||||
status = int(e.code)
|
||||
elapsed_ms = int((time.time() - start) * 1000)
|
||||
return False, status, elapsed_ms, None
|
||||
except URLError as e:
|
||||
elapsed_ms = int((time.time() - start) * 1000)
|
||||
return False, None, elapsed_ms, str(e.reason)
|
||||
except Exception as e:
|
||||
elapsed_ms = int((time.time() - start) * 1000)
|
||||
return False, None, elapsed_ms, str(e)
|
||||
|
||||
elapsed_ms = int((time.time() - start) * 1000)
|
||||
ok = status < 400
|
||||
return ok, status, elapsed_ms, None
|
||||
Reference in New Issue
Block a user