mkdocs-auto/script_creator.py

132 lines
5.0 KiB
Python

from flask import Flask, request, jsonify
import os
import subprocess
import base64
import requests
from redlock import Redlock
from threading import Thread, Lock
import time
app = Flask(__name__)
# Variables d'environnement
MINIO_BUCKET = os.getenv("MINIO_BUCKET", "nextcloud")
MINIO_HOST = os.getenv("MINIO_HOST", "minio.minio.svc.cluster.local:9000")
MINIO_REGION = os.getenv("MINIO_REGION", "us-east-1")
MINIO_MOUNT_PATH = "/mnt"
N8N_WEBHOOK_URL = os.getenv("N8N_WEBHOOK_URL", "https://n8n.n8n.svc.kube.ia86.cc/webhook/7950310f-e526-475a-82d1-63818da79339")
DEBUG = bool(os.getenv("DEBUG", False))
S3_ACCESS_KEY = os.getenv("S3_ACCESS_KEY")
S3_SECRET_KEY = os.getenv("S3_SECRET_KEY")
if not S3_ACCESS_KEY or not S3_SECRET_KEY:
raise ValueError("❌ ERREUR: S3_ACCESS_KEY ou S3_SECRET_KEY manquantes")
redis_host = os.getenv("REDIS_HOST", "redis.redis.svc.cluster.local")
redis_port = int(os.getenv("REDIS_PORT", 6379))
dlm = Redlock([{"host": redis_host, "port": redis_port, "db": 0}])
S3_UNMOUNT_CHECK_INTERVAL = int(os.getenv("S3_UNMOUNT_CHECK_INTERVAL", 300)) # 5 minutes par défaut
lock_prefix = "lock:mkdocs:"
local_lock = Lock()
def log_debug(msg):
if DEBUG:
print(f"🔍 DEBUG: {msg}")
def mount_s3():
with local_lock:
if not os.path.ismount(MINIO_MOUNT_PATH):
os.makedirs(MINIO_MOUNT_PATH, exist_ok=True)
credentials_file = "/etc/passwd-s3fs"
with open(credentials_file, "w") as f:
f.write(f"{S3_ACCESS_KEY}:{S3_SECRET_KEY}\n")
os.chmod(credentials_file, 0o600)
cmd = (
f"s3fs {MINIO_BUCKET} {MINIO_MOUNT_PATH} "
f"-o passwd_file={credentials_file} "
f"-o url=https://{MINIO_HOST} "
"-o use_path_request_style "
"-o allow_other"
)
log_debug(f"🚀 Montage S3: {cmd}")
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
log_debug(f"❌ Erreur montage: {result.stderr}")
raise RuntimeError(f"Erreur montage: {result.stderr}")
log_debug("✅ Montage réussi.")
else:
log_debug("✅ Montage S3 déjà actif.")
def unmount_s3():
with local_lock:
if os.path.ismount(MINIO_MOUNT_PATH):
cmd = f"fusermount -u {MINIO_MOUNT_PATH}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode == 0:
log_debug("✅ Démontage S3 réussi.")
else:
log_debug(f"⚠️ Échec démontage S3: {result.stderr}")
def unmount_checker():
while True:
time.sleep(S3_UNMOUNT_CHECK_INTERVAL)
log_debug("⏰ Vérification périodique pour démontage S3...")
# Vérification si aucun build actif
active_locks = dlm.redis_clients[0].keys(f"{lock_prefix}*")
if not active_locks:
log_debug("🟢 Aucun build actif, démontage S3...")
unmount_s3()
else:
log_debug("🔴 Builds en cours détectés, S3 reste monté.")
@app.route("/build", methods=["POST"])
def build_mkdocs():
data = request.json
website = data.get("WEBSITE")
error_callback = data.get("ERROR_CALLBACK", N8N_WEBHOOK_URL)
if not website:
return jsonify({"error": "WEBSITE manquant"}), 400
lock_key = f"{lock_prefix}{website}"
lock = dlm.lock(lock_key, 60000)
if not lock:
log_debug(f"⚠️ Build déjà actif: {website}")
return jsonify({"status": "busy", "message": f"Build déjà actif: {website}"}), 429
try:
mount_s3()
src = f"{MINIO_MOUNT_PATH}/files/sites/@{website}/mkdocs.yml"
tmp = f"/srv/{website}"
if not os.path.exists(src):
log_debug(f"❌ Config introuvable: {src}")
return jsonify({"error": f"{src} introuvable"}), 404
cmd = f"mkdocs build --quiet --no-strict --config-file {src} --site-dir {tmp}"
log_debug(f"🚀 Build MkDocs: {cmd}")
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
build_error = base64.b64encode(result.stderr.encode()).decode()
json_payload = {"site": website, "erreur": build_error}
log_debug(f"❌ Échec build: {result.stderr}")
requests.post(error_callback, json=json_payload, headers={"Content-Type": "application/json"})
return jsonify({"status": "error", "message": "Build échoué", "error": result.stderr}), 500
log_debug(f"✅ Build réussi: {website}")
return jsonify({"status": "success", "message": "Build réussi"}), 200
finally:
dlm.unlock(lock)
log_debug(f"🔓 Verrou libéré: {website}")
if __name__ == "__main__":
log_debug("🚀 Flask démarré (0.0.0.0:80)")
checker_thread = Thread(target=unmount_checker, daemon=True)
checker_thread.start()
app.run(host="0.0.0.0", port=80)