Files
waitfordb/internal/driver/postgres.go
T
unkin-agent 2b37986218 waitfordb: initial tool — env-configured wait-for-DB init container
Small Go tool + distroless container used as a K8s initContainer to block an
app until its database (Postgres/MySQL) is reachable. Env-var configured
(WAITFORDB_* + libpq PG* fallback), configurable timeout/interval, redacted
logs, exit codes. Woodpecker CI publishes docker-internal/waitfordb on tag.
2026-08-22 13:31:44 +10:00

49 lines
1.2 KiB
Go

package driver
import (
"fmt"
"net/url"
"strconv"
"git.unkin.net/unkin/waitfordb/internal/config"
_ "github.com/jackc/pgx/v5/stdlib" // registers the "pgx" database/sql driver
)
func init() { register(postgres{}) }
type postgres struct{}
func (postgres) Name() string { return "postgres" }
func (postgres) Open(cfg config.Config) (Pinger, error) {
dsn := cfg.DSN
if dsn == "" {
dsn = postgresDSN(cfg)
}
return openSQL("pgx", dsn)
}
// postgresDSN builds a URL-style DSN. net/url escapes the userinfo and query so
// passwords with special characters are handled safely.
func postgresDSN(cfg config.Config) string {
u := url.URL{
Scheme: "postgres",
Host: fmt.Sprintf("%s:%s", cfg.Host, cfg.Port),
Path: "/" + cfg.Database,
}
if cfg.User != "" {
u.User = url.UserPassword(cfg.User, cfg.Password)
}
q := url.Values{}
if cfg.SSLMode != "" {
q.Set("sslmode", cfg.SSLMode)
}
// connect_timeout is a per-attempt safety net in addition to the context
// deadline the wait loop applies; it is in whole seconds.
if secs := int(cfg.ConnectTimeout.Seconds()); secs > 0 {
q.Set("connect_timeout", strconv.Itoa(secs))
}
u.RawQuery = q.Encode()
return u.String()
}