diff --git a/Dockerfile b/Dockerfile index b261e72f8..fb9c43b4a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,13 +7,10 @@ COPY ./deployment/entrypoint.sh / # COPY deployment/entrypoint.sh / # COPY deployment/odoo.conf /etc/odoo/ USER root -RUN apt update -y && \ - apt install -y python3-pip libldap2-dev libpq-dev libsasl2-dev postgresql-client libreoffice wkhtmltopdf ansible terraform && \ - apt clean && rm -rf /var/lib/apt/lists/* - -COPY ./requirements.txt /usr/lib/python3/dist-packages/ - -RUN pip install -r /usr/lib/python3/dist-packages/requirements.txt +RUN apt-get update && apt-get install -y libreoffice +USER odoo +COPY ./deployment/requirements.txt /usr/lib/python3/dist-packages/odoo +RUN pip install -r /usr/lib/python3/dist-packages/odoo/requirements.txt --break-system-packages # Set permissions and Mount /var/lib/odoo to allow restoring filestore and /mnt/extra-addons for users addons and /mnt/backup for backup RUN chown odoo /etc/odoo/odoo.conf \ && mkdir -p /mnt/extra-addons \ diff --git a/Makefile b/Makefile index e288c89bb..844c4ec91 100644 --- a/Makefile +++ b/Makefile @@ -100,9 +100,9 @@ gen_config_docker: $(MAKE) download_backup LINKDB=${BACKUP} ${PWD}/setup/init_config.sh --docker ${ODOO_IMAGE} ${TAG} ${CONTAINER_ID} build_image: - DOCKER_BUILDKIT=1 ${DOCKER_BUILD} . --progress plain --tag ${ODOO_IMAGE}:${TAG} + DOCKER_BUILDKIT=1 ${DOCKER_BUILD} . --progress plain --tag $(shell echo ${ODOO_IMAGE}| tr A-Z a-z):${TAG} push_image: - $(DOCKER_PUSH) ${ODOO_IMAGE}:${TAG} + $(DOCKER_PUSH) $(shell echo ${ODOO_IMAGE}| tr A-Z a-z):${TAG} run_server_docker: @if ! docker ps | grep -q "${CONTAINER_ID}"; then \ echo "Container not found. Running docker-compose up -d"; \ @@ -137,6 +137,7 @@ clean_up: ! -name "*.template" \ ! -name "*.py" \ ! -name "*.yml" \ + ! -name "*.txt" \ -print0 | sudo xargs -0 rm -rf {} && \ sudo rm -rf ${DEPLOY_PATH}/etc/* diff --git a/deployment/docker-compose.nodb.yml b/deployment/docker-compose.nodb.yml new file mode 100755 index 000000000..06530a825 --- /dev/null +++ b/deployment/docker-compose.nodb.yml @@ -0,0 +1,20 @@ +version: '3.8' +services: + app: + image: ${ODOO_IMAGE:-odoo}:${ODOO_TAG:-18} + container_name: ${ODOO_CONTAINER:-odoo} + ports: + - ${ODOO_PORT:-8069}:8069 + # - "${ODOO_CHAT_PORT:-8072}:8072" + tty: true + command: -- + environment: + - HOST=db + - USER=${PG_USER:-changeme} + - PASSWORD=${PG_PASS:-password} + volumes: + - ${ODOO_ADDONS:-./addons}:/mnt/extra-addons + - ${ODOO_CONFIG:-./etc}:/etc/odoo + - ${ODOO_BACKUP:-./backup}:/var/lib/odoo/backup + restart: always + diff --git a/deployment/env.template b/deployment/env.template index 009edac12..cb38dfbf8 100755 --- a/deployment/env.template +++ b/deployment/env.template @@ -1,10 +1,10 @@ -COMPOSE_PROJECT_NAME= +COMPOSE_PROJECT_NAME = #Odoo -ODOO_IMAGE= +ODOO_IMAGE = ODOO_TAG= -ODOO_PORT=10017 -ODOO_CONTAINER= -# ODOO_CHAT_PORT= +ODOO_PORT = 10017 +ODOO_CONTAINER = +# ODOO_CHAT_PORT = ODOO_ADDONS=./addons ODOO_CONFIG=./etc ODOO_BACKUP=./backup diff --git a/deployment/requirements.txt b/deployment/requirements.txt new file mode 100644 index 000000000..25990d4b2 --- /dev/null +++ b/deployment/requirements.txt @@ -0,0 +1,21 @@ +python-dotenv==1.0.1; python_version > '3.10' +python_docx_replace ; python_version > '3.10' +python-docx ; python_version > '3.10' +html2text ; python_version > '3.10' +docx ; python_version > '3.10' +dropbox ; python_version > '3.10' +pyncclient ; python_version > '3.10' +nextcloud-api-wrapper ; python_version > '3.10' +boto3 ; python_version > '3.10' +paramiko ; python_version > '3.10' +proxmoxer ; python_version > '3.10' +requests ; python_version > '3.10' +google_auth ; python_version > '3.10' +odoorpc ; python_version > '3.10' +openai ; python_version > '3.10' +pysftp ; python_version > '3.10' and sys_platform != 'win32' +unidecode ; python_version > '3.10' +pdfkit ; python_version > '3.10' +pdfminer.six ; python_version > '3.10' +weasyprint +beautifulsoup4 \ No newline at end of file diff --git a/setup/backup_db.py b/setup/backup_db.py new file mode 100644 index 000000000..181e4b451 --- /dev/null +++ b/setup/backup_db.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +import odoorpc +import color_log +import argparse +import sys +import base64 +import os + +# Default configuration +DEFAULT_HOST = "localhost" +DEFAULT_PORT = 8069 +DEFAULT_USERNAME = "admin" +DEFAULT_PASSWORD = "admin" +BACKUP_DIR = "odoo_backups" +CHUNK_SIZE = 500 # Records per batch for search operations +OK, FAIL, INFO, WARNING = 0, 1, 2, 3 + + +def connect_to_odoo(args: argparse.Namespace) -> odoorpc.ODOO: + """Establish and verify Odoo connection.""" + try: + odoo = odoorpc.ODOO(args.host, port=args.port) + if args.verbose: + color_log.Show(INFO, f"Available databases: {odoo.db.list()}") + + odoo.login(args.db_name, args.username, args.password) + color_log.Show(OK, f"Connected to {args.host}:{args.port}, DB: {args.db_name}") + return odoo + except odoorpc.error.RPCError as e: + color_log.Show(FAIL, f"Login failed: {e}") + sys.exit(1) + except Exception as e: + color_log.Show(FAIL, f"Connection error: {e}") + sys.exit(1) + + +def parse_arguments() -> argparse.Namespace: + """Parse and validate command-line arguments.""" + parser = argparse.ArgumentParser(description="Backup all Odoo databases.") + parser.add_argument("--host", default=DEFAULT_HOST, help="Odoo server host") + parser.add_argument( + "--port", type=int, default=DEFAULT_PORT, help="Odoo server port" + ) + parser.add_argument("--username", default=DEFAULT_USERNAME, help="Odoo username") + parser.add_argument("--password", default=DEFAULT_PASSWORD, help="Odoo password") + parser.add_argument( + "--admin-password", required=True, help="Odoo master admin password" + ) + return parser.parse_args() + + +def backup_database(odoo: odoorpc.ODOO, db_name: str, admin_password: str): + """Backup a single Odoo database.""" + try: + print(f"Backing up database: {db_name}...") + backup_data = odoo.db.dump(admin_password, admin_password, db_name) + + os.makedirs(BACKUP_DIR, exist_ok=True) + backup_path = os.path.join(BACKUP_DIR, f"{db_name}.zip") + with open(backup_path, "wb") as f: + f.write(base64.b64decode(backup_data)) + print(f"Backup saved: {backup_path}") + except Exception as e: + print(f"Failed to backup {db_name}: {e}") + + +def backup_all_databases(odoo: odoorpc.ODOO, admin_password: str): + """Backup all available databases.""" + try: + db_list = odoo.db.list() + print("Databases found:", db_list) + for db_name in db_list: + backup_database(odoo, db_name, admin_password) + except Exception as e: + print(f"Error retrieving database list: {e}") + + +def main(): + """Main execution flow.""" + args = parse_arguments() + odoo = connect_to_odoo(args) + backup_all_databases(odoo, args.admin_password) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + color_log.Show(FAIL, "\nOperation cancelled by user") + sys.exit(1) diff --git a/setup/gen_config_docker.py b/setup/gen_config_docker.py index ce15bc55f..06ac8b91a 100755 --- a/setup/gen_config_docker.py +++ b/setup/gen_config_docker.py @@ -84,9 +84,9 @@ def main(): set_key(dotenv_path=env_file_path, key_to_set="ODOO_CONFIG", value_to_set=config_path,quote_mode="never") set_key(dotenv_path=env_file_path, key_to_set="ODOO_ADDONS", value_to_set=addons,quote_mode="never") set_key(dotenv_path=env_file_path, key_to_set="ODOO_PORT", value_to_set=find_available_port(app_port),quote_mode="never") - set_key(dotenv_path=env_file_path, key_to_set="ODOO_IMAGE", value_to_set=image,quote_mode="never") + set_key(dotenv_path=env_file_path, key_to_set="ODOO_IMAGE", value_to_set=image.lower(),quote_mode="never") set_key(dotenv_path=env_file_path, key_to_set="ODOO_TAG", value_to_set=tag,quote_mode="never") - set_key(dotenv_path=env_file_path, key_to_set="ODOO_CONTAINER", value_to_set=container,quote_mode="never") + set_key(dotenv_path=env_file_path, key_to_set="ODOO_CONTAINER", value_to_set=container.lower(),quote_mode="never") set_key(dotenv_path=env_file_path, key_to_set="ODOO_BACKUP", value_to_set=backup,quote_mode="never") if __name__ == "__main__":