From e854e0dc87becbbed598c982fa873691442f1d12 Mon Sep 17 00:00:00 2001 From: Luc Pierson Date: Sun, 5 Apr 2026 10:52:57 +0200 Subject: [PATCH] initial commit --- 1.gitclone.sh | 30 ++++++++++ 2.build.postgresql.sh | 6 ++ 3.build.odoo.sh | 1 + 4.LaunchOdoo.sh | 1 + 5.install_modules_OCA.sh | 40 +++++++++++++ Dockerfile | 109 +++++++++++++++++++++++++++++++++++ docker-compose.yml | 30 ++++++++++ entrypoint.sh | 49 ++++++++++++++++ find_dependances.py | 89 ++++++++++++++++++++++++++++ modules_OCA.env | 6 ++ odoo.conf | 13 +++++ postgresql-config/Dockerfile | 10 ++++ requirements.txt | 15 +++++ tail_odoo_logs.sh | 2 + update_modules_OCA.sh | 30 ++++++++++ wait-for-psql.py | 32 ++++++++++ 16 files changed, 463 insertions(+) create mode 100755 1.gitclone.sh create mode 100755 2.build.postgresql.sh create mode 100755 3.build.odoo.sh create mode 100755 4.LaunchOdoo.sh create mode 100755 5.install_modules_OCA.sh create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100755 entrypoint.sh create mode 100644 find_dependances.py create mode 100644 modules_OCA.env create mode 100644 odoo.conf create mode 100644 postgresql-config/Dockerfile create mode 100644 requirements.txt create mode 100755 tail_odoo_logs.sh create mode 100755 update_modules_OCA.sh create mode 100755 wait-for-psql.py diff --git a/1.gitclone.sh b/1.gitclone.sh new file mode 100755 index 0000000..4f15a23 --- /dev/null +++ b/1.gitclone.sh @@ -0,0 +1,30 @@ +mkdir -p ./custom +cd custom +git clone https://github.com/OCA/account-analytic.git +git clone https://github.com/OCA/account-financial-reporting.git +git clone https://github.com/OCA/account-financial-tools.git +git clone https://github.com/OCA/account-invoicing.git +git clone https://github.com/OCA/account-payment.git +git clone https://github.com/OCA/account-reconcile.git +git clone https://github.com/OCA/bank-payment.git +git clone https://github.com/OCA/bank-statement-import.git +git clone https://github.com/OCA/community-data-files.git +git clone https://github.com/OCA/currency.git +git clone https://github.com/OCA/edi.git +git clone https://github.com/OCA/knowledge.git +git clone https://github.com/OCA/l10n-france.git +git clone https://github.com/OCA/mail.git +git clone https://github.com/OCA/mis-builder.git +git clone https://github.com/OCA/partner-contact.git +git clone https://github.com/OCA/queue.git +git clone https://github.com/OCA/reporting-engine.git +git clone https://github.com/OCA/sale-reporting.git +git clone https://github.com/OCA/sale-workflow.git +git clone https://github.com/OCA/server-auth.git +git clone https://github.com/OCA/server-brand.git +git clone https://github.com/OCA/account-financial-reporting.git +git clone https://github.com/OCA/server-tools.git +git clone https://github.com/OCA/server-ux.git +git clone https://github.com/OCA/social.git +git clone https://github.com/OCA/web.git + diff --git a/2.build.postgresql.sh b/2.build.postgresql.sh new file mode 100755 index 0000000..2581ba0 --- /dev/null +++ b/2.build.postgresql.sh @@ -0,0 +1,6 @@ +#cd postgresql-config +#docker build -t postgres15-5434-image . +docker build \ + -f ./postgresql-config/Dockerfile \ + -t postgres15-5434-image . +#cd .. diff --git a/3.build.odoo.sh b/3.build.odoo.sh new file mode 100755 index 0000000..c76e66d --- /dev/null +++ b/3.build.odoo.sh @@ -0,0 +1 @@ +docker build -t odoo18-20260324-image . diff --git a/4.LaunchOdoo.sh b/4.LaunchOdoo.sh new file mode 100755 index 0000000..e6fb3f1 --- /dev/null +++ b/4.LaunchOdoo.sh @@ -0,0 +1 @@ +docker compose up -d diff --git a/5.install_modules_OCA.sh b/5.install_modules_OCA.sh new file mode 100755 index 0000000..fc811e7 --- /dev/null +++ b/5.install_modules_OCA.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -euo pipefail +######################## +### +### installation de modules OCA +### +######################## +source ./modules_OCA.env + +echo "=== Vérification que le container tourne ===" +if ! docker inspect -f '{{.State.Running}}' "${ODOO_CONTAINER}" 2>/dev/null | grep -q true; then + echo "ERREUR : container ${ODOO_CONTAINER} non démarré ou inexistant" + exit 1 +fi +echo "=== Mise à jour de la liste des addons ===" +docker exec "${ODOO_CONTAINER}" \ + chown -R odoo:odoo /var/lib/odoo/filestore + +docker exec -u odoo "${ODOO_CONTAINER}" \ + odoo \ + -c /etc/odoo/odoo.conf \ + -d "${DB_NAME}" \ + --update base \ + --stop-after-init \ + --no-http \ + --logfile "" \ + --log-level info + +echo "=== Installation des modules OCA ===" +docker exec -u odoo "${ODOO_CONTAINER}" \ + odoo \ + -c /etc/odoo/odoo.conf \ + -d "${DB_NAME}" \ + -i "${OCA_MODULES}" \ + --stop-after-init \ + --no-http \ + --logfile "" \ + --log-level info + +echo "=== Installation terminée ===" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..41963ff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,109 @@ +FROM ubuntu:noble +MAINTAINER Odoo S.A. + +SHELL ["/bin/bash", "-xo", "pipefail", "-c"] + +# Generate locale C.UTF-8 for postgres and general locale data +ENV LANG en_US.UTF-8 + +# Retrieve the target architecture to install the correct wkhtmltopdf package +ARG TARGETARCH + +# Install some deps, lessc and less-plugin-clean-css, and wkhtmltopdf + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + dirmngr \ + fonts-noto-cjk \ + gnupg \ + libssl-dev \ + node-less \ + npm \ + vim \ + python3-magic \ + python3-num2words \ + python3-odf \ + python3-pdfminer \ + python3-pip \ + python3-phonenumbers \ + python3-pyldap \ + python3-qrcode \ + python3-renderpm \ + python3-setuptools \ + python3-slugify \ + python3-vobject \ + python3-watchdog \ + python3-xlrd \ + python3-xlwt \ + xz-utils && \ + if [ -z "${TARGETARCH}" ]; then \ + TARGETARCH="$(dpkg --print-architecture)"; \ + fi; \ + WKHTMLTOPDF_ARCH=${TARGETARCH} && \ + case ${TARGETARCH} in \ + "amd64") WKHTMLTOPDF_ARCH=amd64 && WKHTMLTOPDF_SHA=967390a759707337b46d1c02452e2bb6b2dc6d59 ;; \ + "arm64") WKHTMLTOPDF_SHA=90f6e69896d51ef77339d3f3a20f8582bdf496cc ;; \ + "ppc64le" | "ppc64el") WKHTMLTOPDF_ARCH=ppc64el && WKHTMLTOPDF_SHA=5312d7d34a25b321282929df82e3574319aed25c ;; \ + esac \ + && curl -o wkhtmltox.deb -sSL https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_${WKHTMLTOPDF_ARCH}.deb \ + && echo ${WKHTMLTOPDF_SHA} wkhtmltox.deb | sha1sum -c - \ + && apt-get install -y --no-install-recommends ./wkhtmltox.deb \ + && rm -rf /var/lib/apt/lists/* wkhtmltox.deb + +# install latest postgresql-client +RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ noble-pgdg main' > /etc/apt/sources.list.d/pgdg.list \ + && GNUPGHOME="$(mktemp -d)" \ + && export GNUPGHOME \ + && repokey='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8' \ + && gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "${repokey}" \ + && gpg --batch --armor --export "${repokey}" > /etc/apt/trusted.gpg.d/pgdg.gpg.asc \ + && gpgconf --kill all \ + && rm -rf "$GNUPGHOME" \ + && apt-get update \ + && apt-get install --no-install-recommends -y postgresql-client \ + && rm -f /etc/apt/sources.list.d/pgdg.list \ + && rm -rf /var/lib/apt/lists/* + +# Install rtlcss (on Debian buster) +RUN npm install -g rtlcss + +# Install Odoo +ENV ODOO_VERSION 18.0 +ARG ODOO_RELEASE=20260324 +ARG ODOO_SHA=ae28e50ed972a6e57f7de42fc3b267acd4ab1f33 +RUN curl -o odoo.deb -sSL http://nightly.odoo.com/${ODOO_VERSION}/nightly/deb/odoo_${ODOO_VERSION}.${ODOO_RELEASE}_all.deb \ + && echo "${ODOO_SHA} odoo.deb" | sha1sum -c - \ + && apt-get update \ + && apt-get -y install --no-install-recommends ./odoo.deb \ + && rm -rf /var/lib/apt/lists/* odoo.deb + +# Install Python dependencies for OCA modules +COPY ./requirements.txt /tmp/requirements.txt +RUN pip install --no-cache-dir --break-system-packages -r /tmp/requirements.txt + +# Copy entrypoint script and Odoo configuration file +COPY ./entrypoint.sh / +COPY ./odoo.conf /etc/odoo/ + +# Set permissions and Mount /var/lib/odoo to allow restoring filestore and /mnt/extra-addons for users addons +RUN chown odoo /etc/odoo/odoo.conf \ + && mkdir -p /mnt/extra-addons \ + && chown -R odoo /mnt/extra-addons +VOLUME ["/var/lib/odoo", "/mnt/extra-addons"] + +# Expose Odoo services +EXPOSE 8069 8071 8072 + +# Set the default config file +ENV ODOO_RC /etc/odoo/odoo.conf + +COPY wait-for-psql.py /usr/local/bin/wait-for-psql.py + +# Set default user when running the container +USER odoo + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["odoo"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d499c96 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3' + +services: + odoo-ls-transcription: # Configuration du container Odoo + image: odoo18-20260324-image:latest # Nom de notre image personnalisée + container_name: odoo-mercier + restart: unless-stopped + user: root + depends_on: + - postgres # L'exécution de notre service dépend de celui de postgres + ports: + - "18069:8069" # Le port 18069 est exposé pour accéder à l'application Odoo + + volumes: + - ./:/etc/odoo:z + - ./odoo-filestore:/var/lib/odoo/filestore:z + - ./custom:/mnt/extra-addons:z + - ./logs:/var/log/odoo:z + + postgres: # Configuration de notre service PostgreSQL + image: postgres15-5434-image:latest # Image postgres 15 de Docker hub + container_name: postgres-mercier + restart: unless-stopped + environment: + - POSTGRES_USER=odoo + - POSTGRES_PASSWORD=odoo + - POSTGRES_DB=postgres + volumes: + - ./postgresql-data:/var/lib/postgresql/data:z + diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..f802bcb --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e + +if [ -v PASSWORD_FILE ]; then + PASSWORD="$(< $PASSWORD_FILE)" +fi + +# set the postgres database host, port, user and password according to the environment +# and pass them as arguments to the odoo process if not present in the config file +: ${HOST:=${DB_PORT_5432_TCP_ADDR:='db'}} +: ${PORT:=${DB_PORT_5432_TCP_PORT:=5432}} +: ${USER:=${DB_ENV_POSTGRES_USER:=${POSTGRES_USER:='odoo'}}} +: ${PASSWORD:=${DB_ENV_POSTGRES_PASSWORD:=${POSTGRES_PASSWORD:='odoo'}}} + +DB_ARGS=() +function check_config() { + param="$1" + value="$2" + if grep -q -E "^\s*\b${param}\b\s*=" "$ODOO_RC" ; then + value=$(grep -E "^\s*\b${param}\b\s*=" "$ODOO_RC" |cut -d " " -f3|sed 's/["\n\r]//g') + fi; + DB_ARGS+=("--${param}") + DB_ARGS+=("${value}") +} +check_config "db_host" "$HOST" +check_config "db_port" "$PORT" +check_config "db_user" "$USER" +check_config "db_password" "$PASSWORD" + +case "$1" in + -- | odoo) + shift + if [[ "$1" == "scaffold" ]] ; then + exec odoo "$@" + else + wait-for-psql.py ${DB_ARGS[@]} --timeout=30 + exec odoo "$@" "${DB_ARGS[@]}" + fi + ;; + -*) + wait-for-psql.py ${DB_ARGS[@]} --timeout=30 + exec odoo "$@" "${DB_ARGS[@]}" + ;; + *) + exec "$@" +esac + +exit 1 diff --git a/find_dependances.py b/find_dependances.py new file mode 100644 index 0000000..c2abb92 --- /dev/null +++ b/find_dependances.py @@ -0,0 +1,89 @@ +import ast +from pathlib import Path + +env_file = Path("/home/lpierson/mercier18/modules_OCA.env") +MODULES = set() + +for line in env_file.read_text().splitlines(): + line = line.strip() + if line.startswith("OCA_MODULES="): + raw = line.split("=", 1)[1] + MODULES = {m.strip() for m in raw.split(",") if m.strip()} + break + +print(f"→ {len(MODULES)} modules chargés depuis {env_file.name}\n") + +IGNORE_ODOO_DEPS = { + "base", "web", "mail", "account", "sale", "purchase", "stock", + "hr", "project", "crm", "contacts", "portal", "website", +} + +scan_root = Path("/home/lpierson/mercier18/custom") + +python_deps = {} +odoo_deps_external = {} # pas dans MODULES, pas ignoré +odoo_deps_internal = {} # dans MODULES → déjà couvert +not_found = set(MODULES) + +for manifest in sorted(scan_root.rglob("__manifest__.py")): + module_name = manifest.parent.name + if module_name not in MODULES: + continue + not_found.discard(module_name) + try: + data = ast.literal_eval(manifest.read_text()) + except Exception as e: + print(f"[ERREUR parsing] {module_name}: {e}") + continue + + ext = data.get("external_dependencies", {}) + for pkg in ext.get("python", []): + python_deps.setdefault(pkg, []).append(module_name) + + for dep in data.get("depends", []): + if dep in IGNORE_ODOO_DEPS: + continue + if dep in MODULES: + odoo_deps_internal.setdefault(dep, []).append(module_name) + else: + odoo_deps_external.setdefault(dep, []).append(module_name) + +print("=" * 65) +print("DÉPENDANCES PYTHON → à ajouter dans requirements.txt") +print("=" * 65) +if python_deps: + for dep, mods in sorted(python_deps.items()): + print(f" {dep:<35} ← {', '.join(sorted(mods))}") +else: + print(" (aucune)") + +print() +print("=" * 65) +print("DÉPENDANCES ODOO DÉJÀ DANS LA LISTE → ordre d'install OK") +print("=" * 65) +if odoo_deps_internal: + for dep, mods in sorted(odoo_deps_internal.items()): + print(f" {dep:<35} ← requis par : {', '.join(sorted(mods))}") +else: + print(" (aucune)") + +print() +print("=" * 65) +print("DÉPENDANCES ODOO MANQUANTES → à ajouter dans OCA_MODULES") +print("=" * 65) +if odoo_deps_external: + for dep, mods in sorted(odoo_deps_external.items()): + print(f" {dep:<35} ← requis par : {', '.join(sorted(mods))}") +else: + print(" (aucune)") + +print() +print("=" * 65) +print("MODULES NON TROUVÉS → dépôts OCA pas encore clonés ?") +print("=" * 65) +if not_found: + for m in sorted(not_found): + print(f" {m}") +else: + print(" (tous trouvés)") + diff --git a/modules_OCA.env b/modules_OCA.env new file mode 100644 index 0000000..83c9f74 --- /dev/null +++ b/modules_OCA.env @@ -0,0 +1,6 @@ +DB_NAME=mercier +ODOO_CONTAINER=odoo-mercier + +# Modules à installer (séparés par des virgules, sans espaces) + +OCA_MODULES=account_check_printing,account_einvoice_generate,account_invoice_export,account_invoice_import_facturx,account_invoice_import_simple_pdf,account_payment,account_statement_import_base,account_tax_unece,auth_password_policy_signup,auth_signup,auth_totp,base_business_document_import,base_facturx,base_iban,base_search_fuzzy,base_setup,base_sparse_field,base_tier_validation,base_vat,base_view_inheritance_extension,board,l10n_fr,l10n_fr_account,payment,point_of_sale,purchase_stock,report_xlsx_helper,sale_management,server_environment,sms,web_tour,account_invoice_facturx,account_statement_import_file,account_banking_mandate,account_banking_mandate_contact,account_banking_mandate_sale,account_banking_mandate_sale_contact,account_banking_pain_base,account_banking_sepa_credit_transfer,account_banking_sepa_direct_debit,account_invoice_select_for_payment,account_payment_method_base_mode,account_payment_mode,account_payment_order,account_payment_order_grouped_output,account_payment_order_notification,account_payment_order_return,account_payment_order_tier_validation,account_payment_partner,account_payment_purchase,account_payment_purchase_stock,account_payment_sale,account_vendor_bank_account_default,account_vendor_bank_account_default_purchase,account_cash_invoice,account_check_printing_report_base,account_due_list,account_due_list_payment_mode,account_force_early_discount,account_payment_credit_card,account_payment_line,account_payment_method_base,account_payment_notification,account_payment_promissory_note,account_payment_return,account_payment_return_import,account_payment_return_import_iso20022,account_payment_show_invoice,account_payment_term_extension,account_payment_tier_validation,account_payment_widget_amount,account_refund_early_payment_discount,account_voucher_killer,partner_aging,payment_partner,account_analytic_required,partner_statement,account_asset_management,account_chart_update,account_journal_lock_date,account_lock_date_update,account_move_line_tax_editable,account_usability,account_reconcile_model_oca,account_reconcile_oca,account_statement_base,currency_rate_update,document_url,mail_debrand,mail_tracking,mis_builder,mis_builder_budget,mis_builder_demo,partner_contact_access_link,partner_firstname,queue_job,report_xlsx,sale_report_salesperson_from_partner,portal_sale_order_search,sale_cancel_reason,sale_commercial_partner,sale_delivery_state,sale_order_archive,sale_order_line_delivery_state,sale_order_line_input,sale_order_line_menu,sale_order_line_price_history,password_security,disable_odoo_online,remove_odoo_enterprise,account_financial_report,auditlog,base_name_search_improved,date_range,date_range_account,server_action_mass_edit ,base_search_mail_content,mail_activity_plan,web_advanced_search,web_dialog_size,web_environment_ribbon,web_favicon,web_listview_range_select,web_m2x_options,web_no_bubble,web_pivot_computed_measure,web_refresher,web_responsive,web_search_with_and,web_tree_many2one_clickable,account_balance_ebp_csv_export,account_statement_import_fr_cfonb,country_fr,l10n_fr_account_invoice_facturx,l10n_fr_account_invoice_import_facturx,l10n_fr_account_invoice_import_simple_pdf,l10n_fr_account_tax_unece,l10n_fr_business_document_import,l10n_fr_cog,l10n_fr_das2,l10n_fr_department,l10n_fr_department_oversea,l10n_fr_hr_check_ssnid,l10n_fr_mis_reports,l10n_fr_siret,l10n_fr_siret_account,l10n_fr_siret_lookup,l10n_fr_state diff --git a/odoo.conf b/odoo.conf new file mode 100644 index 0000000..85914d0 --- /dev/null +++ b/odoo.conf @@ -0,0 +1,13 @@ +[options] +addons_path=/mnt/extra-addons/account-invoicing,/mnt/extra-addons/account-payment,/mnt/extra-addons,/mnt/extra-addons/account-analytic,/mnt/extra-addons/account-financial-reporting,/mnt/extra-addons/account-financial-tools,/mnt/extra-addons/account-reconcile,/mnt/extra-addons/bank-payment,/mnt/extra-addons/bank-statement-import,/mnt/extra-addons/community-data-files,/mnt/extra-addons/currency,/mnt/extra-addons/edi,/mnt/extra-addons/knowledge,/mnt/extra-addons/l10n-france,/mnt/extra-addons/mail,/mnt/extra-addons/mis-builder,/mnt/extra-addons/partner-contact,/mnt/extra-addons/queue,/mnt/extra-addons/reporting-engine,/mnt/extra-addons/sale-reporting,/mnt/extra-addons/sale-workflow,/mnt/extra-addons/server-auth,/mnt/extra-addons/server-brand,/mnt/extra-addons/account-financial-reporting,/mnt/extra-addons/server-tools,/mnt/extra-addons/server-ux,/mnt/extra-addons/social,/mnt/extra-addons/web +data_dir = /var/lib/odoo +db_host = postgres +db_port = 5434 +db_user = odoo +db_password = odoo +limit_time_real = 120 +log_level = info +logfile = /var/log/odoo/odoo.log +proxy_mode = True +admin_passwd = $pbkdf2-sha512$600000$1LqXMqY0ZgyBkDImZGzt3Q$XuJXeq8FD56aZ06fBYZPtLUVa15LPe7bGEkrcbH/zdh4UuSJdbEeb88h9OPRiMBA7vFKYhJzgBztYnJ59p6Zcw + diff --git a/postgresql-config/Dockerfile b/postgresql-config/Dockerfile new file mode 100644 index 0000000..83e4eaf --- /dev/null +++ b/postgresql-config/Dockerfile @@ -0,0 +1,10 @@ +# Utiliser l'image officielle PostgreSQL 15 +FROM postgres:15 + +# Changer le port d'écoute dans la configuration PostgreSQL +RUN sed -i 's/^#port = 5432/port = 5434/' /usr/share/postgresql/postgresql.conf.sample + +# Copier la configuration dans le répertoire de configuration PostgreSQL +CMD ["postgres", "-c", "config_file=/usr/share/postgresql/postgresql.conf.sample"] + + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8a1b6ef --- /dev/null +++ b/requirements.txt @@ -0,0 +1,15 @@ +packaging +regex +dateparser +pymupdf +factur-x +lxml +num2words +pyfrdas2>=0.10 +pypdf>=3.1.0 +python-dateutil +python-stdnum +requests +requests_oauthlib +unidecode + diff --git a/tail_odoo_logs.sh b/tail_odoo_logs.sh new file mode 100755 index 0000000..ef841dc --- /dev/null +++ b/tail_odoo_logs.sh @@ -0,0 +1,2 @@ +tail -f ./logs/odoo.log + diff --git a/update_modules_OCA.sh b/update_modules_OCA.sh new file mode 100755 index 0000000..aff44a3 --- /dev/null +++ b/update_modules_OCA.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -euo pipefail + + +######################## +### +### Update de modules OCA +### +######################## + + +source ./modules_OCA.env + + +echo "=== Mise à jour de la liste des addons ===" +docker exec "${ODOO_CONTAINER}" \ + chown -R odoo:odoo /var/lib/odoo/filestore + +docker exec -u odoo "${ODOO_CONTAINER}" \ + odoo \ + -c /etc/odoo/odoo.conf \ + -d "${DB_NAME}" \ + -u "${OCA_MODULES}" \ + --stop-after-init \ + --no-http \ + --logfile "" \ + --log-level info + + +echo "=== Mise à jour terminée ===" diff --git a/wait-for-psql.py b/wait-for-psql.py new file mode 100755 index 0000000..a55f440 --- /dev/null +++ b/wait-for-psql.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import argparse +import psycopg2 +import sys +import time + + +if __name__ == '__main__': + arg_parser = argparse.ArgumentParser() + arg_parser.add_argument('--db_host', required=True) + arg_parser.add_argument('--db_port', required=True) + arg_parser.add_argument('--db_user', required=True) + arg_parser.add_argument('--db_password', required=True) + arg_parser.add_argument('--timeout', type=int, default=5) + + args = arg_parser.parse_args() + + start_time = time.time() + while (time.time() - start_time) < args.timeout: + try: + conn = psycopg2.connect(user=args.db_user, host=args.db_host, port=args.db_port, password=args.db_password, dbname='postgres') + error = '' + break + except psycopg2.OperationalError as e: + error = e + else: + conn.close() + time.sleep(1) + + if error: + print("Database connection failure: %s" % error, file=sys.stderr) + sys.exit(1)