Merge pull request #3056 from CoolCoolTomato/fix/postgres-dsn-dbname

fix(setup): bootstrap postgres connection with maintenance db
This commit is contained in:
Wesley Liddick
2026-06-06 10:42:42 +08:00
committed by GitHub
2 changed files with 38 additions and 10 deletions
+15 -10
View File
@@ -160,13 +160,23 @@ func NeedsSetup() bool {
return true
}
func buildPostgresDSN(cfg *DatabaseConfig, dbName string) string {
return fmt.Sprintf(
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
cfg.Host, cfg.Port, cfg.User, cfg.Password, dbName, cfg.SSLMode,
)
}
func buildDatabaseConnectionDSNs(cfg *DatabaseConfig) (bootstrapDSN, targetDSN string) {
return buildPostgresDSN(cfg, "postgres"), buildPostgresDSN(cfg, cfg.DBName)
}
// TestDatabaseConnection tests the database connection and creates database if not exists
func TestDatabaseConnection(cfg *DatabaseConfig) error {
// First, connect to the default 'postgres' database to check/create target database
defaultDSN := fmt.Sprintf(
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.DBName, cfg.SSLMode,
)
// First, connect to the default 'postgres' database to check/create target database.
// Connecting to cfg.DBName here fails when the target database has not been
// created yet, so the bootstrap connection must use PostgreSQL's maintenance DB.
defaultDSN, targetDSN := buildDatabaseConnectionDSNs(cfg)
db, err := sql.Open("postgres", defaultDSN)
if err != nil {
@@ -214,11 +224,6 @@ func TestDatabaseConnection(cfg *DatabaseConfig) error {
}
db = nil
targetDSN := fmt.Sprintf(
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.DBName, cfg.SSLMode,
)
targetDB, err := sql.Open("postgres", targetDSN)
if err != nil {
return fmt.Errorf("failed to connect to database '%s': %w", cfg.DBName, err)
+23
View File
@@ -87,3 +87,26 @@ func TestWriteConfigFileKeepsDefaultUserConcurrency(t *testing.T) {
t.Fatalf("config missing default user concurrency, got:\n%s", string(data))
}
}
func TestBuildDatabaseConnectionDSNsUsesPostgresForBootstrap(t *testing.T) {
cfg := &DatabaseConfig{
Host: "db",
Port: 5432,
User: "sub2api",
Password: "secret",
DBName: "sub2api",
SSLMode: "disable",
}
bootstrapDSN, targetDSN := buildDatabaseConnectionDSNs(cfg)
if !strings.Contains(bootstrapDSN, "dbname=postgres") {
t.Fatalf("bootstrap DSN = %q, want default postgres database", bootstrapDSN)
}
if strings.Contains(bootstrapDSN, "dbname=sub2api") {
t.Fatalf("bootstrap DSN = %q, should not connect to target database before checking/creating it", bootstrapDSN)
}
if !strings.Contains(targetDSN, "dbname=sub2api") {
t.Fatalf("target DSN = %q, want configured database", targetDSN)
}
}