Feat: implement dynamic agent version fetching and update mechanism
All checks were successful
Build and Push Docker Images / docker (push) Successful in 16s

This commit is contained in:
jeanotx32
2026-06-02 20:06:39 -04:00
parent b2b660e035
commit 38bc430348
2 changed files with 43 additions and 4 deletions

View File

@@ -8,6 +8,7 @@ import asyncio
import base64 import base64
import json import json
import os import os
import re
import secrets import secrets
import sqlite3 import sqlite3
import time import time
@@ -47,7 +48,18 @@ from webauthn.helpers.structs import (
# ─── Config ─────────────────────────────────────────────────────────────────── # ─── Config ───────────────────────────────────────────────────────────────────
DB_FILE = Path(os.getenv("DB_FILE", "data/monitor.db")) DB_FILE = Path(os.getenv("DB_FILE", "data/monitor.db"))
EXPECTED_AGENT_VERSION = os.getenv("EXPECTED_AGENT_VERSION", "1.2.0")
# Version de référence : d'abord env var explicite, sinon récupérée dynamiquement depuis le dépôt
_FORCED_AGENT_VERSION = os.getenv("EXPECTED_AGENT_VERSION", "") # si non vide, court-circuite le fetch
REPO_AGENT_URL = os.getenv(
"REPO_AGENT_URL",
"https://git.jeanbonapp.com/jeanbon/ScriptVPS/raw/branch/main/vps-monitor/agent/agent.py",
)
_latest_agent_version: str = _FORCED_AGENT_VERSION or "unknown"
def _get_expected_version() -> str:
return _latest_agent_version
# ─── Ring buffer de stats (en mémoire) ─────────────────────────────────────── # ─── Ring buffer de stats (en mémoire) ───────────────────────────────────────
_STATS_MAX_POINTS = 120 # 10 min à 5 s d'intervalle _STATS_MAX_POINTS = 120 # 10 min à 5 s d'intervalle
@@ -541,8 +553,8 @@ async def fetch_vps_status(vps: dict) -> dict:
"system": system, "system": system,
"tags": vps.get("tags", []), "tags": vps.get("tags", []),
"agent_version": agent_version, "agent_version": agent_version,
"expected_agent_version": EXPECTED_AGENT_VERSION, "expected_agent_version": _get_expected_version(),
"agent_up_to_date": agent_version == EXPECTED_AGENT_VERSION, "agent_up_to_date": agent_version == _get_expected_version() and _get_expected_version() != "unknown",
} }
except Exception as e: except Exception as e:
return { return {
@@ -557,7 +569,7 @@ async def fetch_vps_status(vps: dict) -> dict:
"system": None, "system": None,
"tags": vps.get("tags", []), "tags": vps.get("tags", []),
"agent_version": None, "agent_version": None,
"expected_agent_version": EXPECTED_AGENT_VERSION, "expected_agent_version": _get_expected_version(),
"agent_up_to_date": False, "agent_up_to_date": False,
} }
@@ -614,10 +626,37 @@ async def _stats_collector() -> None:
await asyncio.sleep(5) await asyncio.sleep(5)
async def _refresh_latest_agent_version() -> None:
"""Récupère AGENT_VERSION depuis le dépôt Gitea toutes les heures.
Si EXPECTED_AGENT_VERSION est défini en env var, cette tâche n'écrase pas la valeur forcée.
"""
global _latest_agent_version
if _FORCED_AGENT_VERSION:
return # version forcée par env var — pas besoin de fetcher
while True:
try:
timeout = aiohttp.ClientTimeout(total=10)
async with aiohttp.ClientSession() as session:
async with session.get(REPO_AGENT_URL, timeout=timeout) as r:
if r.status == 200:
text = await r.text()
m = re.search(
r'^AGENT_VERSION\s*=\s*["\']([^"\']+)["\']',
text,
re.MULTILINE,
)
if m:
_latest_agent_version = m.group(1)
except Exception:
pass # garder la dernière valeur connue en cas d'erreur réseau
await asyncio.sleep(3600) # rafraîchit toutes les heures
@app.on_event("startup") @app.on_event("startup")
async def startup_event() -> None: async def startup_event() -> None:
asyncio.create_task(_stats_collector()) asyncio.create_task(_stats_collector())
asyncio.create_task(_cleanup_old_stats()) asyncio.create_task(_cleanup_old_stats())
asyncio.create_task(_refresh_latest_agent_version())
async def _cleanup_old_stats() -> None: async def _cleanup_old_stats() -> None: