update
This commit is contained in:
parent
dbd5a8325c
commit
ffc7cef059
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,7 @@ __pycache__/
|
|||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
config/*.yaml
|
||||||
# Distribution / packaging
|
# Distribution / packaging
|
||||||
.Python
|
.Python
|
||||||
build/
|
build/
|
||||||
|
22
cli.py
22
cli.py
@ -3,6 +3,7 @@ import argparse
|
|||||||
import tqdm
|
import tqdm
|
||||||
from services.odoo.service import OdooServiceManager
|
from services.odoo.service import OdooServiceManager
|
||||||
from services.odoo.module import OdooModuleManager
|
from services.odoo.module import OdooModuleManager
|
||||||
|
import lib.color_log as color_log
|
||||||
|
|
||||||
|
|
||||||
def service(args):
|
def service(args):
|
||||||
@ -15,7 +16,10 @@ def service(args):
|
|||||||
case "restart":
|
case "restart":
|
||||||
service.restart_service(args.instance)
|
service.restart_service(args.instance)
|
||||||
case _:
|
case _:
|
||||||
print("Invalid action")
|
color_log.Show(
|
||||||
|
"FAILED",
|
||||||
|
f"Invalid action '{args.action}' for service management.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def module(args):
|
def module(args):
|
||||||
@ -23,12 +27,17 @@ def module(args):
|
|||||||
|
|
||||||
# If modules are provided in the command line
|
# If modules are provided in the command line
|
||||||
if args.modules:
|
if args.modules:
|
||||||
print(f"Processing modules: {', '.join(args.modules)} for {args.instance}")
|
color_log.Show(
|
||||||
|
"INFO",
|
||||||
|
f"Processing modules: {', '.join(args.modules)} for {args.instance}",
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# Fallback if no modules are provided (can use default from instance settings)
|
# Fallback if no modules are provided (can use default from instance settings)
|
||||||
print(f"No modules specified. Using default modules for {args.instance}")
|
color_log.Show(
|
||||||
|
"INFO",
|
||||||
|
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)
|
||||||
|
|
||||||
# Create a progress bar using tqdm
|
# Create a progress bar using tqdm
|
||||||
for module_name in tqdm.tqdm(
|
for module_name in tqdm.tqdm(
|
||||||
args.modules, desc="Processing modules", unit="module"
|
args.modules, desc="Processing modules", unit="module"
|
||||||
@ -41,7 +50,10 @@ def module(args):
|
|||||||
case "upgrade":
|
case "upgrade":
|
||||||
module_manager.upgrade(args.instance, [module_name])
|
module_manager.upgrade(args.instance, [module_name])
|
||||||
case _:
|
case _:
|
||||||
print("Invalid action")
|
color_log.Show(
|
||||||
|
"FAILED",
|
||||||
|
f"Invalid action '{args.action}' for module management.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def setup_cli():
|
def setup_cli():
|
||||||
|
54
config/settings.template
Normal file
54
config/settings.template
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
odoo_instances:
|
||||||
|
- name: "ftacpa"
|
||||||
|
host: "10.1.1.31"
|
||||||
|
port: 8069
|
||||||
|
database: "ftacpa"
|
||||||
|
username: "nextzen"
|
||||||
|
password: "smartyourlife"
|
||||||
|
type: "systemctl"
|
||||||
|
service_name: "odoo18"
|
||||||
|
git:
|
||||||
|
repo_url: "https://hoangvv:smartyourlife@git.nextzenos.com/NextERP/Odoo18-FTACPA.git"
|
||||||
|
branch: "community/demo/ftacpa"
|
||||||
|
local_path: "/opt/odoo18/addons"
|
||||||
|
ssh:
|
||||||
|
user: root
|
||||||
|
password: Smartyourlife123@*
|
||||||
|
key_path: "/root/.ssh/privatessh.key"
|
||||||
|
odoo_instances:
|
||||||
|
- name: "ftacpa"
|
||||||
|
host: "10.1.1.31"
|
||||||
|
port: 8069
|
||||||
|
database: "server"
|
||||||
|
username: "nextzen"
|
||||||
|
password: "smartyourlife"
|
||||||
|
type: "systemctl"
|
||||||
|
service_name: "odoo18"
|
||||||
|
git:
|
||||||
|
repo_url: "https://hoangvv:smartyourlife@git.nextzenos.com/NextERP/Odoo18-FTACPA.git"
|
||||||
|
branch: "community/demo/ftacpa"
|
||||||
|
local_path: "/opt/ftacpa/addons"
|
||||||
|
ssh:
|
||||||
|
user: root
|
||||||
|
password: Smartyourlife123@*
|
||||||
|
key_path: "/root/.ssh/privatessh.key"
|
||||||
|
# - name: "server1_test"
|
||||||
|
# host: "server1.example.com"
|
||||||
|
# port: 8069
|
||||||
|
# database: "test_db1"
|
||||||
|
# username: "admin"
|
||||||
|
# password: "test_password"
|
||||||
|
# module_names:
|
||||||
|
# - "your_module"
|
||||||
|
# type: "docker"
|
||||||
|
# - name: "server2_prod"
|
||||||
|
# host: "server2.example.com"
|
||||||
|
# port: 8070
|
||||||
|
# database: "prod_db2"
|
||||||
|
# username: "admin"
|
||||||
|
# password: "admin_password"
|
||||||
|
# module_names:
|
||||||
|
# - "your_module"
|
||||||
|
# - "custom_module"
|
||||||
|
# - "third_module"
|
||||||
|
# type: "systemctl"
|
@ -9,16 +9,16 @@ def colorize(text, code):
|
|||||||
def Show(status, message):
|
def Show(status, message):
|
||||||
"""Displays a message with a status indicator."""
|
"""Displays a message with a status indicator."""
|
||||||
colors = {
|
colors = {
|
||||||
0: (
|
'OK': (
|
||||||
colorize("[", "90") + colorize(" OK ", "38;5;154") + colorize("]", "90")
|
colorize("[", "90") + colorize(" OK ", "38;5;154") + colorize("]", "90")
|
||||||
), # Green, Grey
|
), # Green, Grey
|
||||||
1: (
|
'FAILED': (
|
||||||
colorize("[", "90") + colorize(" FAILED ", "91") + colorize("]", "90")
|
colorize("[", "90") + colorize(" FAILED ", "91") + colorize("]", "90")
|
||||||
), # Red, Grey
|
), # Red, Grey
|
||||||
2: (
|
'INFO': (
|
||||||
colorize("[", "90") + colorize(" INFO ", "38;5;154") + colorize("]", "90")
|
colorize("[", "90") + colorize(" INFO ", "38;5;154") + colorize("]", "90")
|
||||||
), # Green, Grey
|
), # Green, Grey
|
||||||
3: (
|
'WARNING': (
|
||||||
colorize("[", "90") + colorize(" WARNING ", "33") + colorize("]", "90")
|
colorize("[", "90") + colorize(" WARNING ", "33") + colorize("]", "90")
|
||||||
), # Yellow, Grey
|
), # Yellow, Grey
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ from odoorpc import ODOO
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from services.config import Config
|
from services.config import Config
|
||||||
|
import lib.color_log as color_log
|
||||||
|
|
||||||
|
|
||||||
class OdooConnection:
|
class OdooConnection:
|
||||||
@ -48,11 +49,15 @@ class OdooConnection:
|
|||||||
instance["database"], instance["username"], instance["password"]
|
instance["database"], instance["username"], instance["password"]
|
||||||
)
|
)
|
||||||
self.connections[instance["name"]] = odoo
|
self.connections[instance["name"]] = odoo
|
||||||
print(
|
color_log.Show(
|
||||||
f"Connected to {instance['host']}:{instance['port']} - {instance['database']}"
|
"OK",
|
||||||
|
f"Connected to {instance['name']} at {instance['host']}:{instance['port']}",
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to connect to {instance['name']}: {e}")
|
color_log.Show(
|
||||||
|
"FAILED",
|
||||||
|
f"Failed to connect to {instance['name']} at {instance['host']}:{instance['port']}: {e}",
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def get_connection(self, instance_name):
|
def get_connection(self, instance_name):
|
||||||
@ -69,7 +74,7 @@ class OdooConnection:
|
|||||||
if name in self.connections:
|
if name in self.connections:
|
||||||
# odoorpc doesn't have an explicit disconnect, so we just remove the reference
|
# odoorpc doesn't have an explicit disconnect, so we just remove the reference
|
||||||
del self.connections[name]
|
del self.connections[name]
|
||||||
print(f"Disconnected from instance: {name}")
|
color_log.Show("OK", f"Disconnected from {name}")
|
||||||
|
|
||||||
def get_instances(self):
|
def get_instances(self):
|
||||||
"""Return the list of configured instances."""
|
"""Return the list of configured instances."""
|
||||||
@ -80,11 +85,13 @@ class OdooConnection:
|
|||||||
odoo = self.get_connection(instance_name)
|
odoo = self.get_connection(instance_name)
|
||||||
if not odoo:
|
if not odoo:
|
||||||
raise ValueError(f"No connection available for instance '{instance_name}'")
|
raise ValueError(f"No connection available for instance '{instance_name}'")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
model_obj = odoo.env[model]
|
model_obj = odoo.env[model]
|
||||||
result = getattr(model_obj, method)(*args, **kwargs)
|
result = getattr(model_obj, method)(*args, **kwargs)
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error executing {method} on {model} for {instance_name}: {e}")
|
color_log.Show(
|
||||||
|
"FAILED",
|
||||||
|
f"Error executing {method} on {model} for {instance_name}: {e}",
|
||||||
|
)
|
||||||
raise
|
raise
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from services.git.handler import GitHandler
|
from services.git.handler import GitHandler
|
||||||
from services.odoo.connection import OdooConnection
|
from services.odoo.connection import OdooConnection
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import lib.color_log as color_log
|
||||||
|
|
||||||
|
|
||||||
class OdooModuleManager:
|
class OdooModuleManager:
|
||||||
@ -19,14 +20,13 @@ class OdooModuleManager:
|
|||||||
for instance in self.config.get_instances():
|
for instance in self.config.get_instances():
|
||||||
if instance_name and instance["name"] != instance_name:
|
if instance_name and instance["name"] != instance_name:
|
||||||
continue
|
continue
|
||||||
|
color_log.Show("INFO", f"Processing instance: {instance['name']}")
|
||||||
print(f"Processing instance: {instance['name']}")
|
|
||||||
for module_name in module_names:
|
for module_name in module_names:
|
||||||
try:
|
try:
|
||||||
print(
|
color_log.Show(
|
||||||
f"{action.capitalize()}ing module: {module_name} in {instance['name']}"
|
"INFO",
|
||||||
|
f"{action.capitalize()}ing module: {module_name} in {instance['name']}",
|
||||||
)
|
)
|
||||||
|
|
||||||
module_ids = self.config.execute(
|
module_ids = self.config.execute(
|
||||||
instance["name"],
|
instance["name"],
|
||||||
"ir.module.module",
|
"ir.module.module",
|
||||||
@ -34,9 +34,10 @@ class OdooModuleManager:
|
|||||||
[("name", "=", module_name)],
|
[("name", "=", module_name)],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not module_ids:
|
if not module_ids and action in ["upgrade", "uninstall"]:
|
||||||
print(
|
color_log.Show(
|
||||||
f"Module {module_name} not found in {instance['name']}, skipping."
|
"WARNING",
|
||||||
|
f"Module {module_name} not found in {instance['name']}, skipping.",
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -47,23 +48,41 @@ class OdooModuleManager:
|
|||||||
button_action,
|
button_action,
|
||||||
module_ids, # Pass list directly instead of wrapping in another list
|
module_ids, # Pass list directly instead of wrapping in another list
|
||||||
)
|
)
|
||||||
|
color_log.Show(
|
||||||
print(
|
"OK",
|
||||||
f"Module {module_name} {action}ed successfully in {instance['name']}"
|
f"Module {module_name} {action}ed successfully in {instance['name']}",
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
color_log.Show(
|
||||||
f"Error while {action}ing {module_name} in {instance['name']}: {e}"
|
"FAILED",
|
||||||
|
f"Error while {action}ing {module_name} in {instance['name']}: {e}",
|
||||||
)
|
)
|
||||||
|
|
||||||
def install(self, instance_name: str = None,module_names: list = None) -> None:
|
def get_modules(self, instance_name: str = None) -> list:
|
||||||
|
"""Get a list of installed modules for the specified instance(s)."""
|
||||||
|
self.config.connect(instance_name)
|
||||||
|
modules = []
|
||||||
|
for instance in self.config.get_instances():
|
||||||
|
if instance_name and instance["name"] != instance_name:
|
||||||
|
continue
|
||||||
|
color_log.Show("INFO", f"Fetching modules for instance: {instance['name']}")
|
||||||
|
module_ids = self.config.execute(
|
||||||
|
instance["name"],
|
||||||
|
"ir.module.module",
|
||||||
|
"search_read",
|
||||||
|
[],
|
||||||
|
["name"],
|
||||||
|
)
|
||||||
|
modules.extend([mod["name"] for mod in module_ids])
|
||||||
|
return modules
|
||||||
|
def install(self, instance_name: str = None, module_names: list = None) -> None:
|
||||||
"""Install multiple modules for the specified instance(s)."""
|
"""Install multiple modules for the specified instance(s)."""
|
||||||
self._manage_module("install", instance_name,module_names)
|
self._manage_module("install", instance_name, module_names)
|
||||||
|
|
||||||
def uninstall(self, instance_name: str = None,module_names: list = None) -> None:
|
def uninstall(self, instance_name: str = None, module_names: list = None) -> None:
|
||||||
"""Uninstall multiple modules for the specified instance(s)."""
|
"""Uninstall multiple modules for the specified instance(s)."""
|
||||||
self._manage_module("uninstall", instance_name,module_names)
|
self._manage_module("uninstall", instance_name, module_names)
|
||||||
|
|
||||||
def upgrade(self, instance_name: str = None,module_names: list = None) -> None:
|
def upgrade(self, instance_name: str = None, module_names: list = None) -> None:
|
||||||
"""Upgrade multiple modules for the specified instance(s)."""
|
"""Upgrade multiple modules for the specified instance(s)."""
|
||||||
self._manage_module("upgrade", instance_name,module_names)
|
self._manage_module("upgrade", instance_name, module_names)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
from services.odoo.connection import OdooConnection
|
from services.odoo.connection import OdooConnection
|
||||||
|
import lib.color_log as color_log
|
||||||
|
|
||||||
|
|
||||||
class OdooServiceManager:
|
class OdooServiceManager:
|
||||||
@ -9,11 +10,15 @@ class OdooServiceManager:
|
|||||||
def _execute_command(self, cmd, instance_name):
|
def _execute_command(self, cmd, instance_name):
|
||||||
"""Execute a shell command and handle errors."""
|
"""Execute a shell command and handle errors."""
|
||||||
try:
|
try:
|
||||||
print(f"Executing: {cmd}")
|
color_log.Show("INFO", f"Executing command: {cmd}")
|
||||||
subprocess.run(cmd, shell=True, check=True, capture_output=True, text=True)
|
subprocess.run(cmd, shell=True, check=True, capture_output=True, text=True)
|
||||||
print(f"Service operation successful for {instance_name}")
|
color_log.Show("OK", f"Command executed successfully for {instance_name}")
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print(f"Error performing service operation for {instance_name}: {e}")
|
color_log.Show(
|
||||||
|
"FAILED",
|
||||||
|
f"Error performing service operation for {instance_name}: {e}",
|
||||||
|
)
|
||||||
|
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _get_command(self, instance, action):
|
def _get_command(self, instance, action):
|
||||||
@ -35,7 +40,10 @@ class OdooServiceManager:
|
|||||||
container_name = instance.get("container_name", f"odoo_{instance['name']}")
|
container_name = instance.get("container_name", f"odoo_{instance['name']}")
|
||||||
cmd = f"docker {action} {container_name}"
|
cmd = f"docker {action} {container_name}"
|
||||||
else:
|
else:
|
||||||
print(f"Unsupported service type '{service_type}' for {instance['name']}")
|
color_log.Show(
|
||||||
|
"WARNING",
|
||||||
|
f"Unsupported service type '{service_type}' for {instance['name']}",
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not local_host:
|
if not local_host:
|
||||||
@ -52,14 +60,16 @@ class OdooServiceManager:
|
|||||||
:param action: "stop" or "restart"
|
:param action: "stop" or "restart"
|
||||||
:param instance_name: Specific instance name, or None for all instances.
|
:param instance_name: Specific instance name, or None for all instances.
|
||||||
"""
|
"""
|
||||||
if action not in ["stop", "restart","start"]:
|
if action not in ["stop", "restart", "start"]:
|
||||||
raise ValueError("Action must be 'stop' or 'restart'.")
|
raise ValueError("Action must be 'stop' or 'restart'.")
|
||||||
|
|
||||||
for instance in self.config.get_instances():
|
for instance in self.config.get_instances():
|
||||||
if instance_name and instance["name"] != instance_name:
|
if instance_name and instance["name"] != instance_name:
|
||||||
continue
|
continue
|
||||||
|
color_log.Show(
|
||||||
print(f"{action.capitalize()}ing service for instance: {instance['name']}")
|
"INFO",
|
||||||
|
f"{action.capitalize()}ing service for instance: {instance['name']}",
|
||||||
|
)
|
||||||
cmd = self._get_command(instance, action)
|
cmd = self._get_command(instance, action)
|
||||||
if cmd:
|
if cmd:
|
||||||
self._execute_command(cmd, instance["name"])
|
self._execute_command(cmd, instance["name"])
|
||||||
|
Loading…
Reference in New Issue
Block a user