summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/armon/consul-api/api.go
diff options
context:
space:
mode:
authorWim <wim@42.be>2018-03-04 23:46:13 +0100
committerWim <wim@42.be>2018-03-04 23:46:13 +0100
commit25a72113b122f984c904b24c4af23a1cba1eff45 (patch)
treef0fb7067d7c958d60ac964afa5b8d5fb79ebc339 /vendor/github.com/armon/consul-api/api.go
parent79c4ad5015bd2be47b32141c6d53f0d128bf865b (diff)
downloadmatterbridge-msglm-25a72113b122f984c904b24c4af23a1cba1eff45.tar.gz
matterbridge-msglm-25a72113b122f984c904b24c4af23a1cba1eff45.tar.bz2
matterbridge-msglm-25a72113b122f984c904b24c4af23a1cba1eff45.zip
Add vendor files for spf13/viper
Diffstat (limited to 'vendor/github.com/armon/consul-api/api.go')
-rw-r--r--vendor/github.com/armon/consul-api/api.go323
1 files changed, 323 insertions, 0 deletions
diff --git a/vendor/github.com/armon/consul-api/api.go b/vendor/github.com/armon/consul-api/api.go
new file mode 100644
index 00000000..e1335769
--- /dev/null
+++ b/vendor/github.com/armon/consul-api/api.go
@@ -0,0 +1,323 @@
+package consulapi
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strconv"
+ "time"
+)
+
+// QueryOptions are used to parameterize a query
+type QueryOptions struct {
+ // Providing a datacenter overwrites the DC provided
+ // by the Config
+ Datacenter string
+
+ // AllowStale allows any Consul server (non-leader) to service
+ // a read. This allows for lower latency and higher throughput
+ AllowStale bool
+
+ // RequireConsistent forces the read to be fully consistent.
+ // This is more expensive but prevents ever performing a stale
+ // read.
+ RequireConsistent bool
+
+ // WaitIndex is used to enable a blocking query. Waits
+ // until the timeout or the next index is reached
+ WaitIndex uint64
+
+ // WaitTime is used to bound the duration of a wait.
+ // Defaults to that of the Config, but can be overriden.
+ WaitTime time.Duration
+
+ // Token is used to provide a per-request ACL token
+ // which overrides the agent's default token.
+ Token string
+}
+
+// WriteOptions are used to parameterize a write
+type WriteOptions struct {
+ // Providing a datacenter overwrites the DC provided
+ // by the Config
+ Datacenter string
+
+ // Token is used to provide a per-request ACL token
+ // which overrides the agent's default token.
+ Token string
+}
+
+// QueryMeta is used to return meta data about a query
+type QueryMeta struct {
+ // LastIndex. This can be used as a WaitIndex to perform
+ // a blocking query
+ LastIndex uint64
+
+ // Time of last contact from the leader for the
+ // server servicing the request
+ LastContact time.Duration
+
+ // Is there a known leader
+ KnownLeader bool
+
+ // How long did the request take
+ RequestTime time.Duration
+}
+
+// WriteMeta is used to return meta data about a write
+type WriteMeta struct {
+ // How long did the request take
+ RequestTime time.Duration
+}
+
+// HttpBasicAuth is used to authenticate http client with HTTP Basic Authentication
+type HttpBasicAuth struct {
+ // Username to use for HTTP Basic Authentication
+ Username string
+
+ // Password to use for HTTP Basic Authentication
+ Password string
+}
+
+// Config is used to configure the creation of a client
+type Config struct {
+ // Address is the address of the Consul server
+ Address string
+
+ // Scheme is the URI scheme for the Consul server
+ Scheme string
+
+ // Datacenter to use. If not provided, the default agent datacenter is used.
+ Datacenter string
+
+ // HttpClient is the client to use. Default will be
+ // used if not provided.
+ HttpClient *http.Client
+
+ // HttpAuth is the auth info to use for http access.
+ HttpAuth *HttpBasicAuth
+
+ // WaitTime limits how long a Watch will block. If not provided,
+ // the agent default values will be used.
+ WaitTime time.Duration
+
+ // Token is used to provide a per-request ACL token
+ // which overrides the agent's default token.
+ Token string
+}
+
+// DefaultConfig returns a default configuration for the client
+func DefaultConfig() *Config {
+ return &Config{
+ Address: "127.0.0.1:8500",
+ Scheme: "http",
+ HttpClient: http.DefaultClient,
+ }
+}
+
+// Client provides a client to the Consul API
+type Client struct {
+ config Config
+}
+
+// NewClient returns a new client
+func NewClient(config *Config) (*Client, error) {
+ // bootstrap the config
+ defConfig := DefaultConfig()
+
+ if len(config.Address) == 0 {
+ config.Address = defConfig.Address
+ }
+
+ if len(config.Scheme) == 0 {
+ config.Scheme = defConfig.Scheme
+ }
+
+ if config.HttpClient == nil {
+ config.HttpClient = defConfig.HttpClient
+ }
+
+ client := &Client{
+ config: *config,
+ }
+ return client, nil
+}
+
+// request is used to help build up a request
+type request struct {
+ config *Config
+ method string
+ url *url.URL
+ params url.Values
+ body io.Reader
+ obj interface{}
+}
+
+// setQueryOptions is used to annotate the request with
+// additional query options
+func (r *request) setQueryOptions(q *QueryOptions) {
+ if q == nil {
+ return
+ }
+ if q.Datacenter != "" {
+ r.params.Set("dc", q.Datacenter)
+ }
+ if q.AllowStale {
+ r.params.Set("stale", "")
+ }
+ if q.RequireConsistent {
+ r.params.Set("consistent", "")
+ }
+ if q.WaitIndex != 0 {
+ r.params.Set("index", strconv.FormatUint(q.WaitIndex, 10))
+ }
+ if q.WaitTime != 0 {
+ r.params.Set("wait", durToMsec(q.WaitTime))
+ }
+ if q.Token != "" {
+ r.params.Set("token", q.Token)
+ }
+}
+
+// durToMsec converts a duration to a millisecond specified string
+func durToMsec(dur time.Duration) string {
+ return fmt.Sprintf("%dms", dur/time.Millisecond)
+}
+
+// setWriteOptions is used to annotate the request with
+// additional write options
+func (r *request) setWriteOptions(q *WriteOptions) {
+ if q == nil {
+ return
+ }
+ if q.Datacenter != "" {
+ r.params.Set("dc", q.Datacenter)
+ }
+ if q.Token != "" {
+ r.params.Set("token", q.Token)
+ }
+}
+
+// toHTTP converts the request to an HTTP request
+func (r *request) toHTTP() (*http.Request, error) {
+ // Encode the query parameters
+ r.url.RawQuery = r.params.Encode()
+
+ // Get the url sring
+ urlRaw := r.url.String()
+
+ // Check if we should encode the body
+ if r.body == nil && r.obj != nil {
+ if b, err := encodeBody(r.obj); err != nil {
+ return nil, err
+ } else {
+ r.body = b
+ }
+ }
+
+ // Create the HTTP request
+ req, err := http.NewRequest(r.method, urlRaw, r.body)
+
+ // Setup auth
+ if err == nil && r.config.HttpAuth != nil {
+ req.SetBasicAuth(r.config.HttpAuth.Username, r.config.HttpAuth.Password)
+ }
+
+ return req, err
+}
+
+// newRequest is used to create a new request
+func (c *Client) newRequest(method, path string) *request {
+ r := &request{
+ config: &c.config,
+ method: method,
+ url: &url.URL{
+ Scheme: c.config.Scheme,
+ Host: c.config.Address,
+ Path: path,
+ },
+ params: make(map[string][]string),
+ }
+ if c.config.Datacenter != "" {
+ r.params.Set("dc", c.config.Datacenter)
+ }
+ if c.config.WaitTime != 0 {
+ r.params.Set("wait", durToMsec(r.config.WaitTime))
+ }
+ if c.config.Token != "" {
+ r.params.Set("token", r.config.Token)
+ }
+ return r
+}
+
+// doRequest runs a request with our client
+func (c *Client) doRequest(r *request) (time.Duration, *http.Response, error) {
+ req, err := r.toHTTP()
+ if err != nil {
+ return 0, nil, err
+ }
+ start := time.Now()
+ resp, err := c.config.HttpClient.Do(req)
+ diff := time.Now().Sub(start)
+ return diff, resp, err
+}
+
+// parseQueryMeta is used to help parse query meta-data
+func parseQueryMeta(resp *http.Response, q *QueryMeta) error {
+ header := resp.Header
+
+ // Parse the X-Consul-Index
+ index, err := strconv.ParseUint(header.Get("X-Consul-Index"), 10, 64)
+ if err != nil {
+ return fmt.Errorf("Failed to parse X-Consul-Index: %v", err)
+ }
+ q.LastIndex = index
+
+ // Parse the X-Consul-LastContact
+ last, err := strconv.ParseUint(header.Get("X-Consul-LastContact"), 10, 64)
+ if err != nil {
+ return fmt.Errorf("Failed to parse X-Consul-LastContact: %v", err)
+ }
+ q.LastContact = time.Duration(last) * time.Millisecond
+
+ // Parse the X-Consul-KnownLeader
+ switch header.Get("X-Consul-KnownLeader") {
+ case "true":
+ q.KnownLeader = true
+ default:
+ q.KnownLeader = false
+ }
+ return nil
+}
+
+// decodeBody is used to JSON decode a body
+func decodeBody(resp *http.Response, out interface{}) error {
+ dec := json.NewDecoder(resp.Body)
+ return dec.Decode(out)
+}
+
+// encodeBody is used to encode a request body
+func encodeBody(obj interface{}) (io.Reader, error) {
+ buf := bytes.NewBuffer(nil)
+ enc := json.NewEncoder(buf)
+ if err := enc.Encode(obj); err != nil {
+ return nil, err
+ }
+ return buf, nil
+}
+
+// requireOK is used to wrap doRequest and check for a 200
+func requireOK(d time.Duration, resp *http.Response, e error) (time.Duration, *http.Response, error) {
+ if e != nil {
+ return d, resp, e
+ }
+ if resp.StatusCode != 200 {
+ var buf bytes.Buffer
+ io.Copy(&buf, resp.Body)
+ return d, resp, fmt.Errorf("Unexpected response code: %d (%s)", resp.StatusCode, buf.Bytes())
+ }
+ return d, resp, e
+}