-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathtarget.go
101 lines (92 loc) · 2.85 KB
/
target.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package consul
import (
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/go-playground/form"
"github.com/hashicorp/consul/api"
"github.com/pkg/errors"
)
type target struct {
Addr string `form:"-"`
User string `form:"-"`
Password string `form:"-"`
Service string `form:"-"`
Wait time.Duration `form:"wait"`
Timeout time.Duration `form:"timeout"`
MaxBackoff time.Duration `form:"max-backoff"`
Tag string `form:"tag"`
Near string `form:"near"`
Limit int `form:"limit"`
Healthy bool `form:"healthy"`
TLSInsecure bool `form:"insecure"`
Token string `form:"token"`
Dc string `form:"dc"`
AllowStale bool `form:"allow-stale"`
RequireConsistent bool `form:"require-consistent"`
// TODO(mbobakov): custom parameters for the http-transport
// TODO(mbobakov): custom parameters for the TLS subsystem
}
func (t *target) String() string {
return fmt.Sprintf("service='%s' healthy='%t' tag='%s'", t.Service, t.Healthy, t.Tag)
}
// parseURL with parameters
// see README.md for the actual format
// URL schema will stay stable in the future for backward compatibility
func parseURL(u string) (target, error) {
rawURL, err := url.Parse(u)
if err != nil {
return target{}, errors.Wrap(err, "Malformed URL")
}
if rawURL.Scheme != schemeName ||
len(rawURL.Host) == 0 || len(strings.TrimLeft(rawURL.Path, "/")) == 0 {
return target{},
errors.Errorf("Malformed URL('%s'). Must be in the next format: 'consul://[user:passwd]@host/service?param=value'", u)
}
var tgt target
tgt.User = rawURL.User.Username()
tgt.Password, _ = rawURL.User.Password()
tgt.Addr = rawURL.Host
tgt.Service = strings.TrimLeft(rawURL.Path, "/")
decoder := form.NewDecoder()
decoder.RegisterCustomTypeFunc(func(vals []string) (interface{}, error) {
return time.ParseDuration(vals[0])
}, time.Duration(0))
err = decoder.Decode(&tgt, rawURL.Query())
if err != nil {
return target{}, errors.Wrap(err, "Malformed URL parameters")
}
if len(tgt.Near) == 0 {
tgt.Near = "_agent"
}
if tgt.MaxBackoff == 0 {
tgt.MaxBackoff = time.Second
}
return tgt, nil
}
// consulConfig returns config based on the parsed target.
// It uses custom http-client.
func (t *target) consulConfig() *api.Config {
var creds *api.HttpBasicAuth
if len(t.User) > 0 && len(t.Password) > 0 {
creds = new(api.HttpBasicAuth)
creds.Password = t.Password
creds.Username = t.User
}
// custom http.Client
c := &http.Client{
Timeout: t.Timeout,
}
return &api.Config{
Address: t.Addr,
HttpAuth: creds,
WaitTime: t.Wait,
HttpClient: c,
TLSConfig: api.TLSConfig{
InsecureSkipVerify: t.TLSInsecure,
},
Token: t.Token,
}
}