diff --git a/install-update-srs.sh b/install-update-srs.sh index 9bb51ca..b425b59 100755 --- a/install-update-srs.sh +++ b/install-update-srs.sh @@ -476,9 +476,28 @@ show_apt_plan() { printf ' New packages......................: %s\n' "$packages" } +# Color only interactive --check output. Redirected logs stay free of ANSI codes. +# Colorization is presentation-only; it does not affect readiness decisions. +colorize_check_output() { + if [[ -t 1 && ! -v NO_COLOR && "${TERM:-}" != dumb ]]; then + local line green=$'\033[32m' yellow=$'\033[33m' red=$'\033[31m' reset=$'\033[0m' + while IFS= read -r line || [[ -n "$line" ]]; do + line="${line//\[ ok \]/${green}[ ok ]${reset}}" + line="${line//\[ missing \]/${yellow}[ missing ]${reset}}" + line="${line//\[ blocked \]/${red}[ blocked ]${reset}}" + line="${line//: OK/: ${green}OK${reset}}" + printf '%s\n' "$line" + done + else + cat + fi +} + # Read-only inventory. Deliberately does not call init_srs_runtime(). read_only_check() { - local cmd file unit + local cmd file unit apt_preview mail_env reason + local cmake_missing=false ctest_missing=false apt_plan_safe=false + local -a blockers=() echo echo 'Selective SRS installer - read-only inventory' echo " Host..............................: $(hostname -f)" @@ -490,6 +509,7 @@ read_only_check() { echo ' Public SRS DNS validation (authoritative nameservers):' if ! verify_srs_domain_dns; then echo ' [ warning ] Public DNS is not ready; --install is blocked.' + blockers+=("Public SRS DNS validation or Postfix diagnostics failed") fi echo @@ -498,26 +518,66 @@ read_only_check() { printf ' [ ok ] %s\n' "$cmd" else printf ' [ missing ] %s\n' "$cmd" + case "$cmd" in + cmake) cmake_missing=true ;; + ctest) ctest_missing=true ;; + *) blockers+=("Required command is missing: ${cmd}") ;; + esac fi done + # An installed CMake must also satisfy the version required by --install. + if ! $cmake_missing; then + local cmake_ver cmake_major cmake_minor + cmake_ver="$(cmake --version 2>/dev/null | head -n 1)" + if [[ "$cmake_ver" =~ ([0-9]+)\.([0-9]+)\.([0-9]+) ]]; then + cmake_major="${BASH_REMATCH[1]}" + cmake_minor="${BASH_REMATCH[2]}" + if ((10#$cmake_major < 3 || (10#$cmake_major == 3 && 10#$cmake_minor < 24))); then + blockers+=("Installed CMake is older than the required version 3.24") + fi + else + blockers+=("Installed CMake version cannot be determined") + fi + fi if ! command -v cmake >/dev/null 2>&1; then echo echo ' Read-only APT simulation for missing cmake/ctest:' if command -v apt-get >/dev/null 2>&1; then - local apt_preview if apt_preview="$(LC_ALL=C apt-get -s install --no-install-recommends cmake)"; then - show_apt_plan "$apt_preview" || true + if show_apt_plan "$apt_preview" && + grep -Eq '^0 upgraded, [1-9][0-9]* newly installed, 0 to remove and [0-9]+ not upgraded\.$' <<< "$apt_preview"; then + apt_plan_safe=true + else + blockers+=("CMake/CTest APT transaction needs manual review") + fi else echo ' [ warning ] APT simulation failed; prerequisite cannot yet be installed.' + blockers+=("CMake/CTest APT simulation failed") fi else echo ' [ warning ] apt-get is unavailable.' + blockers+=("Cannot install missing CMake/CTest without apt-get") fi echo fi - check_templates && echo ' [ ok ] SRS configuration templates' || echo ' [ missing ] SRS configuration templates' - check_python_sources && echo ' [ ok ] Four SRS Python source files' || echo ' [ missing ] SRS Python sources' - [[ -r "$SRS_DNS_CHECKER" ]] && echo ' [ ok ] Public DNS preflight helper' || echo ' [ missing ] Public DNS preflight helper' + if check_templates; then + echo ' [ ok ] SRS configuration templates' + else + echo ' [ missing ] SRS configuration templates' + blockers+=("SRS configuration templates are missing") + fi + if check_python_sources; then + echo ' [ ok ] Four SRS Python source files' + else + echo ' [ missing ] SRS Python sources' + blockers+=("SRS Python source files are missing") + fi + if [[ -r "$SRS_DNS_CHECKER" ]]; then + echo ' [ ok ] Public DNS preflight helper' + else + echo ' [ missing ] Public DNS preflight helper' + blockers+=("Public DNS preflight helper is missing") + fi echo if [[ -L "$POSTSRSD_LINK" ]]; then @@ -533,13 +593,16 @@ read_only_check() { done if [[ -f "$SRS_CONF_FILE" && -z "$CONFIG_DOMAIN_HINT" ]]; then printf ' [ warning ] Existing SRS config has no simple readable _SRS_DOMAIN setting\n' + blockers+=("Existing SRS configuration has no readable _SRS_DOMAIN") elif [[ -n "$CONFIG_DOMAIN_HINT" && "$CONFIG_DOMAIN_HINT" != "$SELECTED_SRS_DOMAIN" ]]; then printf ' [ conflict ] Existing config domain: %s\n' "$CONFIG_DOMAIN_HINT" + blockers+=("Chosen SRS domain conflicts with existing configuration") fi if [[ -f "$SRS_CONF_FILE" && -z "$CONFIG_MX_HINT" ]]; then printf ' [ legacy ] Existing config has no _MX_HOST; maintenance-update will add it.\n' elif [[ -n "$CONFIG_MX_HINT" && "$CONFIG_MX_HINT" != "$SELECTED_MX_HOST" ]]; then printf ' [ conflict ] Existing MX hostname: %s\n' "$CONFIG_MX_HINT" + blockers+=("Chosen public MX hostname conflicts with existing configuration") fi echo for unit in "$POSTSRSD_SERVICE" "$SRS_REVERSE_MAP_SERVICE"; do @@ -559,12 +622,54 @@ read_only_check() { fi echo echo ' Delivery service MAIL_CONFIG (if defined):' - systemctl show -P Environment "$SRS_DELIVERY_SERVICE" 2>/dev/null || true + mail_env="$(systemctl show -P Environment "$SRS_DELIVERY_SERVICE" 2>/dev/null || true)" + if [[ -n "$mail_env" ]]; then + printf ' %s\n' "${mail_env//$'\n'/$'\n' }" + else + echo ' (not defined)' + fi + + echo + echo ' ------------------------------------------------------------' + echo ' Installation readiness summary' + echo ' ------------------------------------------------------------' + if $cmake_missing; then + if $apt_plan_safe; then + echo ' [ missing ] CMake/CTest: --install can install these after explicit APT approval.' + else + echo ' [ missing ] CMake/CTest: APT prerequisites require manual review.' + fi + elif $ctest_missing; then + echo ' [ missing ] CTest is unavailable although CMake is installed.' + blockers+=("CTest is missing despite installed CMake") + fi + if ((${#blockers[@]})); then + echo ' [ blocked ] INSTALLATION PREREQUISITES NOT SATISFIED.' + echo ' Resolve the following issues before proceeding:' + for reason in "${blockers[@]}"; do + printf ' - %s\n' "$reason" + done + echo ' Re-run ./install-update-srs.sh --check after fixing the issues.' + else + if $cmake_missing; then + echo ' [ ok ] READY TO START INSTALLATION (CMake/CTest approval required).' + else + echo ' [ ok ] ALL CHECKED INSTALLATION PREREQUISITES ARE SATISFIED.' + echo ' [ ok ] READY TO START INSTALLATION.' + fi + echo + echo ' Installation command:' + printf ' ./install-update-srs.sh --install --version %s\n' "$POSTSRSD_VERSION" + echo + echo ' --install repeats safety checks and requests confirmation.' + echo ' Installation does NOT activate SRS in the main Postfix instance.' + fi + echo ' Missing SRS installation files/services are normal before first installation.' echo echo 'No changes made.' } -[[ "$MODE" == '--check' ]] && { read_only_check; exit 0; } +[[ "$MODE" == '--check' ]] && { read_only_check | colorize_check_output; exit 0; } # CMake 3.24+ is required by the pinned PostSRSd build. The Debian # package "cmake" also supplies ctest. Never install any packages in --check.