import importlib.util import argparse import os import subprocess import sys from ..services import config as Config from ..lib import color_log def run_command(cmd, description): """Run a command and handle its output.""" try: color_log.Show("INFO", f"Executing: {description}") result = subprocess.run(cmd, capture_output=True, text=True) if result.stdout: print(result.stdout.strip()) if result.stderr: print(result.stderr.strip()) return result.returncode == 0 except subprocess.CalledProcessError as e: color_log.Show("FAILED", f"Error executing {description}: {str(e)}") return False def update_instance(instance_name, action, force_pull=False): """Update a single instance with git pull, module update, and service restart.""" # 1. Pull latest code pull_cmd = ["python", "utility/main.py", "git", "pull", instance_name] if force_pull: pull_cmd.append("--force") if not run_command(pull_cmd, f"Pulling latest code for {instance_name}"): color_log.Show("WARNING", f"Skipping module update for {instance_name} due to pull failure") return False # 2. Update modules module_cmd = ["python", "utility/main.py", "module", action, instance_name] if not run_command(module_cmd, f"Updating modules for {instance_name}"): color_log.Show("WARNING", f"Module update failed for {instance_name}") return False # 3. Restart service restart_cmd = ["python", "utility/main.py", "service", "restart", instance_name] if not run_command(restart_cmd, f"Restarting service for {instance_name}"): color_log.Show("WARNING", f"Service restart failed for {instance_name}") return False return True def main(): # Parse arguments parser = argparse.ArgumentParser(description="Update modules for all instances") parser.add_argument( "action", help="Action to perform", choices=["uninstall", "install", "upgrade"] ) parser.add_argument( "config_path", help="Path to the config file" ) parser.add_argument( "--force-pull", action="store_true", help="Force pull with hard reset (discards local changes)" ) args = parser.parse_args() # Load the configuration color_log.Show("INFO", f"Loading configuration from {args.config_path}") config = Config.Config(config_path=args.config_path) # Get instances instances = config.get_instances() if not isinstance(instances, list): color_log.Show("FAILED", "Error: instances is not a valid list.") sys.exit(1) # Process each instance success_count = 0 for instance in instances: if "name" not in instance: color_log.Show("WARNING", f"Instance missing 'name' field. Skipping.") continue instance_name = instance["name"] color_log.Show("INFO", f"\nProcessing instance: {instance_name}") if update_instance(instance_name, args.action, args.force_pull): success_count += 1 color_log.Show("OK", f"Successfully updated {instance_name}") else: color_log.Show("FAILED", f"Failed to update {instance_name}") # Summary color_log.Show("INFO", f"\nUpdate Summary:") color_log.Show("INFO", f"Total instances: {len(instances)}") color_log.Show("INFO", f"Successful updates: {success_count}") color_log.Show("INFO", f"Failed updates: {len(instances) - success_count}") if __name__ == "__main__": main()