From 23bcc18766c5b1178ecc5e1a5d44037c6dd57722 Mon Sep 17 00:00:00 2001 From: Matt Keeler Date: Sat, 22 Jun 2019 09:00:17 -0400 Subject: [PATCH] Fix vendoring to not include our own code. --- .../github.com/hashicorp/consul/api/README.md | 67 - vendor/github.com/hashicorp/consul/api/acl.go | 1116 ----------------- .../github.com/hashicorp/consul/api/agent.go | 1035 --------------- vendor/github.com/hashicorp/consul/api/api.go | 966 -------------- .../hashicorp/consul/api/catalog.go | 244 ---- .../hashicorp/consul/api/config_entry.go | 255 ---- .../hashicorp/consul/api/connect.go | 12 - .../hashicorp/consul/api/connect_ca.go | 174 --- .../hashicorp/consul/api/connect_intention.go | 302 ----- .../hashicorp/consul/api/coordinate.go | 106 -- .../github.com/hashicorp/consul/api/debug.go | 106 -- .../github.com/hashicorp/consul/api/event.go | 104 -- vendor/github.com/hashicorp/consul/api/go.mod | 16 - vendor/github.com/hashicorp/consul/api/go.sum | 76 -- .../github.com/hashicorp/consul/api/health.go | 330 ----- vendor/github.com/hashicorp/consul/api/kv.go | 286 ----- .../github.com/hashicorp/consul/api/lock.go | 386 ------ .../hashicorp/consul/api/operator.go | 11 - .../hashicorp/consul/api/operator_area.go | 194 --- .../consul/api/operator_autopilot.go | 219 ---- .../hashicorp/consul/api/operator_keyring.go | 89 -- .../hashicorp/consul/api/operator_raft.go | 89 -- .../hashicorp/consul/api/operator_segment.go | 11 - .../hashicorp/consul/api/prepared_query.go | 217 ---- vendor/github.com/hashicorp/consul/api/raw.go | 24 - .../hashicorp/consul/api/semaphore.go | 514 -------- .../hashicorp/consul/api/session.go | 224 ---- .../hashicorp/consul/api/snapshot.go | 47 - .../github.com/hashicorp/consul/api/status.go | 43 - vendor/github.com/hashicorp/consul/api/txn.go | 230 ---- .../hashicorp/consul/api/watch/funcs.go | 349 ------ .../hashicorp/consul/api/watch/plan.go | 167 --- .../hashicorp/consul/api/watch/watch.go | 289 ----- .../hashicorp/consul/sdk/freeport/freeport.go | 139 -- .../hashicorp/consul/sdk/testutil/README.md | 78 -- .../hashicorp/consul/sdk/testutil/io.go | 68 - .../consul/sdk/testutil/retry/retry.go | 207 --- .../hashicorp/consul/sdk/testutil/server.go | 473 ------- .../consul/sdk/testutil/server_methods.go | 256 ---- .../consul/sdk/testutil/server_wrapper.go | 65 - .../hashicorp/consul/sdk/testutil/testlog.go | 42 - 41 files changed, 9626 deletions(-) delete mode 100644 vendor/github.com/hashicorp/consul/api/README.md delete mode 100644 vendor/github.com/hashicorp/consul/api/acl.go delete mode 100644 vendor/github.com/hashicorp/consul/api/agent.go delete mode 100644 vendor/github.com/hashicorp/consul/api/api.go delete mode 100644 vendor/github.com/hashicorp/consul/api/catalog.go delete mode 100644 vendor/github.com/hashicorp/consul/api/config_entry.go delete mode 100644 vendor/github.com/hashicorp/consul/api/connect.go delete mode 100644 vendor/github.com/hashicorp/consul/api/connect_ca.go delete mode 100644 vendor/github.com/hashicorp/consul/api/connect_intention.go delete mode 100644 vendor/github.com/hashicorp/consul/api/coordinate.go delete mode 100644 vendor/github.com/hashicorp/consul/api/debug.go delete mode 100644 vendor/github.com/hashicorp/consul/api/event.go delete mode 100644 vendor/github.com/hashicorp/consul/api/go.mod delete mode 100644 vendor/github.com/hashicorp/consul/api/go.sum delete mode 100644 vendor/github.com/hashicorp/consul/api/health.go delete mode 100644 vendor/github.com/hashicorp/consul/api/kv.go delete mode 100644 vendor/github.com/hashicorp/consul/api/lock.go delete mode 100644 vendor/github.com/hashicorp/consul/api/operator.go delete mode 100644 vendor/github.com/hashicorp/consul/api/operator_area.go delete mode 100644 vendor/github.com/hashicorp/consul/api/operator_autopilot.go delete mode 100644 vendor/github.com/hashicorp/consul/api/operator_keyring.go delete mode 100644 vendor/github.com/hashicorp/consul/api/operator_raft.go delete mode 100644 vendor/github.com/hashicorp/consul/api/operator_segment.go delete mode 100644 vendor/github.com/hashicorp/consul/api/prepared_query.go delete mode 100644 vendor/github.com/hashicorp/consul/api/raw.go delete mode 100644 vendor/github.com/hashicorp/consul/api/semaphore.go delete mode 100644 vendor/github.com/hashicorp/consul/api/session.go delete mode 100644 vendor/github.com/hashicorp/consul/api/snapshot.go delete mode 100644 vendor/github.com/hashicorp/consul/api/status.go delete mode 100644 vendor/github.com/hashicorp/consul/api/txn.go delete mode 100644 vendor/github.com/hashicorp/consul/api/watch/funcs.go delete mode 100644 vendor/github.com/hashicorp/consul/api/watch/plan.go delete mode 100644 vendor/github.com/hashicorp/consul/api/watch/watch.go delete mode 100644 vendor/github.com/hashicorp/consul/sdk/freeport/freeport.go delete mode 100644 vendor/github.com/hashicorp/consul/sdk/testutil/README.md delete mode 100644 vendor/github.com/hashicorp/consul/sdk/testutil/io.go delete mode 100644 vendor/github.com/hashicorp/consul/sdk/testutil/retry/retry.go delete mode 100644 vendor/github.com/hashicorp/consul/sdk/testutil/server.go delete mode 100644 vendor/github.com/hashicorp/consul/sdk/testutil/server_methods.go delete mode 100644 vendor/github.com/hashicorp/consul/sdk/testutil/server_wrapper.go delete mode 100644 vendor/github.com/hashicorp/consul/sdk/testutil/testlog.go diff --git a/vendor/github.com/hashicorp/consul/api/README.md b/vendor/github.com/hashicorp/consul/api/README.md deleted file mode 100644 index 3255cbb246..0000000000 --- a/vendor/github.com/hashicorp/consul/api/README.md +++ /dev/null @@ -1,67 +0,0 @@ -Consul API client -================= - -This package provides the `api` package which attempts to -provide programmatic access to the full Consul API. - -Currently, all of the Consul APIs included in version 0.6.0 are supported. - -Documentation -============= - -The full documentation is available on [Godoc](https://godoc.org/github.com/hashicorp/consul/api) - -Usage -===== - -Below is an example of using the Consul client: - -```go -package main - -import "github.com/hashicorp/consul/api" -import "fmt" - -func main() { - // Get a new client - client, err := api.NewClient(api.DefaultConfig()) - if err != nil { - panic(err) - } - - // Get a handle to the KV API - kv := client.KV() - - // PUT a new KV pair - p := &api.KVPair{Key: "REDIS_MAXCLIENTS", Value: []byte("1000")} - _, err = kv.Put(p, nil) - if err != nil { - panic(err) - } - - // Lookup the pair - pair, _, err := kv.Get("REDIS_MAXCLIENTS", nil) - if err != nil { - panic(err) - } - fmt.Printf("KV: %v %s\n", pair.Key, pair.Value) -} -``` - -To run this example, start a Consul server: - -```bash -consul agent -dev -``` - -Copy the code above into a file such as `main.go`. - -Install and run. You'll see a key (`REDIS_MAXCLIENTS`) and value (`1000`) printed. - -```bash -$ go get -$ go run main.go -KV: REDIS_MAXCLIENTS 1000 -``` - -After running the code, you can also view the values in the Consul UI on your local machine at http://localhost:8500/ui/dc1/kv diff --git a/vendor/github.com/hashicorp/consul/api/acl.go b/vendor/github.com/hashicorp/consul/api/acl.go deleted file mode 100644 index 124409ff2b..0000000000 --- a/vendor/github.com/hashicorp/consul/api/acl.go +++ /dev/null @@ -1,1116 +0,0 @@ -package api - -import ( - "fmt" - "io" - "io/ioutil" - "net/url" - "time" - - "github.com/mitchellh/mapstructure" -) - -const ( - // ACLClientType is the client type token - ACLClientType = "client" - - // ACLManagementType is the management type token - ACLManagementType = "management" -) - -type ACLTokenPolicyLink struct { - ID string - Name string -} -type ACLTokenRoleLink struct { - ID string - Name string -} - -// ACLToken represents an ACL Token -type ACLToken struct { - CreateIndex uint64 - ModifyIndex uint64 - AccessorID string - SecretID string - Description string - Policies []*ACLTokenPolicyLink `json:",omitempty"` - Roles []*ACLTokenRoleLink `json:",omitempty"` - ServiceIdentities []*ACLServiceIdentity `json:",omitempty"` - Local bool - ExpirationTTL time.Duration `json:",omitempty"` - ExpirationTime *time.Time `json:",omitempty"` - CreateTime time.Time `json:",omitempty"` - Hash []byte `json:",omitempty"` - - // DEPRECATED (ACL-Legacy-Compat) - // Rules will only be present for legacy tokens returned via the new APIs - Rules string `json:",omitempty"` -} - -type ACLTokenListEntry struct { - CreateIndex uint64 - ModifyIndex uint64 - AccessorID string - Description string - Policies []*ACLTokenPolicyLink `json:",omitempty"` - Roles []*ACLTokenRoleLink `json:",omitempty"` - ServiceIdentities []*ACLServiceIdentity `json:",omitempty"` - Local bool - ExpirationTime *time.Time `json:",omitempty"` - CreateTime time.Time - Hash []byte - Legacy bool -} - -// ACLEntry is used to represent a legacy ACL token -// The legacy tokens are deprecated. -type ACLEntry struct { - CreateIndex uint64 - ModifyIndex uint64 - ID string - Name string - Type string - Rules string -} - -// ACLReplicationStatus is used to represent the status of ACL replication. -type ACLReplicationStatus struct { - Enabled bool - Running bool - SourceDatacenter string - ReplicationType string - ReplicatedIndex uint64 - ReplicatedRoleIndex uint64 - ReplicatedTokenIndex uint64 - LastSuccess time.Time - LastError time.Time -} - -// ACLServiceIdentity represents a high-level grant of all necessary privileges -// to assume the identity of the named Service in the Catalog and within -// Connect. -type ACLServiceIdentity struct { - ServiceName string - Datacenters []string `json:",omitempty"` -} - -// ACLPolicy represents an ACL Policy. -type ACLPolicy struct { - ID string - Name string - Description string - Rules string - Datacenters []string - Hash []byte - CreateIndex uint64 - ModifyIndex uint64 -} - -type ACLPolicyListEntry struct { - ID string - Name string - Description string - Datacenters []string - Hash []byte - CreateIndex uint64 - ModifyIndex uint64 -} - -type ACLRolePolicyLink struct { - ID string - Name string -} - -// ACLRole represents an ACL Role. -type ACLRole struct { - ID string - Name string - Description string - Policies []*ACLRolePolicyLink `json:",omitempty"` - ServiceIdentities []*ACLServiceIdentity `json:",omitempty"` - Hash []byte - CreateIndex uint64 - ModifyIndex uint64 -} - -// BindingRuleBindType is the type of binding rule mechanism used. -type BindingRuleBindType string - -const ( - // BindingRuleBindTypeService binds to a service identity with the given name. - BindingRuleBindTypeService BindingRuleBindType = "service" - - // BindingRuleBindTypeRole binds to pre-existing roles with the given name. - BindingRuleBindTypeRole BindingRuleBindType = "role" -) - -type ACLBindingRule struct { - ID string - Description string - AuthMethod string - Selector string - BindType BindingRuleBindType - BindName string - - CreateIndex uint64 - ModifyIndex uint64 -} - -type ACLAuthMethod struct { - Name string - Type string - Description string - - // Configuration is arbitrary configuration for the auth method. This - // should only contain primitive values and containers (such as lists and - // maps). - Config map[string]interface{} - - CreateIndex uint64 - ModifyIndex uint64 -} - -type ACLAuthMethodListEntry struct { - Name string - Type string - Description string - CreateIndex uint64 - ModifyIndex uint64 -} - -// ParseKubernetesAuthMethodConfig takes a raw config map and returns a parsed -// KubernetesAuthMethodConfig. -func ParseKubernetesAuthMethodConfig(raw map[string]interface{}) (*KubernetesAuthMethodConfig, error) { - var config KubernetesAuthMethodConfig - decodeConf := &mapstructure.DecoderConfig{ - Result: &config, - WeaklyTypedInput: true, - } - - decoder, err := mapstructure.NewDecoder(decodeConf) - if err != nil { - return nil, err - } - - if err := decoder.Decode(raw); err != nil { - return nil, fmt.Errorf("error decoding config: %s", err) - } - - return &config, nil -} - -// KubernetesAuthMethodConfig is the config for the built-in Consul auth method -// for Kubernetes. -type KubernetesAuthMethodConfig struct { - Host string `json:",omitempty"` - CACert string `json:",omitempty"` - ServiceAccountJWT string `json:",omitempty"` -} - -// RenderToConfig converts this into a map[string]interface{} suitable for use -// in the ACLAuthMethod.Config field. -func (c *KubernetesAuthMethodConfig) RenderToConfig() map[string]interface{} { - return map[string]interface{}{ - "Host": c.Host, - "CACert": c.CACert, - "ServiceAccountJWT": c.ServiceAccountJWT, - } -} - -type ACLLoginParams struct { - AuthMethod string - BearerToken string - Meta map[string]string `json:",omitempty"` -} - -// ACL can be used to query the ACL endpoints -type ACL struct { - c *Client -} - -// ACL returns a handle to the ACL endpoints -func (c *Client) ACL() *ACL { - return &ACL{c} -} - -// Bootstrap is used to perform a one-time ACL bootstrap operation on a cluster -// to get the first management token. -func (a *ACL) Bootstrap() (*ACLToken, *WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/bootstrap") - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLToken - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, wm, nil -} - -// Create is used to generate a new token with the given parameters -// -// Deprecated: Use TokenCreate instead. -func (a *ACL) Create(acl *ACLEntry, q *WriteOptions) (string, *WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/create") - r.setWriteOptions(q) - r.obj = acl - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out struct{ ID string } - if err := decodeBody(resp, &out); err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// Update is used to update the rules of an existing token -// -// Deprecated: Use TokenUpdate instead. -func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/update") - r.setWriteOptions(q) - r.obj = acl - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} - -// Destroy is used to destroy a given ACL token ID -// -// Deprecated: Use TokenDelete instead. -func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id) - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} - -// Clone is used to return a new token cloned from an existing one -// -// Deprecated: Use TokenClone instead. -func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/clone/"+id) - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out struct{ ID string } - if err := decodeBody(resp, &out); err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// Info is used to query for information about an ACL token -// -// Deprecated: Use TokenRead instead. -func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/info/"+id) - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*ACLEntry - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - if len(entries) > 0 { - return entries[0], qm, nil - } - return nil, qm, nil -} - -// List is used to get all the ACL tokens -// -// Deprecated: Use TokenList instead. -func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/list") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*ACLEntry - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// Replication returns the status of the ACL replication process in the datacenter -func (a *ACL) Replication(q *QueryOptions) (*ACLReplicationStatus, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/replication") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries *ACLReplicationStatus - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// TokenCreate creates a new ACL token. If either the AccessorID or SecretID fields -// of the ACLToken structure are empty they will be filled in by Consul. -func (a *ACL) TokenCreate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/token") - r.setWriteOptions(q) - r.obj = token - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLToken - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// TokenUpdate updates a token in place without modifying its AccessorID or SecretID. A valid -// AccessorID must be set in the ACLToken structure passed to this function but the SecretID may -// be omitted and will be filled in by Consul with its existing value. -func (a *ACL) TokenUpdate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) { - if token.AccessorID == "" { - return nil, nil, fmt.Errorf("Must specify an AccessorID for Token Updating") - } - r := a.c.newRequest("PUT", "/v1/acl/token/"+token.AccessorID) - r.setWriteOptions(q) - r.obj = token - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLToken - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// TokenClone will create a new token with the same policies and locality as the original -// token but will have its own auto-generated AccessorID and SecretID as well having the -// description passed to this function. The tokenID parameter must be a valid Accessor ID -// of an existing token. -func (a *ACL) TokenClone(tokenID string, description string, q *WriteOptions) (*ACLToken, *WriteMeta, error) { - if tokenID == "" { - return nil, nil, fmt.Errorf("Must specify a tokenID for Token Cloning") - } - - r := a.c.newRequest("PUT", "/v1/acl/token/"+tokenID+"/clone") - r.setWriteOptions(q) - r.obj = struct{ Description string }{description} - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLToken - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// TokenDelete removes a single ACL token. The tokenID parameter must be a valid -// Accessor ID of an existing token. -func (a *ACL) TokenDelete(tokenID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/token/"+tokenID) - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} - -// TokenRead retrieves the full token details. The tokenID parameter must be a valid -// Accessor ID of an existing token. -func (a *ACL) TokenRead(tokenID string, q *QueryOptions) (*ACLToken, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/token/"+tokenID) - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out ACLToken - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, qm, nil -} - -// TokenReadSelf retrieves the full token details of the token currently -// assigned to the API Client. In this manner its possible to read a token -// by its Secret ID. -func (a *ACL) TokenReadSelf(q *QueryOptions) (*ACLToken, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/token/self") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out ACLToken - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, qm, nil -} - -// TokenList lists all tokens. The listing does not contain any SecretIDs as those -// may only be retrieved by a call to TokenRead. -func (a *ACL) TokenList(q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/tokens") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*ACLTokenListEntry - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// PolicyCreate will create a new policy. It is not allowed for the policy parameters -// ID field to be set as this will be generated by Consul while processing the request. -func (a *ACL) PolicyCreate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) { - if policy.ID != "" { - return nil, nil, fmt.Errorf("Cannot specify an ID in Policy Creation") - } - r := a.c.newRequest("PUT", "/v1/acl/policy") - r.setWriteOptions(q) - r.obj = policy - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLPolicy - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// PolicyUpdate updates a policy. The ID field of the policy parameter must be set to an -// existing policy ID -func (a *ACL) PolicyUpdate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) { - if policy.ID == "" { - return nil, nil, fmt.Errorf("Must specify an ID in Policy Update") - } - - r := a.c.newRequest("PUT", "/v1/acl/policy/"+policy.ID) - r.setWriteOptions(q) - r.obj = policy - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLPolicy - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// PolicyDelete deletes a policy given its ID. -func (a *ACL) PolicyDelete(policyID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/policy/"+policyID) - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} - -// PolicyRead retrieves the policy details including the rule set. -func (a *ACL) PolicyRead(policyID string, q *QueryOptions) (*ACLPolicy, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/policy/"+policyID) - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out ACLPolicy - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, qm, nil -} - -// PolicyList retrieves a listing of all policies. The listing does not include the -// rules for any policy as those should be retrieved by subsequent calls to PolicyRead. -func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/policies") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*ACLPolicyListEntry - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// RulesTranslate translates the legacy rule syntax into the current syntax. -// -// Deprecated: Support for the legacy syntax translation will be removed -// when legacy ACL support is removed. -func (a *ACL) RulesTranslate(rules io.Reader) (string, error) { - r := a.c.newRequest("POST", "/v1/acl/rules/translate") - r.body = rules - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return "", err - } - defer resp.Body.Close() - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - ruleBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("Failed to read translated rule body: %v", err) - } - - return string(ruleBytes), nil -} - -// RulesTranslateToken translates the rules associated with the legacy syntax -// into the current syntax and returns the results. -// -// Deprecated: Support for the legacy syntax translation will be removed -// when legacy ACL support is removed. -func (a *ACL) RulesTranslateToken(tokenID string) (string, error) { - r := a.c.newRequest("GET", "/v1/acl/rules/translate/"+tokenID) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return "", err - } - defer resp.Body.Close() - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - ruleBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("Failed to read translated rule body: %v", err) - } - - return string(ruleBytes), nil -} - -// RoleCreate will create a new role. It is not allowed for the role parameters -// ID field to be set as this will be generated by Consul while processing the request. -func (a *ACL) RoleCreate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, error) { - if role.ID != "" { - return nil, nil, fmt.Errorf("Cannot specify an ID in Role Creation") - } - - r := a.c.newRequest("PUT", "/v1/acl/role") - r.setWriteOptions(q) - r.obj = role - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLRole - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// RoleUpdate updates a role. The ID field of the role parameter must be set to an -// existing role ID -func (a *ACL) RoleUpdate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, error) { - if role.ID == "" { - return nil, nil, fmt.Errorf("Must specify an ID in Role Update") - } - - r := a.c.newRequest("PUT", "/v1/acl/role/"+role.ID) - r.setWriteOptions(q) - r.obj = role - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLRole - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// RoleDelete deletes a role given its ID. -func (a *ACL) RoleDelete(roleID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/role/"+roleID) - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} - -// RoleRead retrieves the role details (by ID). Returns nil if not found. -func (a *ACL) RoleRead(roleID string, q *QueryOptions) (*ACLRole, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/role/"+roleID) - r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if !found { - return nil, qm, nil - } - - var out ACLRole - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, qm, nil -} - -// RoleReadByName retrieves the role details (by name). Returns nil if not found. -func (a *ACL) RoleReadByName(roleName string, q *QueryOptions) (*ACLRole, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/role/name/"+url.QueryEscape(roleName)) - r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if !found { - return nil, qm, nil - } - - var out ACLRole - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, qm, nil -} - -// RoleList retrieves a listing of all roles. The listing does not include some -// metadata for the role as those should be retrieved by subsequent calls to -// RoleRead. -func (a *ACL) RoleList(q *QueryOptions) ([]*ACLRole, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/roles") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*ACLRole - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// AuthMethodCreate will create a new auth method. -func (a *ACL) AuthMethodCreate(method *ACLAuthMethod, q *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) { - if method.Name == "" { - return nil, nil, fmt.Errorf("Must specify a Name in Auth Method Creation") - } - - r := a.c.newRequest("PUT", "/v1/acl/auth-method") - r.setWriteOptions(q) - r.obj = method - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLAuthMethod - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// AuthMethodUpdate updates an auth method. -func (a *ACL) AuthMethodUpdate(method *ACLAuthMethod, q *WriteOptions) (*ACLAuthMethod, *WriteMeta, error) { - if method.Name == "" { - return nil, nil, fmt.Errorf("Must specify a Name in Auth Method Update") - } - - r := a.c.newRequest("PUT", "/v1/acl/auth-method/"+url.QueryEscape(method.Name)) - r.setWriteOptions(q) - r.obj = method - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLAuthMethod - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// AuthMethodDelete deletes an auth method given its Name. -func (a *ACL) AuthMethodDelete(methodName string, q *WriteOptions) (*WriteMeta, error) { - if methodName == "" { - return nil, fmt.Errorf("Must specify a Name in Auth Method Delete") - } - - r := a.c.newRequest("DELETE", "/v1/acl/auth-method/"+url.QueryEscape(methodName)) - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} - -// AuthMethodRead retrieves the auth method. Returns nil if not found. -func (a *ACL) AuthMethodRead(methodName string, q *QueryOptions) (*ACLAuthMethod, *QueryMeta, error) { - if methodName == "" { - return nil, nil, fmt.Errorf("Must specify a Name in Auth Method Read") - } - - r := a.c.newRequest("GET", "/v1/acl/auth-method/"+url.QueryEscape(methodName)) - r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if !found { - return nil, qm, nil - } - - var out ACLAuthMethod - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, qm, nil -} - -// AuthMethodList retrieves a listing of all auth methods. The listing does not -// include some metadata for the auth method as those should be retrieved by -// subsequent calls to AuthMethodRead. -func (a *ACL) AuthMethodList(q *QueryOptions) ([]*ACLAuthMethodListEntry, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/auth-methods") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*ACLAuthMethodListEntry - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// BindingRuleCreate will create a new binding rule. It is not allowed for the -// binding rule parameter's ID field to be set as this will be generated by -// Consul while processing the request. -func (a *ACL) BindingRuleCreate(rule *ACLBindingRule, q *WriteOptions) (*ACLBindingRule, *WriteMeta, error) { - if rule.ID != "" { - return nil, nil, fmt.Errorf("Cannot specify an ID in Binding Rule Creation") - } - - r := a.c.newRequest("PUT", "/v1/acl/binding-rule") - r.setWriteOptions(q) - r.obj = rule - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLBindingRule - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// BindingRuleUpdate updates a binding rule. The ID field of the role binding -// rule parameter must be set to an existing binding rule ID. -func (a *ACL) BindingRuleUpdate(rule *ACLBindingRule, q *WriteOptions) (*ACLBindingRule, *WriteMeta, error) { - if rule.ID == "" { - return nil, nil, fmt.Errorf("Must specify an ID in Binding Rule Update") - } - - r := a.c.newRequest("PUT", "/v1/acl/binding-rule/"+rule.ID) - r.setWriteOptions(q) - r.obj = rule - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLBindingRule - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, wm, nil -} - -// BindingRuleDelete deletes a binding rule given its ID. -func (a *ACL) BindingRuleDelete(bindingRuleID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/binding-rule/"+bindingRuleID) - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} - -// BindingRuleRead retrieves the binding rule details. Returns nil if not found. -func (a *ACL) BindingRuleRead(bindingRuleID string, q *QueryOptions) (*ACLBindingRule, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/binding-rule/"+bindingRuleID) - r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if !found { - return nil, qm, nil - } - - var out ACLBindingRule - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return &out, qm, nil -} - -// BindingRuleList retrieves a listing of all binding rules. -func (a *ACL) BindingRuleList(methodName string, q *QueryOptions) ([]*ACLBindingRule, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/binding-rules") - if methodName != "" { - r.params.Set("authmethod", methodName) - } - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*ACLBindingRule - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// Login is used to exchange auth method credentials for a newly-minted Consul Token. -func (a *ACL) Login(auth *ACLLoginParams, q *WriteOptions) (*ACLToken, *WriteMeta, error) { - r := a.c.newRequest("POST", "/v1/acl/login") - r.setWriteOptions(q) - r.obj = auth - - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out ACLToken - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, wm, nil -} - -// Logout is used to destroy a Consul Token created via Login(). -func (a *ACL) Logout(q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("POST", "/v1/acl/logout") - r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/agent.go b/vendor/github.com/hashicorp/consul/api/agent.go deleted file mode 100644 index 04043ba842..0000000000 --- a/vendor/github.com/hashicorp/consul/api/agent.go +++ /dev/null @@ -1,1035 +0,0 @@ -package api - -import ( - "bufio" - "bytes" - "fmt" - "io" - "net/http" - "net/url" -) - -// ServiceKind is the kind of service being registered. -type ServiceKind string - -const ( - // ServiceKindTypical is a typical, classic Consul service. This is - // represented by the absence of a value. This was chosen for ease of - // backwards compatibility: existing services in the catalog would - // default to the typical service. - ServiceKindTypical ServiceKind = "" - - // ServiceKindConnectProxy is a proxy for the Connect feature. This - // service proxies another service within Consul and speaks the connect - // protocol. - ServiceKindConnectProxy ServiceKind = "connect-proxy" -) - -// ProxyExecMode is the execution mode for a managed Connect proxy. -type ProxyExecMode string - -const ( - // ProxyExecModeDaemon indicates that the proxy command should be long-running - // and should be started and supervised by the agent until it's target service - // is deregistered. - ProxyExecModeDaemon ProxyExecMode = "daemon" - - // ProxyExecModeScript indicates that the proxy command should be invoke to - // completion on each change to the configuration of lifecycle event. The - // script typically fetches the config and certificates from the agent API and - // then configures an externally managed daemon, perhaps starting and stopping - // it if necessary. - ProxyExecModeScript ProxyExecMode = "script" -) - -// UpstreamDestType is the type of upstream discovery mechanism. -type UpstreamDestType string - -const ( - // UpstreamDestTypeService discovers instances via healthy service lookup. - UpstreamDestTypeService UpstreamDestType = "service" - - // UpstreamDestTypePreparedQuery discovers instances via prepared query - // execution. - UpstreamDestTypePreparedQuery UpstreamDestType = "prepared_query" -) - -// AgentCheck represents a check known to the agent -type AgentCheck struct { - Node string - CheckID string - Name string - Status string - Notes string - Output string - ServiceID string - ServiceName string - Definition HealthCheckDefinition -} - -// AgentWeights represent optional weights for a service -type AgentWeights struct { - Passing int - Warning int -} - -// AgentService represents a service known to the agent -type AgentService struct { - Kind ServiceKind `json:",omitempty"` - ID string - Service string - Tags []string - Meta map[string]string - Port int - Address string - Weights AgentWeights - EnableTagOverride bool - CreateIndex uint64 `json:",omitempty" bexpr:"-"` - ModifyIndex uint64 `json:",omitempty" bexpr:"-"` - ContentHash string `json:",omitempty" bexpr:"-"` - // DEPRECATED (ProxyDestination) - remove this field - ProxyDestination string `json:",omitempty" bexpr:"-"` - Proxy *AgentServiceConnectProxyConfig `json:",omitempty"` - Connect *AgentServiceConnect `json:",omitempty"` -} - -// AgentServiceChecksInfo returns information about a Service and its checks -type AgentServiceChecksInfo struct { - AggregatedStatus string - Service *AgentService - Checks HealthChecks -} - -// AgentServiceConnect represents the Connect configuration of a service. -type AgentServiceConnect struct { - Native bool `json:",omitempty"` - Proxy *AgentServiceConnectProxy `json:",omitempty" bexpr:"-"` - SidecarService *AgentServiceRegistration `json:",omitempty" bexpr:"-"` -} - -// AgentServiceConnectProxy represents the Connect Proxy configuration of a -// service. -type AgentServiceConnectProxy struct { - ExecMode ProxyExecMode `json:",omitempty"` - Command []string `json:",omitempty"` - Config map[string]interface{} `json:",omitempty" bexpr:"-"` - Upstreams []Upstream `json:",omitempty"` -} - -// AgentServiceConnectProxyConfig is the proxy configuration in a connect-proxy -// ServiceDefinition or response. -type AgentServiceConnectProxyConfig struct { - DestinationServiceName string - DestinationServiceID string `json:",omitempty"` - LocalServiceAddress string `json:",omitempty"` - LocalServicePort int `json:",omitempty"` - Config map[string]interface{} `json:",omitempty" bexpr:"-"` - Upstreams []Upstream -} - -// AgentMember represents a cluster member known to the agent -type AgentMember struct { - Name string - Addr string - Port uint16 - Tags map[string]string - Status int - ProtocolMin uint8 - ProtocolMax uint8 - ProtocolCur uint8 - DelegateMin uint8 - DelegateMax uint8 - DelegateCur uint8 -} - -// AllSegments is used to select for all segments in MembersOpts. -const AllSegments = "_all" - -// MembersOpts is used for querying member information. -type MembersOpts struct { - // WAN is whether to show members from the WAN. - WAN bool - - // Segment is the LAN segment to show members for. Setting this to the - // AllSegments value above will show members in all segments. - Segment string -} - -// AgentServiceRegistration is used to register a new service -type AgentServiceRegistration struct { - Kind ServiceKind `json:",omitempty"` - ID string `json:",omitempty"` - Name string `json:",omitempty"` - Tags []string `json:",omitempty"` - Port int `json:",omitempty"` - Address string `json:",omitempty"` - EnableTagOverride bool `json:",omitempty"` - Meta map[string]string `json:",omitempty"` - Weights *AgentWeights `json:",omitempty"` - Check *AgentServiceCheck - Checks AgentServiceChecks - // DEPRECATED (ProxyDestination) - remove this field - ProxyDestination string `json:",omitempty"` - Proxy *AgentServiceConnectProxyConfig `json:",omitempty"` - Connect *AgentServiceConnect `json:",omitempty"` -} - -// AgentCheckRegistration is used to register a new check -type AgentCheckRegistration struct { - ID string `json:",omitempty"` - Name string `json:",omitempty"` - Notes string `json:",omitempty"` - ServiceID string `json:",omitempty"` - AgentServiceCheck -} - -// AgentServiceCheck is used to define a node or service level check -type AgentServiceCheck struct { - CheckID string `json:",omitempty"` - Name string `json:",omitempty"` - Args []string `json:"ScriptArgs,omitempty"` - DockerContainerID string `json:",omitempty"` - Shell string `json:",omitempty"` // Only supported for Docker. - Interval string `json:",omitempty"` - Timeout string `json:",omitempty"` - TTL string `json:",omitempty"` - HTTP string `json:",omitempty"` - Header map[string][]string `json:",omitempty"` - Method string `json:",omitempty"` - TCP string `json:",omitempty"` - Status string `json:",omitempty"` - Notes string `json:",omitempty"` - TLSSkipVerify bool `json:",omitempty"` - GRPC string `json:",omitempty"` - GRPCUseTLS bool `json:",omitempty"` - AliasNode string `json:",omitempty"` - AliasService string `json:",omitempty"` - - // In Consul 0.7 and later, checks that are associated with a service - // may also contain this optional DeregisterCriticalServiceAfter field, - // which is a timeout in the same Go time format as Interval and TTL. If - // a check is in the critical state for more than this configured value, - // then its associated service (and all of its associated checks) will - // automatically be deregistered. - DeregisterCriticalServiceAfter string `json:",omitempty"` -} -type AgentServiceChecks []*AgentServiceCheck - -// AgentToken is used when updating ACL tokens for an agent. -type AgentToken struct { - Token string -} - -// Metrics info is used to store different types of metric values from the agent. -type MetricsInfo struct { - Timestamp string - Gauges []GaugeValue - Points []PointValue - Counters []SampledValue - Samples []SampledValue -} - -// GaugeValue stores one value that is updated as time goes on, such as -// the amount of memory allocated. -type GaugeValue struct { - Name string - Value float32 - Labels map[string]string -} - -// PointValue holds a series of points for a metric. -type PointValue struct { - Name string - Points []float32 -} - -// SampledValue stores info about a metric that is incremented over time, -// such as the number of requests to an HTTP endpoint. -type SampledValue struct { - Name string - Count int - Sum float64 - Min float64 - Max float64 - Mean float64 - Stddev float64 - Labels map[string]string -} - -// AgentAuthorizeParams are the request parameters for authorizing a request. -type AgentAuthorizeParams struct { - Target string - ClientCertURI string - ClientCertSerial string -} - -// AgentAuthorize is the response structure for Connect authorization. -type AgentAuthorize struct { - Authorized bool - Reason string -} - -// ConnectProxyConfig is the response structure for agent-local proxy -// configuration. -type ConnectProxyConfig struct { - ProxyServiceID string - TargetServiceID string - TargetServiceName string - ContentHash string - // DEPRECATED(managed-proxies) - this struct is re-used for sidecar configs - // but they don't need ExecMode or Command - ExecMode ProxyExecMode `json:",omitempty"` - Command []string `json:",omitempty"` - Config map[string]interface{} `bexpr:"-"` - Upstreams []Upstream -} - -// Upstream is the response structure for a proxy upstream configuration. -type Upstream struct { - DestinationType UpstreamDestType `json:",omitempty"` - DestinationNamespace string `json:",omitempty"` - DestinationName string - Datacenter string `json:",omitempty"` - LocalBindAddress string `json:",omitempty"` - LocalBindPort int `json:",omitempty"` - Config map[string]interface{} `json:",omitempty" bexpr:"-"` -} - -// Agent can be used to query the Agent endpoints -type Agent struct { - c *Client - - // cache the node name - nodeName string -} - -// Agent returns a handle to the agent endpoints -func (c *Client) Agent() *Agent { - return &Agent{c: c} -} - -// Self is used to query the agent we are speaking to for -// information about itself -func (a *Agent) Self() (map[string]map[string]interface{}, error) { - r := a.c.newRequest("GET", "/v1/agent/self") - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out map[string]map[string]interface{} - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// Host is used to retrieve information about the host the -// agent is running on such as CPU, memory, and disk. Requires -// a operator:read ACL token. -func (a *Agent) Host() (map[string]interface{}, error) { - r := a.c.newRequest("GET", "/v1/agent/host") - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out map[string]interface{} - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// Metrics is used to query the agent we are speaking to for -// its current internal metric data -func (a *Agent) Metrics() (*MetricsInfo, error) { - r := a.c.newRequest("GET", "/v1/agent/metrics") - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out *MetricsInfo - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// Reload triggers a configuration reload for the agent we are connected to. -func (a *Agent) Reload() error { - r := a.c.newRequest("PUT", "/v1/agent/reload") - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// NodeName is used to get the node name of the agent -func (a *Agent) NodeName() (string, error) { - if a.nodeName != "" { - return a.nodeName, nil - } - info, err := a.Self() - if err != nil { - return "", err - } - name := info["Config"]["NodeName"].(string) - a.nodeName = name - return name, nil -} - -// Checks returns the locally registered checks -func (a *Agent) Checks() (map[string]*AgentCheck, error) { - return a.ChecksWithFilter("") -} - -// ChecksWithFilter returns a subset of the locally registered checks that match -// the given filter expression -func (a *Agent) ChecksWithFilter(filter string) (map[string]*AgentCheck, error) { - r := a.c.newRequest("GET", "/v1/agent/checks") - r.filterQuery(filter) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out map[string]*AgentCheck - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// Services returns the locally registered services -func (a *Agent) Services() (map[string]*AgentService, error) { - return a.ServicesWithFilter("") -} - -// ServicesWithFilter returns a subset of the locally registered services that match -// the given filter expression -func (a *Agent) ServicesWithFilter(filter string) (map[string]*AgentService, error) { - r := a.c.newRequest("GET", "/v1/agent/services") - r.filterQuery(filter) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out map[string]*AgentService - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - - return out, nil -} - -// AgentHealthServiceByID returns for a given serviceID: the aggregated health status, the service definition or an error if any -// - If the service is not found, will return status (critical, nil, nil) -// - If the service is found, will return (critical|passing|warning), AgentServiceChecksInfo, nil) -// - In all other cases, will return an error -func (a *Agent) AgentHealthServiceByID(serviceID string) (string, *AgentServiceChecksInfo, error) { - path := fmt.Sprintf("/v1/agent/health/service/id/%v", url.PathEscape(serviceID)) - r := a.c.newRequest("GET", path) - r.params.Add("format", "json") - r.header.Set("Accept", "application/json") - _, resp, err := a.c.doRequest(r) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - // Service not Found - if resp.StatusCode == http.StatusNotFound { - return HealthCritical, nil, nil - } - var out *AgentServiceChecksInfo - if err := decodeBody(resp, &out); err != nil { - return HealthCritical, out, err - } - switch resp.StatusCode { - case http.StatusOK: - return HealthPassing, out, nil - case http.StatusTooManyRequests: - return HealthWarning, out, nil - case http.StatusServiceUnavailable: - return HealthCritical, out, nil - } - return HealthCritical, out, fmt.Errorf("Unexpected Error Code %v for %s", resp.StatusCode, path) -} - -// AgentHealthServiceByName returns for a given service name: the aggregated health status for all services -// having the specified name. -// - If no service is not found, will return status (critical, [], nil) -// - If the service is found, will return (critical|passing|warning), []api.AgentServiceChecksInfo, nil) -// - In all other cases, will return an error -func (a *Agent) AgentHealthServiceByName(service string) (string, []AgentServiceChecksInfo, error) { - path := fmt.Sprintf("/v1/agent/health/service/name/%v", url.PathEscape(service)) - r := a.c.newRequest("GET", path) - r.params.Add("format", "json") - r.header.Set("Accept", "application/json") - _, resp, err := a.c.doRequest(r) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - // Service not Found - if resp.StatusCode == http.StatusNotFound { - return HealthCritical, nil, nil - } - var out []AgentServiceChecksInfo - if err := decodeBody(resp, &out); err != nil { - return HealthCritical, out, err - } - switch resp.StatusCode { - case http.StatusOK: - return HealthPassing, out, nil - case http.StatusTooManyRequests: - return HealthWarning, out, nil - case http.StatusServiceUnavailable: - return HealthCritical, out, nil - } - return HealthCritical, out, fmt.Errorf("Unexpected Error Code %v for %s", resp.StatusCode, path) -} - -// Service returns a locally registered service instance and allows for -// hash-based blocking. -// -// Note that this uses an unconventional blocking mechanism since it's -// agent-local state. That means there is no persistent raft index so we block -// based on object hash instead. -func (a *Agent) Service(serviceID string, q *QueryOptions) (*AgentService, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/agent/service/"+serviceID) - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out *AgentService - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - - return out, qm, nil -} - -// Members returns the known gossip members. The WAN -// flag can be used to query a server for WAN members. -func (a *Agent) Members(wan bool) ([]*AgentMember, error) { - r := a.c.newRequest("GET", "/v1/agent/members") - if wan { - r.params.Set("wan", "1") - } - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out []*AgentMember - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// MembersOpts returns the known gossip members and can be passed -// additional options for WAN/segment filtering. -func (a *Agent) MembersOpts(opts MembersOpts) ([]*AgentMember, error) { - r := a.c.newRequest("GET", "/v1/agent/members") - r.params.Set("segment", opts.Segment) - if opts.WAN { - r.params.Set("wan", "1") - } - - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out []*AgentMember - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// ServiceRegister is used to register a new service with -// the local agent -func (a *Agent) ServiceRegister(service *AgentServiceRegistration) error { - r := a.c.newRequest("PUT", "/v1/agent/service/register") - r.obj = service - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// ServiceDeregister is used to deregister a service with -// the local agent -func (a *Agent) ServiceDeregister(serviceID string) error { - r := a.c.newRequest("PUT", "/v1/agent/service/deregister/"+serviceID) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// PassTTL is used to set a TTL check to the passing state. -// -// DEPRECATION NOTICE: This interface is deprecated in favor of UpdateTTL(). -// The client interface will be removed in 0.8 or changed to use -// UpdateTTL()'s endpoint and the server endpoints will be removed in 0.9. -func (a *Agent) PassTTL(checkID, note string) error { - return a.updateTTL(checkID, note, "pass") -} - -// WarnTTL is used to set a TTL check to the warning state. -// -// DEPRECATION NOTICE: This interface is deprecated in favor of UpdateTTL(). -// The client interface will be removed in 0.8 or changed to use -// UpdateTTL()'s endpoint and the server endpoints will be removed in 0.9. -func (a *Agent) WarnTTL(checkID, note string) error { - return a.updateTTL(checkID, note, "warn") -} - -// FailTTL is used to set a TTL check to the failing state. -// -// DEPRECATION NOTICE: This interface is deprecated in favor of UpdateTTL(). -// The client interface will be removed in 0.8 or changed to use -// UpdateTTL()'s endpoint and the server endpoints will be removed in 0.9. -func (a *Agent) FailTTL(checkID, note string) error { - return a.updateTTL(checkID, note, "fail") -} - -// updateTTL is used to update the TTL of a check. This is the internal -// method that uses the old API that's present in Consul versions prior to -// 0.6.4. Since Consul didn't have an analogous "update" API before it seemed -// ok to break this (former) UpdateTTL in favor of the new UpdateTTL below, -// but keep the old Pass/Warn/Fail methods using the old API under the hood. -// -// DEPRECATION NOTICE: This interface is deprecated in favor of UpdateTTL(). -// The client interface will be removed in 0.8 and the server endpoints will -// be removed in 0.9. -func (a *Agent) updateTTL(checkID, note, status string) error { - switch status { - case "pass": - case "warn": - case "fail": - default: - return fmt.Errorf("Invalid status: %s", status) - } - endpoint := fmt.Sprintf("/v1/agent/check/%s/%s", status, checkID) - r := a.c.newRequest("PUT", endpoint) - r.params.Set("note", note) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// checkUpdate is the payload for a PUT for a check update. -type checkUpdate struct { - // Status is one of the api.Health* states: HealthPassing - // ("passing"), HealthWarning ("warning"), or HealthCritical - // ("critical"). - Status string - - // Output is the information to post to the UI for operators as the - // output of the process that decided to hit the TTL check. This is - // different from the note field that's associated with the check - // itself. - Output string -} - -// UpdateTTL is used to update the TTL of a check. This uses the newer API -// that was introduced in Consul 0.6.4 and later. We translate the old status -// strings for compatibility (though a newer version of Consul will still be -// required to use this API). -func (a *Agent) UpdateTTL(checkID, output, status string) error { - switch status { - case "pass", HealthPassing: - status = HealthPassing - case "warn", HealthWarning: - status = HealthWarning - case "fail", HealthCritical: - status = HealthCritical - default: - return fmt.Errorf("Invalid status: %s", status) - } - - endpoint := fmt.Sprintf("/v1/agent/check/update/%s", checkID) - r := a.c.newRequest("PUT", endpoint) - r.obj = &checkUpdate{ - Status: status, - Output: output, - } - - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// CheckRegister is used to register a new check with -// the local agent -func (a *Agent) CheckRegister(check *AgentCheckRegistration) error { - r := a.c.newRequest("PUT", "/v1/agent/check/register") - r.obj = check - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// CheckDeregister is used to deregister a check with -// the local agent -func (a *Agent) CheckDeregister(checkID string) error { - r := a.c.newRequest("PUT", "/v1/agent/check/deregister/"+checkID) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// Join is used to instruct the agent to attempt a join to -// another cluster member -func (a *Agent) Join(addr string, wan bool) error { - r := a.c.newRequest("PUT", "/v1/agent/join/"+addr) - if wan { - r.params.Set("wan", "1") - } - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// Leave is used to have the agent gracefully leave the cluster and shutdown -func (a *Agent) Leave() error { - r := a.c.newRequest("PUT", "/v1/agent/leave") - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// ForceLeave is used to have the agent eject a failed node -func (a *Agent) ForceLeave(node string) error { - r := a.c.newRequest("PUT", "/v1/agent/force-leave/"+node) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// ConnectAuthorize is used to authorize an incoming connection -// to a natively integrated Connect service. -func (a *Agent) ConnectAuthorize(auth *AgentAuthorizeParams) (*AgentAuthorize, error) { - r := a.c.newRequest("POST", "/v1/agent/connect/authorize") - r.obj = auth - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out AgentAuthorize - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return &out, nil -} - -// ConnectCARoots returns the list of roots. -func (a *Agent) ConnectCARoots(q *QueryOptions) (*CARootList, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/agent/connect/ca/roots") - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out CARootList - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, qm, nil -} - -// ConnectCALeaf gets the leaf certificate for the given service ID. -func (a *Agent) ConnectCALeaf(serviceID string, q *QueryOptions) (*LeafCert, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/agent/connect/ca/leaf/"+serviceID) - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out LeafCert - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, qm, nil -} - -// ConnectProxyConfig gets the configuration for a local managed proxy instance. -// -// Note that this uses an unconventional blocking mechanism since it's -// agent-local state. That means there is no persistent raft index so we block -// based on object hash instead. -func (a *Agent) ConnectProxyConfig(proxyServiceID string, q *QueryOptions) (*ConnectProxyConfig, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/agent/connect/proxy/"+proxyServiceID) - r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out ConnectProxyConfig - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, qm, nil -} - -// EnableServiceMaintenance toggles service maintenance mode on -// for the given service ID. -func (a *Agent) EnableServiceMaintenance(serviceID, reason string) error { - r := a.c.newRequest("PUT", "/v1/agent/service/maintenance/"+serviceID) - r.params.Set("enable", "true") - r.params.Set("reason", reason) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// DisableServiceMaintenance toggles service maintenance mode off -// for the given service ID. -func (a *Agent) DisableServiceMaintenance(serviceID string) error { - r := a.c.newRequest("PUT", "/v1/agent/service/maintenance/"+serviceID) - r.params.Set("enable", "false") - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// EnableNodeMaintenance toggles node maintenance mode on for the -// agent we are connected to. -func (a *Agent) EnableNodeMaintenance(reason string) error { - r := a.c.newRequest("PUT", "/v1/agent/maintenance") - r.params.Set("enable", "true") - r.params.Set("reason", reason) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// DisableNodeMaintenance toggles node maintenance mode off for the -// agent we are connected to. -func (a *Agent) DisableNodeMaintenance() error { - r := a.c.newRequest("PUT", "/v1/agent/maintenance") - r.params.Set("enable", "false") - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// Monitor returns a channel which will receive streaming logs from the agent -// Providing a non-nil stopCh can be used to close the connection and stop the -// log stream. An empty string will be sent down the given channel when there's -// nothing left to stream, after which the caller should close the stopCh. -func (a *Agent) Monitor(loglevel string, stopCh <-chan struct{}, q *QueryOptions) (chan string, error) { - r := a.c.newRequest("GET", "/v1/agent/monitor") - r.setQueryOptions(q) - if loglevel != "" { - r.params.Add("loglevel", loglevel) - } - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return nil, err - } - - logCh := make(chan string, 64) - go func() { - defer resp.Body.Close() - - scanner := bufio.NewScanner(resp.Body) - for { - select { - case <-stopCh: - close(logCh) - return - default: - } - if scanner.Scan() { - // An empty string signals to the caller that - // the scan is done, so make sure we only emit - // that when the scanner says it's done, not if - // we happen to ingest an empty line. - if text := scanner.Text(); text != "" { - logCh <- text - } else { - logCh <- " " - } - } else { - logCh <- "" - } - } - }() - - return logCh, nil -} - -// UpdateACLToken updates the agent's "acl_token". See updateToken for more -// details. -// -// DEPRECATED (ACL-Legacy-Compat) - Prefer UpdateDefaultACLToken for v1.4.3 and above -func (a *Agent) UpdateACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateToken("acl_token", token, q) -} - -// UpdateACLAgentToken updates the agent's "acl_agent_token". See updateToken -// for more details. -// -// DEPRECATED (ACL-Legacy-Compat) - Prefer UpdateAgentACLToken for v1.4.3 and above -func (a *Agent) UpdateACLAgentToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateToken("acl_agent_token", token, q) -} - -// UpdateACLAgentMasterToken updates the agent's "acl_agent_master_token". See -// updateToken for more details. -// -// DEPRECATED (ACL-Legacy-Compat) - Prefer UpdateAgentMasterACLToken for v1.4.3 and above -func (a *Agent) UpdateACLAgentMasterToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateToken("acl_agent_master_token", token, q) -} - -// UpdateACLReplicationToken updates the agent's "acl_replication_token". See -// updateToken for more details. -// -// DEPRECATED (ACL-Legacy-Compat) - Prefer UpdateReplicationACLToken for v1.4.3 and above -func (a *Agent) UpdateACLReplicationToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateToken("acl_replication_token", token, q) -} - -// UpdateDefaultACLToken updates the agent's "default" token. See updateToken -// for more details -func (a *Agent) UpdateDefaultACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("default", "acl_token", token, q) -} - -// UpdateAgentACLToken updates the agent's "agent" token. See updateToken -// for more details -func (a *Agent) UpdateAgentACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("agent", "acl_agent_token", token, q) -} - -// UpdateAgentMasterACLToken updates the agent's "agent_master" token. See updateToken -// for more details -func (a *Agent) UpdateAgentMasterACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("agent_master", "acl_agent_master_token", token, q) -} - -// UpdateReplicationACLToken updates the agent's "replication" token. See updateToken -// for more details -func (a *Agent) UpdateReplicationACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("replication", "acl_replication_token", token, q) -} - -// updateToken can be used to update one of an agent's ACL tokens after the agent has -// started. The tokens are may not be persisted, so will need to be updated again if -// the agent is restarted unless the agent is configured to persist them. -func (a *Agent) updateToken(target, token string, q *WriteOptions) (*WriteMeta, error) { - meta, _, err := a.updateTokenOnce(target, token, q) - return meta, err -} - -func (a *Agent) updateTokenFallback(target, fallback, token string, q *WriteOptions) (*WriteMeta, error) { - meta, status, err := a.updateTokenOnce(target, token, q) - if err != nil && status == 404 { - meta, _, err = a.updateTokenOnce(fallback, token, q) - } - return meta, err -} - -func (a *Agent) updateTokenOnce(target, token string, q *WriteOptions) (*WriteMeta, int, error) { - r := a.c.newRequest("PUT", fmt.Sprintf("/v1/agent/token/%s", target)) - r.setWriteOptions(q) - r.obj = &AgentToken{Token: token} - - rtt, resp, err := a.c.doRequest(r) - if err != nil { - return nil, 0, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - - if resp.StatusCode != 200 { - var buf bytes.Buffer - io.Copy(&buf, resp.Body) - return wm, resp.StatusCode, fmt.Errorf("Unexpected response code: %d (%s)", resp.StatusCode, buf.Bytes()) - } - - return wm, resp.StatusCode, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/api.go b/vendor/github.com/hashicorp/consul/api/api.go deleted file mode 100644 index 4b17ff6cda..0000000000 --- a/vendor/github.com/hashicorp/consul/api/api.go +++ /dev/null @@ -1,966 +0,0 @@ -package api - -import ( - "bytes" - "context" - "crypto/tls" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/url" - "os" - "strconv" - "strings" - "time" - - "github.com/hashicorp/go-cleanhttp" - "github.com/hashicorp/go-rootcerts" -) - -const ( - // HTTPAddrEnvName defines an environment variable name which sets - // the HTTP address if there is no -http-addr specified. - HTTPAddrEnvName = "CONSUL_HTTP_ADDR" - - // HTTPTokenEnvName defines an environment variable name which sets - // the HTTP token. - HTTPTokenEnvName = "CONSUL_HTTP_TOKEN" - - // HTTPTokenFileEnvName defines an environment variable name which sets - // the HTTP token file. - HTTPTokenFileEnvName = "CONSUL_HTTP_TOKEN_FILE" - - // HTTPAuthEnvName defines an environment variable name which sets - // the HTTP authentication header. - HTTPAuthEnvName = "CONSUL_HTTP_AUTH" - - // HTTPSSLEnvName defines an environment variable name which sets - // whether or not to use HTTPS. - HTTPSSLEnvName = "CONSUL_HTTP_SSL" - - // HTTPCAFile defines an environment variable name which sets the - // CA file to use for talking to Consul over TLS. - HTTPCAFile = "CONSUL_CACERT" - - // HTTPCAPath defines an environment variable name which sets the - // path to a directory of CA certs to use for talking to Consul over TLS. - HTTPCAPath = "CONSUL_CAPATH" - - // HTTPClientCert defines an environment variable name which sets the - // client cert file to use for talking to Consul over TLS. - HTTPClientCert = "CONSUL_CLIENT_CERT" - - // HTTPClientKey defines an environment variable name which sets the - // client key file to use for talking to Consul over TLS. - HTTPClientKey = "CONSUL_CLIENT_KEY" - - // HTTPTLSServerName defines an environment variable name which sets the - // server name to use as the SNI host when connecting via TLS - HTTPTLSServerName = "CONSUL_TLS_SERVER_NAME" - - // HTTPSSLVerifyEnvName defines an environment variable name which sets - // whether or not to disable certificate checking. - HTTPSSLVerifyEnvName = "CONSUL_HTTP_SSL_VERIFY" - - // GRPCAddrEnvName defines an environment variable name which sets the gRPC - // address for consul connect envoy. Note this isn't actually used by the api - // client in this package but is defined here for consistency with all the - // other ENV names we use. - GRPCAddrEnvName = "CONSUL_GRPC_ADDR" -) - -// 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 - - // UseCache requests that the agent cache results locally. See - // https://www.consul.io/api/index.html#agent-caching for more details on the - // semantics. - UseCache bool - - // MaxAge limits how old a cached value will be returned if UseCache is true. - // If there is a cached response that is older than the MaxAge, it is treated - // as a cache miss and a new fetch invoked. If the fetch fails, the error is - // returned. Clients that wish to allow for stale results on error can set - // StaleIfError to a longer duration to change this behavior. It is ignored - // if the endpoint supports background refresh caching. See - // https://www.consul.io/api/index.html#agent-caching for more details. - MaxAge time.Duration - - // StaleIfError specifies how stale the client will accept a cached response - // if the servers are unavailable to fetch a fresh one. Only makes sense when - // UseCache is true and MaxAge is set to a lower, non-zero value. It is - // ignored if the endpoint supports background refresh caching. See - // https://www.consul.io/api/index.html#agent-caching for more details. - StaleIfError time.Duration - - // WaitIndex is used to enable a blocking query. Waits - // until the timeout or the next index is reached - WaitIndex uint64 - - // WaitHash is used by some endpoints instead of WaitIndex to perform blocking - // on state based on a hash of the response rather than a monotonic index. - // This is required when the state being blocked on is not stored in Raft, for - // example agent-local proxy configuration. - WaitHash string - - // WaitTime is used to bound the duration of a wait. - // Defaults to that of the Config, but can be overridden. - WaitTime time.Duration - - // Token is used to provide a per-request ACL token - // which overrides the agent's default token. - Token string - - // Near is used to provide a node name that will sort the results - // in ascending order based on the estimated round trip time from - // that node. Setting this to "_agent" will use the agent's node - // for the sort. - Near string - - // NodeMeta is used to filter results by nodes with the given - // metadata key/value pairs. Currently, only one key/value pair can - // be provided for filtering. - NodeMeta map[string]string - - // RelayFactor is used in keyring operations to cause responses to be - // relayed back to the sender through N other random nodes. Must be - // a value from 0 to 5 (inclusive). - RelayFactor uint8 - - // Connect filters prepared query execution to only include Connect-capable - // services. This currently affects prepared query execution. - Connect bool - - // ctx is an optional context pass through to the underlying HTTP - // request layer. Use Context() and WithContext() to manage this. - ctx context.Context - - // Filter requests filtering data prior to it being returned. The string - // is a go-bexpr compatible expression. - Filter string -} - -func (o *QueryOptions) Context() context.Context { - if o != nil && o.ctx != nil { - return o.ctx - } - return context.Background() -} - -func (o *QueryOptions) WithContext(ctx context.Context) *QueryOptions { - o2 := new(QueryOptions) - if o != nil { - *o2 = *o - } - o2.ctx = ctx - return o2 -} - -// 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 - - // RelayFactor is used in keyring operations to cause responses to be - // relayed back to the sender through N other random nodes. Must be - // a value from 0 to 5 (inclusive). - RelayFactor uint8 - - // ctx is an optional context pass through to the underlying HTTP - // request layer. Use Context() and WithContext() to manage this. - ctx context.Context -} - -func (o *WriteOptions) Context() context.Context { - if o != nil && o.ctx != nil { - return o.ctx - } - return context.Background() -} - -func (o *WriteOptions) WithContext(ctx context.Context) *WriteOptions { - o2 := new(WriteOptions) - if o != nil { - *o2 = *o - } - o2.ctx = ctx - return o2 -} - -// 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 - - // LastContentHash. This can be used as a WaitHash to perform a blocking query - // for endpoints that support hash-based blocking. Endpoints that do not - // support it will return an empty hash. - LastContentHash string - - // 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 - - // Is address translation enabled for HTTP responses on this agent - AddressTranslationEnabled bool - - // CacheHit is true if the result was served from agent-local cache. - CacheHit bool - - // CacheAge is set if request was ?cached and indicates how stale the cached - // response is. - CacheAge 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 - - // Transport is the Transport to use for the http client. - Transport *http.Transport - - // 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 - - // TokenFile is a file containing the current token to use for this client. - // If provided it is read once at startup and never again. - TokenFile string - - TLSConfig TLSConfig -} - -// TLSConfig is used to generate a TLSClientConfig that's useful for talking to -// Consul using TLS. -type TLSConfig struct { - // Address is the optional address of the Consul server. The port, if any - // will be removed from here and this will be set to the ServerName of the - // resulting config. - Address string - - // CAFile is the optional path to the CA certificate used for Consul - // communication, defaults to the system bundle if not specified. - CAFile string - - // CAPath is the optional path to a directory of CA certificates to use for - // Consul communication, defaults to the system bundle if not specified. - CAPath string - - // CertFile is the optional path to the certificate for Consul - // communication. If this is set then you need to also set KeyFile. - CertFile string - - // KeyFile is the optional path to the private key for Consul communication. - // If this is set then you need to also set CertFile. - KeyFile string - - // InsecureSkipVerify if set to true will disable TLS host verification. - InsecureSkipVerify bool -} - -// DefaultConfig returns a default configuration for the client. By default this -// will pool and reuse idle connections to Consul. If you have a long-lived -// client object, this is the desired behavior and should make the most efficient -// use of the connections to Consul. If you don't reuse a client object, which -// is not recommended, then you may notice idle connections building up over -// time. To avoid this, use the DefaultNonPooledConfig() instead. -func DefaultConfig() *Config { - return defaultConfig(cleanhttp.DefaultPooledTransport) -} - -// DefaultNonPooledConfig returns a default configuration for the client which -// does not pool connections. This isn't a recommended configuration because it -// will reconnect to Consul on every request, but this is useful to avoid the -// accumulation of idle connections if you make many client objects during the -// lifetime of your application. -func DefaultNonPooledConfig() *Config { - return defaultConfig(cleanhttp.DefaultTransport) -} - -// defaultConfig returns the default configuration for the client, using the -// given function to make the transport. -func defaultConfig(transportFn func() *http.Transport) *Config { - config := &Config{ - Address: "127.0.0.1:8500", - Scheme: "http", - Transport: transportFn(), - } - - if addr := os.Getenv(HTTPAddrEnvName); addr != "" { - config.Address = addr - } - - if tokenFile := os.Getenv(HTTPTokenFileEnvName); tokenFile != "" { - config.TokenFile = tokenFile - } - - if token := os.Getenv(HTTPTokenEnvName); token != "" { - config.Token = token - } - - if auth := os.Getenv(HTTPAuthEnvName); auth != "" { - var username, password string - if strings.Contains(auth, ":") { - split := strings.SplitN(auth, ":", 2) - username = split[0] - password = split[1] - } else { - username = auth - } - - config.HttpAuth = &HttpBasicAuth{ - Username: username, - Password: password, - } - } - - if ssl := os.Getenv(HTTPSSLEnvName); ssl != "" { - enabled, err := strconv.ParseBool(ssl) - if err != nil { - log.Printf("[WARN] client: could not parse %s: %s", HTTPSSLEnvName, err) - } - - if enabled { - config.Scheme = "https" - } - } - - if v := os.Getenv(HTTPTLSServerName); v != "" { - config.TLSConfig.Address = v - } - if v := os.Getenv(HTTPCAFile); v != "" { - config.TLSConfig.CAFile = v - } - if v := os.Getenv(HTTPCAPath); v != "" { - config.TLSConfig.CAPath = v - } - if v := os.Getenv(HTTPClientCert); v != "" { - config.TLSConfig.CertFile = v - } - if v := os.Getenv(HTTPClientKey); v != "" { - config.TLSConfig.KeyFile = v - } - if v := os.Getenv(HTTPSSLVerifyEnvName); v != "" { - doVerify, err := strconv.ParseBool(v) - if err != nil { - log.Printf("[WARN] client: could not parse %s: %s", HTTPSSLVerifyEnvName, err) - } - if !doVerify { - config.TLSConfig.InsecureSkipVerify = true - } - } - - return config -} - -// TLSConfig is used to generate a TLSClientConfig that's useful for talking to -// Consul using TLS. -func SetupTLSConfig(tlsConfig *TLSConfig) (*tls.Config, error) { - tlsClientConfig := &tls.Config{ - InsecureSkipVerify: tlsConfig.InsecureSkipVerify, - } - - if tlsConfig.Address != "" { - server := tlsConfig.Address - hasPort := strings.LastIndex(server, ":") > strings.LastIndex(server, "]") - if hasPort { - var err error - server, _, err = net.SplitHostPort(server) - if err != nil { - return nil, err - } - } - tlsClientConfig.ServerName = server - } - - if tlsConfig.CertFile != "" && tlsConfig.KeyFile != "" { - tlsCert, err := tls.LoadX509KeyPair(tlsConfig.CertFile, tlsConfig.KeyFile) - if err != nil { - return nil, err - } - tlsClientConfig.Certificates = []tls.Certificate{tlsCert} - } - - if tlsConfig.CAFile != "" || tlsConfig.CAPath != "" { - rootConfig := &rootcerts.Config{ - CAFile: tlsConfig.CAFile, - CAPath: tlsConfig.CAPath, - } - if err := rootcerts.ConfigureTLS(tlsClientConfig, rootConfig); err != nil { - return nil, err - } - } - - return tlsClientConfig, nil -} - -func (c *Config) GenerateEnv() []string { - env := make([]string, 0, 10) - - env = append(env, - fmt.Sprintf("%s=%s", HTTPAddrEnvName, c.Address), - fmt.Sprintf("%s=%s", HTTPTokenEnvName, c.Token), - fmt.Sprintf("%s=%s", HTTPTokenFileEnvName, c.TokenFile), - fmt.Sprintf("%s=%t", HTTPSSLEnvName, c.Scheme == "https"), - fmt.Sprintf("%s=%s", HTTPCAFile, c.TLSConfig.CAFile), - fmt.Sprintf("%s=%s", HTTPCAPath, c.TLSConfig.CAPath), - fmt.Sprintf("%s=%s", HTTPClientCert, c.TLSConfig.CertFile), - fmt.Sprintf("%s=%s", HTTPClientKey, c.TLSConfig.KeyFile), - fmt.Sprintf("%s=%s", HTTPTLSServerName, c.TLSConfig.Address), - fmt.Sprintf("%s=%t", HTTPSSLVerifyEnvName, !c.TLSConfig.InsecureSkipVerify)) - - if c.HttpAuth != nil { - env = append(env, fmt.Sprintf("%s=%s:%s", HTTPAuthEnvName, c.HttpAuth.Username, c.HttpAuth.Password)) - } else { - env = append(env, fmt.Sprintf("%s=", HTTPAuthEnvName)) - } - - return env -} - -// 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.Transport == nil { - config.Transport = defConfig.Transport - } - - if config.TLSConfig.Address == "" { - config.TLSConfig.Address = defConfig.TLSConfig.Address - } - - if config.TLSConfig.CAFile == "" { - config.TLSConfig.CAFile = defConfig.TLSConfig.CAFile - } - - if config.TLSConfig.CAPath == "" { - config.TLSConfig.CAPath = defConfig.TLSConfig.CAPath - } - - if config.TLSConfig.CertFile == "" { - config.TLSConfig.CertFile = defConfig.TLSConfig.CertFile - } - - if config.TLSConfig.KeyFile == "" { - config.TLSConfig.KeyFile = defConfig.TLSConfig.KeyFile - } - - if !config.TLSConfig.InsecureSkipVerify { - config.TLSConfig.InsecureSkipVerify = defConfig.TLSConfig.InsecureSkipVerify - } - - if config.HttpClient == nil { - var err error - config.HttpClient, err = NewHttpClient(config.Transport, config.TLSConfig) - if err != nil { - return nil, err - } - } - - parts := strings.SplitN(config.Address, "://", 2) - if len(parts) == 2 { - switch parts[0] { - case "http": - config.Scheme = "http" - case "https": - config.Scheme = "https" - case "unix": - trans := cleanhttp.DefaultTransport() - trans.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", parts[1]) - } - config.HttpClient = &http.Client{ - Transport: trans, - } - default: - return nil, fmt.Errorf("Unknown protocol scheme: %s", parts[0]) - } - config.Address = parts[1] - } - - // If the TokenFile is set, always use that, even if a Token is configured. - // This is because when TokenFile is set it is read into the Token field. - // We want any derived clients to have to re-read the token file. - if config.TokenFile != "" { - data, err := ioutil.ReadFile(config.TokenFile) - if err != nil { - return nil, fmt.Errorf("Error loading token file: %s", err) - } - - if token := strings.TrimSpace(string(data)); token != "" { - config.Token = token - } - } - if config.Token == "" { - config.Token = defConfig.Token - } - - return &Client{config: *config}, nil -} - -// NewHttpClient returns an http client configured with the given Transport and TLS -// config. -func NewHttpClient(transport *http.Transport, tlsConf TLSConfig) (*http.Client, error) { - client := &http.Client{ - Transport: transport, - } - - // TODO (slackpad) - Once we get some run time on the HTTP/2 support we - // should turn it on by default if TLS is enabled. We would basically - // just need to call http2.ConfigureTransport(transport) here. We also - // don't want to introduce another external dependency on - // golang.org/x/net/http2 at this time. For a complete recipe for how - // to enable HTTP/2 support on a transport suitable for the API client - // library see agent/http_test.go:TestHTTPServer_H2. - - if transport.TLSClientConfig == nil { - tlsClientConfig, err := SetupTLSConfig(&tlsConf) - - if err != nil { - return nil, err - } - - transport.TLSClientConfig = tlsClientConfig - } - - 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 - header http.Header - obj interface{} - ctx context.Context -} - -// 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.WaitHash != "" { - r.params.Set("hash", q.WaitHash) - } - if q.Token != "" { - r.header.Set("X-Consul-Token", q.Token) - } - if q.Near != "" { - r.params.Set("near", q.Near) - } - if q.Filter != "" { - r.params.Set("filter", q.Filter) - } - if len(q.NodeMeta) > 0 { - for key, value := range q.NodeMeta { - r.params.Add("node-meta", key+":"+value) - } - } - if q.RelayFactor != 0 { - r.params.Set("relay-factor", strconv.Itoa(int(q.RelayFactor))) - } - if q.Connect { - r.params.Set("connect", "true") - } - if q.UseCache && !q.RequireConsistent { - r.params.Set("cached", "") - - cc := []string{} - if q.MaxAge > 0 { - cc = append(cc, fmt.Sprintf("max-age=%.0f", q.MaxAge.Seconds())) - } - if q.StaleIfError > 0 { - cc = append(cc, fmt.Sprintf("stale-if-error=%.0f", q.StaleIfError.Seconds())) - } - if len(cc) > 0 { - r.header.Set("Cache-Control", strings.Join(cc, ", ")) - } - } - r.ctx = q.ctx -} - -// durToMsec converts a duration to a millisecond specified string. If the -// user selected a positive value that rounds to 0 ms, then we will use 1 ms -// so they get a short delay, otherwise Consul will translate the 0 ms into -// a huge default delay. -func durToMsec(dur time.Duration) string { - ms := dur / time.Millisecond - if dur > 0 && ms == 0 { - ms = 1 - } - return fmt.Sprintf("%dms", ms) -} - -// serverError is a string we look for to detect 500 errors. -const serverError = "Unexpected response code: 500" - -// IsRetryableError returns true for 500 errors from the Consul servers, and -// network connection errors. These are usually retryable at a later time. -// This applies to reads but NOT to writes. This may return true for errors -// on writes that may have still gone through, so do not use this to retry -// any write operations. -func IsRetryableError(err error) bool { - if err == nil { - return false - } - - if _, ok := err.(net.Error); ok { - return true - } - - // TODO (slackpad) - Make a real error type here instead of using - // a string check. - return strings.Contains(err.Error(), serverError) -} - -// 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.header.Set("X-Consul-Token", q.Token) - } - if q.RelayFactor != 0 { - r.params.Set("relay-factor", strconv.Itoa(int(q.RelayFactor))) - } - r.ctx = q.ctx -} - -// 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() - - // Check if we should encode the body - if r.body == nil && r.obj != nil { - b, err := encodeBody(r.obj) - if err != nil { - return nil, err - } - r.body = b - } - - // Create the HTTP request - req, err := http.NewRequest(r.method, r.url.RequestURI(), r.body) - if err != nil { - return nil, err - } - - req.URL.Host = r.url.Host - req.URL.Scheme = r.url.Scheme - req.Host = r.url.Host - req.Header = r.header - - // Setup auth - if r.config.HttpAuth != nil { - req.SetBasicAuth(r.config.HttpAuth.Username, r.config.HttpAuth.Password) - } - if r.ctx != nil { - return req.WithContext(r.ctx), nil - } - - return req, nil -} - -// 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), - header: make(http.Header), - } - 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.header.Set("X-Consul-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.Since(start) - return diff, resp, err -} - -// Query is used to do a GET request against an endpoint -// and deserialize the response into an interface using -// standard Consul conventions. -func (c *Client) query(endpoint string, out interface{}, q *QueryOptions) (*QueryMeta, error) { - r := c.newRequest("GET", endpoint) - r.setQueryOptions(q) - rtt, resp, err := c.doRequest(r) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if err := decodeBody(resp, out); err != nil { - return nil, err - } - return qm, nil -} - -// write is used to do a PUT request against an endpoint -// and serialize/deserialized using the standard Consul conventions. -func (c *Client) write(endpoint string, in, out interface{}, q *WriteOptions) (*WriteMeta, error) { - r := c.newRequest("PUT", endpoint) - r.setWriteOptions(q) - r.obj = in - rtt, resp, err := requireOK(c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - if out != nil { - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - } else if _, err := ioutil.ReadAll(resp.Body); err != nil { - return nil, err - } - return wm, nil -} - -// parseQueryMeta is used to help parse query meta-data -// -// TODO(rb): bug? the error from this function is never handled -func parseQueryMeta(resp *http.Response, q *QueryMeta) error { - header := resp.Header - - // Parse the X-Consul-Index (if it's set - hash based blocking queries don't - // set this) - if indexStr := header.Get("X-Consul-Index"); indexStr != "" { - index, err := strconv.ParseUint(indexStr, 10, 64) - if err != nil { - return fmt.Errorf("Failed to parse X-Consul-Index: %v", err) - } - q.LastIndex = index - } - q.LastContentHash = header.Get("X-Consul-ContentHash") - - // 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 - } - - // Parse X-Consul-Translate-Addresses - switch header.Get("X-Consul-Translate-Addresses") { - case "true": - q.AddressTranslationEnabled = true - default: - q.AddressTranslationEnabled = false - } - - // Parse Cache info - if cacheStr := header.Get("X-Cache"); cacheStr != "" { - q.CacheHit = strings.EqualFold(cacheStr, "HIT") - } - if ageStr := header.Get("Age"); ageStr != "" { - age, err := strconv.ParseUint(ageStr, 10, 64) - if err != nil { - return fmt.Errorf("Failed to parse Age Header: %v", err) - } - q.CacheAge = time.Duration(age) * time.Second - } - - 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 { - if resp != nil { - resp.Body.Close() - } - return d, nil, e - } - if resp.StatusCode != 200 { - return d, nil, generateUnexpectedResponseCodeError(resp) - } - return d, resp, nil -} - -func (req *request) filterQuery(filter string) { - if filter == "" { - return - } - - req.params.Set("filter", filter) -} - -// generateUnexpectedResponseCodeError consumes the rest of the body, closes -// the body stream and generates an error indicating the status code was -// unexpected. -func generateUnexpectedResponseCodeError(resp *http.Response) error { - var buf bytes.Buffer - io.Copy(&buf, resp.Body) - resp.Body.Close() - return fmt.Errorf("Unexpected response code: %d (%s)", resp.StatusCode, buf.Bytes()) -} - -func requireNotFoundOrOK(d time.Duration, resp *http.Response, e error) (bool, time.Duration, *http.Response, error) { - if e != nil { - if resp != nil { - resp.Body.Close() - } - return false, d, nil, e - } - switch resp.StatusCode { - case 200: - return true, d, resp, nil - case 404: - return false, d, resp, nil - default: - return false, d, nil, generateUnexpectedResponseCodeError(resp) - } -} diff --git a/vendor/github.com/hashicorp/consul/api/catalog.go b/vendor/github.com/hashicorp/consul/api/catalog.go deleted file mode 100644 index c175c3fff5..0000000000 --- a/vendor/github.com/hashicorp/consul/api/catalog.go +++ /dev/null @@ -1,244 +0,0 @@ -package api - -type Weights struct { - Passing int - Warning int -} - -type Node struct { - ID string - Node string - Address string - Datacenter string - TaggedAddresses map[string]string - Meta map[string]string - CreateIndex uint64 - ModifyIndex uint64 -} - -type CatalogService struct { - ID string - Node string - Address string - Datacenter string - TaggedAddresses map[string]string - NodeMeta map[string]string - ServiceID string - ServiceName string - ServiceAddress string - ServiceTags []string - ServiceMeta map[string]string - ServicePort int - ServiceWeights Weights - ServiceEnableTagOverride bool - // DEPRECATED (ProxyDestination) - remove the next comment! - // We forgot to ever add ServiceProxyDestination here so no need to deprecate! - ServiceProxy *AgentServiceConnectProxyConfig - CreateIndex uint64 - Checks HealthChecks - ModifyIndex uint64 -} - -type CatalogNode struct { - Node *Node - Services map[string]*AgentService -} - -type CatalogRegistration struct { - ID string - Node string - Address string - TaggedAddresses map[string]string - NodeMeta map[string]string - Datacenter string - Service *AgentService - Check *AgentCheck - Checks HealthChecks - SkipNodeUpdate bool -} - -type CatalogDeregistration struct { - Node string - Address string // Obsolete. - Datacenter string - ServiceID string - CheckID string -} - -// Catalog can be used to query the Catalog endpoints -type Catalog struct { - c *Client -} - -// Catalog returns a handle to the catalog endpoints -func (c *Client) Catalog() *Catalog { - return &Catalog{c} -} - -func (c *Catalog) Register(reg *CatalogRegistration, q *WriteOptions) (*WriteMeta, error) { - r := c.c.newRequest("PUT", "/v1/catalog/register") - r.setWriteOptions(q) - r.obj = reg - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - return wm, nil -} - -func (c *Catalog) Deregister(dereg *CatalogDeregistration, q *WriteOptions) (*WriteMeta, error) { - r := c.c.newRequest("PUT", "/v1/catalog/deregister") - r.setWriteOptions(q) - r.obj = dereg - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - return wm, nil -} - -// Datacenters is used to query for all the known datacenters -func (c *Catalog) Datacenters() ([]string, error) { - r := c.c.newRequest("GET", "/v1/catalog/datacenters") - _, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out []string - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// Nodes is used to query all the known nodes -func (c *Catalog) Nodes(q *QueryOptions) ([]*Node, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/catalog/nodes") - r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out []*Node - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Services is used to query for all known services -func (c *Catalog) Services(q *QueryOptions) (map[string][]string, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/catalog/services") - r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out map[string][]string - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Service is used to query catalog entries for a given service -func (c *Catalog) Service(service, tag string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { - var tags []string - if tag != "" { - tags = []string{tag} - } - return c.service(service, tags, q, false) -} - -// Supports multiple tags for filtering -func (c *Catalog) ServiceMultipleTags(service string, tags []string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { - return c.service(service, tags, q, false) -} - -// Connect is used to query catalog entries for a given Connect-enabled service -func (c *Catalog) Connect(service, tag string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { - var tags []string - if tag != "" { - tags = []string{tag} - } - return c.service(service, tags, q, true) -} - -// Supports multiple tags for filtering -func (c *Catalog) ConnectMultipleTags(service string, tags []string, q *QueryOptions) ([]*CatalogService, *QueryMeta, error) { - return c.service(service, tags, q, true) -} - -func (c *Catalog) service(service string, tags []string, q *QueryOptions, connect bool) ([]*CatalogService, *QueryMeta, error) { - path := "/v1/catalog/service/" + service - if connect { - path = "/v1/catalog/connect/" + service - } - r := c.c.newRequest("GET", path) - r.setQueryOptions(q) - if len(tags) > 0 { - for _, tag := range tags { - r.params.Add("tag", tag) - } - } - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out []*CatalogService - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Node is used to query for service information about a single node -func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/catalog/node/"+node) - r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out *CatalogNode - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/config_entry.go b/vendor/github.com/hashicorp/consul/api/config_entry.go deleted file mode 100644 index 0c18963fd6..0000000000 --- a/vendor/github.com/hashicorp/consul/api/config_entry.go +++ /dev/null @@ -1,255 +0,0 @@ -package api - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "strconv" - "strings" - - "github.com/mitchellh/mapstructure" -) - -const ( - ServiceDefaults string = "service-defaults" - ProxyDefaults string = "proxy-defaults" - ProxyConfigGlobal string = "global" -) - -type ConfigEntry interface { - GetKind() string - GetName() string - GetCreateIndex() uint64 - GetModifyIndex() uint64 -} - -type ServiceConfigEntry struct { - Kind string - Name string - Protocol string - CreateIndex uint64 - ModifyIndex uint64 -} - -func (s *ServiceConfigEntry) GetKind() string { - return s.Kind -} - -func (s *ServiceConfigEntry) GetName() string { - return s.Name -} - -func (s *ServiceConfigEntry) GetCreateIndex() uint64 { - return s.CreateIndex -} - -func (s *ServiceConfigEntry) GetModifyIndex() uint64 { - return s.ModifyIndex -} - -type ProxyConfigEntry struct { - Kind string - Name string - Config map[string]interface{} - CreateIndex uint64 - ModifyIndex uint64 -} - -func (p *ProxyConfigEntry) GetKind() string { - return p.Kind -} - -func (p *ProxyConfigEntry) GetName() string { - return p.Name -} - -func (p *ProxyConfigEntry) GetCreateIndex() uint64 { - return p.CreateIndex -} - -func (p *ProxyConfigEntry) GetModifyIndex() uint64 { - return p.ModifyIndex -} - -type rawEntryListResponse struct { - kind string - Entries []map[string]interface{} -} - -func makeConfigEntry(kind, name string) (ConfigEntry, error) { - switch kind { - case ServiceDefaults: - return &ServiceConfigEntry{Name: name}, nil - case ProxyDefaults: - return &ProxyConfigEntry{Name: name}, nil - default: - return nil, fmt.Errorf("invalid config entry kind: %s", kind) - } -} - -func DecodeConfigEntry(raw map[string]interface{}) (ConfigEntry, error) { - var entry ConfigEntry - - kindVal, ok := raw["Kind"] - if !ok { - kindVal, ok = raw["kind"] - } - if !ok { - return nil, fmt.Errorf("Payload does not contain a kind/Kind key at the top level") - } - - if kindStr, ok := kindVal.(string); ok { - newEntry, err := makeConfigEntry(kindStr, "") - if err != nil { - return nil, err - } - entry = newEntry - } else { - return nil, fmt.Errorf("Kind value in payload is not a string") - } - - decodeConf := &mapstructure.DecoderConfig{ - DecodeHook: mapstructure.StringToTimeDurationHookFunc(), - Result: &entry, - WeaklyTypedInput: true, - } - - decoder, err := mapstructure.NewDecoder(decodeConf) - if err != nil { - return nil, err - } - - return entry, decoder.Decode(raw) -} - -func DecodeConfigEntryFromJSON(data []byte) (ConfigEntry, error) { - var raw map[string]interface{} - if err := json.Unmarshal(data, &raw); err != nil { - return nil, err - } - - return DecodeConfigEntry(raw) -} - -// Config can be used to query the Config endpoints -type ConfigEntries struct { - c *Client -} - -// Config returns a handle to the Config endpoints -func (c *Client) ConfigEntries() *ConfigEntries { - return &ConfigEntries{c} -} - -func (conf *ConfigEntries) Get(kind string, name string, q *QueryOptions) (ConfigEntry, *QueryMeta, error) { - if kind == "" || name == "" { - return nil, nil, fmt.Errorf("Both kind and name parameters must not be empty") - } - - entry, err := makeConfigEntry(kind, name) - if err != nil { - return nil, nil, err - } - - r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s/%s", kind, name)) - r.setQueryOptions(q) - rtt, resp, err := requireOK(conf.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if err := decodeBody(resp, entry); err != nil { - return nil, nil, err - } - - return entry, qm, nil -} - -func (conf *ConfigEntries) List(kind string, q *QueryOptions) ([]ConfigEntry, *QueryMeta, error) { - if kind == "" { - return nil, nil, fmt.Errorf("The kind parameter must not be empty") - } - - r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s", kind)) - r.setQueryOptions(q) - rtt, resp, err := requireOK(conf.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var raw []map[string]interface{} - if err := decodeBody(resp, &raw); err != nil { - return nil, nil, err - } - - var entries []ConfigEntry - for _, rawEntry := range raw { - entry, err := DecodeConfigEntry(rawEntry) - if err != nil { - return nil, nil, err - } - entries = append(entries, entry) - } - - return entries, qm, nil -} - -func (conf *ConfigEntries) Set(entry ConfigEntry, w *WriteOptions) (bool, *WriteMeta, error) { - return conf.set(entry, nil, w) -} - -func (conf *ConfigEntries) CAS(entry ConfigEntry, index uint64, w *WriteOptions) (bool, *WriteMeta, error) { - return conf.set(entry, map[string]string{"cas": strconv.FormatUint(index, 10)}, w) -} - -func (conf *ConfigEntries) set(entry ConfigEntry, params map[string]string, w *WriteOptions) (bool, *WriteMeta, error) { - r := conf.c.newRequest("PUT", "/v1/config") - r.setWriteOptions(w) - for param, value := range params { - r.params.Set(param, value) - } - r.obj = entry - rtt, resp, err := requireOK(conf.c.doRequest(r)) - if err != nil { - return false, nil, err - } - defer resp.Body.Close() - - var buf bytes.Buffer - if _, err := io.Copy(&buf, resp.Body); err != nil { - return false, nil, fmt.Errorf("Failed to read response: %v", err) - } - res := strings.Contains(buf.String(), "true") - - wm := &WriteMeta{RequestTime: rtt} - return res, wm, nil -} - -func (conf *ConfigEntries) Delete(kind string, name string, w *WriteOptions) (*WriteMeta, error) { - if kind == "" || name == "" { - return nil, fmt.Errorf("Both kind and name parameters must not be empty") - } - - r := conf.c.newRequest("DELETE", fmt.Sprintf("/v1/config/%s/%s", kind, name)) - r.setWriteOptions(w) - rtt, resp, err := requireOK(conf.c.doRequest(r)) - if err != nil { - return nil, err - } - resp.Body.Close() - wm := &WriteMeta{RequestTime: rtt} - return wm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/connect.go b/vendor/github.com/hashicorp/consul/api/connect.go deleted file mode 100644 index a40d1e2321..0000000000 --- a/vendor/github.com/hashicorp/consul/api/connect.go +++ /dev/null @@ -1,12 +0,0 @@ -package api - -// Connect can be used to work with endpoints related to Connect, the -// feature for securely connecting services within Consul. -type Connect struct { - c *Client -} - -// Connect returns a handle to the connect-related endpoints -func (c *Client) Connect() *Connect { - return &Connect{c} -} diff --git a/vendor/github.com/hashicorp/consul/api/connect_ca.go b/vendor/github.com/hashicorp/consul/api/connect_ca.go deleted file mode 100644 index 600a3e0dbf..0000000000 --- a/vendor/github.com/hashicorp/consul/api/connect_ca.go +++ /dev/null @@ -1,174 +0,0 @@ -package api - -import ( - "fmt" - "time" - - "github.com/mitchellh/mapstructure" -) - -// CAConfig is the structure for the Connect CA configuration. -type CAConfig struct { - // Provider is the CA provider implementation to use. - Provider string - - // Configuration is arbitrary configuration for the provider. This - // should only contain primitive values and containers (such as lists - // and maps). - Config map[string]interface{} - - CreateIndex uint64 - ModifyIndex uint64 -} - -// CommonCAProviderConfig is the common options available to all CA providers. -type CommonCAProviderConfig struct { - LeafCertTTL time.Duration - SkipValidate bool - CSRMaxPerSecond float32 - CSRMaxConcurrent int -} - -// ConsulCAProviderConfig is the config for the built-in Consul CA provider. -type ConsulCAProviderConfig struct { - CommonCAProviderConfig `mapstructure:",squash"` - - PrivateKey string - RootCert string - RotationPeriod time.Duration -} - -// ParseConsulCAConfig takes a raw config map and returns a parsed -// ConsulCAProviderConfig. -func ParseConsulCAConfig(raw map[string]interface{}) (*ConsulCAProviderConfig, error) { - var config ConsulCAProviderConfig - decodeConf := &mapstructure.DecoderConfig{ - DecodeHook: mapstructure.StringToTimeDurationHookFunc(), - Result: &config, - WeaklyTypedInput: true, - } - - decoder, err := mapstructure.NewDecoder(decodeConf) - if err != nil { - return nil, err - } - - if err := decoder.Decode(raw); err != nil { - return nil, fmt.Errorf("error decoding config: %s", err) - } - - return &config, nil -} - -// CARootList is the structure for the results of listing roots. -type CARootList struct { - ActiveRootID string - TrustDomain string - Roots []*CARoot -} - -// CARoot represents a root CA certificate that is trusted. -type CARoot struct { - // ID is a globally unique ID (UUID) representing this CA root. - ID string - - // Name is a human-friendly name for this CA root. This value is - // opaque to Consul and is not used for anything internally. - Name string - - // RootCertPEM is the PEM-encoded public certificate. - RootCertPEM string `json:"RootCert"` - - // Active is true if this is the current active CA. This must only - // be true for exactly one CA. For any method that modifies roots in the - // state store, tests should be written to verify that multiple roots - // cannot be active. - Active bool - - CreateIndex uint64 - ModifyIndex uint64 -} - -// LeafCert is a certificate that has been issued by a Connect CA. -type LeafCert struct { - // SerialNumber is the unique serial number for this certificate. - // This is encoded in standard hex separated by :. - SerialNumber string - - // CertPEM and PrivateKeyPEM are the PEM-encoded certificate and private - // key for that cert, respectively. This should not be stored in the - // state store, but is present in the sign API response. - CertPEM string `json:",omitempty"` - PrivateKeyPEM string `json:",omitempty"` - - // Service is the name of the service for which the cert was issued. - // ServiceURI is the cert URI value. - Service string - ServiceURI string - - // ValidAfter and ValidBefore are the validity periods for the - // certificate. - ValidAfter time.Time - ValidBefore time.Time - - CreateIndex uint64 - ModifyIndex uint64 -} - -// CARoots queries the list of available roots. -func (h *Connect) CARoots(q *QueryOptions) (*CARootList, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/connect/ca/roots") - r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out CARootList - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, qm, nil -} - -// CAGetConfig returns the current CA configuration. -func (h *Connect) CAGetConfig(q *QueryOptions) (*CAConfig, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/connect/ca/configuration") - r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out CAConfig - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, qm, nil -} - -// CASetConfig sets the current CA configuration. -func (h *Connect) CASetConfig(conf *CAConfig, q *WriteOptions) (*WriteMeta, error) { - r := h.c.newRequest("PUT", "/v1/connect/ca/configuration") - r.setWriteOptions(q) - r.obj = conf - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - return wm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/connect_intention.go b/vendor/github.com/hashicorp/consul/api/connect_intention.go deleted file mode 100644 index a996c03e5e..0000000000 --- a/vendor/github.com/hashicorp/consul/api/connect_intention.go +++ /dev/null @@ -1,302 +0,0 @@ -package api - -import ( - "bytes" - "fmt" - "io" - "time" -) - -// Intention defines an intention for the Connect Service Graph. This defines -// the allowed or denied behavior of a connection between two services using -// Connect. -type Intention struct { - // ID is the UUID-based ID for the intention, always generated by Consul. - ID string - - // Description is a human-friendly description of this intention. - // It is opaque to Consul and is only stored and transferred in API - // requests. - Description string - - // SourceNS, SourceName are the namespace and name, respectively, of - // the source service. Either of these may be the wildcard "*", but only - // the full value can be a wildcard. Partial wildcards are not allowed. - // The source may also be a non-Consul service, as specified by SourceType. - // - // DestinationNS, DestinationName is the same, but for the destination - // service. The same rules apply. The destination is always a Consul - // service. - SourceNS, SourceName string - DestinationNS, DestinationName string - - // SourceType is the type of the value for the source. - SourceType IntentionSourceType - - // Action is whether this is a whitelist or blacklist intention. - Action IntentionAction - - // DefaultAddr, DefaultPort of the local listening proxy (if any) to - // make this connection. - DefaultAddr string - DefaultPort int - - // Meta is arbitrary metadata associated with the intention. This is - // opaque to Consul but is served in API responses. - Meta map[string]string - - // Precedence is the order that the intention will be applied, with - // larger numbers being applied first. This is a read-only field, on - // any intention update it is updated. - Precedence int - - // CreatedAt and UpdatedAt keep track of when this record was created - // or modified. - CreatedAt, UpdatedAt time.Time - - CreateIndex uint64 - ModifyIndex uint64 -} - -// String returns human-friendly output describing ths intention. -func (i *Intention) String() string { - return fmt.Sprintf("%s => %s (%s)", - i.SourceString(), - i.DestinationString(), - i.Action) -} - -// SourceString returns the namespace/name format for the source, or -// just "name" if the namespace is the default namespace. -func (i *Intention) SourceString() string { - return i.partString(i.SourceNS, i.SourceName) -} - -// DestinationString returns the namespace/name format for the source, or -// just "name" if the namespace is the default namespace. -func (i *Intention) DestinationString() string { - return i.partString(i.DestinationNS, i.DestinationName) -} - -func (i *Intention) partString(ns, n string) string { - // For now we omit the default namespace from the output. In the future - // we might want to look at this and show this in a multi-namespace world. - if ns != "" && ns != IntentionDefaultNamespace { - n = ns + "/" + n - } - - return n -} - -// IntentionDefaultNamespace is the default namespace value. -const IntentionDefaultNamespace = "default" - -// IntentionAction is the action that the intention represents. This -// can be "allow" or "deny" to whitelist or blacklist intentions. -type IntentionAction string - -const ( - IntentionActionAllow IntentionAction = "allow" - IntentionActionDeny IntentionAction = "deny" -) - -// IntentionSourceType is the type of the source within an intention. -type IntentionSourceType string - -const ( - // IntentionSourceConsul is a service within the Consul catalog. - IntentionSourceConsul IntentionSourceType = "consul" -) - -// IntentionMatch are the arguments for the intention match API. -type IntentionMatch struct { - By IntentionMatchType - Names []string -} - -// IntentionMatchType is the target for a match request. For example, -// matching by source will look for all intentions that match the given -// source value. -type IntentionMatchType string - -const ( - IntentionMatchSource IntentionMatchType = "source" - IntentionMatchDestination IntentionMatchType = "destination" -) - -// IntentionCheck are the arguments for the intention check API. For -// more documentation see the IntentionCheck function. -type IntentionCheck struct { - // Source and Destination are the source and destination values to - // check. The destination is always a Consul service, but the source - // may be other values as defined by the SourceType. - Source, Destination string - - // SourceType is the type of the value for the source. - SourceType IntentionSourceType -} - -// Intentions returns the list of intentions. -func (h *Connect) Intentions(q *QueryOptions) ([]*Intention, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/connect/intentions") - r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out []*Intention - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// IntentionGet retrieves a single intention. -func (h *Connect) IntentionGet(id string, q *QueryOptions) (*Intention, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/connect/intentions/"+id) - r.setQueryOptions(q) - rtt, resp, err := h.c.doRequest(r) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if resp.StatusCode == 404 { - return nil, qm, nil - } else if resp.StatusCode != 200 { - var buf bytes.Buffer - io.Copy(&buf, resp.Body) - return nil, nil, fmt.Errorf( - "Unexpected response %d: %s", resp.StatusCode, buf.String()) - } - - var out Intention - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return &out, qm, nil -} - -// IntentionDelete deletes a single intention. -func (h *Connect) IntentionDelete(id string, q *WriteOptions) (*WriteMeta, error) { - r := h.c.newRequest("DELETE", "/v1/connect/intentions/"+id) - r.setWriteOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - qm := &WriteMeta{} - qm.RequestTime = rtt - - return qm, nil -} - -// IntentionMatch returns the list of intentions that match a given source -// or destination. The returned intentions are ordered by precedence where -// result[0] is the highest precedence (if that matches, then that rule overrides -// all other rules). -// -// Matching can be done for multiple names at the same time. The resulting -// map is keyed by the given names. Casing is preserved. -func (h *Connect) IntentionMatch(args *IntentionMatch, q *QueryOptions) (map[string][]*Intention, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/connect/intentions/match") - r.setQueryOptions(q) - r.params.Set("by", string(args.By)) - for _, name := range args.Names { - r.params.Add("name", name) - } - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out map[string][]*Intention - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// IntentionCheck returns whether a given source/destination would be allowed -// or not given the current set of intentions and the configuration of Consul. -func (h *Connect) IntentionCheck(args *IntentionCheck, q *QueryOptions) (bool, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/connect/intentions/check") - r.setQueryOptions(q) - r.params.Set("source", args.Source) - r.params.Set("destination", args.Destination) - if args.SourceType != "" { - r.params.Set("source-type", string(args.SourceType)) - } - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return false, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out struct{ Allowed bool } - if err := decodeBody(resp, &out); err != nil { - return false, nil, err - } - return out.Allowed, qm, nil -} - -// IntentionCreate will create a new intention. The ID in the given -// structure must be empty and a generate ID will be returned on -// success. -func (c *Connect) IntentionCreate(ixn *Intention, q *WriteOptions) (string, *WriteMeta, error) { - r := c.c.newRequest("POST", "/v1/connect/intentions") - r.setWriteOptions(q) - r.obj = ixn - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - var out struct{ ID string } - if err := decodeBody(resp, &out); err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// IntentionUpdate will update an existing intention. The ID in the given -// structure must be non-empty. -func (c *Connect) IntentionUpdate(ixn *Intention, q *WriteOptions) (*WriteMeta, error) { - r := c.c.newRequest("PUT", "/v1/connect/intentions/"+ixn.ID) - r.setWriteOptions(q) - r.obj = ixn - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - return wm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/coordinate.go b/vendor/github.com/hashicorp/consul/api/coordinate.go deleted file mode 100644 index 53318f11dd..0000000000 --- a/vendor/github.com/hashicorp/consul/api/coordinate.go +++ /dev/null @@ -1,106 +0,0 @@ -package api - -import ( - "github.com/hashicorp/serf/coordinate" -) - -// CoordinateEntry represents a node and its associated network coordinate. -type CoordinateEntry struct { - Node string - Segment string - Coord *coordinate.Coordinate -} - -// CoordinateDatacenterMap has the coordinates for servers in a given datacenter -// and area. Network coordinates are only compatible within the same area. -type CoordinateDatacenterMap struct { - Datacenter string - AreaID string - Coordinates []CoordinateEntry -} - -// Coordinate can be used to query the coordinate endpoints -type Coordinate struct { - c *Client -} - -// Coordinate returns a handle to the coordinate endpoints -func (c *Client) Coordinate() *Coordinate { - return &Coordinate{c} -} - -// Datacenters is used to return the coordinates of all the servers in the WAN -// pool. -func (c *Coordinate) Datacenters() ([]*CoordinateDatacenterMap, error) { - r := c.c.newRequest("GET", "/v1/coordinate/datacenters") - _, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out []*CoordinateDatacenterMap - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// Nodes is used to return the coordinates of all the nodes in the LAN pool. -func (c *Coordinate) Nodes(q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/coordinate/nodes") - r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out []*CoordinateEntry - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Update inserts or updates the LAN coordinate of a node. -func (c *Coordinate) Update(coord *CoordinateEntry, q *WriteOptions) (*WriteMeta, error) { - r := c.c.newRequest("PUT", "/v1/coordinate/update") - r.setWriteOptions(q) - r.obj = coord - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - return wm, nil -} - -// Node is used to return the coordinates of a single in the LAN pool. -func (c *Coordinate) Node(node string, q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/coordinate/node/"+node) - r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out []*CoordinateEntry - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/debug.go b/vendor/github.com/hashicorp/consul/api/debug.go deleted file mode 100644 index 238046853a..0000000000 --- a/vendor/github.com/hashicorp/consul/api/debug.go +++ /dev/null @@ -1,106 +0,0 @@ -package api - -import ( - "fmt" - "io/ioutil" - "strconv" -) - -// Debug can be used to query the /debug/pprof endpoints to gather -// profiling information about the target agent.Debug -// -// The agent must have enable_debug set to true for profiling to be enabled -// and for these endpoints to function. -type Debug struct { - c *Client -} - -// Debug returns a handle that exposes the internal debug endpoints. -func (c *Client) Debug() *Debug { - return &Debug{c} -} - -// Heap returns a pprof heap dump -func (d *Debug) Heap() ([]byte, error) { - r := d.c.newRequest("GET", "/debug/pprof/heap") - _, resp, err := d.c.doRequest(r) - if err != nil { - return nil, fmt.Errorf("error making request: %s", err) - } - defer resp.Body.Close() - - // We return a raw response because we're just passing through a response - // from the pprof handlers - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("error decoding body: %s", err) - } - - return body, nil -} - -// Profile returns a pprof CPU profile for the specified number of seconds -func (d *Debug) Profile(seconds int) ([]byte, error) { - r := d.c.newRequest("GET", "/debug/pprof/profile") - - // Capture a profile for the specified number of seconds - r.params.Set("seconds", strconv.Itoa(seconds)) - - _, resp, err := d.c.doRequest(r) - if err != nil { - return nil, fmt.Errorf("error making request: %s", err) - } - defer resp.Body.Close() - - // We return a raw response because we're just passing through a response - // from the pprof handlers - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("error decoding body: %s", err) - } - - return body, nil -} - -// Trace returns an execution trace -func (d *Debug) Trace(seconds int) ([]byte, error) { - r := d.c.newRequest("GET", "/debug/pprof/trace") - - // Capture a trace for the specified number of seconds - r.params.Set("seconds", strconv.Itoa(seconds)) - - _, resp, err := d.c.doRequest(r) - if err != nil { - return nil, fmt.Errorf("error making request: %s", err) - } - defer resp.Body.Close() - - // We return a raw response because we're just passing through a response - // from the pprof handlers - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("error decoding body: %s", err) - } - - return body, nil -} - -// Goroutine returns a pprof goroutine profile -func (d *Debug) Goroutine() ([]byte, error) { - r := d.c.newRequest("GET", "/debug/pprof/goroutine") - - _, resp, err := d.c.doRequest(r) - if err != nil { - return nil, fmt.Errorf("error making request: %s", err) - } - defer resp.Body.Close() - - // We return a raw response because we're just passing through a response - // from the pprof handlers - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("error decoding body: %s", err) - } - - return body, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/event.go b/vendor/github.com/hashicorp/consul/api/event.go deleted file mode 100644 index 85b5b069b0..0000000000 --- a/vendor/github.com/hashicorp/consul/api/event.go +++ /dev/null @@ -1,104 +0,0 @@ -package api - -import ( - "bytes" - "strconv" -) - -// Event can be used to query the Event endpoints -type Event struct { - c *Client -} - -// UserEvent represents an event that was fired by the user -type UserEvent struct { - ID string - Name string - Payload []byte - NodeFilter string - ServiceFilter string - TagFilter string - Version int - LTime uint64 -} - -// Event returns a handle to the event endpoints -func (c *Client) Event() *Event { - return &Event{c} -} - -// Fire is used to fire a new user event. Only the Name, Payload and Filters -// are respected. This returns the ID or an associated error. Cross DC requests -// are supported. -func (e *Event) Fire(params *UserEvent, q *WriteOptions) (string, *WriteMeta, error) { - r := e.c.newRequest("PUT", "/v1/event/fire/"+params.Name) - r.setWriteOptions(q) - if params.NodeFilter != "" { - r.params.Set("node", params.NodeFilter) - } - if params.ServiceFilter != "" { - r.params.Set("service", params.ServiceFilter) - } - if params.TagFilter != "" { - r.params.Set("tag", params.TagFilter) - } - if params.Payload != nil { - r.body = bytes.NewReader(params.Payload) - } - - rtt, resp, err := requireOK(e.c.doRequest(r)) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - var out UserEvent - if err := decodeBody(resp, &out); err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// List is used to get the most recent events an agent has received. -// This list can be optionally filtered by the name. This endpoint supports -// quasi-blocking queries. The index is not monotonic, nor does it provide provide -// LastContact or KnownLeader. -func (e *Event) List(name string, q *QueryOptions) ([]*UserEvent, *QueryMeta, error) { - r := e.c.newRequest("GET", "/v1/event/list") - r.setQueryOptions(q) - if name != "" { - r.params.Set("name", name) - } - rtt, resp, err := requireOK(e.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var entries []*UserEvent - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// IDToIndex is a bit of a hack. This simulates the index generation to -// convert an event ID into a WaitIndex. -func (e *Event) IDToIndex(uuid string) uint64 { - lower := uuid[0:8] + uuid[9:13] + uuid[14:18] - upper := uuid[19:23] + uuid[24:36] - lowVal, err := strconv.ParseUint(lower, 16, 64) - if err != nil { - panic("Failed to convert " + lower) - } - highVal, err := strconv.ParseUint(upper, 16, 64) - if err != nil { - panic("Failed to convert " + upper) - } - return lowVal ^ highVal -} diff --git a/vendor/github.com/hashicorp/consul/api/go.mod b/vendor/github.com/hashicorp/consul/api/go.mod deleted file mode 100644 index e198218915..0000000000 --- a/vendor/github.com/hashicorp/consul/api/go.mod +++ /dev/null @@ -1,16 +0,0 @@ -module github.com/hashicorp/consul/api - -go 1.12 - -replace github.com/hashicorp/consul/sdk => ../sdk - -require ( - github.com/hashicorp/consul/sdk v0.1.1 - github.com/hashicorp/go-cleanhttp v0.5.1 - github.com/hashicorp/go-rootcerts v1.0.0 - github.com/hashicorp/go-uuid v1.0.1 - github.com/hashicorp/serf v0.8.2 - github.com/mitchellh/mapstructure v1.1.2 - github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c - github.com/stretchr/testify v1.3.0 -) diff --git a/vendor/github.com/hashicorp/consul/api/go.sum b/vendor/github.com/hashicorp/consul/api/go.sum deleted file mode 100644 index 372ebc1416..0000000000 --- a/vendor/github.com/hashicorp/consul/api/go.sum +++ /dev/null @@ -1,76 +0,0 @@ -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 h1:x6r4Jo0KNzOOzYd8lbcRsqjuqEASK6ob3auvWYM4/8U= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/hashicorp/consul/api/health.go b/vendor/github.com/hashicorp/consul/api/health.go deleted file mode 100644 index 9faf6b665a..0000000000 --- a/vendor/github.com/hashicorp/consul/api/health.go +++ /dev/null @@ -1,330 +0,0 @@ -package api - -import ( - "encoding/json" - "fmt" - "strings" - "time" -) - -const ( - // HealthAny is special, and is used as a wild card, - // not as a specific state. - HealthAny = "any" - HealthPassing = "passing" - HealthWarning = "warning" - HealthCritical = "critical" - HealthMaint = "maintenance" -) - -const ( - // NodeMaint is the special key set by a node in maintenance mode. - NodeMaint = "_node_maintenance" - - // ServiceMaintPrefix is the prefix for a service in maintenance mode. - ServiceMaintPrefix = "_service_maintenance:" -) - -// HealthCheck is used to represent a single check -type HealthCheck struct { - Node string - CheckID string - Name string - Status string - Notes string - Output string - ServiceID string - ServiceName string - ServiceTags []string - - Definition HealthCheckDefinition - - CreateIndex uint64 - ModifyIndex uint64 -} - -// HealthCheckDefinition is used to store the details about -// a health check's execution. -type HealthCheckDefinition struct { - HTTP string - Header map[string][]string - Method string - TLSSkipVerify bool - TCP string - IntervalDuration time.Duration `json:"-"` - TimeoutDuration time.Duration `json:"-"` - DeregisterCriticalServiceAfterDuration time.Duration `json:"-"` - - // DEPRECATED in Consul 1.4.1. Use the above time.Duration fields instead. - Interval ReadableDuration - Timeout ReadableDuration - DeregisterCriticalServiceAfter ReadableDuration -} - -func (d *HealthCheckDefinition) MarshalJSON() ([]byte, error) { - type Alias HealthCheckDefinition - out := &struct { - Interval string - Timeout string - DeregisterCriticalServiceAfter string - *Alias - }{ - Interval: d.Interval.String(), - Timeout: d.Timeout.String(), - DeregisterCriticalServiceAfter: d.DeregisterCriticalServiceAfter.String(), - Alias: (*Alias)(d), - } - - if d.IntervalDuration != 0 { - out.Interval = d.IntervalDuration.String() - } else if d.Interval != 0 { - out.Interval = d.Interval.String() - } - if d.TimeoutDuration != 0 { - out.Timeout = d.TimeoutDuration.String() - } else if d.Timeout != 0 { - out.Timeout = d.Timeout.String() - } - if d.DeregisterCriticalServiceAfterDuration != 0 { - out.DeregisterCriticalServiceAfter = d.DeregisterCriticalServiceAfterDuration.String() - } else if d.DeregisterCriticalServiceAfter != 0 { - out.DeregisterCriticalServiceAfter = d.DeregisterCriticalServiceAfter.String() - } - - return json.Marshal(out) -} - -func (d *HealthCheckDefinition) UnmarshalJSON(data []byte) error { - type Alias HealthCheckDefinition - aux := &struct { - Interval string - Timeout string - DeregisterCriticalServiceAfter string - *Alias - }{ - Alias: (*Alias)(d), - } - if err := json.Unmarshal(data, &aux); err != nil { - return err - } - - // Parse the values into both the time.Duration and old ReadableDuration fields. - var err error - if aux.Interval != "" { - if d.IntervalDuration, err = time.ParseDuration(aux.Interval); err != nil { - return err - } - d.Interval = ReadableDuration(d.IntervalDuration) - } - if aux.Timeout != "" { - if d.TimeoutDuration, err = time.ParseDuration(aux.Timeout); err != nil { - return err - } - d.Timeout = ReadableDuration(d.TimeoutDuration) - } - if aux.DeregisterCriticalServiceAfter != "" { - if d.DeregisterCriticalServiceAfterDuration, err = time.ParseDuration(aux.DeregisterCriticalServiceAfter); err != nil { - return err - } - d.DeregisterCriticalServiceAfter = ReadableDuration(d.DeregisterCriticalServiceAfterDuration) - } - return nil -} - -// HealthChecks is a collection of HealthCheck structs. -type HealthChecks []*HealthCheck - -// AggregatedStatus returns the "best" status for the list of health checks. -// Because a given entry may have many service and node-level health checks -// attached, this function determines the best representative of the status as -// as single string using the following heuristic: -// -// maintenance > critical > warning > passing -// -func (c HealthChecks) AggregatedStatus() string { - var passing, warning, critical, maintenance bool - for _, check := range c { - id := string(check.CheckID) - if id == NodeMaint || strings.HasPrefix(id, ServiceMaintPrefix) { - maintenance = true - continue - } - - switch check.Status { - case HealthPassing: - passing = true - case HealthWarning: - warning = true - case HealthCritical: - critical = true - default: - return "" - } - } - - switch { - case maintenance: - return HealthMaint - case critical: - return HealthCritical - case warning: - return HealthWarning - case passing: - return HealthPassing - default: - return HealthPassing - } -} - -// ServiceEntry is used for the health service endpoint -type ServiceEntry struct { - Node *Node - Service *AgentService - Checks HealthChecks -} - -// Health can be used to query the Health endpoints -type Health struct { - c *Client -} - -// Health returns a handle to the health endpoints -func (c *Client) Health() *Health { - return &Health{c} -} - -// Node is used to query for checks belonging to a given node -func (h *Health) Node(node string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/health/node/"+node) - r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out HealthChecks - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Checks is used to return the checks associated with a service -func (h *Health) Checks(service string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { - r := h.c.newRequest("GET", "/v1/health/checks/"+service) - r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out HealthChecks - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Service is used to query health information along with service info -// for a given service. It can optionally do server-side filtering on a tag -// or nodes with passing health checks only. -func (h *Health) Service(service, tag string, passingOnly bool, q *QueryOptions) ([]*ServiceEntry, *QueryMeta, error) { - var tags []string - if tag != "" { - tags = []string{tag} - } - return h.service(service, tags, passingOnly, q, false) -} - -func (h *Health) ServiceMultipleTags(service string, tags []string, passingOnly bool, q *QueryOptions) ([]*ServiceEntry, *QueryMeta, error) { - return h.service(service, tags, passingOnly, q, false) -} - -// Connect is equivalent to Service except that it will only return services -// which are Connect-enabled and will returns the connection address for Connect -// client's to use which may be a proxy in front of the named service. If -// passingOnly is true only instances where both the service and any proxy are -// healthy will be returned. -func (h *Health) Connect(service, tag string, passingOnly bool, q *QueryOptions) ([]*ServiceEntry, *QueryMeta, error) { - var tags []string - if tag != "" { - tags = []string{tag} - } - return h.service(service, tags, passingOnly, q, true) -} - -func (h *Health) ConnectMultipleTags(service string, tags []string, passingOnly bool, q *QueryOptions) ([]*ServiceEntry, *QueryMeta, error) { - return h.service(service, tags, passingOnly, q, true) -} - -func (h *Health) service(service string, tags []string, passingOnly bool, q *QueryOptions, connect bool) ([]*ServiceEntry, *QueryMeta, error) { - path := "/v1/health/service/" + service - if connect { - path = "/v1/health/connect/" + service - } - r := h.c.newRequest("GET", path) - r.setQueryOptions(q) - if len(tags) > 0 { - for _, tag := range tags { - r.params.Add("tag", tag) - } - } - if passingOnly { - r.params.Set(HealthPassing, "1") - } - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out []*ServiceEntry - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// State is used to retrieve all the checks in a given state. -// The wildcard "any" state can also be used for all checks. -func (h *Health) State(state string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { - switch state { - case HealthAny: - case HealthWarning: - case HealthCritical: - case HealthPassing: - default: - return nil, nil, fmt.Errorf("Unsupported state: %v", state) - } - r := h.c.newRequest("GET", "/v1/health/state/"+state) - r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - var out HealthChecks - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/kv.go b/vendor/github.com/hashicorp/consul/api/kv.go deleted file mode 100644 index bd45a067c9..0000000000 --- a/vendor/github.com/hashicorp/consul/api/kv.go +++ /dev/null @@ -1,286 +0,0 @@ -package api - -import ( - "bytes" - "fmt" - "io" - "net/http" - "strconv" - "strings" -) - -// KVPair is used to represent a single K/V entry -type KVPair struct { - // Key is the name of the key. It is also part of the URL path when accessed - // via the API. - Key string - - // CreateIndex holds the index corresponding the creation of this KVPair. This - // is a read-only field. - CreateIndex uint64 - - // ModifyIndex is used for the Check-And-Set operations and can also be fed - // back into the WaitIndex of the QueryOptions in order to perform blocking - // queries. - ModifyIndex uint64 - - // LockIndex holds the index corresponding to a lock on this key, if any. This - // is a read-only field. - LockIndex uint64 - - // Flags are any user-defined flags on the key. It is up to the implementer - // to check these values, since Consul does not treat them specially. - Flags uint64 - - // Value is the value for the key. This can be any value, but it will be - // base64 encoded upon transport. - Value []byte - - // Session is a string representing the ID of the session. Any other - // interactions with this key over the same session must specify the same - // session ID. - Session string -} - -// KVPairs is a list of KVPair objects -type KVPairs []*KVPair - -// KV is used to manipulate the K/V API -type KV struct { - c *Client -} - -// KV is used to return a handle to the K/V apis -func (c *Client) KV() *KV { - return &KV{c} -} - -// Get is used to lookup a single key. The returned pointer -// to the KVPair will be nil if the key does not exist. -func (k *KV) Get(key string, q *QueryOptions) (*KVPair, *QueryMeta, error) { - resp, qm, err := k.getInternal(key, nil, q) - if err != nil { - return nil, nil, err - } - if resp == nil { - return nil, qm, nil - } - defer resp.Body.Close() - - var entries []*KVPair - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - if len(entries) > 0 { - return entries[0], qm, nil - } - return nil, qm, nil -} - -// List is used to lookup all keys under a prefix -func (k *KV) List(prefix string, q *QueryOptions) (KVPairs, *QueryMeta, error) { - resp, qm, err := k.getInternal(prefix, map[string]string{"recurse": ""}, q) - if err != nil { - return nil, nil, err - } - if resp == nil { - return nil, qm, nil - } - defer resp.Body.Close() - - var entries []*KVPair - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// Keys is used to list all the keys under a prefix. Optionally, -// a separator can be used to limit the responses. -func (k *KV) Keys(prefix, separator string, q *QueryOptions) ([]string, *QueryMeta, error) { - params := map[string]string{"keys": ""} - if separator != "" { - params["separator"] = separator - } - resp, qm, err := k.getInternal(prefix, params, q) - if err != nil { - return nil, nil, err - } - if resp == nil { - return nil, qm, nil - } - defer resp.Body.Close() - - var entries []string - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -func (k *KV) getInternal(key string, params map[string]string, q *QueryOptions) (*http.Response, *QueryMeta, error) { - r := k.c.newRequest("GET", "/v1/kv/"+strings.TrimPrefix(key, "/")) - r.setQueryOptions(q) - for param, val := range params { - r.params.Set(param, val) - } - rtt, resp, err := k.c.doRequest(r) - if err != nil { - return nil, nil, err - } - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if resp.StatusCode == 404 { - resp.Body.Close() - return nil, qm, nil - } else if resp.StatusCode != 200 { - resp.Body.Close() - return nil, nil, fmt.Errorf("Unexpected response code: %d", resp.StatusCode) - } - return resp, qm, nil -} - -// Put is used to write a new value. Only the -// Key, Flags and Value is respected. -func (k *KV) Put(p *KVPair, q *WriteOptions) (*WriteMeta, error) { - params := make(map[string]string, 1) - if p.Flags != 0 { - params["flags"] = strconv.FormatUint(p.Flags, 10) - } - _, wm, err := k.put(p.Key, params, p.Value, q) - return wm, err -} - -// CAS is used for a Check-And-Set operation. The Key, -// ModifyIndex, Flags and Value are respected. Returns true -// on success or false on failures. -func (k *KV) CAS(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) { - params := make(map[string]string, 2) - if p.Flags != 0 { - params["flags"] = strconv.FormatUint(p.Flags, 10) - } - params["cas"] = strconv.FormatUint(p.ModifyIndex, 10) - return k.put(p.Key, params, p.Value, q) -} - -// Acquire is used for a lock acquisition operation. The Key, -// Flags, Value and Session are respected. Returns true -// on success or false on failures. -func (k *KV) Acquire(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) { - params := make(map[string]string, 2) - if p.Flags != 0 { - params["flags"] = strconv.FormatUint(p.Flags, 10) - } - params["acquire"] = p.Session - return k.put(p.Key, params, p.Value, q) -} - -// Release is used for a lock release operation. The Key, -// Flags, Value and Session are respected. Returns true -// on success or false on failures. -func (k *KV) Release(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) { - params := make(map[string]string, 2) - if p.Flags != 0 { - params["flags"] = strconv.FormatUint(p.Flags, 10) - } - params["release"] = p.Session - return k.put(p.Key, params, p.Value, q) -} - -func (k *KV) put(key string, params map[string]string, body []byte, q *WriteOptions) (bool, *WriteMeta, error) { - if len(key) > 0 && key[0] == '/' { - return false, nil, fmt.Errorf("Invalid key. Key must not begin with a '/': %s", key) - } - - r := k.c.newRequest("PUT", "/v1/kv/"+key) - r.setWriteOptions(q) - for param, val := range params { - r.params.Set(param, val) - } - r.body = bytes.NewReader(body) - rtt, resp, err := requireOK(k.c.doRequest(r)) - if err != nil { - return false, nil, err - } - defer resp.Body.Close() - - qm := &WriteMeta{} - qm.RequestTime = rtt - - var buf bytes.Buffer - if _, err := io.Copy(&buf, resp.Body); err != nil { - return false, nil, fmt.Errorf("Failed to read response: %v", err) - } - res := strings.Contains(buf.String(), "true") - return res, qm, nil -} - -// Delete is used to delete a single key -func (k *KV) Delete(key string, w *WriteOptions) (*WriteMeta, error) { - _, qm, err := k.deleteInternal(key, nil, w) - return qm, err -} - -// DeleteCAS is used for a Delete Check-And-Set operation. The Key -// and ModifyIndex are respected. Returns true on success or false on failures. -func (k *KV) DeleteCAS(p *KVPair, q *WriteOptions) (bool, *WriteMeta, error) { - params := map[string]string{ - "cas": strconv.FormatUint(p.ModifyIndex, 10), - } - return k.deleteInternal(p.Key, params, q) -} - -// DeleteTree is used to delete all keys under a prefix -func (k *KV) DeleteTree(prefix string, w *WriteOptions) (*WriteMeta, error) { - _, qm, err := k.deleteInternal(prefix, map[string]string{"recurse": ""}, w) - return qm, err -} - -func (k *KV) deleteInternal(key string, params map[string]string, q *WriteOptions) (bool, *WriteMeta, error) { - r := k.c.newRequest("DELETE", "/v1/kv/"+strings.TrimPrefix(key, "/")) - r.setWriteOptions(q) - for param, val := range params { - r.params.Set(param, val) - } - rtt, resp, err := requireOK(k.c.doRequest(r)) - if err != nil { - return false, nil, err - } - defer resp.Body.Close() - - qm := &WriteMeta{} - qm.RequestTime = rtt - - var buf bytes.Buffer - if _, err := io.Copy(&buf, resp.Body); err != nil { - return false, nil, fmt.Errorf("Failed to read response: %v", err) - } - res := strings.Contains(buf.String(), "true") - return res, qm, nil -} - -// The Txn function has been deprecated from the KV object; please see the Txn -// object for more information about Transactions. -func (k *KV) Txn(txn KVTxnOps, q *QueryOptions) (bool, *KVTxnResponse, *QueryMeta, error) { - var ops TxnOps - for _, op := range txn { - ops = append(ops, &TxnOp{KV: op}) - } - - respOk, txnResp, qm, err := k.c.txn(ops, q) - if err != nil { - return false, nil, nil, err - } - - // Convert from the internal format. - kvResp := KVTxnResponse{ - Errors: txnResp.Errors, - } - for _, result := range txnResp.Results { - kvResp.Results = append(kvResp.Results, result.KV) - } - return respOk, &kvResp, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/lock.go b/vendor/github.com/hashicorp/consul/api/lock.go deleted file mode 100644 index 82339cb744..0000000000 --- a/vendor/github.com/hashicorp/consul/api/lock.go +++ /dev/null @@ -1,386 +0,0 @@ -package api - -import ( - "fmt" - "sync" - "time" -) - -const ( - // DefaultLockSessionName is the Session Name we assign if none is provided - DefaultLockSessionName = "Consul API Lock" - - // DefaultLockSessionTTL is the default session TTL if no Session is provided - // when creating a new Lock. This is used because we do not have another - // other check to depend upon. - DefaultLockSessionTTL = "15s" - - // DefaultLockWaitTime is how long we block for at a time to check if lock - // acquisition is possible. This affects the minimum time it takes to cancel - // a Lock acquisition. - DefaultLockWaitTime = 15 * time.Second - - // DefaultLockRetryTime is how long we wait after a failed lock acquisition - // before attempting to do the lock again. This is so that once a lock-delay - // is in effect, we do not hot loop retrying the acquisition. - DefaultLockRetryTime = 5 * time.Second - - // DefaultMonitorRetryTime is how long we wait after a failed monitor check - // of a lock (500 response code). This allows the monitor to ride out brief - // periods of unavailability, subject to the MonitorRetries setting in the - // lock options which is by default set to 0, disabling this feature. This - // affects locks and semaphores. - DefaultMonitorRetryTime = 2 * time.Second - - // LockFlagValue is a magic flag we set to indicate a key - // is being used for a lock. It is used to detect a potential - // conflict with a semaphore. - LockFlagValue = 0x2ddccbc058a50c18 -) - -var ( - // ErrLockHeld is returned if we attempt to double lock - ErrLockHeld = fmt.Errorf("Lock already held") - - // ErrLockNotHeld is returned if we attempt to unlock a lock - // that we do not hold. - ErrLockNotHeld = fmt.Errorf("Lock not held") - - // ErrLockInUse is returned if we attempt to destroy a lock - // that is in use. - ErrLockInUse = fmt.Errorf("Lock in use") - - // ErrLockConflict is returned if the flags on a key - // used for a lock do not match expectation - ErrLockConflict = fmt.Errorf("Existing key does not match lock use") -) - -// Lock is used to implement client-side leader election. It is follows the -// algorithm as described here: https://www.consul.io/docs/guides/leader-election.html. -type Lock struct { - c *Client - opts *LockOptions - - isHeld bool - sessionRenew chan struct{} - lockSession string - l sync.Mutex -} - -// LockOptions is used to parameterize the Lock behavior. -type LockOptions struct { - Key string // Must be set and have write permissions - Value []byte // Optional, value to associate with the lock - Session string // Optional, created if not specified - SessionOpts *SessionEntry // Optional, options to use when creating a session - SessionName string // Optional, defaults to DefaultLockSessionName (ignored if SessionOpts is given) - SessionTTL string // Optional, defaults to DefaultLockSessionTTL (ignored if SessionOpts is given) - MonitorRetries int // Optional, defaults to 0 which means no retries - MonitorRetryTime time.Duration // Optional, defaults to DefaultMonitorRetryTime - LockWaitTime time.Duration // Optional, defaults to DefaultLockWaitTime - LockTryOnce bool // Optional, defaults to false which means try forever -} - -// LockKey returns a handle to a lock struct which can be used -// to acquire and release the mutex. The key used must have -// write permissions. -func (c *Client) LockKey(key string) (*Lock, error) { - opts := &LockOptions{ - Key: key, - } - return c.LockOpts(opts) -} - -// LockOpts returns a handle to a lock struct which can be used -// to acquire and release the mutex. The key used must have -// write permissions. -func (c *Client) LockOpts(opts *LockOptions) (*Lock, error) { - if opts.Key == "" { - return nil, fmt.Errorf("missing key") - } - if opts.SessionName == "" { - opts.SessionName = DefaultLockSessionName - } - if opts.SessionTTL == "" { - opts.SessionTTL = DefaultLockSessionTTL - } else { - if _, err := time.ParseDuration(opts.SessionTTL); err != nil { - return nil, fmt.Errorf("invalid SessionTTL: %v", err) - } - } - if opts.MonitorRetryTime == 0 { - opts.MonitorRetryTime = DefaultMonitorRetryTime - } - if opts.LockWaitTime == 0 { - opts.LockWaitTime = DefaultLockWaitTime - } - l := &Lock{ - c: c, - opts: opts, - } - return l, nil -} - -// Lock attempts to acquire the lock and blocks while doing so. -// Providing a non-nil stopCh can be used to abort the lock attempt. -// Returns a channel that is closed if our lock is lost or an error. -// This channel could be closed at any time due to session invalidation, -// communication errors, operator intervention, etc. It is NOT safe to -// assume that the lock is held until Unlock() unless the Session is specifically -// created without any associated health checks. By default Consul sessions -// prefer liveness over safety and an application must be able to handle -// the lock being lost. -func (l *Lock) Lock(stopCh <-chan struct{}) (<-chan struct{}, error) { - // Hold the lock as we try to acquire - l.l.Lock() - defer l.l.Unlock() - - // Check if we already hold the lock - if l.isHeld { - return nil, ErrLockHeld - } - - // Check if we need to create a session first - l.lockSession = l.opts.Session - if l.lockSession == "" { - s, err := l.createSession() - if err != nil { - return nil, fmt.Errorf("failed to create session: %v", err) - } - - l.sessionRenew = make(chan struct{}) - l.lockSession = s - session := l.c.Session() - go session.RenewPeriodic(l.opts.SessionTTL, s, nil, l.sessionRenew) - - // If we fail to acquire the lock, cleanup the session - defer func() { - if !l.isHeld { - close(l.sessionRenew) - l.sessionRenew = nil - } - }() - } - - // Setup the query options - kv := l.c.KV() - qOpts := &QueryOptions{ - WaitTime: l.opts.LockWaitTime, - } - - start := time.Now() - attempts := 0 -WAIT: - // Check if we should quit - select { - case <-stopCh: - return nil, nil - default: - } - - // Handle the one-shot mode. - if l.opts.LockTryOnce && attempts > 0 { - elapsed := time.Since(start) - if elapsed > l.opts.LockWaitTime { - return nil, nil - } - - // Query wait time should not exceed the lock wait time - qOpts.WaitTime = l.opts.LockWaitTime - elapsed - } - attempts++ - - // Look for an existing lock, blocking until not taken - pair, meta, err := kv.Get(l.opts.Key, qOpts) - if err != nil { - return nil, fmt.Errorf("failed to read lock: %v", err) - } - if pair != nil && pair.Flags != LockFlagValue { - return nil, ErrLockConflict - } - locked := false - if pair != nil && pair.Session == l.lockSession { - goto HELD - } - if pair != nil && pair.Session != "" { - qOpts.WaitIndex = meta.LastIndex - goto WAIT - } - - // Try to acquire the lock - pair = l.lockEntry(l.lockSession) - locked, _, err = kv.Acquire(pair, nil) - if err != nil { - return nil, fmt.Errorf("failed to acquire lock: %v", err) - } - - // Handle the case of not getting the lock - if !locked { - // Determine why the lock failed - qOpts.WaitIndex = 0 - pair, meta, err = kv.Get(l.opts.Key, qOpts) - if pair != nil && pair.Session != "" { - //If the session is not null, this means that a wait can safely happen - //using a long poll - qOpts.WaitIndex = meta.LastIndex - goto WAIT - } else { - // If the session is empty and the lock failed to acquire, then it means - // a lock-delay is in effect and a timed wait must be used - select { - case <-time.After(DefaultLockRetryTime): - goto WAIT - case <-stopCh: - return nil, nil - } - } - } - -HELD: - // Watch to ensure we maintain leadership - leaderCh := make(chan struct{}) - go l.monitorLock(l.lockSession, leaderCh) - - // Set that we own the lock - l.isHeld = true - - // Locked! All done - return leaderCh, nil -} - -// Unlock released the lock. It is an error to call this -// if the lock is not currently held. -func (l *Lock) Unlock() error { - // Hold the lock as we try to release - l.l.Lock() - defer l.l.Unlock() - - // Ensure the lock is actually held - if !l.isHeld { - return ErrLockNotHeld - } - - // Set that we no longer own the lock - l.isHeld = false - - // Stop the session renew - if l.sessionRenew != nil { - defer func() { - close(l.sessionRenew) - l.sessionRenew = nil - }() - } - - // Get the lock entry, and clear the lock session - lockEnt := l.lockEntry(l.lockSession) - l.lockSession = "" - - // Release the lock explicitly - kv := l.c.KV() - _, _, err := kv.Release(lockEnt, nil) - if err != nil { - return fmt.Errorf("failed to release lock: %v", err) - } - return nil -} - -// Destroy is used to cleanup the lock entry. It is not necessary -// to invoke. It will fail if the lock is in use. -func (l *Lock) Destroy() error { - // Hold the lock as we try to release - l.l.Lock() - defer l.l.Unlock() - - // Check if we already hold the lock - if l.isHeld { - return ErrLockHeld - } - - // Look for an existing lock - kv := l.c.KV() - pair, _, err := kv.Get(l.opts.Key, nil) - if err != nil { - return fmt.Errorf("failed to read lock: %v", err) - } - - // Nothing to do if the lock does not exist - if pair == nil { - return nil - } - - // Check for possible flag conflict - if pair.Flags != LockFlagValue { - return ErrLockConflict - } - - // Check if it is in use - if pair.Session != "" { - return ErrLockInUse - } - - // Attempt the delete - didRemove, _, err := kv.DeleteCAS(pair, nil) - if err != nil { - return fmt.Errorf("failed to remove lock: %v", err) - } - if !didRemove { - return ErrLockInUse - } - return nil -} - -// createSession is used to create a new managed session -func (l *Lock) createSession() (string, error) { - session := l.c.Session() - se := l.opts.SessionOpts - if se == nil { - se = &SessionEntry{ - Name: l.opts.SessionName, - TTL: l.opts.SessionTTL, - } - } - id, _, err := session.Create(se, nil) - if err != nil { - return "", err - } - return id, nil -} - -// lockEntry returns a formatted KVPair for the lock -func (l *Lock) lockEntry(session string) *KVPair { - return &KVPair{ - Key: l.opts.Key, - Value: l.opts.Value, - Session: session, - Flags: LockFlagValue, - } -} - -// monitorLock is a long running routine to monitor a lock ownership -// It closes the stopCh if we lose our leadership. -func (l *Lock) monitorLock(session string, stopCh chan struct{}) { - defer close(stopCh) - kv := l.c.KV() - opts := &QueryOptions{RequireConsistent: true} -WAIT: - retries := l.opts.MonitorRetries -RETRY: - pair, meta, err := kv.Get(l.opts.Key, opts) - if err != nil { - // If configured we can try to ride out a brief Consul unavailability - // by doing retries. Note that we have to attempt the retry in a non- - // blocking fashion so that we have a clean place to reset the retry - // counter if service is restored. - if retries > 0 && IsRetryableError(err) { - time.Sleep(l.opts.MonitorRetryTime) - retries-- - opts.WaitIndex = 0 - goto RETRY - } - return - } - if pair != nil && pair.Session == session { - opts.WaitIndex = meta.LastIndex - goto WAIT - } -} diff --git a/vendor/github.com/hashicorp/consul/api/operator.go b/vendor/github.com/hashicorp/consul/api/operator.go deleted file mode 100644 index 079e224866..0000000000 --- a/vendor/github.com/hashicorp/consul/api/operator.go +++ /dev/null @@ -1,11 +0,0 @@ -package api - -// Operator can be used to perform low-level operator tasks for Consul. -type Operator struct { - c *Client -} - -// Operator returns a handle to the operator endpoints. -func (c *Client) Operator() *Operator { - return &Operator{c} -} diff --git a/vendor/github.com/hashicorp/consul/api/operator_area.go b/vendor/github.com/hashicorp/consul/api/operator_area.go deleted file mode 100644 index 5cf7e49730..0000000000 --- a/vendor/github.com/hashicorp/consul/api/operator_area.go +++ /dev/null @@ -1,194 +0,0 @@ -package api - -// The /v1/operator/area endpoints are available only in Consul Enterprise and -// interact with its network area subsystem. Network areas are used to link -// together Consul servers in different Consul datacenters. With network areas, -// Consul datacenters can be linked together in ways other than a fully-connected -// mesh, as is required for Consul's WAN. - -import ( - "net" - "time" -) - -// Area defines a network area. -type Area struct { - // ID is this identifier for an area (a UUID). This must be left empty - // when creating a new area. - ID string - - // PeerDatacenter is the peer Consul datacenter that will make up the - // other side of this network area. Network areas always involve a pair - // of datacenters: the datacenter where the area was created, and the - // peer datacenter. This is required. - PeerDatacenter string - - // RetryJoin specifies the address of Consul servers to join to, such as - // an IPs or hostnames with an optional port number. This is optional. - RetryJoin []string - - // UseTLS specifies whether gossip over this area should be encrypted with TLS - // if possible. - UseTLS bool -} - -// AreaJoinResponse is returned when a join occurs and gives the result for each -// address. -type AreaJoinResponse struct { - // The address that was joined. - Address string - - // Whether or not the join was a success. - Joined bool - - // If we couldn't join, this is the message with information. - Error string -} - -// SerfMember is a generic structure for reporting information about members in -// a Serf cluster. This is only used by the area endpoints right now, but this -// could be expanded to other endpoints in the future. -type SerfMember struct { - // ID is the node identifier (a UUID). - ID string - - // Name is the node name. - Name string - - // Addr has the IP address. - Addr net.IP - - // Port is the RPC port. - Port uint16 - - // Datacenter is the DC name. - Datacenter string - - // Role is "client", "server", or "unknown". - Role string - - // Build has the version of the Consul agent. - Build string - - // Protocol is the protocol of the Consul agent. - Protocol int - - // Status is the Serf health status "none", "alive", "leaving", "left", - // or "failed". - Status string - - // RTT is the estimated round trip time from the server handling the - // request to the this member. This will be negative if no RTT estimate - // is available. - RTT time.Duration -} - -// AreaCreate will create a new network area. The ID in the given structure must -// be empty and a generated ID will be returned on success. -func (op *Operator) AreaCreate(area *Area, q *WriteOptions) (string, *WriteMeta, error) { - r := op.c.newRequest("POST", "/v1/operator/area") - r.setWriteOptions(q) - r.obj = area - rtt, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - var out struct{ ID string } - if err := decodeBody(resp, &out); err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// AreaUpdate will update the configuration of the network area with the given ID. -func (op *Operator) AreaUpdate(areaID string, area *Area, q *WriteOptions) (string, *WriteMeta, error) { - r := op.c.newRequest("PUT", "/v1/operator/area/"+areaID) - r.setWriteOptions(q) - r.obj = area - rtt, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - var out struct{ ID string } - if err := decodeBody(resp, &out); err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// AreaGet returns a single network area. -func (op *Operator) AreaGet(areaID string, q *QueryOptions) ([]*Area, *QueryMeta, error) { - var out []*Area - qm, err := op.c.query("/v1/operator/area/"+areaID, &out, q) - if err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// AreaList returns all the available network areas. -func (op *Operator) AreaList(q *QueryOptions) ([]*Area, *QueryMeta, error) { - var out []*Area - qm, err := op.c.query("/v1/operator/area", &out, q) - if err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// AreaDelete deletes the given network area. -func (op *Operator) AreaDelete(areaID string, q *WriteOptions) (*WriteMeta, error) { - r := op.c.newRequest("DELETE", "/v1/operator/area/"+areaID) - r.setWriteOptions(q) - rtt, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - return wm, nil -} - -// AreaJoin attempts to join the given set of join addresses to the given -// network area. See the Area structure for details about join addresses. -func (op *Operator) AreaJoin(areaID string, addresses []string, q *WriteOptions) ([]*AreaJoinResponse, *WriteMeta, error) { - r := op.c.newRequest("PUT", "/v1/operator/area/"+areaID+"/join") - r.setWriteOptions(q) - r.obj = addresses - rtt, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - var out []*AreaJoinResponse - if err := decodeBody(resp, &out); err != nil { - return nil, nil, err - } - return out, wm, nil -} - -// AreaMembers lists the Serf information about the members in the given area. -func (op *Operator) AreaMembers(areaID string, q *QueryOptions) ([]*SerfMember, *QueryMeta, error) { - var out []*SerfMember - qm, err := op.c.query("/v1/operator/area/"+areaID+"/members", &out, q) - if err != nil { - return nil, nil, err - } - return out, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/operator_autopilot.go b/vendor/github.com/hashicorp/consul/api/operator_autopilot.go deleted file mode 100644 index b179406dc1..0000000000 --- a/vendor/github.com/hashicorp/consul/api/operator_autopilot.go +++ /dev/null @@ -1,219 +0,0 @@ -package api - -import ( - "bytes" - "fmt" - "io" - "strconv" - "strings" - "time" -) - -// AutopilotConfiguration is used for querying/setting the Autopilot configuration. -// Autopilot helps manage operator tasks related to Consul servers like removing -// failed servers from the Raft quorum. -type AutopilotConfiguration struct { - // CleanupDeadServers controls whether to remove dead servers from the Raft - // peer list when a new server joins - CleanupDeadServers bool - - // LastContactThreshold is the limit on the amount of time a server can go - // without leader contact before being considered unhealthy. - LastContactThreshold *ReadableDuration - - // MaxTrailingLogs is the amount of entries in the Raft Log that a server can - // be behind before being considered unhealthy. - MaxTrailingLogs uint64 - - // ServerStabilizationTime is the minimum amount of time a server must be - // in a stable, healthy state before it can be added to the cluster. Only - // applicable with Raft protocol version 3 or higher. - ServerStabilizationTime *ReadableDuration - - // (Enterprise-only) RedundancyZoneTag is the node tag to use for separating - // servers into zones for redundancy. If left blank, this feature will be disabled. - RedundancyZoneTag string - - // (Enterprise-only) DisableUpgradeMigration will disable Autopilot's upgrade migration - // strategy of waiting until enough newer-versioned servers have been added to the - // cluster before promoting them to voters. - DisableUpgradeMigration bool - - // (Enterprise-only) UpgradeVersionTag is the node tag to use for version info when - // performing upgrade migrations. If left blank, the Consul version will be used. - UpgradeVersionTag string - - // CreateIndex holds the index corresponding the creation of this configuration. - // This is a read-only field. - CreateIndex uint64 - - // ModifyIndex will be set to the index of the last update when retrieving the - // Autopilot configuration. Resubmitting a configuration with - // AutopilotCASConfiguration will perform a check-and-set operation which ensures - // there hasn't been a subsequent update since the configuration was retrieved. - ModifyIndex uint64 -} - -// ServerHealth is the health (from the leader's point of view) of a server. -type ServerHealth struct { - // ID is the raft ID of the server. - ID string - - // Name is the node name of the server. - Name string - - // Address is the address of the server. - Address string - - // The status of the SerfHealth check for the server. - SerfStatus string - - // Version is the Consul version of the server. - Version string - - // Leader is whether this server is currently the leader. - Leader bool - - // LastContact is the time since this node's last contact with the leader. - LastContact *ReadableDuration - - // LastTerm is the highest leader term this server has a record of in its Raft log. - LastTerm uint64 - - // LastIndex is the last log index this server has a record of in its Raft log. - LastIndex uint64 - - // Healthy is whether or not the server is healthy according to the current - // Autopilot config. - Healthy bool - - // Voter is whether this is a voting server. - Voter bool - - // StableSince is the last time this server's Healthy value changed. - StableSince time.Time -} - -// OperatorHealthReply is a representation of the overall health of the cluster -type OperatorHealthReply struct { - // Healthy is true if all the servers in the cluster are healthy. - Healthy bool - - // FailureTolerance is the number of healthy servers that could be lost without - // an outage occurring. - FailureTolerance int - - // Servers holds the health of each server. - Servers []ServerHealth -} - -// ReadableDuration is a duration type that is serialized to JSON in human readable format. -type ReadableDuration time.Duration - -func NewReadableDuration(dur time.Duration) *ReadableDuration { - d := ReadableDuration(dur) - return &d -} - -func (d *ReadableDuration) String() string { - return d.Duration().String() -} - -func (d *ReadableDuration) Duration() time.Duration { - if d == nil { - return time.Duration(0) - } - return time.Duration(*d) -} - -func (d *ReadableDuration) MarshalJSON() ([]byte, error) { - return []byte(fmt.Sprintf(`"%s"`, d.Duration().String())), nil -} - -func (d *ReadableDuration) UnmarshalJSON(raw []byte) error { - if d == nil { - return fmt.Errorf("cannot unmarshal to nil pointer") - } - - str := string(raw) - if len(str) < 2 || str[0] != '"' || str[len(str)-1] != '"' { - return fmt.Errorf("must be enclosed with quotes: %s", str) - } - dur, err := time.ParseDuration(str[1 : len(str)-1]) - if err != nil { - return err - } - *d = ReadableDuration(dur) - return nil -} - -// AutopilotGetConfiguration is used to query the current Autopilot configuration. -func (op *Operator) AutopilotGetConfiguration(q *QueryOptions) (*AutopilotConfiguration, error) { - r := op.c.newRequest("GET", "/v1/operator/autopilot/configuration") - r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out AutopilotConfiguration - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - - return &out, nil -} - -// AutopilotSetConfiguration is used to set the current Autopilot configuration. -func (op *Operator) AutopilotSetConfiguration(conf *AutopilotConfiguration, q *WriteOptions) error { - r := op.c.newRequest("PUT", "/v1/operator/autopilot/configuration") - r.setWriteOptions(q) - r.obj = conf - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// AutopilotCASConfiguration is used to perform a Check-And-Set update on the -// Autopilot configuration. The ModifyIndex value will be respected. Returns -// true on success or false on failures. -func (op *Operator) AutopilotCASConfiguration(conf *AutopilotConfiguration, q *WriteOptions) (bool, error) { - r := op.c.newRequest("PUT", "/v1/operator/autopilot/configuration") - r.setWriteOptions(q) - r.params.Set("cas", strconv.FormatUint(conf.ModifyIndex, 10)) - r.obj = conf - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return false, err - } - defer resp.Body.Close() - - var buf bytes.Buffer - if _, err := io.Copy(&buf, resp.Body); err != nil { - return false, fmt.Errorf("Failed to read response: %v", err) - } - res := strings.Contains(buf.String(), "true") - - return res, nil -} - -// AutopilotServerHealth -func (op *Operator) AutopilotServerHealth(q *QueryOptions) (*OperatorHealthReply, error) { - r := op.c.newRequest("GET", "/v1/operator/autopilot/health") - r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out OperatorHealthReply - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return &out, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/operator_keyring.go b/vendor/github.com/hashicorp/consul/api/operator_keyring.go deleted file mode 100644 index 038d5d5b02..0000000000 --- a/vendor/github.com/hashicorp/consul/api/operator_keyring.go +++ /dev/null @@ -1,89 +0,0 @@ -package api - -// keyringRequest is used for performing Keyring operations -type keyringRequest struct { - Key string -} - -// KeyringResponse is returned when listing the gossip encryption keys -type KeyringResponse struct { - // Whether this response is for a WAN ring - WAN bool - - // The datacenter name this request corresponds to - Datacenter string - - // Segment has the network segment this request corresponds to. - Segment string - - // Messages has information or errors from serf - Messages map[string]string `json:",omitempty"` - - // A map of the encryption keys to the number of nodes they're installed on - Keys map[string]int - - // The total number of nodes in this ring - NumNodes int -} - -// KeyringInstall is used to install a new gossip encryption key into the cluster -func (op *Operator) KeyringInstall(key string, q *WriteOptions) error { - r := op.c.newRequest("POST", "/v1/operator/keyring") - r.setWriteOptions(q) - r.obj = keyringRequest{ - Key: key, - } - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// KeyringList is used to list the gossip keys installed in the cluster -func (op *Operator) KeyringList(q *QueryOptions) ([]*KeyringResponse, error) { - r := op.c.newRequest("GET", "/v1/operator/keyring") - r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out []*KeyringResponse - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return out, nil -} - -// KeyringRemove is used to remove a gossip encryption key from the cluster -func (op *Operator) KeyringRemove(key string, q *WriteOptions) error { - r := op.c.newRequest("DELETE", "/v1/operator/keyring") - r.setWriteOptions(q) - r.obj = keyringRequest{ - Key: key, - } - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} - -// KeyringUse is used to change the active gossip encryption key -func (op *Operator) KeyringUse(key string, q *WriteOptions) error { - r := op.c.newRequest("PUT", "/v1/operator/keyring") - r.setWriteOptions(q) - r.obj = keyringRequest{ - Key: key, - } - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil -} diff --git a/vendor/github.com/hashicorp/consul/api/operator_raft.go b/vendor/github.com/hashicorp/consul/api/operator_raft.go deleted file mode 100644 index a9844df2dd..0000000000 --- a/vendor/github.com/hashicorp/consul/api/operator_raft.go +++ /dev/null @@ -1,89 +0,0 @@ -package api - -// RaftServer has information about a server in the Raft configuration. -type RaftServer struct { - // ID is the unique ID for the server. These are currently the same - // as the address, but they will be changed to a real GUID in a future - // release of Consul. - ID string - - // Node is the node name of the server, as known by Consul, or this - // will be set to "(unknown)" otherwise. - Node string - - // Address is the IP:port of the server, used for Raft communications. - Address string - - // Leader is true if this server is the current cluster leader. - Leader bool - - // Protocol version is the raft protocol version used by the server - ProtocolVersion string - - // Voter is true if this server has a vote in the cluster. This might - // be false if the server is staging and still coming online, or if - // it's a non-voting server, which will be added in a future release of - // Consul. - Voter bool -} - -// RaftConfiguration is returned when querying for the current Raft configuration. -type RaftConfiguration struct { - // Servers has the list of servers in the Raft configuration. - Servers []*RaftServer - - // Index has the Raft index of this configuration. - Index uint64 -} - -// RaftGetConfiguration is used to query the current Raft peer set. -func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) { - r := op.c.newRequest("GET", "/v1/operator/raft/configuration") - r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var out RaftConfiguration - if err := decodeBody(resp, &out); err != nil { - return nil, err - } - return &out, nil -} - -// RaftRemovePeerByAddress is used to kick a stale peer (one that it in the Raft -// quorum but no longer known to Serf or the catalog) by address in the form of -// "IP:port". -func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) error { - r := op.c.newRequest("DELETE", "/v1/operator/raft/peer") - r.setWriteOptions(q) - - r.params.Set("address", string(address)) - - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return err - } - - resp.Body.Close() - return nil -} - -// RaftRemovePeerByID is used to kick a stale peer (one that it in the Raft -// quorum but no longer known to Serf or the catalog) by ID. -func (op *Operator) RaftRemovePeerByID(id string, q *WriteOptions) error { - r := op.c.newRequest("DELETE", "/v1/operator/raft/peer") - r.setWriteOptions(q) - - r.params.Set("id", string(id)) - - _, resp, err := requireOK(op.c.doRequest(r)) - if err != nil { - return err - } - - resp.Body.Close() - return nil -} diff --git a/vendor/github.com/hashicorp/consul/api/operator_segment.go b/vendor/github.com/hashicorp/consul/api/operator_segment.go deleted file mode 100644 index 92b05d3c03..0000000000 --- a/vendor/github.com/hashicorp/consul/api/operator_segment.go +++ /dev/null @@ -1,11 +0,0 @@ -package api - -// SegmentList returns all the available LAN segments. -func (op *Operator) SegmentList(q *QueryOptions) ([]string, *QueryMeta, error) { - var out []string - qm, err := op.c.query("/v1/operator/segment", &out, q) - if err != nil { - return nil, nil, err - } - return out, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/prepared_query.go b/vendor/github.com/hashicorp/consul/api/prepared_query.go deleted file mode 100644 index 0204581168..0000000000 --- a/vendor/github.com/hashicorp/consul/api/prepared_query.go +++ /dev/null @@ -1,217 +0,0 @@ -package api - -// QueryDatacenterOptions sets options about how we fail over if there are no -// healthy nodes in the local datacenter. -type QueryDatacenterOptions struct { - // NearestN is set to the number of remote datacenters to try, based on - // network coordinates. - NearestN int - - // Datacenters is a fixed list of datacenters to try after NearestN. We - // never try a datacenter multiple times, so those are subtracted from - // this list before proceeding. - Datacenters []string -} - -// QueryDNSOptions controls settings when query results are served over DNS. -type QueryDNSOptions struct { - // TTL is the time to live for the served DNS results. - TTL string -} - -// ServiceQuery is used to query for a set of healthy nodes offering a specific -// service. -type ServiceQuery struct { - // Service is the service to query. - Service string - - // Near allows baking in the name of a node to automatically distance- - // sort from. The magic "_agent" value is supported, which sorts near - // the agent which initiated the request by default. - Near string - - // Failover controls what we do if there are no healthy nodes in the - // local datacenter. - Failover QueryDatacenterOptions - - // IgnoreCheckIDs is an optional list of health check IDs to ignore when - // considering which nodes are healthy. It is useful as an emergency measure - // to temporarily override some health check that is producing false negatives - // for example. - IgnoreCheckIDs []string - - // If OnlyPassing is true then we will only include nodes with passing - // health checks (critical AND warning checks will cause a node to be - // discarded) - OnlyPassing bool - - // Tags are a set of required and/or disallowed tags. If a tag is in - // this list it must be present. If the tag is preceded with "!" then - // it is disallowed. - Tags []string - - // NodeMeta is a map of required node metadata fields. If a key/value - // pair is in this map it must be present on the node in order for the - // service entry to be returned. - NodeMeta map[string]string - - // ServiceMeta is a map of required service metadata fields. If a key/value - // pair is in this map it must be present on the node in order for the - // service entry to be returned. - ServiceMeta map[string]string - - // Connect if true will filter the prepared query results to only - // include Connect-capable services. These include both native services - // and proxies for matching services. Note that if a proxy matches, - // the constraints in the query above (Near, OnlyPassing, etc.) apply - // to the _proxy_ and not the service being proxied. In practice, proxies - // should be directly next to their services so this isn't an issue. - Connect bool -} - -// QueryTemplate carries the arguments for creating a templated query. -type QueryTemplate struct { - // Type specifies the type of the query template. Currently only - // "name_prefix_match" is supported. This field is required. - Type string - - // Regexp allows specifying a regex pattern to match against the name - // of the query being executed. - Regexp string -} - -// PreparedQueryDefinition defines a complete prepared query. -type PreparedQueryDefinition struct { - // ID is this UUID-based ID for the query, always generated by Consul. - ID string - - // Name is an optional friendly name for the query supplied by the - // user. NOTE - if this feature is used then it will reduce the security - // of any read ACL associated with this query/service since this name - // can be used to locate nodes with supplying any ACL. - Name string - - // Session is an optional session to tie this query's lifetime to. If - // this is omitted then the query will not expire. - Session string - - // Token is the ACL token used when the query was created, and it is - // used when a query is subsequently executed. This token, or a token - // with management privileges, must be used to change the query later. - Token string - - // Service defines a service query (leaving things open for other types - // later). - Service ServiceQuery - - // DNS has options that control how the results of this query are - // served over DNS. - DNS QueryDNSOptions - - // Template is used to pass through the arguments for creating a - // prepared query with an attached template. If a template is given, - // interpolations are possible in other struct fields. - Template QueryTemplate -} - -// PreparedQueryExecuteResponse has the results of executing a query. -type PreparedQueryExecuteResponse struct { - // Service is the service that was queried. - Service string - - // Nodes has the nodes that were output by the query. - Nodes []ServiceEntry - - // DNS has the options for serving these results over DNS. - DNS QueryDNSOptions - - // Datacenter is the datacenter that these results came from. - Datacenter string - - // Failovers is a count of how many times we had to query a remote - // datacenter. - Failovers int -} - -// PreparedQuery can be used to query the prepared query endpoints. -type PreparedQuery struct { - c *Client -} - -// PreparedQuery returns a handle to the prepared query endpoints. -func (c *Client) PreparedQuery() *PreparedQuery { - return &PreparedQuery{c} -} - -// Create makes a new prepared query. The ID of the new query is returned. -func (c *PreparedQuery) Create(query *PreparedQueryDefinition, q *WriteOptions) (string, *WriteMeta, error) { - r := c.c.newRequest("POST", "/v1/query") - r.setWriteOptions(q) - r.obj = query - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return "", nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - - var out struct{ ID string } - if err := decodeBody(resp, &out); err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// Update makes updates to an existing prepared query. -func (c *PreparedQuery) Update(query *PreparedQueryDefinition, q *WriteOptions) (*WriteMeta, error) { - return c.c.write("/v1/query/"+query.ID, query, nil, q) -} - -// List is used to fetch all the prepared queries (always requires a management -// token). -func (c *PreparedQuery) List(q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) { - var out []*PreparedQueryDefinition - qm, err := c.c.query("/v1/query", &out, q) - if err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Get is used to fetch a specific prepared query. -func (c *PreparedQuery) Get(queryID string, q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) { - var out []*PreparedQueryDefinition - qm, err := c.c.query("/v1/query/"+queryID, &out, q) - if err != nil { - return nil, nil, err - } - return out, qm, nil -} - -// Delete is used to delete a specific prepared query. -func (c *PreparedQuery) Delete(queryID string, q *WriteOptions) (*WriteMeta, error) { - r := c.c.newRequest("DELETE", "/v1/query/"+queryID) - r.setWriteOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{} - wm.RequestTime = rtt - return wm, nil -} - -// Execute is used to execute a specific prepared query. You can execute using -// a query ID or name. -func (c *PreparedQuery) Execute(queryIDOrName string, q *QueryOptions) (*PreparedQueryExecuteResponse, *QueryMeta, error) { - var out *PreparedQueryExecuteResponse - qm, err := c.c.query("/v1/query/"+queryIDOrName+"/execute", &out, q) - if err != nil { - return nil, nil, err - } - return out, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/raw.go b/vendor/github.com/hashicorp/consul/api/raw.go deleted file mode 100644 index 745a208c99..0000000000 --- a/vendor/github.com/hashicorp/consul/api/raw.go +++ /dev/null @@ -1,24 +0,0 @@ -package api - -// Raw can be used to do raw queries against custom endpoints -type Raw struct { - c *Client -} - -// Raw returns a handle to query endpoints -func (c *Client) Raw() *Raw { - return &Raw{c} -} - -// Query is used to do a GET request against an endpoint -// and deserialize the response into an interface using -// standard Consul conventions. -func (raw *Raw) Query(endpoint string, out interface{}, q *QueryOptions) (*QueryMeta, error) { - return raw.c.query(endpoint, out, q) -} - -// Write is used to do a PUT request against an endpoint -// and serialize/deserialized using the standard Consul conventions. -func (raw *Raw) Write(endpoint string, in, out interface{}, q *WriteOptions) (*WriteMeta, error) { - return raw.c.write(endpoint, in, out, q) -} diff --git a/vendor/github.com/hashicorp/consul/api/semaphore.go b/vendor/github.com/hashicorp/consul/api/semaphore.go deleted file mode 100644 index bc4f885fec..0000000000 --- a/vendor/github.com/hashicorp/consul/api/semaphore.go +++ /dev/null @@ -1,514 +0,0 @@ -package api - -import ( - "encoding/json" - "fmt" - "path" - "sync" - "time" -) - -const ( - // DefaultSemaphoreSessionName is the Session Name we assign if none is provided - DefaultSemaphoreSessionName = "Consul API Semaphore" - - // DefaultSemaphoreSessionTTL is the default session TTL if no Session is provided - // when creating a new Semaphore. This is used because we do not have another - // other check to depend upon. - DefaultSemaphoreSessionTTL = "15s" - - // DefaultSemaphoreWaitTime is how long we block for at a time to check if semaphore - // acquisition is possible. This affects the minimum time it takes to cancel - // a Semaphore acquisition. - DefaultSemaphoreWaitTime = 15 * time.Second - - // DefaultSemaphoreKey is the key used within the prefix to - // use for coordination between all the contenders. - DefaultSemaphoreKey = ".lock" - - // SemaphoreFlagValue is a magic flag we set to indicate a key - // is being used for a semaphore. It is used to detect a potential - // conflict with a lock. - SemaphoreFlagValue = 0xe0f69a2baa414de0 -) - -var ( - // ErrSemaphoreHeld is returned if we attempt to double lock - ErrSemaphoreHeld = fmt.Errorf("Semaphore already held") - - // ErrSemaphoreNotHeld is returned if we attempt to unlock a semaphore - // that we do not hold. - ErrSemaphoreNotHeld = fmt.Errorf("Semaphore not held") - - // ErrSemaphoreInUse is returned if we attempt to destroy a semaphore - // that is in use. - ErrSemaphoreInUse = fmt.Errorf("Semaphore in use") - - // ErrSemaphoreConflict is returned if the flags on a key - // used for a semaphore do not match expectation - ErrSemaphoreConflict = fmt.Errorf("Existing key does not match semaphore use") -) - -// Semaphore is used to implement a distributed semaphore -// using the Consul KV primitives. -type Semaphore struct { - c *Client - opts *SemaphoreOptions - - isHeld bool - sessionRenew chan struct{} - lockSession string - l sync.Mutex -} - -// SemaphoreOptions is used to parameterize the Semaphore -type SemaphoreOptions struct { - Prefix string // Must be set and have write permissions - Limit int // Must be set, and be positive - Value []byte // Optional, value to associate with the contender entry - Session string // Optional, created if not specified - SessionName string // Optional, defaults to DefaultLockSessionName - SessionTTL string // Optional, defaults to DefaultLockSessionTTL - MonitorRetries int // Optional, defaults to 0 which means no retries - MonitorRetryTime time.Duration // Optional, defaults to DefaultMonitorRetryTime - SemaphoreWaitTime time.Duration // Optional, defaults to DefaultSemaphoreWaitTime - SemaphoreTryOnce bool // Optional, defaults to false which means try forever -} - -// semaphoreLock is written under the DefaultSemaphoreKey and -// is used to coordinate between all the contenders. -type semaphoreLock struct { - // Limit is the integer limit of holders. This is used to - // verify that all the holders agree on the value. - Limit int - - // Holders is a list of all the semaphore holders. - // It maps the session ID to true. It is used as a set effectively. - Holders map[string]bool -} - -// SemaphorePrefix is used to created a Semaphore which will operate -// at the given KV prefix and uses the given limit for the semaphore. -// The prefix must have write privileges, and the limit must be agreed -// upon by all contenders. -func (c *Client) SemaphorePrefix(prefix string, limit int) (*Semaphore, error) { - opts := &SemaphoreOptions{ - Prefix: prefix, - Limit: limit, - } - return c.SemaphoreOpts(opts) -} - -// SemaphoreOpts is used to create a Semaphore with the given options. -// The prefix must have write privileges, and the limit must be agreed -// upon by all contenders. If a Session is not provided, one will be created. -func (c *Client) SemaphoreOpts(opts *SemaphoreOptions) (*Semaphore, error) { - if opts.Prefix == "" { - return nil, fmt.Errorf("missing prefix") - } - if opts.Limit <= 0 { - return nil, fmt.Errorf("semaphore limit must be positive") - } - if opts.SessionName == "" { - opts.SessionName = DefaultSemaphoreSessionName - } - if opts.SessionTTL == "" { - opts.SessionTTL = DefaultSemaphoreSessionTTL - } else { - if _, err := time.ParseDuration(opts.SessionTTL); err != nil { - return nil, fmt.Errorf("invalid SessionTTL: %v", err) - } - } - if opts.MonitorRetryTime == 0 { - opts.MonitorRetryTime = DefaultMonitorRetryTime - } - if opts.SemaphoreWaitTime == 0 { - opts.SemaphoreWaitTime = DefaultSemaphoreWaitTime - } - s := &Semaphore{ - c: c, - opts: opts, - } - return s, nil -} - -// Acquire attempts to reserve a slot in the semaphore, blocking until -// success, interrupted via the stopCh or an error is encountered. -// Providing a non-nil stopCh can be used to abort the attempt. -// On success, a channel is returned that represents our slot. -// This channel could be closed at any time due to session invalidation, -// communication errors, operator intervention, etc. It is NOT safe to -// assume that the slot is held until Release() unless the Session is specifically -// created without any associated health checks. By default Consul sessions -// prefer liveness over safety and an application must be able to handle -// the session being lost. -func (s *Semaphore) Acquire(stopCh <-chan struct{}) (<-chan struct{}, error) { - // Hold the lock as we try to acquire - s.l.Lock() - defer s.l.Unlock() - - // Check if we already hold the semaphore - if s.isHeld { - return nil, ErrSemaphoreHeld - } - - // Check if we need to create a session first - s.lockSession = s.opts.Session - if s.lockSession == "" { - sess, err := s.createSession() - if err != nil { - return nil, fmt.Errorf("failed to create session: %v", err) - } - - s.sessionRenew = make(chan struct{}) - s.lockSession = sess - session := s.c.Session() - go session.RenewPeriodic(s.opts.SessionTTL, sess, nil, s.sessionRenew) - - // If we fail to acquire the lock, cleanup the session - defer func() { - if !s.isHeld { - close(s.sessionRenew) - s.sessionRenew = nil - } - }() - } - - // Create the contender entry - kv := s.c.KV() - made, _, err := kv.Acquire(s.contenderEntry(s.lockSession), nil) - if err != nil || !made { - return nil, fmt.Errorf("failed to make contender entry: %v", err) - } - - // Setup the query options - qOpts := &QueryOptions{ - WaitTime: s.opts.SemaphoreWaitTime, - } - - start := time.Now() - attempts := 0 -WAIT: - // Check if we should quit - select { - case <-stopCh: - return nil, nil - default: - } - - // Handle the one-shot mode. - if s.opts.SemaphoreTryOnce && attempts > 0 { - elapsed := time.Since(start) - if elapsed > s.opts.SemaphoreWaitTime { - return nil, nil - } - - // Query wait time should not exceed the semaphore wait time - qOpts.WaitTime = s.opts.SemaphoreWaitTime - elapsed - } - attempts++ - - // Read the prefix - pairs, meta, err := kv.List(s.opts.Prefix, qOpts) - if err != nil { - return nil, fmt.Errorf("failed to read prefix: %v", err) - } - - // Decode the lock - lockPair := s.findLock(pairs) - if lockPair.Flags != SemaphoreFlagValue { - return nil, ErrSemaphoreConflict - } - lock, err := s.decodeLock(lockPair) - if err != nil { - return nil, err - } - - // Verify we agree with the limit - if lock.Limit != s.opts.Limit { - return nil, fmt.Errorf("semaphore limit conflict (lock: %d, local: %d)", - lock.Limit, s.opts.Limit) - } - - // Prune the dead holders - s.pruneDeadHolders(lock, pairs) - - // Check if the lock is held - if len(lock.Holders) >= lock.Limit { - qOpts.WaitIndex = meta.LastIndex - goto WAIT - } - - // Create a new lock with us as a holder - lock.Holders[s.lockSession] = true - newLock, err := s.encodeLock(lock, lockPair.ModifyIndex) - if err != nil { - return nil, err - } - - // Attempt the acquisition - didSet, _, err := kv.CAS(newLock, nil) - if err != nil { - return nil, fmt.Errorf("failed to update lock: %v", err) - } - if !didSet { - // Update failed, could have been a race with another contender, - // retry the operation - goto WAIT - } - - // Watch to ensure we maintain ownership of the slot - lockCh := make(chan struct{}) - go s.monitorLock(s.lockSession, lockCh) - - // Set that we own the lock - s.isHeld = true - - // Acquired! All done - return lockCh, nil -} - -// Release is used to voluntarily give up our semaphore slot. It is -// an error to call this if the semaphore has not been acquired. -func (s *Semaphore) Release() error { - // Hold the lock as we try to release - s.l.Lock() - defer s.l.Unlock() - - // Ensure the lock is actually held - if !s.isHeld { - return ErrSemaphoreNotHeld - } - - // Set that we no longer own the lock - s.isHeld = false - - // Stop the session renew - if s.sessionRenew != nil { - defer func() { - close(s.sessionRenew) - s.sessionRenew = nil - }() - } - - // Get and clear the lock session - lockSession := s.lockSession - s.lockSession = "" - - // Remove ourselves as a lock holder - kv := s.c.KV() - key := path.Join(s.opts.Prefix, DefaultSemaphoreKey) -READ: - pair, _, err := kv.Get(key, nil) - if err != nil { - return err - } - if pair == nil { - pair = &KVPair{} - } - lock, err := s.decodeLock(pair) - if err != nil { - return err - } - - // Create a new lock without us as a holder - if _, ok := lock.Holders[lockSession]; ok { - delete(lock.Holders, lockSession) - newLock, err := s.encodeLock(lock, pair.ModifyIndex) - if err != nil { - return err - } - - // Swap the locks - didSet, _, err := kv.CAS(newLock, nil) - if err != nil { - return fmt.Errorf("failed to update lock: %v", err) - } - if !didSet { - goto READ - } - } - - // Destroy the contender entry - contenderKey := path.Join(s.opts.Prefix, lockSession) - if _, err := kv.Delete(contenderKey, nil); err != nil { - return err - } - return nil -} - -// Destroy is used to cleanup the semaphore entry. It is not necessary -// to invoke. It will fail if the semaphore is in use. -func (s *Semaphore) Destroy() error { - // Hold the lock as we try to acquire - s.l.Lock() - defer s.l.Unlock() - - // Check if we already hold the semaphore - if s.isHeld { - return ErrSemaphoreHeld - } - - // List for the semaphore - kv := s.c.KV() - pairs, _, err := kv.List(s.opts.Prefix, nil) - if err != nil { - return fmt.Errorf("failed to read prefix: %v", err) - } - - // Find the lock pair, bail if it doesn't exist - lockPair := s.findLock(pairs) - if lockPair.ModifyIndex == 0 { - return nil - } - if lockPair.Flags != SemaphoreFlagValue { - return ErrSemaphoreConflict - } - - // Decode the lock - lock, err := s.decodeLock(lockPair) - if err != nil { - return err - } - - // Prune the dead holders - s.pruneDeadHolders(lock, pairs) - - // Check if there are any holders - if len(lock.Holders) > 0 { - return ErrSemaphoreInUse - } - - // Attempt the delete - didRemove, _, err := kv.DeleteCAS(lockPair, nil) - if err != nil { - return fmt.Errorf("failed to remove semaphore: %v", err) - } - if !didRemove { - return ErrSemaphoreInUse - } - return nil -} - -// createSession is used to create a new managed session -func (s *Semaphore) createSession() (string, error) { - session := s.c.Session() - se := &SessionEntry{ - Name: s.opts.SessionName, - TTL: s.opts.SessionTTL, - Behavior: SessionBehaviorDelete, - } - id, _, err := session.Create(se, nil) - if err != nil { - return "", err - } - return id, nil -} - -// contenderEntry returns a formatted KVPair for the contender -func (s *Semaphore) contenderEntry(session string) *KVPair { - return &KVPair{ - Key: path.Join(s.opts.Prefix, session), - Value: s.opts.Value, - Session: session, - Flags: SemaphoreFlagValue, - } -} - -// findLock is used to find the KV Pair which is used for coordination -func (s *Semaphore) findLock(pairs KVPairs) *KVPair { - key := path.Join(s.opts.Prefix, DefaultSemaphoreKey) - for _, pair := range pairs { - if pair.Key == key { - return pair - } - } - return &KVPair{Flags: SemaphoreFlagValue} -} - -// decodeLock is used to decode a semaphoreLock from an -// entry in Consul -func (s *Semaphore) decodeLock(pair *KVPair) (*semaphoreLock, error) { - // Handle if there is no lock - if pair == nil || pair.Value == nil { - return &semaphoreLock{ - Limit: s.opts.Limit, - Holders: make(map[string]bool), - }, nil - } - - l := &semaphoreLock{} - if err := json.Unmarshal(pair.Value, l); err != nil { - return nil, fmt.Errorf("lock decoding failed: %v", err) - } - return l, nil -} - -// encodeLock is used to encode a semaphoreLock into a KVPair -// that can be PUT -func (s *Semaphore) encodeLock(l *semaphoreLock, oldIndex uint64) (*KVPair, error) { - enc, err := json.Marshal(l) - if err != nil { - return nil, fmt.Errorf("lock encoding failed: %v", err) - } - pair := &KVPair{ - Key: path.Join(s.opts.Prefix, DefaultSemaphoreKey), - Value: enc, - Flags: SemaphoreFlagValue, - ModifyIndex: oldIndex, - } - return pair, nil -} - -// pruneDeadHolders is used to remove all the dead lock holders -func (s *Semaphore) pruneDeadHolders(lock *semaphoreLock, pairs KVPairs) { - // Gather all the live holders - alive := make(map[string]struct{}, len(pairs)) - for _, pair := range pairs { - if pair.Session != "" { - alive[pair.Session] = struct{}{} - } - } - - // Remove any holders that are dead - for holder := range lock.Holders { - if _, ok := alive[holder]; !ok { - delete(lock.Holders, holder) - } - } -} - -// monitorLock is a long running routine to monitor a semaphore ownership -// It closes the stopCh if we lose our slot. -func (s *Semaphore) monitorLock(session string, stopCh chan struct{}) { - defer close(stopCh) - kv := s.c.KV() - opts := &QueryOptions{RequireConsistent: true} -WAIT: - retries := s.opts.MonitorRetries -RETRY: - pairs, meta, err := kv.List(s.opts.Prefix, opts) - if err != nil { - // If configured we can try to ride out a brief Consul unavailability - // by doing retries. Note that we have to attempt the retry in a non- - // blocking fashion so that we have a clean place to reset the retry - // counter if service is restored. - if retries > 0 && IsRetryableError(err) { - time.Sleep(s.opts.MonitorRetryTime) - retries-- - opts.WaitIndex = 0 - goto RETRY - } - return - } - lockPair := s.findLock(pairs) - lock, err := s.decodeLock(lockPair) - if err != nil { - return - } - s.pruneDeadHolders(lock, pairs) - if _, ok := lock.Holders[session]; ok { - opts.WaitIndex = meta.LastIndex - goto WAIT - } -} diff --git a/vendor/github.com/hashicorp/consul/api/session.go b/vendor/github.com/hashicorp/consul/api/session.go deleted file mode 100644 index 1613f11a60..0000000000 --- a/vendor/github.com/hashicorp/consul/api/session.go +++ /dev/null @@ -1,224 +0,0 @@ -package api - -import ( - "errors" - "fmt" - "time" -) - -const ( - // SessionBehaviorRelease is the default behavior and causes - // all associated locks to be released on session invalidation. - SessionBehaviorRelease = "release" - - // SessionBehaviorDelete is new in Consul 0.5 and changes the - // behavior to delete all associated locks on session invalidation. - // It can be used in a way similar to Ephemeral Nodes in ZooKeeper. - SessionBehaviorDelete = "delete" -) - -var ErrSessionExpired = errors.New("session expired") - -// SessionEntry represents a session in consul -type SessionEntry struct { - CreateIndex uint64 - ID string - Name string - Node string - Checks []string - LockDelay time.Duration - Behavior string - TTL string -} - -// Session can be used to query the Session endpoints -type Session struct { - c *Client -} - -// Session returns a handle to the session endpoints -func (c *Client) Session() *Session { - return &Session{c} -} - -// CreateNoChecks is like Create but is used specifically to create -// a session with no associated health checks. -func (s *Session) CreateNoChecks(se *SessionEntry, q *WriteOptions) (string, *WriteMeta, error) { - body := make(map[string]interface{}) - body["Checks"] = []string{} - if se != nil { - if se.Name != "" { - body["Name"] = se.Name - } - if se.Node != "" { - body["Node"] = se.Node - } - if se.LockDelay != 0 { - body["LockDelay"] = durToMsec(se.LockDelay) - } - if se.Behavior != "" { - body["Behavior"] = se.Behavior - } - if se.TTL != "" { - body["TTL"] = se.TTL - } - } - return s.create(body, q) - -} - -// Create makes a new session. Providing a session entry can -// customize the session. It can also be nil to use defaults. -func (s *Session) Create(se *SessionEntry, q *WriteOptions) (string, *WriteMeta, error) { - var obj interface{} - if se != nil { - body := make(map[string]interface{}) - obj = body - if se.Name != "" { - body["Name"] = se.Name - } - if se.Node != "" { - body["Node"] = se.Node - } - if se.LockDelay != 0 { - body["LockDelay"] = durToMsec(se.LockDelay) - } - if len(se.Checks) > 0 { - body["Checks"] = se.Checks - } - if se.Behavior != "" { - body["Behavior"] = se.Behavior - } - if se.TTL != "" { - body["TTL"] = se.TTL - } - } - return s.create(obj, q) -} - -func (s *Session) create(obj interface{}, q *WriteOptions) (string, *WriteMeta, error) { - var out struct{ ID string } - wm, err := s.c.write("/v1/session/create", obj, &out, q) - if err != nil { - return "", nil, err - } - return out.ID, wm, nil -} - -// Destroy invalidates a given session -func (s *Session) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { - wm, err := s.c.write("/v1/session/destroy/"+id, nil, nil, q) - if err != nil { - return nil, err - } - return wm, nil -} - -// Renew renews the TTL on a given session -func (s *Session) Renew(id string, q *WriteOptions) (*SessionEntry, *WriteMeta, error) { - r := s.c.newRequest("PUT", "/v1/session/renew/"+id) - r.setWriteOptions(q) - rtt, resp, err := s.c.doRequest(r) - if err != nil { - return nil, nil, err - } - defer resp.Body.Close() - - wm := &WriteMeta{RequestTime: rtt} - - if resp.StatusCode == 404 { - return nil, wm, nil - } else if resp.StatusCode != 200 { - return nil, nil, fmt.Errorf("Unexpected response code: %d", resp.StatusCode) - } - - var entries []*SessionEntry - if err := decodeBody(resp, &entries); err != nil { - return nil, nil, fmt.Errorf("Failed to read response: %v", err) - } - if len(entries) > 0 { - return entries[0], wm, nil - } - return nil, wm, nil -} - -// RenewPeriodic is used to periodically invoke Session.Renew on a -// session until a doneCh is closed. This is meant to be used in a long running -// goroutine to ensure a session stays valid. -func (s *Session) RenewPeriodic(initialTTL string, id string, q *WriteOptions, doneCh <-chan struct{}) error { - ctx := q.Context() - - ttl, err := time.ParseDuration(initialTTL) - if err != nil { - return err - } - - waitDur := ttl / 2 - lastRenewTime := time.Now() - var lastErr error - for { - if time.Since(lastRenewTime) > ttl { - return lastErr - } - select { - case <-time.After(waitDur): - entry, _, err := s.Renew(id, q) - if err != nil { - waitDur = time.Second - lastErr = err - continue - } - if entry == nil { - return ErrSessionExpired - } - - // Handle the server updating the TTL - ttl, _ = time.ParseDuration(entry.TTL) - waitDur = ttl / 2 - lastRenewTime = time.Now() - - case <-doneCh: - // Attempt a session destroy - s.Destroy(id, q) - return nil - - case <-ctx.Done(): - // Bail immediately since attempting the destroy would - // use the canceled context in q, which would just bail. - return ctx.Err() - } - } -} - -// Info looks up a single session -func (s *Session) Info(id string, q *QueryOptions) (*SessionEntry, *QueryMeta, error) { - var entries []*SessionEntry - qm, err := s.c.query("/v1/session/info/"+id, &entries, q) - if err != nil { - return nil, nil, err - } - if len(entries) > 0 { - return entries[0], qm, nil - } - return nil, qm, nil -} - -// List gets sessions for a node -func (s *Session) Node(node string, q *QueryOptions) ([]*SessionEntry, *QueryMeta, error) { - var entries []*SessionEntry - qm, err := s.c.query("/v1/session/node/"+node, &entries, q) - if err != nil { - return nil, nil, err - } - return entries, qm, nil -} - -// List gets all active sessions -func (s *Session) List(q *QueryOptions) ([]*SessionEntry, *QueryMeta, error) { - var entries []*SessionEntry - qm, err := s.c.query("/v1/session/list", &entries, q) - if err != nil { - return nil, nil, err - } - return entries, qm, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/snapshot.go b/vendor/github.com/hashicorp/consul/api/snapshot.go deleted file mode 100644 index e902377dd5..0000000000 --- a/vendor/github.com/hashicorp/consul/api/snapshot.go +++ /dev/null @@ -1,47 +0,0 @@ -package api - -import ( - "io" -) - -// Snapshot can be used to query the /v1/snapshot endpoint to take snapshots of -// Consul's internal state and restore snapshots for disaster recovery. -type Snapshot struct { - c *Client -} - -// Snapshot returns a handle that exposes the snapshot endpoints. -func (c *Client) Snapshot() *Snapshot { - return &Snapshot{c} -} - -// Save requests a new snapshot and provides an io.ReadCloser with the snapshot -// data to save. If this doesn't return an error, then it's the responsibility -// of the caller to close it. Only a subset of the QueryOptions are supported: -// Datacenter, AllowStale, and Token. -func (s *Snapshot) Save(q *QueryOptions) (io.ReadCloser, *QueryMeta, error) { - r := s.c.newRequest("GET", "/v1/snapshot") - r.setQueryOptions(q) - - rtt, resp, err := requireOK(s.c.doRequest(r)) - if err != nil { - return nil, nil, err - } - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - return resp.Body, qm, nil -} - -// Restore streams in an existing snapshot and attempts to restore it. -func (s *Snapshot) Restore(q *WriteOptions, in io.Reader) error { - r := s.c.newRequest("PUT", "/v1/snapshot") - r.body = in - r.setWriteOptions(q) - _, _, err := requireOK(s.c.doRequest(r)) - if err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/hashicorp/consul/api/status.go b/vendor/github.com/hashicorp/consul/api/status.go deleted file mode 100644 index 74ef61a678..0000000000 --- a/vendor/github.com/hashicorp/consul/api/status.go +++ /dev/null @@ -1,43 +0,0 @@ -package api - -// Status can be used to query the Status endpoints -type Status struct { - c *Client -} - -// Status returns a handle to the status endpoints -func (c *Client) Status() *Status { - return &Status{c} -} - -// Leader is used to query for a known leader -func (s *Status) Leader() (string, error) { - r := s.c.newRequest("GET", "/v1/status/leader") - _, resp, err := requireOK(s.c.doRequest(r)) - if err != nil { - return "", err - } - defer resp.Body.Close() - - var leader string - if err := decodeBody(resp, &leader); err != nil { - return "", err - } - return leader, nil -} - -// Peers is used to query for a known raft peers -func (s *Status) Peers() ([]string, error) { - r := s.c.newRequest("GET", "/v1/status/peers") - _, resp, err := requireOK(s.c.doRequest(r)) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var peers []string - if err := decodeBody(resp, &peers); err != nil { - return nil, err - } - return peers, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/txn.go b/vendor/github.com/hashicorp/consul/api/txn.go deleted file mode 100644 index 65d7a16ea0..0000000000 --- a/vendor/github.com/hashicorp/consul/api/txn.go +++ /dev/null @@ -1,230 +0,0 @@ -package api - -import ( - "bytes" - "fmt" - "io" - "net/http" -) - -// Txn is used to manipulate the Txn API -type Txn struct { - c *Client -} - -// Txn is used to return a handle to the K/V apis -func (c *Client) Txn() *Txn { - return &Txn{c} -} - -// TxnOp is the internal format we send to Consul. Currently only K/V and -// check operations are supported. -type TxnOp struct { - KV *KVTxnOp - Node *NodeTxnOp - Service *ServiceTxnOp - Check *CheckTxnOp -} - -// TxnOps is a list of transaction operations. -type TxnOps []*TxnOp - -// TxnResult is the internal format we receive from Consul. -type TxnResult struct { - KV *KVPair - Node *Node - Service *CatalogService - Check *HealthCheck -} - -// TxnResults is a list of TxnResult objects. -type TxnResults []*TxnResult - -// TxnError is used to return information about an operation in a transaction. -type TxnError struct { - OpIndex int - What string -} - -// TxnErrors is a list of TxnError objects. -type TxnErrors []*TxnError - -// TxnResponse is the internal format we receive from Consul. -type TxnResponse struct { - Results TxnResults - Errors TxnErrors -} - -// KVOp constants give possible operations available in a transaction. -type KVOp string - -const ( - KVSet KVOp = "set" - KVDelete KVOp = "delete" - KVDeleteCAS KVOp = "delete-cas" - KVDeleteTree KVOp = "delete-tree" - KVCAS KVOp = "cas" - KVLock KVOp = "lock" - KVUnlock KVOp = "unlock" - KVGet KVOp = "get" - KVGetTree KVOp = "get-tree" - KVCheckSession KVOp = "check-session" - KVCheckIndex KVOp = "check-index" - KVCheckNotExists KVOp = "check-not-exists" -) - -// KVTxnOp defines a single operation inside a transaction. -type KVTxnOp struct { - Verb KVOp - Key string - Value []byte - Flags uint64 - Index uint64 - Session string -} - -// KVTxnOps defines a set of operations to be performed inside a single -// transaction. -type KVTxnOps []*KVTxnOp - -// KVTxnResponse has the outcome of a transaction. -type KVTxnResponse struct { - Results []*KVPair - Errors TxnErrors -} - -// NodeOp constants give possible operations available in a transaction. -type NodeOp string - -const ( - NodeGet NodeOp = "get" - NodeSet NodeOp = "set" - NodeCAS NodeOp = "cas" - NodeDelete NodeOp = "delete" - NodeDeleteCAS NodeOp = "delete-cas" -) - -// NodeTxnOp defines a single operation inside a transaction. -type NodeTxnOp struct { - Verb NodeOp - Node Node -} - -// ServiceOp constants give possible operations available in a transaction. -type ServiceOp string - -const ( - ServiceGet ServiceOp = "get" - ServiceSet ServiceOp = "set" - ServiceCAS ServiceOp = "cas" - ServiceDelete ServiceOp = "delete" - ServiceDeleteCAS ServiceOp = "delete-cas" -) - -// ServiceTxnOp defines a single operation inside a transaction. -type ServiceTxnOp struct { - Verb ServiceOp - Node string - Service AgentService -} - -// CheckOp constants give possible operations available in a transaction. -type CheckOp string - -const ( - CheckGet CheckOp = "get" - CheckSet CheckOp = "set" - CheckCAS CheckOp = "cas" - CheckDelete CheckOp = "delete" - CheckDeleteCAS CheckOp = "delete-cas" -) - -// CheckTxnOp defines a single operation inside a transaction. -type CheckTxnOp struct { - Verb CheckOp - Check HealthCheck -} - -// Txn is used to apply multiple Consul operations in a single, atomic transaction. -// -// Note that Go will perform the required base64 encoding on the values -// automatically because the type is a byte slice. Transactions are defined as a -// list of operations to perform, using the different fields in the TxnOp structure -// to define operations. If any operation fails, none of the changes are applied -// to the state store. -// -// Even though this is generally a write operation, we take a QueryOptions input -// and return a QueryMeta output. If the transaction contains only read ops, then -// Consul will fast-path it to a different endpoint internally which supports -// consistency controls, but not blocking. If there are write operations then -// the request will always be routed through raft and any consistency settings -// will be ignored. -// -// Here's an example: -// -// ops := KVTxnOps{ -// &KVTxnOp{ -// Verb: KVLock, -// Key: "test/lock", -// Session: "adf4238a-882b-9ddc-4a9d-5b6758e4159e", -// Value: []byte("hello"), -// }, -// &KVTxnOp{ -// Verb: KVGet, -// Key: "another/key", -// }, -// &CheckTxnOp{ -// Verb: CheckSet, -// HealthCheck: HealthCheck{ -// Node: "foo", -// CheckID: "redis:a", -// Name: "Redis Health Check", -// Status: "passing", -// }, -// } -// } -// ok, response, _, err := kv.Txn(&ops, nil) -// -// If there is a problem making the transaction request then an error will be -// returned. Otherwise, the ok value will be true if the transaction succeeded -// or false if it was rolled back. The response is a structured return value which -// will have the outcome of the transaction. Its Results member will have entries -// for each operation. For KV operations, Deleted keys will have a nil entry in the -// results, and to save space, the Value of each key in the Results will be nil -// unless the operation is a KVGet. If the transaction was rolled back, the Errors -// member will have entries referencing the index of the operation that failed -// along with an error message. -func (t *Txn) Txn(txn TxnOps, q *QueryOptions) (bool, *TxnResponse, *QueryMeta, error) { - return t.c.txn(txn, q) -} - -func (c *Client) txn(txn TxnOps, q *QueryOptions) (bool, *TxnResponse, *QueryMeta, error) { - r := c.newRequest("PUT", "/v1/txn") - r.setQueryOptions(q) - - r.obj = txn - rtt, resp, err := c.doRequest(r) - if err != nil { - return false, nil, nil, err - } - defer resp.Body.Close() - - qm := &QueryMeta{} - parseQueryMeta(resp, qm) - qm.RequestTime = rtt - - if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusConflict { - var txnResp TxnResponse - if err := decodeBody(resp, &txnResp); err != nil { - return false, nil, nil, err - } - - return resp.StatusCode == http.StatusOK, &txnResp, qm, nil - } - - var buf bytes.Buffer - if _, err := io.Copy(&buf, resp.Body); err != nil { - return false, nil, nil, fmt.Errorf("Failed to read response: %v", err) - } - return false, nil, nil, fmt.Errorf("Failed request: %s", buf.String()) -} diff --git a/vendor/github.com/hashicorp/consul/api/watch/funcs.go b/vendor/github.com/hashicorp/consul/api/watch/funcs.go deleted file mode 100644 index e9b2d81159..0000000000 --- a/vendor/github.com/hashicorp/consul/api/watch/funcs.go +++ /dev/null @@ -1,349 +0,0 @@ -package watch - -import ( - "context" - "fmt" - - consulapi "github.com/hashicorp/consul/api" -) - -// watchFactory is a function that can create a new WatchFunc -// from a parameter configuration -type watchFactory func(params map[string]interface{}) (WatcherFunc, error) - -// watchFuncFactory maps each type to a factory function -var watchFuncFactory map[string]watchFactory - -func init() { - watchFuncFactory = map[string]watchFactory{ - "key": keyWatch, - "keyprefix": keyPrefixWatch, - "services": servicesWatch, - "nodes": nodesWatch, - "service": serviceWatch, - "checks": checksWatch, - "event": eventWatch, - "connect_roots": connectRootsWatch, - "connect_leaf": connectLeafWatch, - "connect_proxy_config": connectProxyConfigWatch, - "agent_service": agentServiceWatch, - } -} - -// keyWatch is used to return a key watching function -func keyWatch(params map[string]interface{}) (WatcherFunc, error) { - stale := false - if err := assignValueBool(params, "stale", &stale); err != nil { - return nil, err - } - - var key string - if err := assignValue(params, "key", &key); err != nil { - return nil, err - } - if key == "" { - return nil, fmt.Errorf("Must specify a single key to watch") - } - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - kv := p.client.KV() - opts := makeQueryOptionsWithContext(p, stale) - defer p.cancelFunc() - pair, meta, err := kv.Get(key, &opts) - if err != nil { - return nil, nil, err - } - if pair == nil { - return WaitIndexVal(meta.LastIndex), nil, err - } - return WaitIndexVal(meta.LastIndex), pair, err - } - return fn, nil -} - -// keyPrefixWatch is used to return a key prefix watching function -func keyPrefixWatch(params map[string]interface{}) (WatcherFunc, error) { - stale := false - if err := assignValueBool(params, "stale", &stale); err != nil { - return nil, err - } - - var prefix string - if err := assignValue(params, "prefix", &prefix); err != nil { - return nil, err - } - if prefix == "" { - return nil, fmt.Errorf("Must specify a single prefix to watch") - } - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - kv := p.client.KV() - opts := makeQueryOptionsWithContext(p, stale) - defer p.cancelFunc() - pairs, meta, err := kv.List(prefix, &opts) - if err != nil { - return nil, nil, err - } - return WaitIndexVal(meta.LastIndex), pairs, err - } - return fn, nil -} - -// servicesWatch is used to watch the list of available services -func servicesWatch(params map[string]interface{}) (WatcherFunc, error) { - stale := false - if err := assignValueBool(params, "stale", &stale); err != nil { - return nil, err - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - catalog := p.client.Catalog() - opts := makeQueryOptionsWithContext(p, stale) - defer p.cancelFunc() - services, meta, err := catalog.Services(&opts) - if err != nil { - return nil, nil, err - } - return WaitIndexVal(meta.LastIndex), services, err - } - return fn, nil -} - -// nodesWatch is used to watch the list of available nodes -func nodesWatch(params map[string]interface{}) (WatcherFunc, error) { - stale := false - if err := assignValueBool(params, "stale", &stale); err != nil { - return nil, err - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - catalog := p.client.Catalog() - opts := makeQueryOptionsWithContext(p, stale) - defer p.cancelFunc() - nodes, meta, err := catalog.Nodes(&opts) - if err != nil { - return nil, nil, err - } - return WaitIndexVal(meta.LastIndex), nodes, err - } - return fn, nil -} - -// serviceWatch is used to watch a specific service for changes -func serviceWatch(params map[string]interface{}) (WatcherFunc, error) { - stale := false - if err := assignValueBool(params, "stale", &stale); err != nil { - return nil, err - } - - var ( - service string - tags []string - ) - if err := assignValue(params, "service", &service); err != nil { - return nil, err - } - if service == "" { - return nil, fmt.Errorf("Must specify a single service to watch") - } - if err := assignValueStringSlice(params, "tag", &tags); err != nil { - return nil, err - } - - passingOnly := false - if err := assignValueBool(params, "passingonly", &passingOnly); err != nil { - return nil, err - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - health := p.client.Health() - opts := makeQueryOptionsWithContext(p, stale) - defer p.cancelFunc() - nodes, meta, err := health.ServiceMultipleTags(service, tags, passingOnly, &opts) - if err != nil { - return nil, nil, err - } - return WaitIndexVal(meta.LastIndex), nodes, err - } - return fn, nil -} - -// checksWatch is used to watch a specific checks in a given state -func checksWatch(params map[string]interface{}) (WatcherFunc, error) { - stale := false - if err := assignValueBool(params, "stale", &stale); err != nil { - return nil, err - } - - var service, state string - if err := assignValue(params, "service", &service); err != nil { - return nil, err - } - if err := assignValue(params, "state", &state); err != nil { - return nil, err - } - if service != "" && state != "" { - return nil, fmt.Errorf("Cannot specify service and state") - } - if service == "" && state == "" { - state = "any" - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - health := p.client.Health() - opts := makeQueryOptionsWithContext(p, stale) - defer p.cancelFunc() - var checks []*consulapi.HealthCheck - var meta *consulapi.QueryMeta - var err error - if state != "" { - checks, meta, err = health.State(state, &opts) - } else { - checks, meta, err = health.Checks(service, &opts) - } - if err != nil { - return nil, nil, err - } - return WaitIndexVal(meta.LastIndex), checks, err - } - return fn, nil -} - -// eventWatch is used to watch for events, optionally filtering on name -func eventWatch(params map[string]interface{}) (WatcherFunc, error) { - // The stale setting doesn't apply to events. - - var name string - if err := assignValue(params, "name", &name); err != nil { - return nil, err - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - event := p.client.Event() - opts := makeQueryOptionsWithContext(p, false) - defer p.cancelFunc() - events, meta, err := event.List(name, &opts) - if err != nil { - return nil, nil, err - } - - // Prune to only the new events - for i := 0; i < len(events); i++ { - if WaitIndexVal(event.IDToIndex(events[i].ID)).Equal(p.lastParamVal) { - events = events[i+1:] - break - } - } - return WaitIndexVal(meta.LastIndex), events, err - } - return fn, nil -} - -// connectRootsWatch is used to watch for changes to Connect Root certificates. -func connectRootsWatch(params map[string]interface{}) (WatcherFunc, error) { - // We don't support stale since roots are cached locally in the agent. - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - agent := p.client.Agent() - opts := makeQueryOptionsWithContext(p, false) - defer p.cancelFunc() - - roots, meta, err := agent.ConnectCARoots(&opts) - if err != nil { - return nil, nil, err - } - - return WaitIndexVal(meta.LastIndex), roots, err - } - return fn, nil -} - -// connectLeafWatch is used to watch for changes to Connect Leaf certificates -// for given local service id. -func connectLeafWatch(params map[string]interface{}) (WatcherFunc, error) { - // We don't support stale since certs are cached locally in the agent. - - var serviceName string - if err := assignValue(params, "service", &serviceName); err != nil { - return nil, err - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - agent := p.client.Agent() - opts := makeQueryOptionsWithContext(p, false) - defer p.cancelFunc() - - leaf, meta, err := agent.ConnectCALeaf(serviceName, &opts) - if err != nil { - return nil, nil, err - } - - return WaitIndexVal(meta.LastIndex), leaf, err - } - return fn, nil -} - -// connectProxyConfigWatch is used to watch for changes to Connect managed proxy -// configuration. Note that this state is agent-local so the watch mechanism -// uses `hash` rather than `index` for deciding whether to block. -func connectProxyConfigWatch(params map[string]interface{}) (WatcherFunc, error) { - // We don't support consistency modes since it's agent local data - - var proxyServiceID string - if err := assignValue(params, "proxy_service_id", &proxyServiceID); err != nil { - return nil, err - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - agent := p.client.Agent() - opts := makeQueryOptionsWithContext(p, false) - defer p.cancelFunc() - - config, _, err := agent.ConnectProxyConfig(proxyServiceID, &opts) - if err != nil { - return nil, nil, err - } - - // Return string ContentHash since we don't have Raft indexes to block on. - return WaitHashVal(config.ContentHash), config, err - } - return fn, nil -} - -// agentServiceWatch is used to watch for changes to a single service instance -// on the local agent. Note that this state is agent-local so the watch -// mechanism uses `hash` rather than `index` for deciding whether to block. -func agentServiceWatch(params map[string]interface{}) (WatcherFunc, error) { - // We don't support consistency modes since it's agent local data - - var serviceID string - if err := assignValue(params, "service_id", &serviceID); err != nil { - return nil, err - } - - fn := func(p *Plan) (BlockingParamVal, interface{}, error) { - agent := p.client.Agent() - opts := makeQueryOptionsWithContext(p, false) - defer p.cancelFunc() - - svc, _, err := agent.Service(serviceID, &opts) - if err != nil { - return nil, nil, err - } - - // Return string ContentHash since we don't have Raft indexes to block on. - return WaitHashVal(svc.ContentHash), svc, err - } - return fn, nil -} - -func makeQueryOptionsWithContext(p *Plan, stale bool) consulapi.QueryOptions { - ctx, cancel := context.WithCancel(context.Background()) - p.setCancelFunc(cancel) - opts := consulapi.QueryOptions{AllowStale: stale} - switch param := p.lastParamVal.(type) { - case WaitIndexVal: - opts.WaitIndex = uint64(param) - case WaitHashVal: - opts.WaitHash = string(param) - } - return *opts.WithContext(ctx) -} diff --git a/vendor/github.com/hashicorp/consul/api/watch/plan.go b/vendor/github.com/hashicorp/consul/api/watch/plan.go deleted file mode 100644 index f0e8a6832a..0000000000 --- a/vendor/github.com/hashicorp/consul/api/watch/plan.go +++ /dev/null @@ -1,167 +0,0 @@ -package watch - -import ( - "context" - "fmt" - "log" - "os" - "reflect" - "time" - - consulapi "github.com/hashicorp/consul/api" -) - -const ( - // retryInterval is the base retry value - retryInterval = 5 * time.Second - - // maximum back off time, this is to prevent - // exponential runaway - maxBackoffTime = 180 * time.Second -) - -func (p *Plan) Run(address string) error { - return p.RunWithConfig(address, nil) -} - -// Run is used to run a watch plan -func (p *Plan) RunWithConfig(address string, conf *consulapi.Config) error { - // Setup the client - p.address = address - if conf == nil { - conf = consulapi.DefaultConfig() - } - conf.Address = address - conf.Datacenter = p.Datacenter - conf.Token = p.Token - client, err := consulapi.NewClient(conf) - if err != nil { - return fmt.Errorf("Failed to connect to agent: %v", err) - } - - // Create the logger - output := p.LogOutput - if output == nil { - output = os.Stderr - } - logger := log.New(output, "", log.LstdFlags) - - return p.RunWithClientAndLogger(client, logger) -} - -// RunWithClientAndLogger runs a watch plan using an external client and -// log.Logger instance. Using this, the plan's Datacenter, Token and LogOutput -// fields are ignored and the passed client is expected to be configured as -// needed. -func (p *Plan) RunWithClientAndLogger(client *consulapi.Client, - logger *log.Logger) error { - - p.client = client - - // Loop until we are canceled - failures := 0 -OUTER: - for !p.shouldStop() { - // Invoke the handler - blockParamVal, result, err := p.Watcher(p) - - // Check if we should terminate since the function - // could have blocked for a while - if p.shouldStop() { - break - } - - // Handle an error in the watch function - if err != nil { - // Perform an exponential backoff - failures++ - if blockParamVal == nil { - p.lastParamVal = nil - } else { - p.lastParamVal = blockParamVal.Next(p.lastParamVal) - } - retry := retryInterval * time.Duration(failures*failures) - if retry > maxBackoffTime { - retry = maxBackoffTime - } - logger.Printf("[ERR] consul.watch: Watch (type: %s) errored: %v, retry in %v", - p.Type, err, retry) - select { - case <-time.After(retry): - continue OUTER - case <-p.stopCh: - return nil - } - } - - // Clear the failures - failures = 0 - - // If the index is unchanged do nothing - if p.lastParamVal != nil && p.lastParamVal.Equal(blockParamVal) { - continue - } - - // Update the index, look for change - oldParamVal := p.lastParamVal - p.lastParamVal = blockParamVal.Next(oldParamVal) - if oldParamVal != nil && reflect.DeepEqual(p.lastResult, result) { - continue - } - - // Handle the updated result - p.lastResult = result - // If a hybrid handler exists use that - if p.HybridHandler != nil { - p.HybridHandler(blockParamVal, result) - } else if p.Handler != nil { - idx, ok := blockParamVal.(WaitIndexVal) - if !ok { - logger.Printf("[ERR] consul.watch: Handler only supports index-based " + - " watches but non index-based watch run. Skipping Handler.") - } - p.Handler(uint64(idx), result) - } - } - return nil -} - -// Stop is used to stop running the watch plan -func (p *Plan) Stop() { - p.stopLock.Lock() - defer p.stopLock.Unlock() - if p.stop { - return - } - p.stop = true - if p.cancelFunc != nil { - p.cancelFunc() - } - close(p.stopCh) -} - -func (p *Plan) shouldStop() bool { - select { - case <-p.stopCh: - return true - default: - return false - } -} - -func (p *Plan) setCancelFunc(cancel context.CancelFunc) { - p.stopLock.Lock() - defer p.stopLock.Unlock() - if p.shouldStop() { - // The watch is stopped and execute the new cancel func to stop watchFactory - cancel() - return - } - p.cancelFunc = cancel -} - -func (p *Plan) IsStopped() bool { - p.stopLock.Lock() - defer p.stopLock.Unlock() - return p.stop -} diff --git a/vendor/github.com/hashicorp/consul/api/watch/watch.go b/vendor/github.com/hashicorp/consul/api/watch/watch.go deleted file mode 100644 index 3690a20c97..0000000000 --- a/vendor/github.com/hashicorp/consul/api/watch/watch.go +++ /dev/null @@ -1,289 +0,0 @@ -package watch - -import ( - "context" - "fmt" - "io" - "sync" - "time" - - consulapi "github.com/hashicorp/consul/api" - "github.com/mitchellh/mapstructure" -) - -const DefaultTimeout = 10 * time.Second - -// Plan is the parsed version of a watch specification. A watch provides -// the details of a query, which generates a view into the Consul data store. -// This view is watched for changes and a handler is invoked to take any -// appropriate actions. -type Plan struct { - Datacenter string - Token string - Type string - HandlerType string - Exempt map[string]interface{} - - Watcher WatcherFunc - // Handler is kept for backward compatibility but only supports watches based - // on index param. To support hash based watches, set HybridHandler instead. - Handler HandlerFunc - HybridHandler HybridHandlerFunc - LogOutput io.Writer - - address string - client *consulapi.Client - lastParamVal BlockingParamVal - lastResult interface{} - - stop bool - stopCh chan struct{} - stopLock sync.Mutex - cancelFunc context.CancelFunc -} - -type HttpHandlerConfig struct { - Path string `mapstructure:"path"` - Method string `mapstructure:"method"` - Timeout time.Duration `mapstructure:"-"` - TimeoutRaw string `mapstructure:"timeout"` - Header map[string][]string `mapstructure:"header"` - TLSSkipVerify bool `mapstructure:"tls_skip_verify"` -} - -// BlockingParamVal is an interface representing the common operations needed for -// different styles of blocking. It's used to abstract the core watch plan from -// whether we are performing index-based or hash-based blocking. -type BlockingParamVal interface { - // Equal returns whether the other param value should be considered equal - // (i.e. representing no change in the watched resource). Equal must not panic - // if other is nil. - Equal(other BlockingParamVal) bool - - // Next is called when deciding which value to use on the next blocking call. - // It assumes the BlockingParamVal value it is called on is the most recent one - // returned and passes the previous one which may be nil as context. This - // allows types to customize logic around ordering without assuming there is - // an order. For example WaitIndexVal can check that the index didn't go - // backwards and if it did then reset to 0. Most other cases should just - // return themselves (the most recent value) to be used in the next request. - Next(previous BlockingParamVal) BlockingParamVal -} - -// WaitIndexVal is a type representing a Consul index that implements -// BlockingParamVal. -type WaitIndexVal uint64 - -// Equal implements BlockingParamVal -func (idx WaitIndexVal) Equal(other BlockingParamVal) bool { - if otherIdx, ok := other.(WaitIndexVal); ok { - return idx == otherIdx - } - return false -} - -// Next implements BlockingParamVal -func (idx WaitIndexVal) Next(previous BlockingParamVal) BlockingParamVal { - if previous == nil { - return idx - } - prevIdx, ok := previous.(WaitIndexVal) - if ok && prevIdx > idx { - // This value is smaller than the previous index, reset. - return WaitIndexVal(0) - } - return idx -} - -// WaitHashVal is a type representing a Consul content hash that implements -// BlockingParamVal. -type WaitHashVal string - -// Equal implements BlockingParamVal -func (h WaitHashVal) Equal(other BlockingParamVal) bool { - if otherHash, ok := other.(WaitHashVal); ok { - return h == otherHash - } - return false -} - -// Next implements BlockingParamVal -func (h WaitHashVal) Next(previous BlockingParamVal) BlockingParamVal { - return h -} - -// WatcherFunc is used to watch for a diff. -type WatcherFunc func(*Plan) (BlockingParamVal, interface{}, error) - -// HandlerFunc is used to handle new data. It only works for index-based watches -// (which is almost all end points currently) and is kept for backwards -// compatibility until more places can make use of hash-based watches too. -type HandlerFunc func(uint64, interface{}) - -// HybridHandlerFunc is used to handle new data. It can support either -// index-based or hash-based watches via the BlockingParamVal. -type HybridHandlerFunc func(BlockingParamVal, interface{}) - -// Parse takes a watch query and compiles it into a WatchPlan or an error -func Parse(params map[string]interface{}) (*Plan, error) { - return ParseExempt(params, nil) -} - -// ParseExempt takes a watch query and compiles it into a WatchPlan or an error -// Any exempt parameters are stored in the Exempt map -func ParseExempt(params map[string]interface{}, exempt []string) (*Plan, error) { - plan := &Plan{ - stopCh: make(chan struct{}), - Exempt: make(map[string]interface{}), - } - - // Parse the generic parameters - if err := assignValue(params, "datacenter", &plan.Datacenter); err != nil { - return nil, err - } - if err := assignValue(params, "token", &plan.Token); err != nil { - return nil, err - } - if err := assignValue(params, "type", &plan.Type); err != nil { - return nil, err - } - // Ensure there is a watch type - if plan.Type == "" { - return nil, fmt.Errorf("Watch type must be specified") - } - - // Get the specific handler - if err := assignValue(params, "handler_type", &plan.HandlerType); err != nil { - return nil, err - } - switch plan.HandlerType { - case "http": - if _, ok := params["http_handler_config"]; !ok { - return nil, fmt.Errorf("Handler type 'http' requires 'http_handler_config' to be set") - } - config, err := parseHttpHandlerConfig(params["http_handler_config"]) - if err != nil { - return nil, fmt.Errorf(fmt.Sprintf("Failed to parse 'http_handler_config': %v", err)) - } - plan.Exempt["http_handler_config"] = config - delete(params, "http_handler_config") - - case "script": - // Let the caller check for configuration in exempt parameters - } - - // Look for a factory function - factory := watchFuncFactory[plan.Type] - if factory == nil { - return nil, fmt.Errorf("Unsupported watch type: %s", plan.Type) - } - - // Get the watch func - fn, err := factory(params) - if err != nil { - return nil, err - } - plan.Watcher = fn - - // Remove the exempt parameters - if len(exempt) > 0 { - for _, ex := range exempt { - val, ok := params[ex] - if ok { - plan.Exempt[ex] = val - delete(params, ex) - } - } - } - - // Ensure all parameters are consumed - if len(params) != 0 { - var bad []string - for key := range params { - bad = append(bad, key) - } - return nil, fmt.Errorf("Invalid parameters: %v", bad) - } - return plan, nil -} - -// assignValue is used to extract a value ensuring it is a string -func assignValue(params map[string]interface{}, name string, out *string) error { - if raw, ok := params[name]; ok { - val, ok := raw.(string) - if !ok { - return fmt.Errorf("Expecting %s to be a string", name) - } - *out = val - delete(params, name) - } - return nil -} - -// assignValueBool is used to extract a value ensuring it is a bool -func assignValueBool(params map[string]interface{}, name string, out *bool) error { - if raw, ok := params[name]; ok { - val, ok := raw.(bool) - if !ok { - return fmt.Errorf("Expecting %s to be a boolean", name) - } - *out = val - delete(params, name) - } - return nil -} - -// assignValueStringSlice is used to extract a value ensuring it is either a string or a slice of strings -func assignValueStringSlice(params map[string]interface{}, name string, out *[]string) error { - if raw, ok := params[name]; ok { - var tmp []string - switch raw.(type) { - case string: - tmp = make([]string, 1, 1) - tmp[0] = raw.(string) - case []string: - l := len(raw.([]string)) - tmp = make([]string, l, l) - copy(tmp, raw.([]string)) - case []interface{}: - l := len(raw.([]interface{})) - tmp = make([]string, l, l) - for i, v := range raw.([]interface{}) { - if s, ok := v.(string); ok { - tmp[i] = s - } else { - return fmt.Errorf("Index %d of %s expected to be string", i, name) - } - } - default: - return fmt.Errorf("Expecting %s to be a string or []string", name) - } - *out = tmp - delete(params, name) - } - return nil -} - -// Parse the 'http_handler_config' parameters -func parseHttpHandlerConfig(configParams interface{}) (*HttpHandlerConfig, error) { - var config HttpHandlerConfig - if err := mapstructure.Decode(configParams, &config); err != nil { - return nil, err - } - - if config.Path == "" { - return nil, fmt.Errorf("Requires 'path' to be set") - } - if config.Method == "" { - config.Method = "POST" - } - if config.TimeoutRaw == "" { - config.Timeout = DefaultTimeout - } else if timeout, err := time.ParseDuration(config.TimeoutRaw); err != nil { - return nil, fmt.Errorf(fmt.Sprintf("Failed to parse timeout: %v", err)) - } else { - config.Timeout = timeout - } - - return &config, nil -} diff --git a/vendor/github.com/hashicorp/consul/sdk/freeport/freeport.go b/vendor/github.com/hashicorp/consul/sdk/freeport/freeport.go deleted file mode 100644 index 806449ba4a..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/freeport/freeport.go +++ /dev/null @@ -1,139 +0,0 @@ -// Package freeport provides a helper for allocating free ports across multiple -// processes on the same machine. -package freeport - -import ( - "fmt" - "math/rand" - "net" - "sync" - "time" - - "github.com/mitchellh/go-testing-interface" -) - -const ( - // blockSize is the size of the allocated port block. ports are given out - // consecutively from that block with roll-over for the lifetime of the - // application/test run. - blockSize = 1500 - - // maxBlocks is the number of available port blocks. - // lowPort + maxBlocks * blockSize must be less than 65535. - maxBlocks = 30 - - // lowPort is the lowest port number that should be used. - lowPort = 10000 - - // attempts is how often we try to allocate a port block - // before giving up. - attempts = 10 -) - -var ( - // firstPort is the first port of the allocated block. - firstPort int - - // lockLn is the system-wide mutex for the port block. - lockLn net.Listener - - // mu guards nextPort - mu sync.Mutex - - // once is used to do the initialization on the first call to retrieve free - // ports - once sync.Once - - // port is the last allocated port. - port int -) - -// initialize is used to initialize freeport. -func initialize() { - if lowPort+maxBlocks*blockSize > 65535 { - panic("freeport: block size too big or too many blocks requested") - } - - rand.Seed(time.Now().UnixNano()) - firstPort, lockLn = alloc() -} - -// alloc reserves a port block for exclusive use for the lifetime of the -// application. lockLn serves as a system-wide mutex for the port block and is -// implemented as a TCP listener which is bound to the firstPort and which will -// be automatically released when the application terminates. -func alloc() (int, net.Listener) { - for i := 0; i < attempts; i++ { - block := int(rand.Int31n(int32(maxBlocks))) - firstPort := lowPort + block*blockSize - ln, err := net.ListenTCP("tcp", tcpAddr("127.0.0.1", firstPort)) - if err != nil { - continue - } - // log.Printf("[DEBUG] freeport: allocated port block %d (%d-%d)", block, firstPort, firstPort+blockSize-1) - return firstPort, ln - } - panic("freeport: cannot allocate port block") -} - -func tcpAddr(ip string, port int) *net.TCPAddr { - return &net.TCPAddr{IP: net.ParseIP(ip), Port: port} -} - -// Get wraps the Free function and panics on any failure retrieving ports. -func Get(n int) (ports []int) { - ports, err := Free(n) - if err != nil { - panic(err) - } - - return ports -} - -// GetT is suitable for use when retrieving unused ports in tests. If there is -// an error retrieving free ports, the test will be failed. -func GetT(t testing.T, n int) (ports []int) { - ports, err := Free(n) - if err != nil { - t.Fatalf("Failed retrieving free port: %v", err) - } - - return ports -} - -// Free returns a list of free ports from the allocated port block. It is safe -// to call this method concurrently. Ports have been tested to be available on -// 127.0.0.1 TCP but there is no guarantee that they will remain free in the -// future. -func Free(n int) (ports []int, err error) { - mu.Lock() - defer mu.Unlock() - - if n > blockSize-1 { - return nil, fmt.Errorf("freeport: block size too small") - } - - // Reserve a port block - once.Do(initialize) - - for len(ports) < n { - port++ - - // roll-over the port - if port < firstPort+1 || port >= firstPort+blockSize { - port = firstPort + 1 - } - - // if the port is in use then skip it - ln, err := net.ListenTCP("tcp", tcpAddr("127.0.0.1", port)) - if err != nil { - // log.Println("[DEBUG] freeport: port already in use: ", port) - continue - } - ln.Close() - - ports = append(ports, port) - } - // log.Println("[DEBUG] freeport: free ports:", ports) - return ports, nil -} diff --git a/vendor/github.com/hashicorp/consul/sdk/testutil/README.md b/vendor/github.com/hashicorp/consul/sdk/testutil/README.md deleted file mode 100644 index 2462d55dfb..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/testutil/README.md +++ /dev/null @@ -1,78 +0,0 @@ -Consul Testing Utilities -======================== - -This package provides some generic helpers to facilitate testing in Consul. - -TestServer -========== - -TestServer is a harness for managing Consul agents and initializing them with -test data. Using it, you can form test clusters, create services, add health -checks, manipulate the K/V store, etc. This test harness is completely decoupled -from Consul's core and API client, meaning it can be easily imported and used in -external unit tests for various applications. It works by invoking the Consul -CLI, which means it is a requirement to have Consul installed in the `$PATH`. - -Following is an example usage: - -```go -package my_program - -import ( - "testing" - - "github.com/hashicorp/consul/consul/structs" - "github.com/hashicorp/consul/sdk/testutil" -) - -func TestFoo_bar(t *testing.T) { - // Create a test Consul server - srv1, err := testutil.NewTestServer() - if err != nil { - t.Fatal(err) - } - defer srv1.Stop() - - // Create a secondary server, passing in configuration - // to avoid bootstrapping as we are forming a cluster. - srv2, err := testutil.NewTestServerConfig(t, func(c *testutil.TestServerConfig) { - c.Bootstrap = false - }) - if err != nil { - t.Fatal(err) - } - defer srv2.Stop() - - // Join the servers together - srv1.JoinLAN(t, srv2.LANAddr) - - // Create a test key/value pair - srv1.SetKV(t, "foo", []byte("bar")) - - // Create lots of test key/value pairs - srv1.PopulateKV(t, map[string][]byte{ - "bar": []byte("123"), - "baz": []byte("456"), - }) - - // Create a service - srv1.AddService(t, "redis", structs.HealthPassing, []string{"master"}) - - // Create a service that will be accessed in target source code - srv1.AddAccessibleService("redis", structs.HealthPassing, "127.0.0.1", 6379, []string{"master"}) - - // Create a service check - srv1.AddCheck(t, "service:redis", "redis", structs.HealthPassing) - - // Create a node check - srv1.AddCheck(t, "mem", "", structs.HealthCritical) - - // The HTTPAddr field contains the address of the Consul - // API on the new test server instance. - println(srv1.HTTPAddr) - - // All functions also have a wrapper method to limit the passing of "t" - wrap := srv1.Wrap(t) - wrap.SetKV("foo", []byte("bar")) -} -``` diff --git a/vendor/github.com/hashicorp/consul/sdk/testutil/io.go b/vendor/github.com/hashicorp/consul/sdk/testutil/io.go deleted file mode 100644 index a137fc6a3f..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/testutil/io.go +++ /dev/null @@ -1,68 +0,0 @@ -package testutil - -import ( - "fmt" - "io/ioutil" - "os" - "strings" - "testing" -) - -// tmpdir is the base directory for all temporary directories -// and files created with TempDir and TempFile. This could be -// achieved by setting a system environment variable but then -// the test execution would depend on whether or not the -// environment variable is set. -// -// On macOS the temp base directory is quite long and that -// triggers a problem with some tests that bind to UNIX sockets -// where the filename seems to be too long. Using a shorter name -// fixes this and makes the paths more readable. -// -// It also provides a single base directory for cleanup. -var tmpdir = "/tmp/consul-test" - -func init() { - if err := os.MkdirAll(tmpdir, 0755); err != nil { - fmt.Printf("Cannot create %s. Reverting to /tmp\n", tmpdir) - tmpdir = "/tmp" - } -} - -// TempDir creates a temporary directory within tmpdir -// with the name 'testname-name'. If the directory cannot -// be created t.Fatal is called. -func TempDir(t *testing.T, name string) string { - if t != nil && t.Name() != "" { - name = t.Name() + "-" + name - } - name = strings.Replace(name, "/", "_", -1) - d, err := ioutil.TempDir(tmpdir, name) - if err != nil { - if t == nil { - panic(err) - } - t.Fatalf("err: %s", err) - } - return d -} - -// TempFile creates a temporary file within tmpdir -// with the name 'testname-name'. If the file cannot -// be created t.Fatal is called. If a temporary directory -// has been created before consider storing the file -// inside this directory to avoid double cleanup. -func TempFile(t *testing.T, name string) *os.File { - if t != nil && t.Name() != "" { - name = t.Name() + "-" + name - } - name = strings.Replace(name, "/", "_", -1) - f, err := ioutil.TempFile(tmpdir, name) - if err != nil { - if t == nil { - panic(err) - } - t.Fatalf("err: %s", err) - } - return f -} diff --git a/vendor/github.com/hashicorp/consul/sdk/testutil/retry/retry.go b/vendor/github.com/hashicorp/consul/sdk/testutil/retry/retry.go deleted file mode 100644 index 2ef3c4c0eb..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/testutil/retry/retry.go +++ /dev/null @@ -1,207 +0,0 @@ -// Package retry provides support for repeating operations in tests. -// -// A sample retry operation looks like this: -// -// func TestX(t *testing.T) { -// retry.Run(t, func(r *retry.R) { -// if err := foo(); err != nil { -// r.Fatal("f: ", err) -// } -// }) -// } -// -package retry - -import ( - "bytes" - "fmt" - "runtime" - "strings" - "sync" - "time" -) - -// Failer is an interface compatible with testing.T. -type Failer interface { - // Log is called for the final test output - Log(args ...interface{}) - - // FailNow is called when the retrying is abandoned. - FailNow() -} - -// R provides context for the retryer. -type R struct { - fail bool - output []string -} - -func (r *R) FailNow() { - r.fail = true - runtime.Goexit() -} - -func (r *R) Fatal(args ...interface{}) { - r.log(fmt.Sprint(args...)) - r.FailNow() -} - -func (r *R) Fatalf(format string, args ...interface{}) { - r.log(fmt.Sprintf(format, args...)) - r.FailNow() -} - -func (r *R) Error(args ...interface{}) { - r.log(fmt.Sprint(args...)) - r.fail = true -} - -func (r *R) Errorf(format string, args ...interface{}) { - r.log(fmt.Sprintf(format, args...)) - r.fail = true -} - -func (r *R) Check(err error) { - if err != nil { - r.log(err.Error()) - r.FailNow() - } -} - -func (r *R) log(s string) { - r.output = append(r.output, decorate(s)) -} - -func decorate(s string) string { - _, file, line, ok := runtime.Caller(3) - if ok { - n := strings.LastIndex(file, "/") - if n >= 0 { - file = file[n+1:] - } - } else { - file = "???" - line = 1 - } - return fmt.Sprintf("%s:%d: %s", file, line, s) -} - -func Run(t Failer, f func(r *R)) { - run(DefaultFailer(), t, f) -} - -func RunWith(r Retryer, t Failer, f func(r *R)) { - run(r, t, f) -} - -func dedup(a []string) string { - if len(a) == 0 { - return "" - } - m := map[string]int{} - for _, s := range a { - m[s] = m[s] + 1 - } - var b bytes.Buffer - for _, s := range a { - if _, ok := m[s]; ok { - b.WriteString(s) - b.WriteRune('\n') - delete(m, s) - } - } - return string(b.Bytes()) -} - -func run(r Retryer, t Failer, f func(r *R)) { - rr := &R{} - fail := func() { - out := dedup(rr.output) - if out != "" { - t.Log(out) - } - t.FailNow() - } - for r.NextOr(fail) { - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - f(rr) - }() - wg.Wait() - if rr.fail { - rr.fail = false - continue - } - break - } -} - -// DefaultFailer provides default retry.Run() behavior for unit tests. -func DefaultFailer() *Timer { - return &Timer{Timeout: 7 * time.Second, Wait: 25 * time.Millisecond} -} - -// TwoSeconds repeats an operation for two seconds and waits 25ms in between. -func TwoSeconds() *Timer { - return &Timer{Timeout: 2 * time.Second, Wait: 25 * time.Millisecond} -} - -// ThreeTimes repeats an operation three times and waits 25ms in between. -func ThreeTimes() *Counter { - return &Counter{Count: 3, Wait: 25 * time.Millisecond} -} - -// Retryer provides an interface for repeating operations -// until they succeed or an exit condition is met. -type Retryer interface { - // NextOr returns true if the operation should be repeated. - // Otherwise, it calls fail and returns false. - NextOr(fail func()) bool -} - -// Counter repeats an operation a given number of -// times and waits between subsequent operations. -type Counter struct { - Count int - Wait time.Duration - - count int -} - -func (r *Counter) NextOr(fail func()) bool { - if r.count == r.Count { - fail() - return false - } - if r.count > 0 { - time.Sleep(r.Wait) - } - r.count++ - return true -} - -// Timer repeats an operation for a given amount -// of time and waits between subsequent operations. -type Timer struct { - Timeout time.Duration - Wait time.Duration - - // stop is the timeout deadline. - // Set on the first invocation of Next(). - stop time.Time -} - -func (r *Timer) NextOr(fail func()) bool { - if r.stop.IsZero() { - r.stop = time.Now().Add(r.Timeout) - return true - } - if time.Now().After(r.stop) { - fail() - return false - } - time.Sleep(r.Wait) - return true -} diff --git a/vendor/github.com/hashicorp/consul/sdk/testutil/server.go b/vendor/github.com/hashicorp/consul/sdk/testutil/server.go deleted file mode 100644 index 4005eea49e..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/testutil/server.go +++ /dev/null @@ -1,473 +0,0 @@ -package testutil - -// TestServer is a test helper. It uses a fork/exec model to create -// a test Consul server instance in the background and initialize it -// with some data and/or services. The test server can then be used -// to run a unit test, and offers an easy API to tear itself down -// when the test has completed. The only prerequisite is to have a consul -// binary available on the $PATH. -// -// This package does not use Consul's official API client. This is -// because we use TestServer to test the API client, which would -// otherwise cause an import cycle. - -import ( - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" - "testing" - "time" - - "github.com/hashicorp/consul/sdk/freeport" - "github.com/hashicorp/consul/sdk/testutil/retry" - "github.com/hashicorp/go-cleanhttp" - "github.com/hashicorp/go-uuid" - "github.com/pkg/errors" -) - -// TestPerformanceConfig configures the performance parameters. -type TestPerformanceConfig struct { - RaftMultiplier uint `json:"raft_multiplier,omitempty"` -} - -// TestPortConfig configures the various ports used for services -// provided by the Consul server. -type TestPortConfig struct { - DNS int `json:"dns,omitempty"` - HTTP int `json:"http,omitempty"` - HTTPS int `json:"https,omitempty"` - SerfLan int `json:"serf_lan,omitempty"` - SerfWan int `json:"serf_wan,omitempty"` - Server int `json:"server,omitempty"` - ProxyMinPort int `json:"proxy_min_port,omitempty"` - ProxyMaxPort int `json:"proxy_max_port,omitempty"` -} - -// TestAddressConfig contains the bind addresses for various -// components of the Consul server. -type TestAddressConfig struct { - HTTP string `json:"http,omitempty"` -} - -// TestNetworkSegment contains the configuration for a network segment. -type TestNetworkSegment struct { - Name string `json:"name"` - Bind string `json:"bind"` - Port int `json:"port"` - Advertise string `json:"advertise"` -} - -// TestServerConfig is the main server configuration struct. -type TestServerConfig struct { - NodeName string `json:"node_name"` - NodeID string `json:"node_id"` - NodeMeta map[string]string `json:"node_meta,omitempty"` - Performance *TestPerformanceConfig `json:"performance,omitempty"` - Bootstrap bool `json:"bootstrap,omitempty"` - Server bool `json:"server,omitempty"` - DataDir string `json:"data_dir,omitempty"` - Datacenter string `json:"datacenter,omitempty"` - Segments []TestNetworkSegment `json:"segments"` - DisableCheckpoint bool `json:"disable_update_check"` - LogLevel string `json:"log_level,omitempty"` - Bind string `json:"bind_addr,omitempty"` - Addresses *TestAddressConfig `json:"addresses,omitempty"` - Ports *TestPortConfig `json:"ports,omitempty"` - RaftProtocol int `json:"raft_protocol,omitempty"` - ACLMasterToken string `json:"acl_master_token,omitempty"` - ACLDatacenter string `json:"acl_datacenter,omitempty"` - PrimaryDatacenter string `json:"primary_datacenter,omitempty"` - ACLDefaultPolicy string `json:"acl_default_policy,omitempty"` - ACLEnforceVersion8 bool `json:"acl_enforce_version_8"` - ACL TestACLs `json:"acl,omitempty"` - Encrypt string `json:"encrypt,omitempty"` - CAFile string `json:"ca_file,omitempty"` - CertFile string `json:"cert_file,omitempty"` - KeyFile string `json:"key_file,omitempty"` - VerifyIncoming bool `json:"verify_incoming,omitempty"` - VerifyIncomingRPC bool `json:"verify_incoming_rpc,omitempty"` - VerifyIncomingHTTPS bool `json:"verify_incoming_https,omitempty"` - VerifyOutgoing bool `json:"verify_outgoing,omitempty"` - EnableScriptChecks bool `json:"enable_script_checks,omitempty"` - Connect map[string]interface{} `json:"connect,omitempty"` - EnableDebug bool `json:"enable_debug,omitempty"` - ReadyTimeout time.Duration `json:"-"` - Stdout, Stderr io.Writer `json:"-"` - Args []string `json:"-"` -} - -type TestACLs struct { - Enabled bool `json:"enabled,omitempty"` - TokenReplication bool `json:"enable_token_replication,omitempty"` - PolicyTTL string `json:"policy_ttl,omitempty"` - TokenTTL string `json:"token_ttl,omitempty"` - DownPolicy string `json:"down_policy,omitempty"` - DefaultPolicy string `json:"default_policy,omitempty"` - EnableKeyListPolicy bool `json:"enable_key_list_policy,omitempty"` - Tokens TestTokens `json:"tokens,omitempty"` - DisabledTTL string `json:"disabled_ttl,omitempty"` -} - -type TestTokens struct { - Master string `json:"master,omitempty"` - Replication string `json:"replication,omitempty"` - AgentMaster string `json:"agent_master,omitempty"` - Default string `json:"default,omitempty"` - Agent string `json:"agent,omitempty"` -} - -// ServerConfigCallback is a function interface which can be -// passed to NewTestServerConfig to modify the server config. -type ServerConfigCallback func(c *TestServerConfig) - -// defaultServerConfig returns a new TestServerConfig struct -// with all of the listen ports incremented by one. -func defaultServerConfig() *TestServerConfig { - nodeID, err := uuid.GenerateUUID() - if err != nil { - panic(err) - } - - ports := freeport.Get(6) - return &TestServerConfig{ - NodeName: "node-" + nodeID, - NodeID: nodeID, - DisableCheckpoint: true, - Performance: &TestPerformanceConfig{ - RaftMultiplier: 1, - }, - Bootstrap: true, - Server: true, - LogLevel: "debug", - Bind: "127.0.0.1", - Addresses: &TestAddressConfig{}, - Ports: &TestPortConfig{ - DNS: ports[0], - HTTP: ports[1], - HTTPS: ports[2], - SerfLan: ports[3], - SerfWan: ports[4], - Server: ports[5], - }, - ReadyTimeout: 10 * time.Second, - Connect: map[string]interface{}{ - "enabled": true, - "ca_config": map[string]interface{}{ - // const TestClusterID causes import cycle so hard code it here. - "cluster_id": "11111111-2222-3333-4444-555555555555", - }, - "proxy": map[string]interface{}{ - "allow_managed_api_registration": true, - }, - }, - } -} - -// TestService is used to serialize a service definition. -type TestService struct { - ID string `json:",omitempty"` - Name string `json:",omitempty"` - Tags []string `json:",omitempty"` - Address string `json:",omitempty"` - Port int `json:",omitempty"` -} - -// TestCheck is used to serialize a check definition. -type TestCheck struct { - ID string `json:",omitempty"` - Name string `json:",omitempty"` - ServiceID string `json:",omitempty"` - TTL string `json:",omitempty"` -} - -// TestKVResponse is what we use to decode KV data. -type TestKVResponse struct { - Value string -} - -// TestServer is the main server wrapper struct. -type TestServer struct { - cmd *exec.Cmd - Config *TestServerConfig - - HTTPAddr string - HTTPSAddr string - LANAddr string - WANAddr string - - HTTPClient *http.Client - - tmpdir string -} - -// NewTestServer is an easy helper method to create a new Consul -// test server with the most basic configuration. -func NewTestServer() (*TestServer, error) { - return NewTestServerConfigT(nil, nil) -} - -func NewTestServerConfig(cb ServerConfigCallback) (*TestServer, error) { - return NewTestServerConfigT(nil, cb) -} - -// NewTestServerConfig creates a new TestServer, and makes a call to an optional -// callback function to modify the configuration. If there is an error -// configuring or starting the server, the server will NOT be running when the -// function returns (thus you do not need to stop it). -func NewTestServerConfigT(t *testing.T, cb ServerConfigCallback) (*TestServer, error) { - return newTestServerConfigT(t, cb) -} - -// newTestServerConfigT is the internal helper for NewTestServerConfigT. -func newTestServerConfigT(t *testing.T, cb ServerConfigCallback) (*TestServer, error) { - path, err := exec.LookPath("consul") - if err != nil || path == "" { - return nil, fmt.Errorf("consul not found on $PATH - download and install " + - "consul or skip this test") - } - - tmpdir := TempDir(t, "consul") - cfg := defaultServerConfig() - cfg.DataDir = filepath.Join(tmpdir, "data") - if cb != nil { - cb(cfg) - } - - b, err := json.Marshal(cfg) - if err != nil { - return nil, errors.Wrap(err, "failed marshaling json") - } - - log.Printf("CONFIG JSON: %s", string(b)) - configFile := filepath.Join(tmpdir, "config.json") - if err := ioutil.WriteFile(configFile, b, 0644); err != nil { - defer os.RemoveAll(tmpdir) - return nil, errors.Wrap(err, "failed writing config content") - } - - stdout := io.Writer(os.Stdout) - if cfg.Stdout != nil { - stdout = cfg.Stdout - } - stderr := io.Writer(os.Stderr) - if cfg.Stderr != nil { - stderr = cfg.Stderr - } - - // Start the server - args := []string{"agent", "-config-file", configFile} - args = append(args, cfg.Args...) - cmd := exec.Command("consul", args...) - cmd.Stdout = stdout - cmd.Stderr = stderr - if err := cmd.Start(); err != nil { - return nil, errors.Wrap(err, "failed starting command") - } - - httpAddr := fmt.Sprintf("127.0.0.1:%d", cfg.Ports.HTTP) - client := cleanhttp.DefaultClient() - if strings.HasPrefix(cfg.Addresses.HTTP, "unix://") { - httpAddr = cfg.Addresses.HTTP - tr := cleanhttp.DefaultTransport() - tr.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", httpAddr[len("unix://"):]) - } - client = &http.Client{Transport: tr} - } - - server := &TestServer{ - Config: cfg, - cmd: cmd, - - HTTPAddr: httpAddr, - HTTPSAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.HTTPS), - LANAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.SerfLan), - WANAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.SerfWan), - - HTTPClient: client, - - tmpdir: tmpdir, - } - - // Wait for the server to be ready - if cfg.Bootstrap { - err = server.waitForLeader() - } else { - err = server.waitForAPI() - } - if err != nil { - defer server.Stop() - return nil, errors.Wrap(err, "failed waiting for server to start") - } - return server, nil -} - -// Stop stops the test Consul server, and removes the Consul data -// directory once we are done. -func (s *TestServer) Stop() error { - defer os.RemoveAll(s.tmpdir) - - // There was no process - if s.cmd == nil { - return nil - } - - if s.cmd.Process != nil { - if err := s.cmd.Process.Signal(os.Interrupt); err != nil { - return errors.Wrap(err, "failed to kill consul server") - } - } - - // wait for the process to exit to be sure that the data dir can be - // deleted on all platforms. - return s.cmd.Wait() -} - -type failer struct { - failed bool -} - -func (f *failer) Log(args ...interface{}) { fmt.Println(args...) } -func (f *failer) FailNow() { f.failed = true } - -// waitForAPI waits for only the agent HTTP endpoint to start -// responding. This is an indication that the agent has started, -// but will likely return before a leader is elected. -func (s *TestServer) waitForAPI() error { - f := &failer{} - retry.Run(f, func(r *retry.R) { - resp, err := s.HTTPClient.Get(s.url("/v1/agent/self")) - if err != nil { - r.Fatal(err) - } - defer resp.Body.Close() - if err := s.requireOK(resp); err != nil { - r.Fatal("failed OK response", err) - } - }) - if f.failed { - return errors.New("failed waiting for API") - } - return nil -} - -// waitForLeader waits for the Consul server's HTTP API to become -// available, and then waits for a known leader and an index of -// 1 or more to be observed to confirm leader election is done. -// It then waits to ensure the anti-entropy sync has completed. -func (s *TestServer) waitForLeader() error { - f := &failer{} - timer := &retry.Timer{ - Timeout: s.Config.ReadyTimeout, - Wait: 250 * time.Millisecond, - } - var index int64 - retry.RunWith(timer, f, func(r *retry.R) { - // Query the API and check the status code. - url := s.url(fmt.Sprintf("/v1/catalog/nodes?index=%d", index)) - resp, err := s.HTTPClient.Get(url) - if err != nil { - r.Fatal("failed http get", err) - } - defer resp.Body.Close() - if err := s.requireOK(resp); err != nil { - r.Fatal("failed OK response", err) - } - - // Ensure we have a leader and a node registration. - if leader := resp.Header.Get("X-Consul-KnownLeader"); leader != "true" { - r.Fatalf("Consul leader status: %#v", leader) - } - index, err = strconv.ParseInt(resp.Header.Get("X-Consul-Index"), 10, 64) - if err != nil { - r.Fatal("bad consul index", err) - } - if index == 0 { - r.Fatal("consul index is 0") - } - - // Watch for the anti-entropy sync to finish. - var v []map[string]interface{} - dec := json.NewDecoder(resp.Body) - if err := dec.Decode(&v); err != nil { - r.Fatal(err) - } - if len(v) < 1 { - r.Fatal("No nodes") - } - taggedAddresses, ok := v[0]["TaggedAddresses"].(map[string]interface{}) - if !ok { - r.Fatal("Missing tagged addresses") - } - if _, ok := taggedAddresses["lan"]; !ok { - r.Fatal("No lan tagged addresses") - } - }) - if f.failed { - return errors.New("failed waiting for leader") - } - return nil -} - -// WaitForSerfCheck ensures we have a node with serfHealth check registered -// Behavior mirrors testrpc.WaitForTestAgent but avoids the dependency cycle in api pkg -func (s *TestServer) WaitForSerfCheck(t *testing.T) { - retry.Run(t, func(r *retry.R) { - // Query the API and check the status code. - url := s.url("/v1/catalog/nodes?index=0") - resp, err := s.HTTPClient.Get(url) - if err != nil { - r.Fatal("failed http get", err) - } - defer resp.Body.Close() - if err := s.requireOK(resp); err != nil { - r.Fatal("failed OK response", err) - } - - // Watch for the anti-entropy sync to finish. - var payload []map[string]interface{} - dec := json.NewDecoder(resp.Body) - if err := dec.Decode(&payload); err != nil { - r.Fatal(err) - } - if len(payload) < 1 { - r.Fatal("No nodes") - } - - // Ensure the serfHealth check is registered - url = s.url(fmt.Sprintf("/v1/health/node/%s", payload[0]["Node"])) - resp, err = s.HTTPClient.Get(url) - if err != nil { - r.Fatal("failed http get", err) - } - defer resp.Body.Close() - if err := s.requireOK(resp); err != nil { - r.Fatal("failed OK response", err) - } - dec = json.NewDecoder(resp.Body) - if err = dec.Decode(&payload); err != nil { - r.Fatal(err) - } - - var found bool - for _, check := range payload { - if check["CheckID"].(string) == "serfHealth" { - found = true - break - } - } - if !found { - r.Fatal("missing serfHealth registration") - } - }) -} diff --git a/vendor/github.com/hashicorp/consul/sdk/testutil/server_methods.go b/vendor/github.com/hashicorp/consul/sdk/testutil/server_methods.go deleted file mode 100644 index dec512054c..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/testutil/server_methods.go +++ /dev/null @@ -1,256 +0,0 @@ -package testutil - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "log" - "net/http" - "testing" - - "github.com/pkg/errors" -) - -// copied from testutil to break circular dependency -const ( - HealthAny = "any" - HealthPassing = "passing" - HealthWarning = "warning" - HealthCritical = "critical" - HealthMaint = "maintenance" -) - -// JoinLAN is used to join local datacenters together. -func (s *TestServer) JoinLAN(t *testing.T, addr string) { - resp := s.put(t, "/v1/agent/join/"+addr, nil) - defer resp.Body.Close() -} - -// JoinWAN is used to join remote datacenters together. -func (s *TestServer) JoinWAN(t *testing.T, addr string) { - resp := s.put(t, "/v1/agent/join/"+addr+"?wan=1", nil) - resp.Body.Close() -} - -// SetKV sets an individual key in the K/V store. -func (s *TestServer) SetKV(t *testing.T, key string, val []byte) { - resp := s.put(t, "/v1/kv/"+key, bytes.NewBuffer(val)) - resp.Body.Close() -} - -// SetKVString sets an individual key in the K/V store, but accepts a string -// instead of []byte. -func (s *TestServer) SetKVString(t *testing.T, key string, val string) { - resp := s.put(t, "/v1/kv/"+key, bytes.NewBufferString(val)) - resp.Body.Close() -} - -// GetKV retrieves a single key and returns its value -func (s *TestServer) GetKV(t *testing.T, key string) []byte { - resp := s.get(t, "/v1/kv/"+key) - defer resp.Body.Close() - - raw, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("failed to read body: %s", err) - } - - var result []*TestKVResponse - if err := json.Unmarshal(raw, &result); err != nil { - t.Fatalf("failed to unmarshal: %s", err) - } - if len(result) < 1 { - t.Fatalf("key does not exist: %s", key) - } - - v, err := base64.StdEncoding.DecodeString(result[0].Value) - if err != nil { - t.Fatalf("failed to base64 decode: %s", err) - } - - return v -} - -// GetKVString retrieves a value from the store, but returns as a string instead -// of []byte. -func (s *TestServer) GetKVString(t *testing.T, key string) string { - return string(s.GetKV(t, key)) -} - -// PopulateKV fills the Consul KV with data from a generic map. -func (s *TestServer) PopulateKV(t *testing.T, data map[string][]byte) { - for k, v := range data { - s.SetKV(t, k, v) - } -} - -// ListKV returns a list of keys present in the KV store. This will list all -// keys under the given prefix recursively and return them as a slice. -func (s *TestServer) ListKV(t *testing.T, prefix string) []string { - resp := s.get(t, "/v1/kv/"+prefix+"?keys") - defer resp.Body.Close() - - raw, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("failed to read body: %s", err) - } - - var result []string - if err := json.Unmarshal(raw, &result); err != nil { - t.Fatalf("failed to unmarshal: %s", err) - } - return result -} - -// AddService adds a new service to the Consul instance. It also -// automatically adds a health check with the given status, which -// can be one of "passing", "warning", or "critical". -func (s *TestServer) AddService(t *testing.T, name, status string, tags []string) { - s.AddAddressableService(t, name, status, "", 0, tags) // set empty address and 0 as port for non-accessible service -} - -// AddAddressableService adds a new service to the Consul instance by -// passing "address" and "port". It is helpful when you need to prepare a fakeService -// that maybe accessed with in target source code. -// It also automatically adds a health check with the given status, which -// can be one of "passing", "warning", or "critical", just like `AddService` does. -func (s *TestServer) AddAddressableService(t *testing.T, name, status, address string, port int, tags []string) { - svc := &TestService{ - Name: name, - Tags: tags, - Address: address, - Port: port, - } - payload, err := s.encodePayload(svc) - if err != nil { - t.Fatal(err) - } - s.put(t, "/v1/agent/service/register", payload) - - chkName := "service:" + name - chk := &TestCheck{ - Name: chkName, - ServiceID: name, - TTL: "10m", - } - payload, err = s.encodePayload(chk) - if err != nil { - t.Fatal(err) - } - s.put(t, "/v1/agent/check/register", payload) - - switch status { - case HealthPassing: - s.put(t, "/v1/agent/check/pass/"+chkName, nil) - case HealthWarning: - s.put(t, "/v1/agent/check/warn/"+chkName, nil) - case HealthCritical: - s.put(t, "/v1/agent/check/fail/"+chkName, nil) - default: - t.Fatalf("Unrecognized status: %s", status) - } -} - -// AddCheck adds a check to the Consul instance. If the serviceID is -// left empty (""), then the check will be associated with the node. -// The check status may be "passing", "warning", or "critical". -func (s *TestServer) AddCheck(t *testing.T, name, serviceID, status string) { - chk := &TestCheck{ - ID: name, - Name: name, - TTL: "10m", - } - if serviceID != "" { - chk.ServiceID = serviceID - } - - payload, err := s.encodePayload(chk) - if err != nil { - t.Fatal(err) - } - s.put(t, "/v1/agent/check/register", payload) - - switch status { - case HealthPassing: - s.put(t, "/v1/agent/check/pass/"+name, nil) - case HealthWarning: - s.put(t, "/v1/agent/check/warn/"+name, nil) - case HealthCritical: - s.put(t, "/v1/agent/check/fail/"+name, nil) - default: - t.Fatalf("Unrecognized status: %s", status) - } -} - -// put performs a new HTTP PUT request. -func (s *TestServer) put(t *testing.T, path string, body io.Reader) *http.Response { - req, err := http.NewRequest("PUT", s.url(path), body) - if err != nil { - t.Fatalf("failed to create PUT request: %s", err) - } - resp, err := s.HTTPClient.Do(req) - if err != nil { - t.Fatalf("failed to make PUT request: %s", err) - } - if err := s.requireOK(resp); err != nil { - defer resp.Body.Close() - t.Fatalf("not OK PUT: %s", err) - } - return resp -} - -// get performs a new HTTP GET request. -func (s *TestServer) get(t *testing.T, path string) *http.Response { - resp, err := s.HTTPClient.Get(s.url(path)) - if err != nil { - t.Fatalf("failed to create GET request: %s", err) - } - if err := s.requireOK(resp); err != nil { - defer resp.Body.Close() - t.Fatalf("not OK GET: %s", err) - } - return resp -} - -// encodePayload returns a new io.Reader wrapping the encoded contents -// of the payload, suitable for passing directly to a new request. -func (s *TestServer) encodePayload(payload interface{}) (io.Reader, error) { - var encoded bytes.Buffer - enc := json.NewEncoder(&encoded) - if err := enc.Encode(payload); err != nil { - return nil, errors.Wrap(err, "failed to encode payload") - } - return &encoded, nil -} - -// url is a helper function which takes a relative URL and -// makes it into a proper URL against the local Consul server. -func (s *TestServer) url(path string) string { - if s == nil { - log.Fatal("s is nil") - } - if s.Config == nil { - log.Fatal("s.Config is nil") - } - if s.Config.Ports == nil { - log.Fatal("s.Config.Ports is nil") - } - if s.Config.Ports.HTTP == 0 { - log.Fatal("s.Config.Ports.HTTP is 0") - } - if path == "" { - log.Fatal("path is empty") - } - return fmt.Sprintf("http://127.0.0.1:%d%s", s.Config.Ports.HTTP, path) -} - -// requireOK checks the HTTP response code and ensures it is acceptable. -func (s *TestServer) requireOK(resp *http.Response) error { - if resp.StatusCode != 200 { - return fmt.Errorf("Bad status code: %d", resp.StatusCode) - } - return nil -} diff --git a/vendor/github.com/hashicorp/consul/sdk/testutil/server_wrapper.go b/vendor/github.com/hashicorp/consul/sdk/testutil/server_wrapper.go deleted file mode 100644 index 17615da8d1..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/testutil/server_wrapper.go +++ /dev/null @@ -1,65 +0,0 @@ -package testutil - -import "testing" - -type WrappedServer struct { - s *TestServer - t *testing.T -} - -// Wrap wraps the test server in a `testing.t` for convenience. -// -// For example, the following code snippets are equivalent. -// -// server.JoinLAN(t, "1.2.3.4") -// server.Wrap(t).JoinLAN("1.2.3.4") -// -// This is useful when you are calling multiple functions and save the wrapped -// value as another variable to reduce the inclusion of "t". -func (s *TestServer) Wrap(t *testing.T) *WrappedServer { - return &WrappedServer{s, t} -} - -func (w *WrappedServer) JoinLAN(addr string) { - w.s.JoinLAN(w.t, addr) -} - -func (w *WrappedServer) JoinWAN(addr string) { - w.s.JoinWAN(w.t, addr) -} - -func (w *WrappedServer) SetKV(key string, val []byte) { - w.s.SetKV(w.t, key, val) -} - -func (w *WrappedServer) SetKVString(key string, val string) { - w.s.SetKVString(w.t, key, val) -} - -func (w *WrappedServer) GetKV(key string) []byte { - return w.s.GetKV(w.t, key) -} - -func (w *WrappedServer) GetKVString(key string) string { - return w.s.GetKVString(w.t, key) -} - -func (w *WrappedServer) PopulateKV(data map[string][]byte) { - w.s.PopulateKV(w.t, data) -} - -func (w *WrappedServer) ListKV(prefix string) []string { - return w.s.ListKV(w.t, prefix) -} - -func (w *WrappedServer) AddService(name, status string, tags []string) { - w.s.AddService(w.t, name, status, tags) -} - -func (w *WrappedServer) AddAddressableService(name, status, address string, port int, tags []string) { - w.s.AddAddressableService(w.t, name, status, address, port, tags) -} - -func (w *WrappedServer) AddCheck(name, serviceID, status string) { - w.s.AddCheck(w.t, name, serviceID, status) -} diff --git a/vendor/github.com/hashicorp/consul/sdk/testutil/testlog.go b/vendor/github.com/hashicorp/consul/sdk/testutil/testlog.go deleted file mode 100644 index 6daee35933..0000000000 --- a/vendor/github.com/hashicorp/consul/sdk/testutil/testlog.go +++ /dev/null @@ -1,42 +0,0 @@ -package testutil - -import ( - "fmt" - "io" - "log" - "os" - "strings" - "testing" -) - -var sendTestLogsToStdout bool - -func init() { - sendTestLogsToStdout = os.Getenv("NOLOGBUFFER") == "1" -} - -func TestLogger(t testing.TB) *log.Logger { - return log.New(&testWriter{t}, "test: ", log.LstdFlags) -} - -func TestLoggerWithName(t testing.TB, name string) *log.Logger { - return log.New(&testWriter{t}, "test["+name+"]: ", log.LstdFlags) -} - -func TestWriter(t testing.TB) io.Writer { - return &testWriter{t} -} - -type testWriter struct { - t testing.TB -} - -func (tw *testWriter) Write(p []byte) (n int, err error) { - tw.t.Helper() - if sendTestLogsToStdout { - fmt.Fprint(os.Stdout, strings.TrimSpace(string(p))+"\n") - } else { - tw.t.Log(strings.TrimSpace(string(p))) - } - return len(p), nil -}