- Fix metrics double-counting: track deltas for WaitCount/WaitDuration instead of adding cumulative values each tick - Replace fmt.Printf with structured logging in pool monitor - Add PoolOptions validation (MaxConns > 0, MinConns >= 0) - Warn when DATABASE_URI overrides non-default PoolOptions - Improve findAndParseConfig to report all tried files and errors - Remove dead code in pgdb/config.go (unreachable host default) - Fix errcheck lint issues for file.Close() calls - Add context parameter to OpenDBMonitor() (breaking change)
60 lines
1.7 KiB
Go
60 lines
1.7 KiB
Go
package pgdb
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"go.ntppool.org/common/database"
|
|
)
|
|
|
|
// CreatePoolConfig converts database.PostgresConfig to pgxpool.Config
|
|
// This is the secure way to create a config without exposing passwords in DSN strings
|
|
func CreatePoolConfig(cfg *database.PostgresConfig) (*pgxpool.Config, error) {
|
|
// Validate required fields
|
|
if cfg.Host == "" {
|
|
return nil, fmt.Errorf("postgres: host is required")
|
|
}
|
|
if cfg.User == "" {
|
|
return nil, fmt.Errorf("postgres: user is required")
|
|
}
|
|
if cfg.Name == "" {
|
|
return nil, fmt.Errorf("postgres: database name is required")
|
|
}
|
|
|
|
// Validate SSLMode
|
|
validSSLModes := map[string]bool{
|
|
"disable": true, "allow": true, "prefer": true,
|
|
"require": true, "verify-ca": true, "verify-full": true,
|
|
}
|
|
if cfg.SSLMode != "" && !validSSLModes[cfg.SSLMode] {
|
|
return nil, fmt.Errorf("postgres: invalid sslmode: %s (valid: disable, allow, prefer, require, verify-ca, verify-full)", cfg.SSLMode)
|
|
}
|
|
|
|
// Apply defaults for optional fields (host is validated as required above)
|
|
port := cfg.Port
|
|
if port == 0 {
|
|
port = 5432
|
|
}
|
|
|
|
sslmode := cfg.SSLMode
|
|
if sslmode == "" {
|
|
sslmode = "prefer"
|
|
}
|
|
|
|
// Build connection string WITHOUT password
|
|
// We'll set the password separately in the config
|
|
connString := fmt.Sprintf("host=%s port=%d user=%s dbname=%s sslmode=%s",
|
|
cfg.Host, port, cfg.User, cfg.Name, sslmode)
|
|
|
|
// Parse the connection string
|
|
poolConfig, err := pgxpool.ParseConfig(connString)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("postgres: failed to parse connection config: %w", err)
|
|
}
|
|
|
|
// Set password separately (security: never put password in the connection string)
|
|
poolConfig.ConnConfig.Password = cfg.Pass
|
|
|
|
return poolConfig, nil
|
|
}
|