From d552798934b1d63f6fc98a13da9141a05f170060 Mon Sep 17 00:00:00 2001 From: Xor290 Date: Sun, 14 Jun 2026 22:49:58 +0200 Subject: [PATCH] chore: add backup script --- monitoring/s3-backup/backup.py | 141 +++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 monitoring/s3-backup/backup.py diff --git a/monitoring/s3-backup/backup.py b/monitoring/s3-backup/backup.py new file mode 100644 index 00000000..66912076 --- /dev/null +++ b/monitoring/s3-backup/backup.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +""" +Script de dump PostgreSQL + upload vers MinIO +SDK officiel MinIO + contournement certificat auto-signe +""" + +import os +import ssl +import subprocess +import sys +from pathlib import Path + +import urllib3 + +# Configuration PostgreSQL +PG_VERSION = "16" +DB_HOST = "localhost" +DB_PORT = 5432 +DB_NAME = "gestion_commande_db" +DB_USER = "admin_gestion_commande_db" +DB_PASSWORD = "1SWDxH20rV7K2Uc2PNlwCaCxfVZEtKomF0CK9OMh" + +# Configuration MinIO +MINIO_ENDPOINT = "10.0.0.4:9000" +MINIO_ACCESS_KEY = "admin" +MINIO_SECRET_KEY = "admin@12345" +MINIO_BUCKET = "backup-db-prod-mln" +MINIO_OBJECT = f"postgresql/{DB_NAME}.dump" +MINIO_SECURE = False # HTTPS + +# Fichier local temporaire +OUTPUT_DIR = Path("./dumps") +OUTPUT_DIR.mkdir(parents=True, exist_ok=True) +DUMP_FILE = OUTPUT_DIR / f"{DB_NAME}.dump" + + +def find_pg_dump() -> str: + candidates = [ + f"/usr/lib/postgresql/{PG_VERSION}/bin/pg_dump", + f"/usr/pgsql-{PG_VERSION}/bin/pg_dump", + "/usr/bin/pg_dump", + "/usr/local/bin/pg_dump", + ] + for path in candidates: + if Path(path).exists(): + return path + result = subprocess.run(["which", "pg_dump"], capture_output=True, text=True) + if result.returncode == 0: + return result.stdout.strip() + sys.exit("pg_dump introuvable.") + + +def run_dump(pg_dump: str) -> None: + env = os.environ.copy() + env["PGPASSWORD"] = DB_PASSWORD + + cmd = [ + pg_dump, + "--host", + DB_HOST, + "--port", + str(DB_PORT), + "--username", + DB_USER, + "--dbname", + DB_NAME, + "--format", + "custom", + "--compress", + "9", + "--verbose", + "--file", + str(DUMP_FILE), + ] + + print(f"[1/2] Dump -> {DUMP_FILE}") + result = subprocess.run(cmd, env=env, capture_output=True, text=True) + if result.stderr: + print(result.stderr) + if result.returncode != 0: + sys.exit(f"Echec du dump (code {result.returncode})") + + size_mb = DUMP_FILE.stat().st_size / 1024 / 1024 + print(f" OK ({size_mb:.2f} Mo)") + + +def upload_to_minio() -> None: + from minio import Minio + + print(f"[2/2] Upload -> {MINIO_ENDPOINT}/{MINIO_BUCKET}/{MINIO_OBJECT}") + + # Contexte SSL qui accepte les certificats auto-signes + ssl_ctx = ssl.create_default_context() + ssl_ctx.check_hostname = False + ssl_ctx.verify_mode = ssl.CERT_NONE + + urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + http_client = urllib3.PoolManager( + ssl_context=ssl_ctx, + cert_reqs="CERT_NONE", + ) + + client = Minio( + MINIO_ENDPOINT, + access_key=MINIO_ACCESS_KEY, + secret_key=MINIO_SECRET_KEY, + secure=MINIO_SECURE, + http_client=http_client, + ) + + if not client.bucket_exists(MINIO_BUCKET): + client.make_bucket(MINIO_BUCKET) + print(f" Bucket '{MINIO_BUCKET}' cree.") + + client.fput_object( + bucket_name=MINIO_BUCKET, + object_name=MINIO_OBJECT, + file_path=str(DUMP_FILE), + content_type="application/octet-stream", + ) + + print(f" OK : s3://{MINIO_BUCKET}/{MINIO_OBJECT}") + + DUMP_FILE.unlink() + print(f" Fichier local supprime.") + + +if __name__ == "__main__": + try: + from minio import Minio # noqa + except ImportError: + sys.exit("SDK MinIO manquant : pip install minio") + + pg_dump_bin = find_pg_dump() + print(f"pg_dump : {pg_dump_bin}\n") + + run_dump(pg_dump_bin) + upload_to_minio() + + print("\nBackup termine avec succes !") + print(f" s3://{MINIO_BUCKET}/{MINIO_OBJECT}")