#!/bin/bash export PATH=/4PROJECTS/bin:$PATH if [ ! -n "$1" ]; then echo "Missing Parameters " exit 0 fi UUID=$1 source /4server/sbin/helpers get_contract_info # Query installed modules from database and save CSV in variable DB_MODULES_CSV=$(PGPASSWORD="$POSTGRES_ADMIN_PASSWORD" PAGER= psql \ -h "$POSTGRES_HOST" \ -U "$POSTGRES_ADMIN_USER" \ -p "$POSTGRES_PORT" \ -d "$UUID" \ --csv \ -c " SELECT name, latest_version, author, summary FROM ir_module_module WHERE state = 'installed' ORDER BY name; ") # Check if container exists and is running if ! doas docker ps --format "{{.Names}}" | grep -q "^${UUID}$"; then echo "Error: Container $UUID is not running" >&2 exit 1 fi # Get addons_path from odoo.conf in container (try multiple possible locations) ADDONS_PATH_RAW="" for ODOO_CONF in "/etc/odoo.conf" "/etc/odoo/odoo.conf" "/opt/odoo/etc/odoo.conf"; do ADDONS_PATH_RAW=$(doas docker exec "$UUID" grep "^addons_path" "$ODOO_CONF" 2>/dev/null | sed 's/.*=//' | xargs) [ -n "$ADDONS_PATH_RAW" ] && break done # Also check standard Odoo library locations ODOO_LIB_PATHS="" # Check standard docker installation path if doas docker exec "$UUID" test -d "/lib/python3/dist-packages/odoo/addons" 2>/dev/null; then ODOO_LIB_PATHS="/lib/python3/dist-packages/odoo/addons" fi # Also check other possible locations for lib_path in $(doas docker exec "$UUID" find /usr/lib /usr/local/lib -maxdepth 3 -type d -path "*/python3*/site-packages/odoo/addons" 2>/dev/null); do ODOO_LIB_PATHS="$ODOO_LIB_PATHS $lib_path" done # Collect all module directories from filesystem FILESYSTEM_MODULES=$(mktemp) trap "rm -f $FILESYSTEM_MODULES" EXIT # Collect from addons_path directories if [ -n "$ADDONS_PATH_RAW" ]; then OLD_IFS="$IFS" IFS=',' read -ra ADDPATHS <<< "$ADDONS_PATH_RAW" IFS="$OLD_IFS" for addons_dir in "${ADDPATHS[@]}"; do addons_dir=$(echo "$addons_dir" | xargs) [ -z "$addons_dir" ] && continue # Get all directories in this addons path doas docker exec "$UUID" find "$addons_dir" -maxdepth 1 -type d 2>/dev/null | \ sed "s|^$addons_dir/||" | sed "s|^$addons_dir$||" | grep -v "^$" >> "$FILESYSTEM_MODULES" done fi # Also collect from standard Odoo library locations if [ -n "$ODOO_LIB_PATHS" ]; then for lib_path in $ODOO_LIB_PATHS; do lib_path=$(echo "$lib_path" | xargs) [ -z "$lib_path" ] && continue # Get all directories in this library path doas docker exec "$UUID" find "$lib_path" -maxdepth 1 -type d 2>/dev/null | \ sed "s|^$lib_path/||" | sed "s|^$lib_path$||" | grep -v "^$" >> "$FILESYSTEM_MODULES" done fi # Sort and deduplicate filesystem modules sort -u "$FILESYSTEM_MODULES" > "${FILESYSTEM_MODULES}.sorted" mv "${FILESYSTEM_MODULES}.sorted" "$FILESYSTEM_MODULES" # Process database modules and find missing ones MISSING_MODULES=$(mktemp) trap "rm -f $FILESYSTEM_MODULES $MISSING_MODULES" EXIT # Process each line from database CSV (skip header) echo "$DB_MODULES_CSV" | tail -n +2 | while IFS= read -r line; do [ -z "$line" ] && continue # Extract module name from first CSV field # Handle quoted CSV: extract first field, remove surrounding quotes if echo "$line" | grep -q '^"'; then # First field is quoted - extract between first quote and comma name=$(echo "$line" | sed 's/^"\([^"]*\)".*/\1/') else # First field is not quoted - extract up to first comma name=$(echo "$line" | cut -d',' -f1) fi name=$(echo "$name" | xargs) [ -z "$name" ] && continue # Check if module exists in filesystem if ! grep -Fxq "$name" "$FILESYSTEM_MODULES"; then # Module not found in filesystem - output the full CSV line echo "$line" >> "$MISSING_MODULES" fi done # Output missing modules if any were found if [ -s "$MISSING_MODULES" ]; then echo "Missing modules:" echo "$DB_MODULES_CSV" | head -n 1 # Output CSV header cat "$MISSING_MODULES" fi