@@ -12,20 +12,19 @@ import (
1212 "github.com/lib/pq"
1313)
1414
15- type postgresJDBC struct {
16- conn string
17- params map [string ]string
15+ type PostgresJDBC struct {
16+ ConnectionInfo
1817}
1918
20- func (s * postgresJDBC ) ping (ctx context.Context ) pingResult {
19+ func (s * PostgresJDBC ) ping (ctx context.Context ) pingResult {
2120 // It is crucial that we try to build a connection string ourselves before using the one we found. This is because
2221 // if the found connection string doesn't include a username, the driver will attempt to connect using the current
2322 // user's name, which will fail in a way that looks like a determinate failure, thus terminating the waterfall. In
2423 // contrast, when we build a connection string ourselves, if there's no username, we try 'postgres' instead, which
2524 // actually has a chance of working.
2625 return ping (ctx , "postgres" , isPostgresErrorDeterminate ,
27- buildPostgresConnectionString (s .params , true ),
28- buildPostgresConnectionString (s .params , false ),
26+ BuildPostgresConnectionString (s .Host , s . User , s . Password , "postgres" , s . Params , true ),
27+ BuildPostgresConnectionString (s .Host , s . User , s . Password , "postgres" , s . Params , false ),
2928 )
3029}
3130
@@ -59,7 +58,7 @@ func joinKeyValues(m map[string]string, sep string) string {
5958 return strings .Join (data , sep )
6059}
6160
62- func parsePostgres (ctx logContext.Context , subname string ) (jdbc , error ) {
61+ func ParsePostgres (ctx logContext.Context , subname string ) (jdbc , error ) {
6362 // expected form: [subprotocol:]//[user:password@]HOST[/DB][?key=val[&key=val]]
6463
6564 if ! strings .HasPrefix (subname , "//" ) {
@@ -77,16 +76,22 @@ func parsePostgres(ctx logContext.Context, subname string) (jdbc, error) {
7776 }
7877
7978 params := map [string ]string {
80- "host" : u .Host ,
81- "dbname" : dbName ,
8279 "connect_timeout" : "5" ,
8380 }
8481
82+ postgresJDBC := & PostgresJDBC {
83+ ConnectionInfo : ConnectionInfo {
84+ Host : u .Host ,
85+ Database : dbName ,
86+ Params : params ,
87+ },
88+ }
89+
8590 if u .User != nil {
86- params [ "user" ] = u .User .Username ()
91+ postgresJDBC . User = u .User .Username ()
8792 pass , set := u .User .Password ()
8893 if set {
89- params [ "password" ] = pass
94+ postgresJDBC . Password = pass
9095 }
9196 }
9297
@@ -95,46 +100,51 @@ func parsePostgres(ctx logContext.Context, subname string) (jdbc, error) {
95100 // https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION
96101 case "disable" , "allow" , "prefer" ,
97102 "require" , "verify-ca" , "verify-full" :
98- params ["sslmode" ] = v [0 ]
103+ postgresJDBC . Params ["sslmode" ] = v [0 ]
99104 }
100105 }
101106
102107 if v := u .Query ().Get ("user" ); v != "" {
103- params [ "user" ] = v
108+ postgresJDBC . User = v
104109 }
105110
106111 if v := u .Query ().Get ("password" ); v != "" {
107- params [ "password" ] = v
112+ postgresJDBC . Password = v
108113 }
109114
110- if params [ "host" ] == "" || params [ "password" ] == "" {
115+ if postgresJDBC . Host == "" || postgresJDBC . Password == "" {
111116 ctx .Logger ().WithName ("jdbc" ).
112117 V (2 ).
113118 Info ("Skipping invalid Postgres URL - no password or host found" )
114119 return nil , fmt .Errorf ("missing host or password in connection string" )
115120 }
116121
117- return & postgresJDBC { subname [ 2 :], params } , nil
122+ return postgresJDBC , nil
118123}
119124
120- func buildPostgresConnectionString ( params map [string ]string , includeDbName bool ) string {
125+ func BuildPostgresConnectionString ( host string , user string , password string , dbName string , params map [string ]string , includeDbName bool ) string {
121126 data := map [string ]string {
122127 // default user
123- "user" : "postgres" ,
128+ "user" : "postgres" ,
129+ "password" : password ,
130+ "host" : host ,
131+ }
132+ if user != "" {
133+ data ["user" ] = user
134+ }
135+ if h , p , ok := strings .Cut (host , ":" ); ok {
136+ data ["host" ] = h
137+ data ["port" ] = p
124138 }
125139 for key , val := range params {
126- if key == "host" {
127- if h , p , found := strings .Cut (val , ":" ); found {
128- data ["host" ] = h
129- data ["port" ] = p
130- continue
131- }
132- }
133140 data [key ] = val
134141 }
135142
136- if ! includeDbName {
143+ if includeDbName {
137144 data ["dbname" ] = "postgres"
145+ if dbName != "" {
146+ data ["dbname" ] = dbName
147+ }
138148 }
139149
140150 connStr := joinKeyValues (data , " " )
0 commit comments