diff --git a/.devcontainer/setup-ha.sh b/.devcontainer/setup-ha.sh index e45e38a..0a6db63 100755 --- a/.devcontainer/setup-ha.sh +++ b/.devcontainer/setup-ha.sh @@ -507,7 +507,7 @@ configure_and_start_teslamate() { break fi if [ "$state" = "error" ]; then - dump_teslamate_logs 50 + dump_diagnostics 50 err "TeslaMate addon failed to start (state: ${state})" fi debug "Attempt $((attempt + 1))/${max_attempts}: TeslaMate state=${state}" @@ -515,7 +515,7 @@ configure_and_start_teslamate() { attempt=$((attempt + 1)) done if [ "$state" != "started" ]; then - dump_teslamate_logs 50 + dump_diagnostics 50 err "TeslaMate addon did not start in time (state: ${state})" fi @@ -523,12 +523,21 @@ configure_and_start_teslamate() { ok "TeslaMate addon started and ready" } -# dump_teslamate_logs() prints the most recent add-on logs (full lines) so a -# startup failure shows its real cause. It closes any open GitHub Actions log -# group first so the output is never hidden inside a collapsed fold. -dump_teslamate_logs() { +# dump_diagnostics() prints PostgreSQL and TeslaMate add-on logs (full lines) so +# a startup failure shows its real cause. PostgreSQL is reported first because +# TeslaMate halts if it cannot reach the database, so a stopped/crashed postgres +# addon is the most common root cause. Closes any open GitHub Actions log group +# first so the output is never hidden inside a collapsed fold. +dump_diagnostics() { local lines="${1:-50}" group_end + + local pg_state + pg_state=$(supervisor_api_jq "/addons/${POSTGRES_SLUG}/info" '.data.state' 2>/dev/null || true) + warn "PostgreSQL addon state: ${pg_state:-unknown}" + warn "Last ${lines} lines of PostgreSQL add-on logs:" + supervisor_api GET "/addons/${POSTGRES_SLUG}/logs" 2>/dev/null | tail -n "${lines}" >&2 || true + warn "Last ${lines} lines of TeslaMate add-on logs:" supervisor_api GET "/addons/${TESLAMATE_SLUG}/logs" 2>/dev/null | tail -n "${lines}" >&2 || true } @@ -551,7 +560,7 @@ wait_for_teslamate_ready() { # instead of polling uselessly until the timeout. state=$(supervisor_api_jq "/addons/${TESLAMATE_SLUG}/info" '.data.state') if [ "$state" = "error" ] || [ "$state" = "stopped" ]; then - dump_teslamate_logs 50 + dump_diagnostics 50 err "TeslaMate crashed during startup (add-on state: ${state})" fi @@ -559,7 +568,7 @@ wait_for_teslamate_ready() { sleep 5 attempt=$((attempt + 1)) done - dump_teslamate_logs 50 + dump_diagnostics 50 err "TeslaMate did not become ready in time (never saw 'TeslaMateWeb.Endpoint' in logs)" } diff --git a/rootfs/etc/s6-overlay/s6-rc.d/teslamate/run b/rootfs/etc/s6-overlay/s6-rc.d/teslamate/run index 93cba36..3752642 100755 --- a/rootfs/etc/s6-overlay/s6-rc.d/teslamate/run +++ b/rootfs/etc/s6-overlay/s6-rc.d/teslamate/run @@ -64,6 +64,13 @@ until pg_isready -h "$DATABASE_HOST" -p "$DATABASE_PORT" > /dev/null 2>&1; do pg_wait_attempt=$((pg_wait_attempt + 1)) if [[ "$pg_wait_attempt" -ge "$pg_wait_max" ]]; then bashio::log.error "PostgreSQL at '$DATABASE_HOST' is not ready or unreachable after $((pg_wait_max * 2))s" + # Distinguish a DNS/networking problem from a database that is simply down, + # so the failure is actionable: resolve the host and report what we find. + if getent hosts "$DATABASE_HOST" > /dev/null 2>&1; then + bashio::log.error "Host '$DATABASE_HOST' resolves to $(getent hosts "$DATABASE_HOST" | awk '{print $1}' | tr '\n' ' ')but is not accepting connections on port $DATABASE_PORT - is the PostgreSQL add-on running and healthy?" + else + bashio::log.error "Host '$DATABASE_HOST' does not resolve - the PostgreSQL add-on may be stopped or on a different network" + fi exit 1 fi bashio::log.info "PostgreSQL not ready yet, retrying in 2s (${pg_wait_attempt}/${pg_wait_max})..."