Module demo_api.main
Point d'entrée principal pour demo_api
Interface d'orchestration avec Typer pour le management des utilisateurs et VMs.
Functions
def create(name: str = <typer.models.OptionInfo object>,
email: str = <typer.models.OptionInfo object>,
password: str = <typer.models.OptionInfo object>,
use_saved_token: bool = <typer.models.OptionInfo object>,
os: str = <typer.models.OptionInfo object>,
cores: int = <typer.models.OptionInfo object>,
ram: int = <typer.models.OptionInfo object>,
disk: int = <typer.models.OptionInfo object>,
status: str = <typer.models.OptionInfo object>,
verbose: bool = <typer.models.OptionInfo object>) ‑> None-
Expand source code
@app.command() def create( name: str = typer.Option("VM de Jean", "--name", "-n", help="Nom de la VM"), email: str = typer.Option( "jean@dupont21.com", "--email", "-e", help="Email de l'utilisateur existant" ), password: str = typer.Option( "password123", "--password", "-p", help="Mot de passe de l'utilisateur" ), use_saved_token: bool = typer.Option( False, "--use-token", "-t", help="Utiliser le token sauvegardé dans la session" ), os: str = typer.Option("Ubuntu 22.04", "--os", "-o", help="Système d'exploitation"), cores: int = typer.Option( 2, "--cores", "-c", help="Nombre de cœurs CPU", min=1, max=16 ), ram: int = typer.Option(4, "--ram", "-r", help="RAM en GB", min=1, max=128), disk: int = typer.Option(50, "--disk", "-d", help="Disque en GB", min=10, max=2048), status: str = typer.Option( "stopped", "--status", "-s", help="Statut initial de la VM" ), verbose: bool = typer.Option(False, "--verbose", "-v", help="Mode verbeux"), ) -> None: """ 🖥️ Créer une VM pour un utilisateur existant Authentifie un utilisateur existant et crée une VM pour lui. Peut utiliser un token sauvegardé ou des identifiants email/mot de passe. Exemples: .. code-block:: shell python main.py create python main.py create --name "Ma VM" --email "alice@example.com" --password "motdepasse" python main.py create -n "VM Test" --ram 8 --disk 100 --verbose python main.py create --name "Ma VM" --use-token """ # Vérifier si on doit utiliser le token sauvegardé if use_saved_token: from utils.password_utils import get_token_from_config saved_token = get_token_from_config() if saved_token: typer.echo("🔑 Utilisation du token sauvegardé dans la session") # Créer un client API avec le token sauvegardé from utils.api import ApiClient api_client = ApiClient(token=saved_token) # Vérifier que le token est valide en récupérant les infos utilisateur try: user_info = api_client.get_user_info() typer.echo( f"✅ Token valide pour: {user_info.get('name')} ({user_info.get('email')})" ) # Créer la VM directement avec l'API vm_result = api_client.vms.create( user_id=user_info["id"], name=name, operating_system=os, cpu_cores=cores, ram_gb=ram, disk_gb=disk, status=status, ) if vm_result: typer.echo("🎉 VM créée avec succès!") typer.echo(f" 🆔 ID: {vm_result.get('id')}") typer.echo(f" 📝 Nom: {vm_result.get('name')}") typer.echo(f" 💻 OS: {vm_result.get('operating_system')}") typer.echo(f" 🔧 CPU: {vm_result.get('cpu_cores')} cores") typer.echo(f" 💾 RAM: {vm_result.get('ram_gb')} GB") typer.echo(f" 💿 Disque: {vm_result.get('disk_gb')} GB") typer.echo(f" ⚡ Statut: {vm_result.get('status')}") typer.echo("✨ Terminé!") else: typer.echo("❌ Échec de la création de la VM") raise typer.Exit(1) except Exception as e: typer.echo(f"❌ Token invalide ou expiré: {e}") typer.echo( "💡 Utilisez --password pour vous authentifier avec email/mot de passe" ) raise typer.Exit(1) else: typer.echo("❌ Aucun token sauvegardé trouvé") typer.echo( "💡 Créez d'abord un utilisateur avec 'signup' ou utilisez --password" ) raise typer.Exit(1) else: # Appeler directement la fonction avec le mot de passe create_vm(name, email, password, os, cores, ram, disk, status, verbose)🖥️ Créer une VM pour un utilisateur existant
Authentifie un utilisateur existant et crée une VM pour lui. Peut utiliser un token sauvegardé ou des identifiants email/mot de passe.
Exemples:
.. code-block:: shell python main.py create python main.py create –name "Ma VM" –email "alice@example.com" –password "motdepasse" python main.py create -n "VM Test" –ram 8 –disk 100 –verbose python main.py create –name "Ma VM" –use-token
def debug() ‑> None-
Expand source code
@app.command() def debug() -> None: """🔍 Afficher les informations de debug sur la configuration""" from utils.config import config import os typer.echo("🔍 Informations de debug - Configuration") typer.echo("=" * 50) # Informations sur les fichiers .env typer.echo("📁 Fichiers .env chargés:") typer.echo(f" Nombre de fichiers: {config.env_files_loaded}") env_files = [".env.defaults", ".env.local", ".env"] for env_file in env_files: exists = os.path.exists(env_file) typer.echo(f" {env_file}: {'✅ Existe' if exists else "❌ N'existe pas"}") typer.echo() # Configuration de l'API typer.echo("🌐 Configuration API:") typer.echo(f" URL de base: {config.DEMO_API_BASE_URL}") typer.echo(f" Timeout: {config.DEMO_API_TIMEOUT}s") typer.echo(f" Max retries: {config.DEMO_API_MAX_RETRIES}") typer.echo( f" Mode debug: {'✅ Activé' if config.DEMO_API_DEBUG else '❌ Désactivé'}" ) typer.echo(f" Niveau de log: {config.DEMO_API_LOG_LEVEL}") typer.echo() # Identifiants typer.echo("🔐 Identifiants:") typer.echo(f" Email défini: {'✅ Oui' if config.DEMO_API_EMAIL else '❌ Non'}") typer.echo( f" Mot de passe défini: {'✅ Oui' if config.DEMO_API_PASSWORD else '❌ Non'}" ) typer.echo(f" Token défini: {'✅ Oui' if config.DEMO_API_TOKEN else '❌ Non'}") if config.DEMO_API_TOKEN: typer.echo(f" Token (tronqué): {config.DEMO_API_TOKEN[:20]}...") typer.echo() # Propriétés de configuration typer.echo("⚙️ Propriétés de configuration:") typer.echo( f" Environnement production: {'✅ Oui' if config.is_production else '❌ Non'}" ) typer.echo( f" Identifiants disponibles: {'✅ Oui' if config.has_credentials else '❌ Non'}" ) typer.echo(f" Token disponible: {'✅ Oui' if config.has_token else '❌ Non'}") typer.echo() # Configuration client typer.echo("🔧 Configuration client:") client_config = config.client_config for key, value in client_config.items(): typer.echo(f" {key}: {value}") typer.echo() typer.echo("✨ Debug terminé!")🔍 Afficher les informations de debug sur la configuration
def generate(user_count: int = <typer.models.OptionInfo object>,
min_vms: int = <typer.models.OptionInfo object>,
max_vms: int = <typer.models.OptionInfo object>,
output_file: str = <typer.models.OptionInfo object>,
verbose: bool = <typer.models.OptionInfo object>) ‑> None-
Expand source code
@app.command() def generate( user_count: int = typer.Option( 50, "--users", "-u", help="Nombre d'utilisateurs à générer", min=1, max=1000 ), min_vms: int = typer.Option( 0, "--min-vms", help="Nombre minimum de VMs par utilisateur", min=0, max=10 ), max_vms: int = typer.Option( 5, "--max-vms", help="Nombre maximum de VMs par utilisateur", min=0, max=20 ), output_file: str = typer.Option( "vm_users.json", "--output", "-o", help="Fichier de sortie JSON" ), verbose: bool = typer.Option(False, "--verbose", "-v", help="Mode verbeux"), ) -> None: """ 🎲 Générer des données factices avec Faker Génère un dataset complet d'utilisateurs français avec des VMs réalistes. Les données sont sauvegardées dans un fichier JSON. Exemples: .. code-block:: shell python main.py generate python main.py generate --users 100 --max-vms 3 python main.py generate -u 25 -o mon_dataset.json --verbose """ if min_vms > max_vms: typer.echo("❌ Le nombre minimum de VMs ne peut pas être supérieur au maximum") raise typer.Exit(1) typer.echo( f"🎲 Génération de {user_count} utilisateurs avec {min_vms}-{max_vms} VMs chacun..." ) try: # Générer les données users_data = DataGenerator.generate_users_with_vms( user_count=user_count, vm_per_user_range=(min_vms, max_vms) ) # Sauvegarder dans le fichier JSON output_path = Path(output_file) with open(output_path, "w", encoding="utf-8") as f: json.dump(users_data, f, indent=4, ensure_ascii=False, default=str) # Statistiques total_vms = sum(len(user["vms"]) for user in users_data) users_with_vms_count = len([u for u in users_data if u["vms"]]) typer.echo("✅ Données générées avec succès !") typer.echo("📊 Statistiques:") typer.echo(f" • Utilisateurs: {len(users_data)}") typer.echo(f" • VMs totales: {total_vms}") typer.echo(f" • Utilisateurs avec VMs: {users_with_vms_count}") typer.echo(f" • Moyenne VMs/utilisateur: {total_vms / len(users_data):.1f}") typer.echo(f"📁 Fichier sauvegardé: {output_path.absolute()}") if verbose: typer.echo("\n🔍 Aperçu des données générées:") for i, user in enumerate(users_data[:3]): typer.echo( f" {i + 1}. {user['name']} ({user['email']}) - {len(user['vms'])} VMs" ) if len(users_data) > 3: typer.echo(f" ... et {len(users_data) - 3} autres utilisateurs") except Exception as e: logger.error("Erreur lors de la génération des données", error=str(e)) typer.echo(f"❌ Erreur lors de la génération: {e}") raise typer.Exit(1)🎲 Générer des données factices avec Faker
Génère un dataset complet d'utilisateurs français avec des VMs réalistes. Les données sont sauvegardées dans un fichier JSON.
Exemples:
.. code-block:: shell python main.py generate python main.py generate –users 100 –max-vms 3 python main.py generate -u 25 -o mon_dataset.json –verbose
def main()-
Expand source code
def main(): """Point d'entrée principal""" import sys # Gérer -h comme alias pour --help if "-h" in sys.argv and "--help" not in sys.argv: sys.argv[sys.argv.index("-h")] = "--help" try: app() except KeyboardInterrupt: typer.echo("\n⚠️ Exécution interrompue") except Exception as e: typer.echo(f"❌ Erreur: {e}") raise typer.Exit(1)Point d'entrée principal
def report(report_type: str = <typer.models.OptionInfo object>,
report_format: str = <typer.models.OptionInfo object>,
output_dir: str = <typer.models.OptionInfo object>,
verbose: bool = <typer.models.OptionInfo object>) ‑> None-
Expand source code
@app.command() def report( report_type: str = typer.Option( "all", "--type", "-t", help="Type de rapport à générer (all, users-vms, status)" ), report_format: str = typer.Option( "all", "--format", "-f", help="Format de rapport (all, json, markdown, html)" ), output_dir: str = typer.Option( "outputs", "--output-dir", "-o", help="Répertoire de sortie pour les rapports" ), verbose: bool = typer.Option(False, "--verbose", "-v", help="Mode verbeux"), ) -> None: """ 📊 Générer des rapports Exemples: .. code-block:: python python main.py report python main.py report --type users-vms --format markdown python main.py report -t status -f html -o ./rapports --verbose python main.py report --format all --type all """ # Convertir les strings en enums try: report_type_enum = ReportType(report_type) except ValueError as exc: typer.echo(f"❌ Type de rapport invalide: {report_type}") typer.echo("Types valides: all, users-vms, status") raise typer.Exit(1) from exc try: format_enum = ReportFormat(report_format) except ValueError as exc: typer.echo(f"❌ Format de rapport invalide: {report_format}") typer.echo("Formats valides: all, json, markdown, html") raise typer.Exit(1) from exc # Appeler directement la fonction generate_reports(report_type_enum, format_enum, output_dir, verbose)📊 Générer des rapports
Exemples:
.. code-block:: python
python main.py report python main.py report --type users-vms --format markdown python main.py report -t status -f html -o ./rapports --verbose python main.py report --format all --type all def signup(name: str = <typer.models.OptionInfo object>,
email: str = <typer.models.OptionInfo object>,
password: str = <typer.models.OptionInfo object>,
verbose: bool = <typer.models.OptionInfo object>) ‑> None-
Expand source code
@app.command() def signup( name: str = typer.Option( "Jean Dupont", "--name", "-n", help="Nom de l'utilisateur" ), email: str = typer.Option( "jean@dupont21.com", "--email", "-e", help="Email de l'utilisateur" ), password: str = typer.Option( "password123", "--password", "-p", help="Mot de passe de l'utilisateur" ), verbose: bool = typer.Option(False, "--verbose", "-v", help="Mode verbeux"), ) -> None: """ 👤 Créer un nouvel utilisateur avec authentification Crée un utilisateur via /auth/signup et récupère son token d'authentification. Exemples: .. code-block:: shell python main.py signup python main.py signup --name "Alice Martin" --email "alice@example.com" python main.py signup -n "Bob Dupont" -e "bob@test.com" -p "monmotdepasse" --verbose """ from utils.api.auth import Auth from utils.config import config if verbose: typer.echo("🔧 Configuration utilisateur:") typer.echo(f" Nom: {name}") typer.echo(f" Email: {email}") typer.echo(f" Mot de passe: {'*' * len(password)}") typer.echo() logger.info("Début du processus de création d'utilisateur", email=email, name=name) # Initialisation du client Auth auth = Auth(config.DEMO_API_BASE_URL) try: # Création de l'utilisateur via /auth/signup typer.echo("🔐 Création de l'utilisateur...") token = auth.create_user(name=name, email=email, password=password) if token: typer.echo("✅ Utilisateur créé avec succès!") typer.echo(f" 👤 Nom: {name}") typer.echo(f" 📧 Email: {email}") typer.echo() typer.echo("🔑 Token d'authentification:") typer.echo(f" {token}") typer.echo() typer.echo("📝 Token tronqué (20 premiers caractères):") typer.echo(f" {token[:20]}...") typer.echo() # Sauvegarder le token dans les variables d'environnement de la session if save_token_to_env(token): typer.echo( "💾 Token sauvegardé dans la session courante et dans .env.local" ) else: typer.echo("⚠️ Impossible de sauvegarder le token") typer.echo() # Récupérer les informations complètes de l'utilisateur typer.echo("📋 Récupération des informations utilisateur...") user_info = auth.get_logged_user_info(token) if user_info: typer.echo("✅ Informations utilisateur récupérées:") typer.echo(f" 🆔 ID: {user_info.get('id')}") typer.echo(f" 👤 Nom: {user_info.get('name')}") typer.echo(f" 📧 Email: {user_info.get('email')}") # Formater la date de création de manière plus lisible created_at = user_info.get("created_at") if created_at: if isinstance(created_at, (int, float)): # Si c'est un timestamp, le convertir from utils.date_utils import parse_unix_timestamp formatted_date = parse_unix_timestamp(created_at).strftime( "%d/%m/%Y à %H:%M:%S" ) else: # Si c'est déjà un objet datetime ou une chaîne formatted_date = str(created_at) typer.echo(f" 📅 Créé le: {formatted_date}") else: typer.echo(" 📅 Créé le: N/A") typer.echo() typer.echo("✨ Utilisateur prêt à utiliser!") typer.echo( "💡 Vous pouvez maintenant utiliser la commande 'create' pour créer des VMs" ) else: typer.echo( "⚠️ Utilisateur créé mais impossible de récupérer les informations" ) else: typer.echo("❌ Échec de la création de l'utilisateur") raise typer.Exit(1) except Exception as e: logger.error("Erreur lors de la création de l'utilisateur", error=str(e)) typer.echo(f"❌ Erreur lors de la création: {e}") raise typer.Exit(1)👤 Créer un nouvel utilisateur avec authentification
Crée un utilisateur via /auth/signup et récupère son token d'authentification.
Exemples:
.. code-block:: shell
python main.py signup python main.py signup --name "Alice Martin" --email "alice@example.com" python main.py signup -n "Bob Dupont" -e "bob@test.com" -p "monmotdepasse" --verbose def version() ‑> None-
Expand source code
@app.command() def version() -> None: """📋 Afficher la version""" typer.echo("demo-api CLI v3.0.0") typer.echo("Powered by Typer 🚀")📋 Afficher la version