Infra_ansible_dockercompose/stacks/glance/container-builder/generate_containers_block.py

125 lines
4.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
import docker
import yaml
import os
import json
import requests
from bs4 import BeautifulSoup
client = docker.from_env()
containers = client.containers.list()
output = {}
print(f"[•] Détection de {len(containers)} conteneur(s)...\n")
override_path = "/app/config/icon_overrides.json"
overrides = {}
# Charger les overrides si présents
if os.path.exists(override_path):
with open(override_path, "r", encoding="utf-8") as f:
overrides = json.load(f)
def extract_image_name(image):
name = image.split("/")[-1]
return name.split(":")[0] if ":" in name else name
def find_favicon(url, project_name, image_name):
print(f"[→] Recherche favicon pour {url}")
# Override manuel ?
if project_name in overrides and overrides[project_name]:
print(f"[✓] Favicon forcé depuis override : {overrides[project_name]}")
return overrides[project_name]
icon_url = None
try:
r = requests.get(url, timeout=5)
r.raise_for_status()
soup = BeautifulSoup(r.text, 'html.parser')
icons = soup.find_all("link", rel=lambda x: x and 'icon' in x.lower())
if icons:
href = icons[0].get("href")
if href:
icon_url = href if href.startswith("http") else url.rstrip("/") + "/" + href.lstrip("/")
print(f"[✓] Favicon trouvé via HTML : {icon_url}")
return icon_url
else:
print("[✗] Aucun favicon trouvé dans HTML")
except Exception:
print(f"[✗] Impossible de charger HTML depuis {url}")
test_favicon = f"{url.rstrip('/')}/favicon.ico"
try:
r = requests.get(test_favicon, timeout=5)
if r.ok:
print(f"[✓] Favicon trouvé via /favicon.ico : {test_favicon}")
return test_favicon
except:
pass
github_icon = f"https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/png/{project_name}.png"
try:
r = requests.get(github_icon, timeout=5)
if r.ok:
print(f"[✓] Favicon fallback via GitHub (project_name) : {github_icon}")
return github_icon
except:
print(f"[✗] Pas dicône GitHub pour {project_name}")
github_icon = f"https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/png/{image_name}.png"
try:
r = requests.get(github_icon, timeout=5)
if r.ok:
print(f"[✓] Favicon fallback via GitHub (image) : {github_icon}")
return github_icon
except:
print(f"[✗] Pas dicône GitHub pour {image_name}")
print("[✗] Aucun favicon disponible\n")
return None
for container in containers:
labels = container.labels
name = container.name
image_name = extract_image_name(container.image.tags[0]) if container.image.tags else container.image.short_id
project_name = labels.get("com.docker.compose.project", name).lower()
print(f"[•] Analyse du conteneur : {name} (projet : {project_name})")
domain = None
for key, value in labels.items():
if key.startswith(f"traefik.http.routers.{project_name}-prod.rule") and "Host(`" in value:
domain = value.split("Host(`")[1].split("`)")[0]
break
if domain:
url = f"https://{domain}"
icon = find_favicon(url, project_name, image_name)
output[name] = {
"name": project_name.capitalize(),
"url": url,
"icon": icon or "mdi:web",
"hide": False
}
if project_name not in overrides:
overrides[project_name] = ""
print(f"[✓] Conteneur ajouté : {project_name}{url}\n")
else:
print("[!] Aucune règle Traefik -prod trouvée pour ce conteneur.\n")
# Générer fichiers
os.makedirs("/output", exist_ok=True)
with open("/output/containers.yml", "w", encoding="utf-8") as f:
yaml.dump({"containers": output}, f, sort_keys=False)
with open(override_path, "w", encoding="utf-8") as f:
json.dump(overrides, f, indent=2, ensure_ascii=False)
print("✅ Fichier containers.yml généré : /output/containers.yml")
print(f"✅ Fichier overrides mis à jour : {override_path}")