106 lines
2.9 KiB
Go
Executable File
106 lines
2.9 KiB
Go
Executable File
package consul
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.wishpal.cn/wishpal_ironfan/xframe/base/mapping"
|
|
"github.com/hashicorp/consul/api"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type target struct {
|
|
Addr string `key:",optional"`
|
|
User string `key:",optional"`
|
|
Password string `key:",optional"`
|
|
Service string `key:",optional"`
|
|
Datacenter string `key:"datacenter,optional"`
|
|
Wait time.Duration `key:"wait,optional"`
|
|
Timeout time.Duration `key:"timeout,optional"`
|
|
MaxBackoff time.Duration `key:"max-backoff,optional"`
|
|
Tag string `key:"tag,optional"`
|
|
Near string `key:"near,optional"`
|
|
Limit int `key:"limit,optional"`
|
|
Healthy bool `key:"healthy,optional"`
|
|
TLSInsecure bool `key:"insecure,optional"`
|
|
Token string `key:"token,optional"`
|
|
Dc string `key:"dc,optional"`
|
|
AllowStale bool `key:"allow-stale,optional"`
|
|
RequireConsistent bool `key:"require-consistent,optional"`
|
|
}
|
|
|
|
func (t *target) String() string {
|
|
return fmt.Sprintf("service='%s' healthy='%t' tag='%s'", t.Service, t.Healthy, t.Tag)
|
|
}
|
|
|
|
// parseURL with parameters
|
|
func parseURL(rawURL url.URL) (target, error) {
|
|
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'", rawURL.String())
|
|
}
|
|
|
|
var tgt target
|
|
params := make(map[string]interface{}, len(rawURL.Query()))
|
|
for name, value := range rawURL.Query() {
|
|
var v interface{}
|
|
switch value[0] {
|
|
case "true":
|
|
v = true
|
|
case "false":
|
|
v = false
|
|
default:
|
|
v = value[0]
|
|
}
|
|
params[name] = v
|
|
}
|
|
err := mapping.UnmarshalKey(params, &tgt)
|
|
if err != nil {
|
|
return target{}, errors.Wrap(err, "Malformed URL parameters")
|
|
}
|
|
|
|
tgt.User = rawURL.User.Username()
|
|
tgt.Password, _ = rawURL.User.Password()
|
|
tgt.Addr = rawURL.Host
|
|
tgt.Service = strings.TrimLeft(rawURL.Path, "/")
|
|
|
|
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,
|
|
Datacenter: t.Datacenter,
|
|
HttpAuth: creds,
|
|
WaitTime: t.Wait,
|
|
HttpClient: c,
|
|
TLSConfig: api.TLSConfig{
|
|
InsecureSkipVerify: t.TLSInsecure,
|
|
},
|
|
Token: t.Token,
|
|
}
|
|
}
|