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}",
|
f"No modules specified. Using default modules for {args.instance}",
|
||||||
)
|
)
|
||||||
args.modules = module_manager.get_modules(args.instance)
|
args.modules = module_manager.get_modules(args.instance)
|
||||||
for module_name in tqdm.tqdm(
|
|
||||||
args.modules, desc="Processing modules", unit="module"
|
pbar = tqdm.tqdm(total=len(args.modules), desc="Processing modules", unit="module")
|
||||||
):
|
|
||||||
match args.action:
|
for module_name in args.modules:
|
||||||
case "install":
|
try:
|
||||||
module_manager.install(args.instance, [module_name])
|
match args.action:
|
||||||
case "uninstall":
|
case "install":
|
||||||
module_manager.uninstall(args.instance, [module_name])
|
pbar.set_description(f"Installing {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...",
|
|
||||||
)
|
|
||||||
module_manager.install(args.instance, [module_name])
|
module_manager.install(args.instance, [module_name])
|
||||||
# Now upgrade the module
|
case "uninstall":
|
||||||
module_manager.upgrade(args.instance, [module_name])
|
pbar.set_description(f"Uninstalling {module_name}")
|
||||||
case _:
|
module_manager.uninstall(args.instance, [module_name])
|
||||||
color_log.Show(
|
case "upgrade":
|
||||||
"FAILED",
|
# Check if module is installed first
|
||||||
f"Invalid action '{args.action}' for module management.",
|
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
|
UTILITY_DIR =${PWD}/utility
|
||||||
SCRIPTS_DIR = ${UTILITY_DIR}/scripts
|
SCRIPTS_DIR = ${UTILITY_DIR}/scripts
|
||||||
UTILITY_CONFIG = ${PWD}/utility/config/settings.yaml
|
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:
|
cleanup_addons:
|
||||||
@bash ${SCRIPT_PATH}/clean_up_addons.sh $(shell echo $(ADDONS) | tr ',' ' ')
|
@bash ${SCRIPT_PATH}/clean_up_addons.sh $(shell echo $(ADDONS) | tr ',' ' ')
|
||||||
gen_config:
|
gen_config:
|
||||||
|
Loading…
Reference in New Issue
Block a user