Add Arcane project restart
This commit is contained in:
@@ -4,7 +4,8 @@ from aiogram.types import Message
|
|||||||
from app import dp, cfg
|
from app import dp, cfg
|
||||||
from auth import is_admin_msg
|
from auth import is_admin_msg
|
||||||
from keyboards import docker_kb, arcane_kb
|
from keyboards import docker_kb, arcane_kb
|
||||||
from services.arcane import list_projects
|
from services.arcane import list_projects, restart_project
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
|
||||||
|
|
||||||
|
|
||||||
def _arcane_cfg():
|
def _arcane_cfg():
|
||||||
@@ -27,15 +28,20 @@ async def cmd_arcane_projects(msg: Message):
|
|||||||
return
|
return
|
||||||
|
|
||||||
lines = ["🧰 Arcane projects\n"]
|
lines = ["🧰 Arcane projects\n"]
|
||||||
|
rows = []
|
||||||
for p in items:
|
for p in items:
|
||||||
status = p.get("status", "unknown")
|
status = p.get("status", "unknown")
|
||||||
name = p.get("name", "?")
|
name = p.get("name", "?")
|
||||||
|
pid = p.get("id", "")
|
||||||
running = p.get("runningCount", 0)
|
running = p.get("runningCount", 0)
|
||||||
total = p.get("serviceCount", 0)
|
total = p.get("serviceCount", 0)
|
||||||
icon = "🟢" if status == "running" else "🟡"
|
icon = "🟢" if status == "running" else "🟡"
|
||||||
lines.append(f"{icon} {name}: {status} ({running}/{total})")
|
lines.append(f"{icon} {name}: {status} ({running}/{total})")
|
||||||
|
if pid:
|
||||||
|
rows.append([InlineKeyboardButton(text=f"🔄 {name}", callback_data=f"arcane:restart:{pid}")])
|
||||||
|
|
||||||
await msg.answer("\n".join(lines), reply_markup=arcane_kb)
|
kb = InlineKeyboardMarkup(inline_keyboard=rows) if rows else arcane_kb
|
||||||
|
await msg.answer("\n".join(lines), reply_markup=kb)
|
||||||
|
|
||||||
asyncio.create_task(worker())
|
asyncio.create_task(worker())
|
||||||
|
|
||||||
@@ -50,3 +56,22 @@ async def arcane_menu(msg: Message):
|
|||||||
async def arcane_refresh(msg: Message):
|
async def arcane_refresh(msg: Message):
|
||||||
if is_admin_msg(msg):
|
if is_admin_msg(msg):
|
||||||
await cmd_arcane_projects(msg)
|
await cmd_arcane_projects(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@dp.callback_query(F.data.startswith("arcane:restart:"))
|
||||||
|
async def arcane_restart(cb: CallbackQuery):
|
||||||
|
if cb.from_user.id != cfg["telegram"]["admin_id"]:
|
||||||
|
return
|
||||||
|
|
||||||
|
_, _, pid = cb.data.split(":", 2)
|
||||||
|
base_url, api_key, env_id = _arcane_cfg()
|
||||||
|
if not base_url or not api_key:
|
||||||
|
await cb.answer("Arcane config missing")
|
||||||
|
return
|
||||||
|
|
||||||
|
await cb.answer("Restarting…")
|
||||||
|
ok, info = await asyncio.to_thread(restart_project, base_url, api_key, env_id, pid)
|
||||||
|
if ok:
|
||||||
|
await cb.message.answer("✅ Arcane restart triggered", reply_markup=arcane_kb)
|
||||||
|
else:
|
||||||
|
await cb.message.answer(f"❌ Arcane restart failed: {info}", reply_markup=arcane_kb)
|
||||||
|
|||||||
@@ -25,3 +25,26 @@ def list_projects(base_url: str, api_key: str, env_id: int, timeout: int = 10) -
|
|||||||
return False, "API returned success=false", []
|
return False, "API returned success=false", []
|
||||||
|
|
||||||
return True, "OK", payload.get("data", [])
|
return True, "OK", payload.get("data", [])
|
||||||
|
|
||||||
|
|
||||||
|
def restart_project(base_url: str, api_key: str, env_id: int, project_id: str, timeout: int = 20) -> tuple[bool, str]:
|
||||||
|
url = f"{base_url.rstrip('/')}/api/environments/{env_id}/projects/{project_id}/restart"
|
||||||
|
req = Request(url, method="POST", headers={"X-Api-Key": api_key})
|
||||||
|
try:
|
||||||
|
with urlopen(req, timeout=timeout) as resp:
|
||||||
|
raw = resp.read().decode("utf-8", errors="ignore")
|
||||||
|
except HTTPError as e:
|
||||||
|
return False, f"HTTP {e.code}"
|
||||||
|
except URLError as e:
|
||||||
|
return False, f"URL error: {e.reason}"
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"Error: {e}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
payload = json.loads(raw) if raw else {}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
payload = {}
|
||||||
|
|
||||||
|
if payload and not payload.get("success", True):
|
||||||
|
return False, "API returned success=false"
|
||||||
|
return True, "OK"
|
||||||
|
|||||||
Reference in New Issue
Block a user