#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" DEFAULT_ENV_FILE="${REPO_DIR}/.env" ENV_FILE="${ENV_FILE:-$DEFAULT_ENV_FILE}" CLI_REQUEST_ID="" NON_INTERACTIVE="${NON_INTERACTIVE:-no}" while [[ $# -gt 0 ]]; do case "$1" in --env-file) [[ $# -ge 2 ]] || { echo "Argument manquant pour --env-file" >&2; exit 1; } ENV_FILE="$2" shift 2 ;; --request-id) [[ $# -ge 2 ]] || { echo "Argument manquant pour --request-id" >&2; exit 1; } CLI_REQUEST_ID="$2" shift 2 ;; --non-interactive) NON_INTERACTIVE="yes" shift ;; *) echo "Argument inconnu : $1" >&2 exit 1 ;; esac done log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" } fail() { log "ERROR: $*" >&2 exit 1 } require_cmd() { command -v "$1" >/dev/null 2>&1 } ensure_postgres_cluster() { if ! require_cmd pg_lsclusters || ! require_cmd pg_createcluster; then return 0 fi if pg_lsclusters --no-header 2>/dev/null | grep -q .; then return 0 fi local version="" if [[ -d /etc/postgresql ]]; then version="$(find /etc/postgresql -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | LC_ALL=C sort -V | tail -n 1)" fi if [[ -z "$version" ]] && require_cmd psql; then version="$(psql --version 2>/dev/null | awk '{print $3}' | cut -d. -f1)" fi [[ -n "$version" ]] || return 1 log "Aucun cluster PostgreSQL détecté, création de ${version}/main..." "$SUDO_BIN" pg_createcluster "$version" main --start >/dev/null 2>&1 || return 1 return 0 } collect_postgres_diagnostics() { local diagnostics="" if "$SUDO_BIN" systemctl status "$POSTGRES_SERVICE_NAME" --no-pager >/dev/null 2>&1; then diagnostics+="systemctl status ${POSTGRES_SERVICE_NAME}: OK; " elif require_cmd systemctl; then diagnostics+="systemctl status ${POSTGRES_SERVICE_NAME}: $( "$SUDO_BIN" systemctl status "$POSTGRES_SERVICE_NAME" --no-pager 2>/dev/null | tail -n 5 | tr '\n' ' ' ); " fi if require_cmd pg_lsclusters; then diagnostics+="pg_lsclusters: $(pg_lsclusters --no-header 2>/dev/null | tr '\n' ' '); " fi if require_cmd journalctl; then diagnostics+="journalctl: $( "$SUDO_BIN" journalctl -u "$POSTGRES_SERVICE_NAME" -n 10 --no-pager 2>/dev/null | tr '\n' ' ' ); " fi printf '%s' "${diagnostics% }" } start_postgres_service() { if "$SUDO_BIN" systemctl start "$POSTGRES_SERVICE_NAME" >/dev/null 2>&1; then return 0 fi if require_cmd service && "$SUDO_BIN" service "$POSTGRES_SERVICE_NAME" start >/dev/null 2>&1; then return 0 fi if require_cmd pg_lsclusters && require_cmd pg_ctlcluster; then local version cluster while read -r version cluster _; do [[ -n "$version" && -n "$cluster" ]] || continue if "$SUDO_BIN" pg_ctlcluster "$version" "$cluster" start >/dev/null 2>&1; then return 0 fi done < <(pg_lsclusters --no-header 2>/dev/null || true) fi return 1 } [[ -f "$ENV_FILE" ]] || fail "fichier .env introuvable : $ENV_FILE" set -a # shellcheck disable=SC1090 source "$ENV_FILE" set +a : "${PGHOST:?Variable PGHOST manquante}" : "${PGPORT:?Variable PGPORT manquante}" : "${PGUSER:?Variable PGUSER manquante}" : "${PGPASSWORD:?Variable PGPASSWORD manquante}" AUTO_INSTALL_POSTGRES="${AUTO_INSTALL_POSTGRES:-yes}" AUTO_CREATE_PGUSER="${AUTO_CREATE_PGUSER:-yes}" PGUSER_SUPERUSER="${PGUSER_SUPERUSER:-no}" POSTGRES_PACKAGE_LIST="${POSTGRES_PACKAGE_LIST:-postgresql postgresql-client postgresql-contrib}" POSTGRES_SERVICE_NAME="${POSTGRES_SERVICE_NAME:-postgresql}" SUDO_BIN="${SUDO_BIN:-sudo}" export PGPASSWORD if ! require_cmd "$SUDO_BIN"; then fail "sudo absent sur la cible" fi if ! "$SUDO_BIN" /usr/bin/systemctl --version >/dev/null 2>&1; then fail "sudo indisponible pour systemctl" fi if [[ ! "$PGPORT" =~ ^[0-9]+$ ]]; then fail "PGPORT invalide : $PGPORT" fi POSTGRES_INSTALLED="no" if ! require_cmd psql || ! require_cmd pg_restore || ! require_cmd createdb || ! require_cmd dropdb; then [[ "${AUTO_INSTALL_POSTGRES,,}" == "yes" ]] || fail "PostgreSQL absent et AUTO_INSTALL_POSTGRES=no" log "PostgreSQL absent : installation en cours..." "$SUDO_BIN" apt update >/dev/null 2>&1 || fail "échec de apt update" "$SUDO_BIN" apt install -y $POSTGRES_PACKAGE_LIST >/dev/null 2>&1 || fail "échec de l'installation PostgreSQL" POSTGRES_INSTALLED="yes" log "Installation PostgreSQL terminée." else log "PostgreSQL déjà installé." fi ensure_postgres_cluster || fail "aucun cluster PostgreSQL disponible et création automatique impossible" if ! "$SUDO_BIN" systemctl is-active --quiet "$POSTGRES_SERVICE_NAME"; then log "Démarrage du service PostgreSQL..." if ! start_postgres_service; then fail "impossible de démarrer PostgreSQL. $(collect_postgres_diagnostics)" fi else log "Service PostgreSQL déjà actif." fi log "Vérification de la disponibilité de PostgreSQL..." for _ in {1..20}; do if "$SUDO_BIN" -u postgres psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then log "PostgreSQL répond correctement." break fi sleep 1 done if ! "$SUDO_BIN" -u postgres psql -d postgres -c "SELECT 1;" >/dev/null 2>&1; then fail "PostgreSQL ne répond pas correctement" fi if [[ "${AUTO_CREATE_PGUSER,,}" == "yes" ]]; then ROLE_EXISTS="$( "$SUDO_BIN" -u postgres psql -d postgres -tAc \ "SELECT 1 FROM pg_roles WHERE rolname='${PGUSER//\'/\'\'}'" 2>/dev/null || true )" if [[ "$ROLE_EXISTS" != "1" ]]; then log "Création du rôle PostgreSQL ${PGUSER}..." ROLE_ATTRIBUTES="LOGIN CREATEDB CREATEROLE" if [[ "${PGUSER_SUPERUSER,,}" == "yes" ]]; then ROLE_ATTRIBUTES="LOGIN SUPERUSER CREATEDB CREATEROLE" fi "$SUDO_BIN" -u postgres psql -d postgres -c \ "CREATE ROLE \"${PGUSER}\" WITH ${ROLE_ATTRIBUTES} PASSWORD '${PGPASSWORD//\'/\'\'}';" \ >/dev/null 2>&1 || fail "échec de création du rôle ${PGUSER}" log "Rôle PostgreSQL ${PGUSER} créé." else log "Rôle PostgreSQL ${PGUSER} déjà présent." fi fi if ! psql -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d postgres -c "SELECT 1;" >/dev/null 2>&1; then fail "connexion PostgreSQL locale impossible avec PGUSER=${PGUSER}" fi log "Check PostgreSQL terminé avec succès."