update utility
This commit is contained in:
parent
f12b605180
commit
e541836cfc
@ -30,26 +30,36 @@ def module(args):
|
||||
f"No modules specified. Using default modules for {args.instance}",
|
||||
)
|
||||
args.modules = module_manager.get_modules(args.instance)
|
||||
for module_name in tqdm.tqdm(
|
||||
args.modules, desc="Processing modules", unit="module"
|
||||
):
|
||||
match args.action:
|
||||
case "install":
|
||||
module_manager.install(args.instance, [module_name])
|
||||
case "uninstall":
|
||||
module_manager.uninstall(args.instance, [module_name])
|
||||
case "upgrade":
|
||||
# Check if module is installed first
|
||||
if not module_manager.is_module_installed(args.instance, module_name):
|
||||
color_log.Show(
|
||||
"INFO",
|
||||
f"Module {module_name} not installed. Installing first...",
|
||||
)
|
||||
|
||||
pbar = tqdm.tqdm(total=len(args.modules), desc="Processing modules", unit="module")
|
||||
|
||||
for module_name in args.modules:
|
||||
try:
|
||||
match args.action:
|
||||
case "install":
|
||||
pbar.set_description(f"Installing {module_name}")
|
||||
module_manager.install(args.instance, [module_name])
|
||||
# Now upgrade the module
|
||||
module_manager.upgrade(args.instance, [module_name])
|
||||
case _:
|
||||
color_log.Show(
|
||||
"FAILED",
|
||||
f"Invalid action '{args.action}' for module management.",
|
||||
)
|
||||
case "uninstall":
|
||||
pbar.set_description(f"Uninstalling {module_name}")
|
||||
module_manager.uninstall(args.instance, [module_name])
|
||||
case "upgrade":
|
||||
# Check if module is installed first
|
||||
if not module_manager.is_module_installed(args.instance, module_name):
|
||||
pbar.set_description(f"Installing {module_name}")
|
||||
module_manager.install(args.instance, [module_name])
|
||||
pbar.set_description(f"Upgrading {module_name}")
|
||||
module_manager.upgrade(args.instance, [module_name])
|
||||
case _:
|
||||
color_log.Show(
|
||||
"FAILED",
|
||||
f"Invalid action '{args.action}' for module management.",
|
||||
)
|
||||
return
|
||||
pbar.update(1)
|
||||
except Exception as e:
|
||||
color_log.Show(
|
||||
"FAILED",
|
||||
f"Error processing module {module_name}: {str(e)}",
|
||||
)
|
||||
continue
|
||||
pbar.close()
|
||||
|
154
scripts/modules_management.py
Normal file
154
scripts/modules_management.py
Normal file
@ -0,0 +1,154 @@
|
||||
import importlib.util
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import fcntl
|
||||
import select
|
||||
from ..services import config as Config
|
||||
from ..lib import color_log
|
||||
|
||||
def set_nonblocking(fd):
|
||||
"""Make a file descriptor non-blocking."""
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
||||
|
||||
def run_command(cmd, description):
|
||||
"""Run a command and display output in real-time."""
|
||||
try:
|
||||
color_log.Show("INFO", f"Executing: {description}")
|
||||
|
||||
# Create process without output buffering
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
bufsize=0, # No buffering
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# Set both pipes to non-blocking mode
|
||||
set_nonblocking(process.stdout.fileno())
|
||||
set_nonblocking(process.stderr.fileno())
|
||||
|
||||
# Use select to read from pipes as data becomes available
|
||||
while True:
|
||||
reads = [process.stdout.fileno(), process.stderr.fileno()]
|
||||
ret = select.select(reads, [], [])
|
||||
|
||||
for fd in ret[0]:
|
||||
if fd == process.stdout.fileno():
|
||||
line = process.stdout.readline()
|
||||
if line:
|
||||
print(line.rstrip())
|
||||
if fd == process.stderr.fileno():
|
||||
line = process.stderr.readline()
|
||||
if line:
|
||||
print(line.rstrip())
|
||||
|
||||
# Check if process has finished
|
||||
if process.poll() is not None:
|
||||
break
|
||||
|
||||
# Read any remaining output
|
||||
stdout, stderr = process.communicate()
|
||||
if stdout:
|
||||
print(stdout.rstrip())
|
||||
if stderr:
|
||||
print(stderr.rstrip())
|
||||
|
||||
return process.returncode == 0
|
||||
|
||||
except Exception 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."""
|
||||
color_log.Show("INFO", f"\n=== Starting update process for {instance_name} ===")
|
||||
|
||||
# 1. Pull latest code
|
||||
color_log.Show("INFO", "Step 1/3: Pulling 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
|
||||
color_log.Show("INFO", "Step 2/3: Updating 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
|
||||
color_log.Show("INFO", "Step 3/3: Restarting 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
|
||||
|
||||
color_log.Show("OK", f"=== Update process completed for {instance_name} ===\n")
|
||||
return True
|
||||
|
||||
def main():
|
||||
# Parse arguments
|
||||
parser = argparse.ArgumentParser(description="Update modules for all instances")
|
||||
parser.add_argument("instance", type=str, help="Instance Name")
|
||||
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)
|
||||
if args.instance == "all":
|
||||
# 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}")
|
||||
else:
|
||||
if update_instance(args.instance, args.action, args.force_pull):
|
||||
color_log.Show("OK", f"Successfully updated {args.instance}")
|
||||
else:
|
||||
color_log.Show("FAILED", f"Failed to update {args.instance}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,99 +0,0 @@
|
||||
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()
|
@ -1,8 +1,13 @@
|
||||
UTILITY_DIR =${PWD}/utility
|
||||
SCRIPTS_DIR = ${UTILITY_DIR}/scripts
|
||||
UTILITY_CONFIG = ${PWD}/utility/config/settings.yaml
|
||||
update_modules_all:
|
||||
${PYTHON} -m utility.scripts.update_modules upgrade ${UTILITY_CONFIG}
|
||||
|
||||
# Default values for update_modules
|
||||
INSTANCE ?= all
|
||||
ACTION ?= upgrade
|
||||
|
||||
update_modules:
|
||||
${PYTHON} -m utility.scripts.modules_management ${INSTANCE} ${ACTION} ${UTILITY_CONFIG}
|
||||
cleanup_addons:
|
||||
@bash ${SCRIPT_PATH}/clean_up_addons.sh $(shell echo $(ADDONS) | tr ',' ' ')
|
||||
gen_config:
|
||||
|
Loading…
Reference in New Issue
Block a user