odoo-openupgrade-wizard/odoo_openupgrade_wizard/cli/cli_shell.py
2024-12-12 10:53:37 +00:00

109 lines
2.9 KiB
Python

import os
import subprocess
import sys
import click
import docker
from loguru import logger
from odoo_openupgrade_wizard.cli.cli_options import (
database_option_required,
get_migration_step_from_options,
step_option,
)
from odoo_openupgrade_wizard.tools.tools_odoo import (
generate_odoo_command_options,
)
from odoo_openupgrade_wizard.tools.tools_postgres import ensure_database
@click.command()
@step_option
@database_option_required
@click.option(
"--code",
default=None,
help="Python code to execute in the Odoo shell. "
"Example: 'print(env.user.name)'",
)
@click.pass_context
def shell(ctx, step, database, code):
"""Run an Odoo shell in the running Odoo container."""
migration_step = get_migration_step_from_options(ctx, step)
ensure_database(ctx, database, state="present")
config = ctx.obj.get("config", {})
project_name = config.get("project_name")
if not project_name:
click.echo("Unable to find the project name.")
sys.exit(1)
expected_container_name_prefix = f"oow-{project_name}-{database}"
# Connect to the Docker daemon
docker_client = docker.from_env()
# List all running containers
running_containers = docker_client.containers.list(
filters={"status": "running"}
)
# Find the running Odoo container
matching_container = next(
(
c
for c in running_containers
if expected_container_name_prefix in c.name and "step" in c.name
),
None,
)
if not matching_container:
logger.error(
"No running Odoo container found. "
"Please run oow run before running the shell."
)
sys.exit(1)
logger.info(f"Execute shell in {matching_container.name} container...")
common_options = generate_odoo_command_options(
ctx, migration_step, "regular", database
)
# Build the docker exec command
command = [
"docker",
"exec",
"-i", # Interactive mode to enable stdin
matching_container.name,
"/odoo_env/src/odoo/odoo-bin",
"shell",
"--no-http",
"--shell-interface=iptyhon",
] + common_options
logger.info(f"Command: {' '.join(command)}")
# If code is provided, send it via stdin
if code:
logger.info(f"Executing code: {code}")
process = subprocess.Popen(
command,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True, # Enables text mode
)
stdout, stderr = process.communicate(code)
if process.returncode != 0:
logger.error(f"Error executing code: {stderr}")
sys.exit(1)
else:
click.echo(stdout)
else:
# Interactive session requires TTY
command.insert(2, "-t")
os.execvp(command[0], command)