Feat : Various features
Some checks failed
Build and Push Docker Images / docker (push) Failing after 9s
Some checks failed
Build and Push Docker Images / docker (push) Failing after 9s
This commit is contained in:
@@ -5,6 +5,7 @@ Agrège les données de tous les agents et expose une API REST pour le frontend.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import secrets
|
||||
import sqlite3
|
||||
@@ -56,12 +57,22 @@ class VpsConfig(BaseModel):
|
||||
port: int = 8001
|
||||
api_key: str
|
||||
description: str = ""
|
||||
tags: list[str] = []
|
||||
|
||||
|
||||
class ActionRequest(BaseModel):
|
||||
action: str # start | stop | restart
|
||||
|
||||
|
||||
class VpsUpdateRequest(BaseModel):
|
||||
name: str
|
||||
host: str
|
||||
port: int = 8001
|
||||
api_key: str = "" # vide = conserver la clé existante
|
||||
description: str = ""
|
||||
tags: list[str] = []
|
||||
|
||||
|
||||
class ComposeUpdateRequest(BaseModel):
|
||||
project: str
|
||||
|
||||
@@ -108,9 +119,15 @@ def init_db() -> None:
|
||||
host TEXT NOT NULL,
|
||||
port INTEGER NOT NULL DEFAULT 8001,
|
||||
api_key TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT ''
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
tags TEXT NOT NULL DEFAULT '[]'
|
||||
)
|
||||
""")
|
||||
# Migration : ajoute la colonne tags si elle n'existe pas encore
|
||||
try:
|
||||
conn.execute("ALTER TABLE vps ADD COLUMN tags TEXT NOT NULL DEFAULT '[]'")
|
||||
except Exception:
|
||||
pass # colonne déjà présente
|
||||
|
||||
|
||||
init_db()
|
||||
@@ -133,14 +150,21 @@ def add_user(user: dict) -> None:
|
||||
|
||||
def load_vps() -> list[dict]:
|
||||
with get_db() as conn:
|
||||
return [dict(r) for r in conn.execute("SELECT * FROM vps").fetchall()]
|
||||
rows = [dict(r) for r in conn.execute("SELECT * FROM vps").fetchall()]
|
||||
for row in rows:
|
||||
try:
|
||||
row["tags"] = json.loads(row.get("tags") or "[]")
|
||||
except Exception:
|
||||
row["tags"] = []
|
||||
return rows
|
||||
|
||||
|
||||
def insert_vps(vps: dict) -> None:
|
||||
with get_db() as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO vps (id, name, host, port, api_key, description) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(vps["id"], vps["name"], vps["host"], vps["port"], vps["api_key"], vps.get("description", "")),
|
||||
"INSERT INTO vps (id, name, host, port, api_key, description, tags) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
(vps["id"], vps["name"], vps["host"], vps["port"], vps["api_key"],
|
||||
vps.get("description", ""), json.dumps(vps.get("tags", []))),
|
||||
)
|
||||
|
||||
|
||||
@@ -150,6 +174,16 @@ def remove_vps(vps_id: str) -> bool:
|
||||
return cur.rowcount > 0
|
||||
|
||||
|
||||
def update_vps(vps_id: str, data: dict) -> bool:
|
||||
with get_db() as conn:
|
||||
cur = conn.execute(
|
||||
"UPDATE vps SET name=?, host=?, port=?, api_key=?, description=?, tags=? WHERE id=?",
|
||||
(data["name"], data["host"], data["port"], data["api_key"],
|
||||
data["description"], json.dumps(data.get("tags", [])), vps_id),
|
||||
)
|
||||
return cur.rowcount > 0
|
||||
|
||||
|
||||
# ─── Auth helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
def create_token(username: str, role: str) -> str:
|
||||
@@ -229,6 +263,7 @@ async def fetch_vps_status(vps: dict) -> dict:
|
||||
"online": True,
|
||||
"containers": containers_res,
|
||||
"system": system,
|
||||
"tags": vps.get("tags", []),
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
@@ -240,6 +275,7 @@ async def fetch_vps_status(vps: dict) -> dict:
|
||||
"error": str(e),
|
||||
"containers": [],
|
||||
"system": None,
|
||||
"tags": vps.get("tags", []),
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +329,8 @@ def me(current_user: Annotated[dict, Depends(get_current_user)]):
|
||||
def list_vps(_: Annotated[dict, Depends(get_current_user)]):
|
||||
"""Liste les VPS configurés (sans les clés API)."""
|
||||
return [
|
||||
{"id": v["id"], "name": v["name"], "host": v["host"], "description": v.get("description", "")}
|
||||
{"id": v["id"], "name": v["name"], "host": v["host"],
|
||||
"description": v.get("description", ""), "tags": v.get("tags", [])}
|
||||
for v in load_vps()
|
||||
]
|
||||
|
||||
@@ -315,6 +352,24 @@ def delete_vps(vps_id: str, _: Annotated[dict, Depends(get_current_user)]):
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
@app.put("/api/vps/{vps_id}")
|
||||
def edit_vps(vps_id: str, body: VpsUpdateRequest, _: Annotated[dict, Depends(get_current_user)]):
|
||||
"""Met à jour les paramètres d'un VPS (name, host, port, api_key, description)."""
|
||||
existing = next((v for v in load_vps() if v["id"] == vps_id), None)
|
||||
if not existing:
|
||||
raise HTTPException(status_code=404, detail="VPS introuvable")
|
||||
data = {
|
||||
"name": body.name,
|
||||
"host": body.host,
|
||||
"port": body.port,
|
||||
"api_key": body.api_key.strip() or existing["api_key"],
|
||||
"description": body.description,
|
||||
"tags": body.tags,
|
||||
}
|
||||
update_vps(vps_id, data)
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
@app.get("/api/status")
|
||||
async def all_status(_: Annotated[dict, Depends(get_current_user)]):
|
||||
"""Retourne l'état de tous les VPS en parallèle."""
|
||||
|
||||
Reference in New Issue
Block a user