From ebfceea2a32a95585ac53d7a73bf83a64808fc24 Mon Sep 17 00:00:00 2001 From: Janik von Rotz Date: Thu, 18 Dec 2025 12:02:57 +0100 Subject: [PATCH] feat(odoo): enhance database and module management with improved scripts and documentation --- images/odoo/README.md | 13 +-- images/odoo/bin/check-database-initialized | 19 ++-- images/odoo/bin/init-db | 109 ++++++++++----------- images/odoo/bin/init-module | 12 +-- images/odoo/bin/list-databases | 5 + images/odoo/bin/run-tests | 4 +- images/odoo/bin/setup-tests | 4 +- images/odoo/bin/update-module | 15 +-- images/odoo/bin/update-modules | 6 +- images/odoo/bin/update-modules-list | 19 ++-- images/odoo/bin/update-translations | 15 ++- task | 1 + 12 files changed, 120 insertions(+), 102 deletions(-) create mode 100755 images/odoo/bin/list-databases diff --git a/images/odoo/README.md b/images/odoo/README.md index cd7bc6b4..9a1c9bca 100644 --- a/images/odoo/README.md +++ b/images/odoo/README.md @@ -266,7 +266,7 @@ There is also the option to update all modules: docker compose exec odoo update-modules ``` -For each installed module Odoo computes and stores a checksum in the database. The update modules script compares the checksum and updates all modules that have changed. +The container use [click-odoo-contrib](https://github.com/acsone/click-odoo-contrib) to update Odoo modules. For each installed module a checksum is computed and stored in the database. Whenever an update of module is triggered, the checksum is computed and compared. Only modules with a different checksum are updated. ### Analyze @@ -334,7 +334,7 @@ Set mail parameters for the company. ### Incoming and Outgoing Mail-Server -Setup mail configuration for the database. +Setup mail configuration for the default database. - `ODOO_MAIL_SMTP_HOST`: If set Odoo sends mails to this host. - `ODOO_MAIL_SMTP_PORT`: SMTP port. Default is `587`. @@ -392,7 +392,7 @@ The entrypoint script searches for module folders in the addons path and creates Set these environment variables for the database init: -- `ODOO_DATABASE` Name of the Odoo database for initialisation. +- `ODOO_DATABASE` Name of the Odoo default database. - `ODOO_INIT_LOGIN` Username of the admin user. Default is `admin`. - `ODOO_INIT_PASSWORD` Password of the admin user. Default is `admin`. - `ODOO_INIT_LANG` Language used for database init. Default is `en_US`. @@ -445,12 +445,12 @@ With the `module_change_auto_install` module you can disable the auto installati ### Module Auto Update -The container provides [click-odoo-contrib](https://github.com/acsone/click-odoo-contrib) to update Odoo modules. Other updates such as the update of translations, can be automated. +Updating translations and the module list can be automated. -- `AUTO_UPDATE_TRANSLATIONS` If enabled translatiosn will be updated when the container starts. Default is `False`. +- `AUTO_UPDATE_TRANSLATIONS` If enabled, translatiosn will be updated when the container starts. Default is `False`. - `AUTO_UPDATE_MODULES_LIST` If enabled, the modules list will be updated when the container starts. Default is `False`. -Both options require `ODOO_DATABASE` and `ODOO_ADDONS_PATH`. +If `ODOO_DATABASE` is set, only this database will be updated. ### Testing @@ -563,6 +563,7 @@ Under the hood the image uses several scripts to manage Odoo. Make yourself fami - [`init-db`](https://github.com/Mint-System/Odoo-Build/blob/main/images/odoo/bin/init-db) - [`init-module`](https://github.com/Mint-System/Odoo-Build/blob/main/images/odoo/bin/init-module) - [`install-python-packages`](https://github.com/Mint-System/Odoo-Build/blob/main/images/odoo/bin/install-python-packages) +- [`list-database`](https://github.com/Mint-System/Odoo-Build/blob/main/images/odoo/bin/list-database) - [`log-entrypoint`](https://github.com/Mint-System/Odoo-Build/blob/main/images/odoo/bin/log-entrypoint) - [`parse-url`](https://github.com/Mint-System/Odoo-Build/blob/main/images/odoo/bin/parse-url) - [`remove-ssh-key`](https://github.com/Mint-System/Odoo-Build/blob/main/images/odoo/bin/remove-ssh-key) diff --git a/images/odoo/bin/check-database-initialized b/images/odoo/bin/check-database-initialized index 1df353f6..895a2aae 100755 --- a/images/odoo/bin/check-database-initialized +++ b/images/odoo/bin/check-database-initialized @@ -1,18 +1,15 @@ #!/usr/bin/env bash set -e -if [[ -n "$ODOO_DATABASE" ]]; then - log-entrypoint "Check if database $ODOO_DATABASE is initialized..." - database_initialized=$(exec psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/$ODOO_DATABASE" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'ir_module_module'") +odoo_database=${1:=$ODOO_DATABASE} - if [[ "$database_initialized" = "1" ]]; then - log-entrypoint "Database $ODOO_DATABASE is initialized." - exit 0 - else - log-entrypoint "Database $ODOO_DATABASE is not initialized." - exit 1 - fi +log-entrypoint "Check if database $odoo_database is initialized..." +database_initialized=$(exec psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/$odoo_database" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'ir_module_module'") + +if [[ "$database_initialized" = "1" ]]; then + log-entrypoint "Database $odoo_database is initialized." + exit 0 else - log-entrypoint 'ODOO_DATABASE environment variable not set.' + log-entrypoint "Database $odoo_database is not initialized." exit 1 fi diff --git a/images/odoo/bin/init-db b/images/odoo/bin/init-db index 65c60bd0..f8d4d99d 100755 --- a/images/odoo/bin/init-db +++ b/images/odoo/bin/init-db @@ -1,75 +1,72 @@ #!/usr/bin/env bash set -e -if [[ -n "$ODOO_DATABASE" ]]; then +odoo_database=${1:=$ODOO_DATABASE} - log-entrypoint "Starting database initialization for $ODOO_DATABASE." - log-entrypoint "Database connection: $PGUSER@$PGHOST:$PGPORT" +log-entrypoint "Starting database initialization for $odoo_database." +log-entrypoint "Database connection: $PGUSER@$PGHOST:$PGPORT" - log-entrypoint 'Waiting for database connection...' - until psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/postgres" -c '\q' 2>/dev/null; do - log-entrypoint 'Database not ready, waiting 2 seconds...' - sleep 2 - done - log-entrypoint 'Database connection established.' +log-entrypoint 'Waiting for database connection...' +until psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/postgres" -c '\q' 2>/dev/null; do + log-entrypoint 'Database not ready, waiting 2 seconds...' + sleep 2 +done +log-entrypoint 'Database connection established.' - log-entrypoint "Check if database $ODOO_DATABASE exists..." - database_exists=$(exec psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/postgres" -tAc "SELECT COUNT(*) FROM pg_database WHERE datname = '$ODOO_DATABASE'") +log-entrypoint "Check if database $odoo_database exists..." +database_exists=$(exec psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/postgres" -tAc "SELECT COUNT(*) FROM pg_database WHERE datname = '$odoo_database'") - # If it does not exist, create it - if [[ "$database_exists" = "0" ]]; then - log-entrypoint "Create database $ODOO_DATABASE..." - (exec psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/postgres" -tAc "CREATE DATABASE \"$ODOO_DATABASE\";") || true - log-entrypoint 'Database creation completed.' - else - log-entrypoint "Database $ODOO_DATABASE already exists." +# If it does not exist, create it +if [[ "$database_exists" = "0" ]]; then + log-entrypoint "Create database $odoo_database..." + (exec psql "postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/postgres" -tAc "CREATE DATABASE \"$odoo_database\";") || true + log-entrypoint 'Database creation completed.' +else + log-entrypoint "Database $odoo_database already exists." +fi + +if ! check-database-initialized "$odoo_database"; then + log-entrypoint 'Database not initialized, starting initialization process' + without_demo=${WITHOUT_DEMO:=True} + odoo_init_login=${ODOO_INIT_LOGIN:="admin"} + odoo_init_password=${ODOO_INIT_PASSWORD:="admin"} + odoo_init_lang=${ODOO_INIT_LANG:="en_US"} + odoo_init_addons=${ODOO_INIT_ADDONS:="web"} + + odoo_init_param="" + if [[ "$without_demo" = "True" ]]; then + odoo_init_param="--without-demo=all" fi - if ! check-database-initialized; then - log-entrypoint 'Database not initialized, starting initialization process' - without_demo=${WITHOUT_DEMO:=True} - odoo_init_login=${ODOO_INIT_LOGIN:="admin"} - odoo_init_password=${ODOO_INIT_PASSWORD:="admin"} - odoo_init_lang=${ODOO_INIT_LANG:="en_US"} - odoo_init_addons=${ODOO_INIT_ADDONS:="web"} + log-entrypoint "Initialize database $odoo_database with modules: $odoo_init_addons." + (exec odoo "${DB_ARGS[@]}" --database "$odoo_database" --init "$odoo_init_addons" --config "$ODOO_RC" --stop-after-init --no-http --load-language "$odoo_init_lang" $odoo_init_param) || true + log-entrypoint 'Odoo initialization command completed.' - odoo_init_param="" - if [[ "$without_demo" = "True" ]]; then - odoo_init_param="--without-demo=all" - fi - - log-entrypoint "Initialize database $ODOO_DATABASE with modules: $odoo_init_addons." - (exec odoo "${DB_ARGS[@]}" --database "$ODOO_DATABASE" --init "$odoo_init_addons" --config "$ODOO_RC" --stop-after-init --no-http --load-language "$odoo_init_lang" $odoo_init_param) || true - log-entrypoint 'Odoo initialization command completed.' - - if [[ "$odoo_init_login" != "admin" ]] || [[ "$odoo_init_password" != "admin" ]]; then - log-entrypoint "Updating admin user credentials..." - (exec odoo shell --database "$ODOO_DATABASE" --config "$ODOO_RC" << EOF + if [[ "$odoo_init_login" != "admin" ]] || [[ "$odoo_init_password" != "admin" ]]; then + log-entrypoint "Updating admin user credentials..." + (exec odoo shell --database "$odoo_database" --config "$ODOO_RC" << EOF admin_user = env['res.users'].browse(2) admin_user.write({ - 'login': '$odoo_init_login', - 'password': '$odoo_init_password' +'login': '$odoo_init_login', +'password': '$odoo_init_password' }) env.cr.commit() print('Credentials for user $odoo_init_login updated successfully.') EOF ) || true - fi fi - - if [[ -n "$ODOO_MAIL_SMTP_HOST" ]] || [[ -n "$ODOO_MAIL_IMAP_HOST" ]]; then - if check-database-initialized; then - log-entrypoint 'Setting up mail server configuration...' - - log-entrypoint "Setup mail server configuration for database $ODOO_DATABASE." - (odoo shell "${DB_ARGS[@]}" --database "$ODOO_DATABASE" --config "$ODOO_RC" --stop-after-init --no-http < /usr/local/bin/setup-mail) || true - log-entrypoint 'Mail server configuration completed.' - else - log-entrypoint 'Database not initialized, cannot setup mail server configuration.' - fi - fi - - log-entrypoint "Database initialization process completed for $ODOO_DATABASE." -else - log-entrypoint 'ODOO_DATABASE environment variable not set, skipping database initialization.' fi + +if [[ -n "$ODOO_MAIL_SMTP_HOST" ]] || [[ -n "$ODOO_MAIL_IMAP_HOST" ]]; then + if check-database-initialized "$odoo_database"; then + log-entrypoint 'Setting up mail server configuration...' + + log-entrypoint "Setup mail server configuration for database $odoo_database." + (odoo shell "${DB_ARGS[@]}" --database "$odoo_database" --config "$ODOO_RC" --stop-after-init --no-http < /usr/local/bin/setup-mail) || true + log-entrypoint 'Mail server configuration completed.' + else + log-entrypoint 'Database not initialized, cannot setup mail server configuration.' + fi +fi + +log-entrypoint "Database initialization process completed for $odoo_database." \ No newline at end of file diff --git a/images/odoo/bin/init-module b/images/odoo/bin/init-module index a5ace599..18636f58 100755 --- a/images/odoo/bin/init-module +++ b/images/odoo/bin/init-module @@ -1,11 +1,11 @@ #!/usr/bin/env bash set -e -if [[ -n "$ODOO_DATABASE" ]]; then - if check-database-initialized; then - odoo_init_lang="${ODOO_INIT_LANG:="en_US"}" +odoo_database=${1:=$ODOO_DATABASE} - log-entrypoint "Initialize module $1 on database $ODOO_DATABASE." - (exec odoo "${DB_ARGS[@]}" --database "$ODOO_DATABASE" --init "$1" --config "$ODOO_RC" --stop-after-init --no-http --load-language "$odoo_init_lang" --without-demo=all) || true - fi +if check-database-initialized "$odoo_database"; then + odoo_init_lang="${ODOO_INIT_LANG:="en_US"}" + + log-entrypoint "Initialize module $1 on database $odoo_database." + (exec odoo "${DB_ARGS[@]}" --database "$odoo_database" --init "$1" --config "$ODOO_RC" --stop-after-init --no-http --load-language "$odoo_init_lang" --without-demo=all) || true fi diff --git a/images/odoo/bin/list-databases b/images/odoo/bin/list-databases new file mode 100755 index 00000000..a9dbbe13 --- /dev/null +++ b/images/odoo/bin/list-databases @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e + +local conn_str="postgres://$PGUSER:$PGPASSWORD@$PGHOST:$PGPORT/postgres" +psql "$conn_str" -t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname NOT IN ('postgres', 'template0', 'template1');" \ No newline at end of file diff --git a/images/odoo/bin/run-tests b/images/odoo/bin/run-tests index 0f6e2db2..f656ee2c 100755 --- a/images/odoo/bin/run-tests +++ b/images/odoo/bin/run-tests @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -e +odoo_database=${1:=$ODOO_DATABASE} + if [[ -n "$TEST_INCLUDE" ]]; then test_modules=$(manifestoo --select-include "$TEST_INCLUDE" --select-exclude "$TEST_EXCLUDE" list --separator=,) else @@ -18,7 +20,7 @@ if [[ "$without_demo" = "True" ]]; then fi unbuffer coverage run --include "$TEST_ADDONS_DIR/*" --branch \ /opt/odoo-venv/bin/odoo \ - -d "$ODOO_DATABASE" \ + -d "$odoo_database" \ -i "$test_modules" \ --workers 0 \ --test-enable \ diff --git a/images/odoo/bin/setup-tests b/images/odoo/bin/setup-tests index cf930745..7f5e5854 100755 --- a/images/odoo/bin/setup-tests +++ b/images/odoo/bin/setup-tests @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -e +odoo_database=${1:=$ODOO_DATABASE} + log-entrypoint 'Install python packages required for testing.' uv pip install --no-cache-dir coverage websocket-client @@ -24,7 +26,7 @@ if [[ "$without_demo" = "True" ]]; then odoo_init_param="--without-demo=all" fi unbuffer /opt/odoo-venv/bin/odoo \ - -d "$ODOO_DATABASE" \ + -d "$odoo_database" \ -i "${test_depends_modules:-base}" \ --load-language=$odoo_init_lang \ --stop-after-init \ diff --git a/images/odoo/bin/update-module b/images/odoo/bin/update-module index d5402f62..8ca5d289 100755 --- a/images/odoo/bin/update-module +++ b/images/odoo/bin/update-module @@ -1,12 +1,13 @@ #!/usr/bin/env bash set -e -if [[ -n "$ODOO_DATABASE" ]]; then - if check-database-initialized; then - odoo_init_lang="${ODOO_INIT_LANG:="en_US"}" +odoo_database=${1:=$ODOO_DATABASE} - log-entrypoint "Update module $1 on database $ODOO_DATABASE." - (exec odoo "${DB_ARGS[@]}" --database "$ODOO_DATABASE" --update "$1" --config "$ODOO_RC" \ - --stop-after-init --no-http --load-language "$odoo_init_lang" --without-demo=all) || true - fi +if check-database-initialized "$odoo_database"; then + odoo_init_lang="${ODOO_INIT_LANG:="en_US"}" + + log-entrypoint "Update module $1 on database $odoo_database." + (exec odoo "${DB_ARGS[@]}" --database "$odoo_database" --update "$1" --config "$ODOO_RC" \ + --stop-after-init --no-http --load-language "$odoo_init_lang" --without-demo=all) || true fi + diff --git a/images/odoo/bin/update-modules b/images/odoo/bin/update-modules index 319512eb..00302713 100755 --- a/images/odoo/bin/update-modules +++ b/images/odoo/bin/update-modules @@ -1,9 +1,11 @@ #!/usr/bin/env bash set -e +odoo_database=${1:=$ODOO_DATABASE} + source set-addons-path -if [[ -n "$ADDONS_PATH" ]] && [[ -n "$ODOO_DATABASE" ]]; then +if [[ -n "$ADDONS_PATH" ]]; then log-entrypoint "Run click-odoo-update for: $ADDONS_PATH" - (exec click-odoo-update --addons-path="$ADDONS_PATH" -d "$ODOO_DATABASE" ) || true + (exec click-odoo-update --addons-path="$ADDONS_PATH" -d "$odoo_database" ) || true fi diff --git a/images/odoo/bin/update-modules-list b/images/odoo/bin/update-modules-list index e5e9cde5..b1fc6ba9 100755 --- a/images/odoo/bin/update-modules-list +++ b/images/odoo/bin/update-modules-list @@ -2,10 +2,17 @@ set -e if [[ -n "$ODOO_DATABASE" ]]; then - if check-database-initialized; then - log-entrypoint "Update modules list on database $ODOO_DATABASE." + odoo_database=${1:=$ODOO_DATABASE} +else + IFS=$'\n' read -rd '' -a odoo_databases <<< "$(list-databases)" +fi + +for odoo_database in "${odoo_databases[@]}"; do + if check-database-initialized "$odoo_database"; then + log-entrypoint "Update modules list on database $odoo_database." + # Execute Odoo shell command to call base.module.update:update_module() - (exec odoo shell "${DB_ARGS[@]}" --database "$ODOO_DATABASE" --config "$ODOO_RC" --stop-after-init --no-http << 'EOF' + (exec odoo shell "${DB_ARGS[@]}" --database "$odoo_database" --config "$ODOO_RC" --stop-after-init --no-http << 'EOF' updater = env['base.module.update'] updater.update_module() env.cr.commit() @@ -13,8 +20,6 @@ print('Module list updated successfully.') EOF ) || true else - log-entrypoint "Database $ODOO_DATABASE is not initialized, skipping modules list update." + log-entrypoint "Database $odoo_database is not initialized, skipping modules list update." fi -else - log-entrypoint 'ODOO_DATABASE environment variable not set, skipping modules list update.' -fi +done \ No newline at end of file diff --git a/images/odoo/bin/update-translations b/images/odoo/bin/update-translations index 59bee4fa..661335eb 100755 --- a/images/odoo/bin/update-translations +++ b/images/odoo/bin/update-translations @@ -4,14 +4,19 @@ set -e source set-addons-path if [[ -n "$ODOO_DATABASE" ]]; then - if check-database-initialized; then + odoo_database=${1:=$ODOO_DATABASE} +else + IFS=$'\n' read -rd '' -a odoo_databases <<< "$(list-databases)" +fi + for odoo_database in "${odoo_databases[@]}"; do + if check-database-initialized "$odoo_database"; then log-entrypoint 'Updating translations for all active languages and installed modules.' - (exec odoo shell --database "$ODOO_DATABASE" --config "$ODOO_RC" << EOF + (exec odoo shell --database "$odoo_database" --config "$ODOO_RC" << EOF for lang in env['res.lang'].search([]): - env['ir.module.module'].search([('state', '=', 'installed')])._update_translations(lang.code, overwrite=True) +env['ir.module.module'].search([('state', '=', 'installed')])._update_translations(lang.code, overwrite=True) env.cr.commit() print('Translations updated successfully') EOF -) || true - fi + ) || true fi +done \ No newline at end of file diff --git a/task b/task index 7524a4cc..c85816a8 100755 --- a/task +++ b/task @@ -2378,6 +2378,7 @@ upgrade-odoo() { if [[ "$2" =~ "update" ]]; then log-warning "Run step 'update' on $TARGET_SERVER." + ssh -p $TARGET_PORT "$TARGET_SERVER" docker exec "$TARGET_ODOO_CONTAINER" update-modules-list ssh -p $TARGET_PORT "$TARGET_SERVER" docker-odoo-update -c "$TARGET_ODOO_CONTAINER" -d "$TARGET_DATABASE" -u all ssh -p "$TARGET_PORT" "$TARGET_SERVER" docker-odoo-clear-assets -c "$TARGET_ODOO_CONTAINER" -d "$TARGET_DATABASE" fi