Add import_environnement: colonne environnement + import CSV iTop verbatim
This commit is contained in:
parent
0f031b2150
commit
242641a085
123
tools/import_environnement.py
Normal file
123
tools/import_environnement.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
"""Ajoute colonne environnement sur servers et importe depuis CSV iTop.
|
||||||
|
|
||||||
|
Stocke les 7 valeurs iTop verbatim: Développement, Intégration, Pré-Prod,
|
||||||
|
Production, Recette, Test, Formation.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python tools/import_environnement.py <csv1> [<csv2> ...] [--dry-run]
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import csv
|
||||||
|
import argparse
|
||||||
|
from sqlalchemy import create_engine, text
|
||||||
|
|
||||||
|
DATABASE_URL = os.getenv("DATABASE_URL_DEMO") or os.getenv("DATABASE_URL") \
|
||||||
|
or "postgresql://patchcenter:PatchCenter2026!@localhost:5432/patchcenter_demo"
|
||||||
|
|
||||||
|
ITOP_ENVS = [
|
||||||
|
"Développement", "Intégration", "Pré-Prod",
|
||||||
|
"Production", "Recette", "Test", "Formation",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Aliases courants -> valeur iTop canonique
|
||||||
|
ENV_ALIASES = {
|
||||||
|
"developpement": "Développement",
|
||||||
|
"dev": "Développement",
|
||||||
|
"integration": "Intégration",
|
||||||
|
"int": "Intégration",
|
||||||
|
"preprod": "Pré-Prod",
|
||||||
|
"pre-prod": "Pré-Prod",
|
||||||
|
"pre prod": "Pré-Prod",
|
||||||
|
"prod": "Production",
|
||||||
|
"production": "Production",
|
||||||
|
"recette": "Recette",
|
||||||
|
"rec": "Recette",
|
||||||
|
"test": "Test",
|
||||||
|
"tests": "Test",
|
||||||
|
"formation": "Formation",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def norm_env(raw):
|
||||||
|
if not raw:
|
||||||
|
return None
|
||||||
|
s = raw.strip()
|
||||||
|
if not s or s in ("-", "(null)", "workgroup"):
|
||||||
|
return None
|
||||||
|
if s in ITOP_ENVS:
|
||||||
|
return s
|
||||||
|
return ENV_ALIASES.get(s.lower())
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("csv_paths", nargs="+")
|
||||||
|
parser.add_argument("--dry-run", action="store_true")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
engine = create_engine(DATABASE_URL)
|
||||||
|
print(f"[INFO] DB: {DATABASE_URL.split('@')[-1]}")
|
||||||
|
conn = engine.connect().execution_options(isolation_level="AUTOCOMMIT")
|
||||||
|
|
||||||
|
# 1. Ajoute colonne + CHECK
|
||||||
|
print("[INFO] Ajoute colonne environnement...")
|
||||||
|
if not args.dry_run:
|
||||||
|
conn.execute(text("ALTER TABLE servers ADD COLUMN IF NOT EXISTS environnement varchar(20)"))
|
||||||
|
conn.execute(text("ALTER TABLE servers DROP CONSTRAINT IF EXISTS servers_environnement_check"))
|
||||||
|
allowed_sql = ", ".join(f"'{v}'" for v in ITOP_ENVS)
|
||||||
|
conn.execute(text(
|
||||||
|
f"ALTER TABLE servers ADD CONSTRAINT servers_environnement_check "
|
||||||
|
f"CHECK (environnement IN ({allowed_sql}) OR environnement IS NULL)"
|
||||||
|
))
|
||||||
|
print(f"[INFO] Envs iTop autorises: {ITOP_ENVS}")
|
||||||
|
|
||||||
|
# 2. Relecture CSV -> update
|
||||||
|
updated = 0
|
||||||
|
unchanged = 0
|
||||||
|
not_found = 0
|
||||||
|
unknown = set()
|
||||||
|
|
||||||
|
for csv_path in args.csv_paths:
|
||||||
|
print(f"\n[INFO] Lecture {csv_path}")
|
||||||
|
with open(csv_path, "r", encoding="utf-8-sig", newline="") as f:
|
||||||
|
sample = f.read(4096)
|
||||||
|
f.seek(0)
|
||||||
|
delim = ";" if sample.count(";") > sample.count(",") else ","
|
||||||
|
reader = csv.DictReader(f, delimiter=delim)
|
||||||
|
rows = list(reader)
|
||||||
|
print(f"[INFO] {len(rows)} lignes (delim={delim!r})")
|
||||||
|
|
||||||
|
for r in rows:
|
||||||
|
hostname = (r.get("Nom") or r.get("Hostname") or "").strip()
|
||||||
|
if not hostname or not any(c.isalpha() for c in hostname):
|
||||||
|
continue
|
||||||
|
raw = (r.get("Environnement") or r.get("Environment") or "").strip()
|
||||||
|
new_env = norm_env(raw)
|
||||||
|
if raw and new_env is None and raw not in ("-", "(null)", "workgroup", ""):
|
||||||
|
unknown.add(raw)
|
||||||
|
continue
|
||||||
|
if new_env is None:
|
||||||
|
continue
|
||||||
|
srv = conn.execute(text("SELECT id, environnement FROM servers WHERE hostname=:h"),
|
||||||
|
{"h": hostname}).fetchone()
|
||||||
|
if not srv:
|
||||||
|
not_found += 1
|
||||||
|
continue
|
||||||
|
if srv.environnement == new_env:
|
||||||
|
unchanged += 1
|
||||||
|
continue
|
||||||
|
if args.dry_run:
|
||||||
|
print(f" DRY: {hostname} {srv.environnement} -> {new_env}")
|
||||||
|
else:
|
||||||
|
conn.execute(text("UPDATE servers SET environnement=:e WHERE id=:sid"),
|
||||||
|
{"e": new_env, "sid": srv.id})
|
||||||
|
updated += 1
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
print(f"\n[DONE] Maj: {updated} | Inchanges: {unchanged} | Hors base: {not_found}")
|
||||||
|
if unknown:
|
||||||
|
print(f"[WARN] Valeurs non mappees: {unknown}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in New Issue
Block a user