@@ -20,7 +20,6 @@ import (
2020 "os"
2121 "regexp"
2222 "strings"
23- "unicode"
2423
2524 "github.com/go-kit/log/level"
2625 "github.com/prometheus/client_golang/prometheus"
@@ -173,196 +172,3 @@ func getDataSources() ([]string, error) {
173172
174173 return []string {dsn }, nil
175174}
176-
177- // dsn represents a parsed datasource. It contains fields for the individual connection components.
178- type dsn struct {
179- scheme string
180- username string
181- password string
182- host string
183- path string
184- query string
185- }
186-
187- // String makes a dsn safe to print by excluding any passwords. This allows dsn to be used in
188- // strings and log messages without needing to call a redaction function first.
189- func (d dsn ) String () string {
190- if d .password != "" {
191- return fmt .Sprintf ("%s://%s:******@%s%s?%s" , d .scheme , d .username , d .host , d .path , d .query )
192- }
193-
194- if d .username != "" {
195- return fmt .Sprintf ("%s://%s@%s%s?%s" , d .scheme , d .username , d .host , d .path , d .query )
196- }
197-
198- return fmt .Sprintf ("%s://%s%s?%s" , d .scheme , d .host , d .path , d .query )
199- }
200-
201- // dsnFromString parses a connection string into a dsn. It will attempt to parse the string as
202- // a URL and as a set of key=value pairs. If both attempts fail, dsnFromString will return an error.
203- func dsnFromString (in string ) (dsn , error ) {
204- if strings .HasPrefix (in , "postgresql://" ) {
205- return dsnFromURL (in )
206- }
207-
208- // Try to parse as key=value pairs
209- d , err := dsnFromKeyValue (in )
210- if err == nil {
211- return d , nil
212- }
213-
214- return dsn {}, fmt .Errorf ("could not understand DSN" )
215- }
216-
217- // dsnFromURL parses the input as a URL and returns the dsn representation.
218- func dsnFromURL (in string ) (dsn , error ) {
219- u , err := url .Parse (in )
220- if err != nil {
221- return dsn {}, err
222- }
223- pass , _ := u .User .Password ()
224- user := u .User .Username ()
225-
226- query := u .Query ()
227-
228- if queryPass := query .Get ("password" ); queryPass != "" {
229- if pass == "" {
230- pass = queryPass
231- }
232- }
233- query .Del ("password" )
234-
235- if queryUser := query .Get ("user" ); queryUser != "" {
236- if user == "" {
237- user = queryUser
238- }
239- }
240- query .Del ("user" )
241-
242- d := dsn {
243- scheme : u .Scheme ,
244- username : user ,
245- password : pass ,
246- host : u .Host ,
247- path : u .Path ,
248- query : query .Encode (),
249- }
250-
251- return d , nil
252- }
253-
254- // dsnFromKeyValue parses the input as a set of key=value pairs and returns the dsn representation.
255- func dsnFromKeyValue (in string ) (dsn , error ) {
256- // Attempt to confirm at least one key=value pair before starting the rune parser
257- connstringRe := regexp .MustCompile (`^ *[a-zA-Z0-9]+ *= *[^= ]+` )
258- if ! connstringRe .MatchString (in ) {
259- return dsn {}, fmt .Errorf ("input is not a key-value DSN" )
260- }
261-
262- // Anything other than known fields should be part of the querystring
263- query := url.Values {}
264-
265- pairs , err := parseKeyValue (in )
266- if err != nil {
267- return dsn {}, fmt .Errorf ("failed to parse key-value DSN: %v" , err )
268- }
269-
270- // Build the dsn from the key=value pairs
271- d := dsn {
272- scheme : "postgresql" ,
273- }
274-
275- hostname := ""
276- port := ""
277-
278- for k , v := range pairs {
279- switch k {
280- case "host" :
281- hostname = v
282- case "port" :
283- port = v
284- case "user" :
285- d .username = v
286- case "password" :
287- d .password = v
288- default :
289- query .Set (k , v )
290- }
291- }
292-
293- if hostname == "" {
294- hostname = "localhost"
295- }
296-
297- if port == "" {
298- d .host = hostname
299- } else {
300- d .host = fmt .Sprintf ("%s:%s" , hostname , port )
301- }
302-
303- d .query = query .Encode ()
304-
305- return d , nil
306- }
307-
308- // parseKeyValue is a key=value parser. It loops over each rune to split out keys and values
309- // and attempting to honor quoted values. parseKeyValue will return an error if it is unable
310- // to properly parse the input.
311- func parseKeyValue (in string ) (map [string ]string , error ) {
312- out := map [string ]string {}
313-
314- inPart := false
315- inQuote := false
316- part := []rune {}
317- key := ""
318- for _ , c := range in {
319- switch {
320- case unicode .In (c , unicode .Quotation_Mark ):
321- if inQuote {
322- inQuote = false
323- } else {
324- inQuote = true
325- }
326- case unicode .In (c , unicode .White_Space ):
327- if inPart {
328- if inQuote {
329- part = append (part , c )
330- } else {
331- // Are we finishing a key=value?
332- if key == "" {
333- return out , fmt .Errorf ("invalid input" )
334- }
335- out [key ] = string (part )
336- inPart = false
337- part = []rune {}
338- }
339- } else {
340- // Are we finishing a key=value?
341- if key == "" {
342- return out , fmt .Errorf ("invalid input" )
343- }
344- out [key ] = string (part )
345- inPart = false
346- part = []rune {}
347- // Do something with the value
348- }
349- case c == '=' :
350- if inPart {
351- inPart = false
352- key = string (part )
353- part = []rune {}
354- } else {
355- return out , fmt .Errorf ("invalid input" )
356- }
357- default :
358- inPart = true
359- part = append (part , c )
360- }
361- }
362-
363- if key != "" && len (part ) > 0 {
364- out [key ] = string (part )
365- }
366-
367- return out , nil
368- }
0 commit comments