From ab862b06d9c82c427640a34081589fabef00d175 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Mon, 16 Oct 2017 14:10:39 -0700 Subject: [PATCH 1/5] Bump Consul to 1.0.0 in vagrant/travis --- scripts/travis-consul.sh | 2 +- scripts/vagrant-linux-priv-consul.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/travis-consul.sh b/scripts/travis-consul.sh index 95fd73707..94027cac1 100755 --- a/scripts/travis-consul.sh +++ b/scripts/travis-consul.sh @@ -2,7 +2,7 @@ set -o errexit -VERSION=0.9.2 +VERSION=1.0.0 DOWNLOAD=https://releases.hashicorp.com/consul/${VERSION}/consul_${VERSION}_linux_amd64.zip function install_consul() { diff --git a/scripts/vagrant-linux-priv-consul.sh b/scripts/vagrant-linux-priv-consul.sh index 95fd73707..94027cac1 100755 --- a/scripts/vagrant-linux-priv-consul.sh +++ b/scripts/vagrant-linux-priv-consul.sh @@ -2,7 +2,7 @@ set -o errexit -VERSION=0.9.2 +VERSION=1.0.0 DOWNLOAD=https://releases.hashicorp.com/consul/${VERSION}/consul_${VERSION}_linux_amd64.zip function install_consul() { From 1e9c41743936c5e18ed925d481d6698349b39803 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Mon, 16 Oct 2017 16:04:14 -0700 Subject: [PATCH 2/5] Update vendored Consul to 1.0.0 Also install new porter dep --- GNUmakefile | 1 + vendor/github.com/hashicorp/consul/LICENSE | 354 ++++++ vendor/github.com/hashicorp/consul/acl/acl.go | 672 ----------- .../github.com/hashicorp/consul/acl/cache.go | 177 --- .../github.com/hashicorp/consul/acl/policy.go | 191 --- .../github.com/hashicorp/consul/api/agent.go | 35 + vendor/github.com/hashicorp/consul/api/api.go | 21 +- .../hashicorp/consul/api/coordinate.go | 5 +- vendor/github.com/hashicorp/consul/api/kv.go | 26 +- .../github.com/hashicorp/consul/api/lock.go | 2 +- .../hashicorp/consul/api/operator_area.go | 25 + .../hashicorp/consul/api/operator_keyring.go | 3 + .../hashicorp/consul/api/operator_raft.go | 5 +- .../hashicorp/consul/api/operator_segment.go | 11 + .../hashicorp/consul/api/semaphore.go | 2 +- .../consul/consul/structs/operator.go | 221 ---- .../consul/consul/structs/prepared_query.go | 257 ---- .../consul/consul/structs/snapshot.go | 40 - .../consul/consul/structs/structs.go | 1059 ----------------- .../hashicorp/consul/consul/structs/txn.go | 85 -- vendor/github.com/hashicorp/consul/lib/eof.go | 27 + vendor/github.com/hashicorp/consul/lib/rtt.go | 33 + .../hashicorp/consul/test/porter/client.go | 36 + .../hashicorp/consul/testutil/server.go | 52 +- .../consul/testutil/server_methods.go | 4 +- .../hashicorp/consul/types/README.md | 39 - .../github.com/hashicorp/consul/types/area.go | 9 - .../hashicorp/consul/types/checks.go | 5 - .../hashicorp/consul/types/node_id.go | 4 - vendor/vendor.json | 46 +- 30 files changed, 603 insertions(+), 2844 deletions(-) create mode 100644 vendor/github.com/hashicorp/consul/LICENSE delete mode 100644 vendor/github.com/hashicorp/consul/acl/acl.go delete mode 100644 vendor/github.com/hashicorp/consul/acl/cache.go delete mode 100644 vendor/github.com/hashicorp/consul/acl/policy.go create mode 100644 vendor/github.com/hashicorp/consul/api/operator_segment.go delete mode 100644 vendor/github.com/hashicorp/consul/consul/structs/operator.go delete mode 100644 vendor/github.com/hashicorp/consul/consul/structs/prepared_query.go delete mode 100644 vendor/github.com/hashicorp/consul/consul/structs/snapshot.go delete mode 100644 vendor/github.com/hashicorp/consul/consul/structs/structs.go delete mode 100644 vendor/github.com/hashicorp/consul/consul/structs/txn.go create mode 100644 vendor/github.com/hashicorp/consul/lib/eof.go create mode 100644 vendor/github.com/hashicorp/consul/test/porter/client.go delete mode 100644 vendor/github.com/hashicorp/consul/types/README.md delete mode 100644 vendor/github.com/hashicorp/consul/types/area.go delete mode 100644 vendor/github.com/hashicorp/consul/types/checks.go delete mode 100644 vendor/github.com/hashicorp/consul/types/node_id.go diff --git a/GNUmakefile b/GNUmakefile index 996302bb0..16ac9d185 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -150,6 +150,7 @@ deps: ## Install build and development dependencies go get -u github.com/elazarl/go-bindata-assetfs/... go get -u github.com/hashicorp/vault go get -u github.com/a8m/tree/cmd/tree + go get -u github.com/hashicorp/consul/test/porter/cmd/porter .PHONY: check check: ## Lint the source code diff --git a/vendor/github.com/hashicorp/consul/LICENSE b/vendor/github.com/hashicorp/consul/LICENSE new file mode 100644 index 000000000..c33dcc7c9 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/consul/acl/acl.go b/vendor/github.com/hashicorp/consul/acl/acl.go deleted file mode 100644 index 3ade9d405..000000000 --- a/vendor/github.com/hashicorp/consul/acl/acl.go +++ /dev/null @@ -1,672 +0,0 @@ -package acl - -import ( - "github.com/armon/go-radix" -) - -var ( - // allowAll is a singleton policy which allows all - // non-management actions - allowAll ACL - - // denyAll is a singleton policy which denies all actions - denyAll ACL - - // manageAll is a singleton policy which allows all - // actions, including management - manageAll ACL -) - -func init() { - // Setup the singletons - allowAll = &StaticACL{ - allowManage: false, - defaultAllow: true, - } - denyAll = &StaticACL{ - allowManage: false, - defaultAllow: false, - } - manageAll = &StaticACL{ - allowManage: true, - defaultAllow: true, - } -} - -// ACL is the interface for policy enforcement. -type ACL interface { - // ACLList checks for permission to list all the ACLs - ACLList() bool - - // ACLModify checks for permission to manipulate ACLs - ACLModify() bool - - // AgentRead checks for permission to read from agent endpoints for a - // given node. - AgentRead(string) bool - - // AgentWrite checks for permission to make changes via agent endpoints - // for a given node. - AgentWrite(string) bool - - // EventRead determines if a specific event can be queried. - EventRead(string) bool - - // EventWrite determines if a specific event may be fired. - EventWrite(string) bool - - // KeyRead checks for permission to read a given key - KeyRead(string) bool - - // KeyWrite checks for permission to write a given key - KeyWrite(string) bool - - // KeyWritePrefix checks for permission to write to an - // entire key prefix. This means there must be no sub-policies - // that deny a write. - KeyWritePrefix(string) bool - - // KeyringRead determines if the encryption keyring used in - // the gossip layer can be read. - KeyringRead() bool - - // KeyringWrite determines if the keyring can be manipulated - KeyringWrite() bool - - // NodeRead checks for permission to read (discover) a given node. - NodeRead(string) bool - - // NodeWrite checks for permission to create or update (register) a - // given node. - NodeWrite(string) bool - - // OperatorRead determines if the read-only Consul operator functions - // can be used. - OperatorRead() bool - - // OperatorWrite determines if the state-changing Consul operator - // functions can be used. - OperatorWrite() bool - - // PrepardQueryRead determines if a specific prepared query can be read - // to show its contents (this is not used for execution). - PreparedQueryRead(string) bool - - // PreparedQueryWrite determines if a specific prepared query can be - // created, modified, or deleted. - PreparedQueryWrite(string) bool - - // ServiceRead checks for permission to read a given service - ServiceRead(string) bool - - // ServiceWrite checks for permission to create or update a given - // service - ServiceWrite(string) bool - - // SessionRead checks for permission to read sessions for a given node. - SessionRead(string) bool - - // SessionWrite checks for permission to create sessions for a given - // node. - SessionWrite(string) bool - - // Snapshot checks for permission to take and restore snapshots. - Snapshot() bool -} - -// StaticACL is used to implement a base ACL policy. It either -// allows or denies all requests. This can be used as a parent -// ACL to act in a blacklist or whitelist mode. -type StaticACL struct { - allowManage bool - defaultAllow bool -} - -func (s *StaticACL) ACLList() bool { - return s.allowManage -} - -func (s *StaticACL) ACLModify() bool { - return s.allowManage -} - -func (s *StaticACL) AgentRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) AgentWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) EventRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) EventWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) KeyRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) KeyWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) KeyWritePrefix(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) KeyringRead() bool { - return s.defaultAllow -} - -func (s *StaticACL) KeyringWrite() bool { - return s.defaultAllow -} - -func (s *StaticACL) NodeRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) NodeWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) OperatorRead() bool { - return s.defaultAllow -} - -func (s *StaticACL) OperatorWrite() bool { - return s.defaultAllow -} - -func (s *StaticACL) PreparedQueryRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) PreparedQueryWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) ServiceRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) ServiceWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) SessionRead(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) SessionWrite(string) bool { - return s.defaultAllow -} - -func (s *StaticACL) Snapshot() bool { - return s.allowManage -} - -// AllowAll returns an ACL rule that allows all operations -func AllowAll() ACL { - return allowAll -} - -// DenyAll returns an ACL rule that denies all operations -func DenyAll() ACL { - return denyAll -} - -// ManageAll returns an ACL rule that can manage all resources -func ManageAll() ACL { - return manageAll -} - -// RootACL returns a possible ACL if the ID matches a root policy -func RootACL(id string) ACL { - switch id { - case "allow": - return allowAll - case "deny": - return denyAll - case "manage": - return manageAll - default: - return nil - } -} - -// PolicyACL is used to wrap a set of ACL policies to provide -// the ACL interface. -type PolicyACL struct { - // parent is used to resolve policy if we have - // no matching rule. - parent ACL - - // agentRules contains the agent policies - agentRules *radix.Tree - - // keyRules contains the key policies - keyRules *radix.Tree - - // nodeRules contains the node policies - nodeRules *radix.Tree - - // serviceRules contains the service policies - serviceRules *radix.Tree - - // sessionRules contains the session policies - sessionRules *radix.Tree - - // eventRules contains the user event policies - eventRules *radix.Tree - - // preparedQueryRules contains the prepared query policies - preparedQueryRules *radix.Tree - - // keyringRule contains the keyring policies. The keyring has - // a very simple yes/no without prefix matching, so here we - // don't need to use a radix tree. - keyringRule string - - // operatorRule contains the operator policies. - operatorRule string -} - -// New is used to construct a policy based ACL from a set of policies -// and a parent policy to resolve missing cases. -func New(parent ACL, policy *Policy) (*PolicyACL, error) { - p := &PolicyACL{ - parent: parent, - agentRules: radix.New(), - keyRules: radix.New(), - nodeRules: radix.New(), - serviceRules: radix.New(), - sessionRules: radix.New(), - eventRules: radix.New(), - preparedQueryRules: radix.New(), - } - - // Load the agent policy - for _, ap := range policy.Agents { - p.agentRules.Insert(ap.Node, ap.Policy) - } - - // Load the key policy - for _, kp := range policy.Keys { - p.keyRules.Insert(kp.Prefix, kp.Policy) - } - - // Load the node policy - for _, np := range policy.Nodes { - p.nodeRules.Insert(np.Name, np.Policy) - } - - // Load the service policy - for _, sp := range policy.Services { - p.serviceRules.Insert(sp.Name, sp.Policy) - } - - // Load the session policy - for _, sp := range policy.Sessions { - p.sessionRules.Insert(sp.Node, sp.Policy) - } - - // Load the event policy - for _, ep := range policy.Events { - p.eventRules.Insert(ep.Event, ep.Policy) - } - - // Load the prepared query policy - for _, pq := range policy.PreparedQueries { - p.preparedQueryRules.Insert(pq.Prefix, pq.Policy) - } - - // Load the keyring policy - p.keyringRule = policy.Keyring - - // Load the operator policy - p.operatorRule = policy.Operator - - return p, nil -} - -// ACLList checks if listing of ACLs is allowed -func (p *PolicyACL) ACLList() bool { - return p.parent.ACLList() -} - -// ACLModify checks if modification of ACLs is allowed -func (p *PolicyACL) ACLModify() bool { - return p.parent.ACLModify() -} - -// AgentRead checks for permission to read from agent endpoints for a given -// node. -func (p *PolicyACL) AgentRead(node string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.agentRules.LongestPrefix(node) - - if ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.AgentRead(node) -} - -// AgentWrite checks for permission to make changes via agent endpoints for a -// given node. -func (p *PolicyACL) AgentWrite(node string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.agentRules.LongestPrefix(node) - - if ok { - switch rule { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.AgentWrite(node) -} - -// Snapshot checks if taking and restoring snapshots is allowed. -func (p *PolicyACL) Snapshot() bool { - return p.parent.Snapshot() -} - -// EventRead is used to determine if the policy allows for a -// specific user event to be read. -func (p *PolicyACL) EventRead(name string) bool { - // Longest-prefix match on event names - if _, rule, ok := p.eventRules.LongestPrefix(name); ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // Nothing matched, use parent - return p.parent.EventRead(name) -} - -// EventWrite is used to determine if new events can be created -// (fired) by the policy. -func (p *PolicyACL) EventWrite(name string) bool { - // Longest-prefix match event names - if _, rule, ok := p.eventRules.LongestPrefix(name); ok { - return rule == PolicyWrite - } - - // No match, use parent - return p.parent.EventWrite(name) -} - -// KeyRead returns if a key is allowed to be read -func (p *PolicyACL) KeyRead(key string) bool { - // Look for a matching rule - _, rule, ok := p.keyRules.LongestPrefix(key) - if ok { - switch rule.(string) { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.KeyRead(key) -} - -// KeyWrite returns if a key is allowed to be written -func (p *PolicyACL) KeyWrite(key string) bool { - // Look for a matching rule - _, rule, ok := p.keyRules.LongestPrefix(key) - if ok { - switch rule.(string) { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.KeyWrite(key) -} - -// KeyWritePrefix returns if a prefix is allowed to be written -func (p *PolicyACL) KeyWritePrefix(prefix string) bool { - // Look for a matching rule that denies - _, rule, ok := p.keyRules.LongestPrefix(prefix) - if ok && rule.(string) != PolicyWrite { - return false - } - - // Look if any of our children have a deny policy - deny := false - p.keyRules.WalkPrefix(prefix, func(path string, rule interface{}) bool { - // We have a rule to prevent a write in a sub-directory! - if rule.(string) != PolicyWrite { - deny = true - return true - } - return false - }) - - // Deny the write if any sub-rules may be violated - if deny { - return false - } - - // If we had a matching rule, done - if ok { - return true - } - - // No matching rule, use the parent. - return p.parent.KeyWritePrefix(prefix) -} - -// KeyringRead is used to determine if the keyring can be -// read by the current ACL token. -func (p *PolicyACL) KeyringRead() bool { - switch p.keyringRule { - case PolicyRead, PolicyWrite: - return true - case PolicyDeny: - return false - default: - return p.parent.KeyringRead() - } -} - -// KeyringWrite determines if the keyring can be manipulated. -func (p *PolicyACL) KeyringWrite() bool { - if p.keyringRule == PolicyWrite { - return true - } - return p.parent.KeyringWrite() -} - -// OperatorRead determines if the read-only operator functions are allowed. -func (p *PolicyACL) OperatorRead() bool { - switch p.operatorRule { - case PolicyRead, PolicyWrite: - return true - case PolicyDeny: - return false - default: - return p.parent.OperatorRead() - } -} - -// NodeRead checks if reading (discovery) of a node is allowed -func (p *PolicyACL) NodeRead(name string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.nodeRules.LongestPrefix(name) - - if ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.NodeRead(name) -} - -// NodeWrite checks if writing (registering) a node is allowed -func (p *PolicyACL) NodeWrite(name string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.nodeRules.LongestPrefix(name) - - if ok { - switch rule { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.NodeWrite(name) -} - -// OperatorWrite determines if the state-changing operator functions are -// allowed. -func (p *PolicyACL) OperatorWrite() bool { - if p.operatorRule == PolicyWrite { - return true - } - return p.parent.OperatorWrite() -} - -// PreparedQueryRead checks if reading (listing) of a prepared query is -// allowed - this isn't execution, just listing its contents. -func (p *PolicyACL) PreparedQueryRead(prefix string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.preparedQueryRules.LongestPrefix(prefix) - - if ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.PreparedQueryRead(prefix) -} - -// PreparedQueryWrite checks if writing (creating, updating, or deleting) of a -// prepared query is allowed. -func (p *PolicyACL) PreparedQueryWrite(prefix string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.preparedQueryRules.LongestPrefix(prefix) - - if ok { - switch rule { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.PreparedQueryWrite(prefix) -} - -// ServiceRead checks if reading (discovery) of a service is allowed -func (p *PolicyACL) ServiceRead(name string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.serviceRules.LongestPrefix(name) - - if ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.ServiceRead(name) -} - -// ServiceWrite checks if writing (registering) a service is allowed -func (p *PolicyACL) ServiceWrite(name string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.serviceRules.LongestPrefix(name) - - if ok { - switch rule { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.ServiceWrite(name) -} - -// SessionRead checks for permission to read sessions for a given node. -func (p *PolicyACL) SessionRead(node string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.sessionRules.LongestPrefix(node) - - if ok { - switch rule { - case PolicyRead, PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.SessionRead(node) -} - -// SessionWrite checks for permission to create sessions for a given node. -func (p *PolicyACL) SessionWrite(node string) bool { - // Check for an exact rule or catch-all - _, rule, ok := p.sessionRules.LongestPrefix(node) - - if ok { - switch rule { - case PolicyWrite: - return true - default: - return false - } - } - - // No matching rule, use the parent. - return p.parent.SessionWrite(node) -} diff --git a/vendor/github.com/hashicorp/consul/acl/cache.go b/vendor/github.com/hashicorp/consul/acl/cache.go deleted file mode 100644 index 0387f9fbe..000000000 --- a/vendor/github.com/hashicorp/consul/acl/cache.go +++ /dev/null @@ -1,177 +0,0 @@ -package acl - -import ( - "crypto/md5" - "fmt" - - "github.com/hashicorp/golang-lru" -) - -// FaultFunc is a function used to fault in the parent, -// rules for an ACL given its ID -type FaultFunc func(id string) (string, string, error) - -// aclEntry allows us to store the ACL with it's policy ID -type aclEntry struct { - ACL ACL - Parent string - RuleID string -} - -// Cache is used to implement policy and ACL caching -type Cache struct { - faultfn FaultFunc - aclCache *lru.TwoQueueCache // Cache id -> acl - policyCache *lru.TwoQueueCache // Cache policy -> acl - ruleCache *lru.TwoQueueCache // Cache rules -> policy -} - -// NewCache constructs a new policy and ACL cache of a given size -func NewCache(size int, faultfn FaultFunc) (*Cache, error) { - if size <= 0 { - return nil, fmt.Errorf("Must provide positive cache size") - } - - rc, err := lru.New2Q(size) - if err != nil { - return nil, err - } - - pc, err := lru.New2Q(size) - if err != nil { - return nil, err - } - - ac, err := lru.New2Q(size) - if err != nil { - return nil, err - } - - c := &Cache{ - faultfn: faultfn, - aclCache: ac, - policyCache: pc, - ruleCache: rc, - } - return c, nil -} - -// GetPolicy is used to get a potentially cached policy set. -// If not cached, it will be parsed, and then cached. -func (c *Cache) GetPolicy(rules string) (*Policy, error) { - return c.getPolicy(RuleID(rules), rules) -} - -// getPolicy is an internal method to get a cached policy, -// but it assumes a pre-computed ID -func (c *Cache) getPolicy(id, rules string) (*Policy, error) { - raw, ok := c.ruleCache.Get(id) - if ok { - return raw.(*Policy), nil - } - policy, err := Parse(rules) - if err != nil { - return nil, err - } - policy.ID = id - c.ruleCache.Add(id, policy) - return policy, nil - -} - -// RuleID is used to generate an ID for a rule -func RuleID(rules string) string { - return fmt.Sprintf("%x", md5.Sum([]byte(rules))) -} - -// policyID returns the cache ID for a policy -func (c *Cache) policyID(parent, ruleID string) string { - return parent + ":" + ruleID -} - -// GetACLPolicy is used to get the potentially cached ACL -// policy. If not cached, it will be generated and then cached. -func (c *Cache) GetACLPolicy(id string) (string, *Policy, error) { - // Check for a cached acl - if raw, ok := c.aclCache.Get(id); ok { - cached := raw.(aclEntry) - if raw, ok := c.ruleCache.Get(cached.RuleID); ok { - return cached.Parent, raw.(*Policy), nil - } - } - - // Fault in the rules - parent, rules, err := c.faultfn(id) - if err != nil { - return "", nil, err - } - - // Get cached - policy, err := c.GetPolicy(rules) - return parent, policy, err -} - -// GetACL is used to get a potentially cached ACL policy. -// If not cached, it will be generated and then cached. -func (c *Cache) GetACL(id string) (ACL, error) { - // Look for the ACL directly - raw, ok := c.aclCache.Get(id) - if ok { - return raw.(aclEntry).ACL, nil - } - - // Get the rules - parentID, rules, err := c.faultfn(id) - if err != nil { - return nil, err - } - ruleID := RuleID(rules) - - // Check for a compiled ACL - policyID := c.policyID(parentID, ruleID) - var compiled ACL - if raw, ok := c.policyCache.Get(policyID); ok { - compiled = raw.(ACL) - } else { - // Get the policy - policy, err := c.getPolicy(ruleID, rules) - if err != nil { - return nil, err - } - - // Get the parent ACL - parent := RootACL(parentID) - if parent == nil { - parent, err = c.GetACL(parentID) - if err != nil { - return nil, err - } - } - - // Compile the ACL - acl, err := New(parent, policy) - if err != nil { - return nil, err - } - - // Cache the compiled ACL - c.policyCache.Add(policyID, acl) - compiled = acl - } - - // Cache and return the ACL - c.aclCache.Add(id, aclEntry{compiled, parentID, ruleID}) - return compiled, nil -} - -// ClearACL is used to clear the ACL cache if any -func (c *Cache) ClearACL(id string) { - c.aclCache.Remove(id) -} - -// Purge is used to clear all the ACL caches. The -// rule and policy caches are not purged, since they -// are content-hashed anyways. -func (c *Cache) Purge() { - c.aclCache.Purge() -} diff --git a/vendor/github.com/hashicorp/consul/acl/policy.go b/vendor/github.com/hashicorp/consul/acl/policy.go deleted file mode 100644 index f7781b81e..000000000 --- a/vendor/github.com/hashicorp/consul/acl/policy.go +++ /dev/null @@ -1,191 +0,0 @@ -package acl - -import ( - "fmt" - - "github.com/hashicorp/hcl" -) - -const ( - PolicyDeny = "deny" - PolicyRead = "read" - PolicyWrite = "write" -) - -// Policy is used to represent the policy specified by -// an ACL configuration. -type Policy struct { - ID string `hcl:"-"` - Agents []*AgentPolicy `hcl:"agent,expand"` - Keys []*KeyPolicy `hcl:"key,expand"` - Nodes []*NodePolicy `hcl:"node,expand"` - Services []*ServicePolicy `hcl:"service,expand"` - Sessions []*SessionPolicy `hcl:"session,expand"` - Events []*EventPolicy `hcl:"event,expand"` - PreparedQueries []*PreparedQueryPolicy `hcl:"query,expand"` - Keyring string `hcl:"keyring"` - Operator string `hcl:"operator"` -} - -// AgentPolicy represents a policy for working with agent endpoints on nodes -// with specific name prefixes. -type AgentPolicy struct { - Node string `hcl:",key"` - Policy string -} - -func (a *AgentPolicy) GoString() string { - return fmt.Sprintf("%#v", *a) -} - -// KeyPolicy represents a policy for a key -type KeyPolicy struct { - Prefix string `hcl:",key"` - Policy string -} - -func (k *KeyPolicy) GoString() string { - return fmt.Sprintf("%#v", *k) -} - -// NodePolicy represents a policy for a node -type NodePolicy struct { - Name string `hcl:",key"` - Policy string -} - -func (n *NodePolicy) GoString() string { - return fmt.Sprintf("%#v", *n) -} - -// ServicePolicy represents a policy for a service -type ServicePolicy struct { - Name string `hcl:",key"` - Policy string -} - -func (s *ServicePolicy) GoString() string { - return fmt.Sprintf("%#v", *s) -} - -// SessionPolicy represents a policy for making sessions tied to specific node -// name prefixes. -type SessionPolicy struct { - Node string `hcl:",key"` - Policy string -} - -func (s *SessionPolicy) GoString() string { - return fmt.Sprintf("%#v", *s) -} - -// EventPolicy represents a user event policy. -type EventPolicy struct { - Event string `hcl:",key"` - Policy string -} - -func (e *EventPolicy) GoString() string { - return fmt.Sprintf("%#v", *e) -} - -// PreparedQueryPolicy represents a prepared query policy. -type PreparedQueryPolicy struct { - Prefix string `hcl:",key"` - Policy string -} - -func (p *PreparedQueryPolicy) GoString() string { - return fmt.Sprintf("%#v", *p) -} - -// isPolicyValid makes sure the given string matches one of the valid policies. -func isPolicyValid(policy string) bool { - switch policy { - case PolicyDeny: - return true - case PolicyRead: - return true - case PolicyWrite: - return true - default: - return false - } -} - -// Parse is used to parse the specified ACL rules into an -// intermediary set of policies, before being compiled into -// the ACL -func Parse(rules string) (*Policy, error) { - // Decode the rules - p := &Policy{} - if rules == "" { - // Hot path for empty rules - return p, nil - } - - if err := hcl.Decode(p, rules); err != nil { - return nil, fmt.Errorf("Failed to parse ACL rules: %v", err) - } - - // Validate the agent policy - for _, ap := range p.Agents { - if !isPolicyValid(ap.Policy) { - return nil, fmt.Errorf("Invalid agent policy: %#v", ap) - } - } - - // Validate the key policy - for _, kp := range p.Keys { - if !isPolicyValid(kp.Policy) { - return nil, fmt.Errorf("Invalid key policy: %#v", kp) - } - } - - // Validate the node policies - for _, np := range p.Nodes { - if !isPolicyValid(np.Policy) { - return nil, fmt.Errorf("Invalid node policy: %#v", np) - } - } - - // Validate the service policies - for _, sp := range p.Services { - if !isPolicyValid(sp.Policy) { - return nil, fmt.Errorf("Invalid service policy: %#v", sp) - } - } - - // Validate the session policies - for _, sp := range p.Sessions { - if !isPolicyValid(sp.Policy) { - return nil, fmt.Errorf("Invalid session policy: %#v", sp) - } - } - - // Validate the user event policies - for _, ep := range p.Events { - if !isPolicyValid(ep.Policy) { - return nil, fmt.Errorf("Invalid event policy: %#v", ep) - } - } - - // Validate the prepared query policies - for _, pq := range p.PreparedQueries { - if !isPolicyValid(pq.Policy) { - return nil, fmt.Errorf("Invalid query policy: %#v", pq) - } - } - - // Validate the keyring policy - this one is allowed to be empty - if p.Keyring != "" && !isPolicyValid(p.Keyring) { - return nil, fmt.Errorf("Invalid keyring policy: %#v", p.Keyring) - } - - // Validate the operator policy - this one is allowed to be empty - if p.Operator != "" && !isPolicyValid(p.Operator) { - return nil, fmt.Errorf("Invalid operator policy: %#v", p.Operator) - } - - return p, nil -} diff --git a/vendor/github.com/hashicorp/consul/api/agent.go b/vendor/github.com/hashicorp/consul/api/agent.go index be4e00ff6..ac57415c1 100644 --- a/vendor/github.com/hashicorp/consul/api/agent.go +++ b/vendor/github.com/hashicorp/consul/api/agent.go @@ -44,6 +44,19 @@ type AgentMember struct { 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 { ID string `json:",omitempty"` @@ -256,6 +269,28 @@ func (a *Agent) Members(wan bool) ([]*AgentMember, error) { 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 { diff --git a/vendor/github.com/hashicorp/consul/api/api.go b/vendor/github.com/hashicorp/consul/api/api.go index 0a62b4f68..87cd3c5a3 100644 --- a/vendor/github.com/hashicorp/consul/api/api.go +++ b/vendor/github.com/hashicorp/consul/api/api.go @@ -446,6 +446,7 @@ func NewClient(config *Config) (*Client, error) { if len(parts) == 2 { switch parts[0] { case "http": + config.Scheme = "http" case "https": config.Scheme = "https" case "unix": @@ -462,10 +463,11 @@ func NewClient(config *Config) (*Client, error) { config.Address = parts[1] } - client := &Client{ - config: *config, + if config.Token == "" { + config.Token = defConfig.Token } - return client, nil + + return &Client{config: *config}, nil } // NewHttpClient returns an http client configured with the given Transport and TLS @@ -553,13 +555,20 @@ func durToMsec(dur time.Duration) string { // serverError is a string we look for to detect 500 errors. const serverError = "Unexpected response code: 500" -// IsServerError returns true for 500 errors from the Consul servers, these are -// usually retryable at a later time. -func IsServerError(err error) bool { +// 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) diff --git a/vendor/github.com/hashicorp/consul/api/coordinate.go b/vendor/github.com/hashicorp/consul/api/coordinate.go index ae8d16ee6..90214e392 100644 --- a/vendor/github.com/hashicorp/consul/api/coordinate.go +++ b/vendor/github.com/hashicorp/consul/api/coordinate.go @@ -6,8 +6,9 @@ import ( // CoordinateEntry represents a node and its associated network coordinate. type CoordinateEntry struct { - Node string - Coord *coordinate.Coordinate + Node string + Segment string + Coord *coordinate.Coordinate } // CoordinateDatacenterMap has the coordinates for servers in a given datacenter diff --git a/vendor/github.com/hashicorp/consul/api/kv.go b/vendor/github.com/hashicorp/consul/api/kv.go index f91bb50fc..5990d3d13 100644 --- a/vendor/github.com/hashicorp/consul/api/kv.go +++ b/vendor/github.com/hashicorp/consul/api/kv.go @@ -353,19 +353,19 @@ type TxnResponse struct { // // 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", -// }, -// } -// ok, response, _, err := kv.Txn(&ops, nil) +// ops := KVTxnOps{ +// &KVTxnOp{ +// Verb: KVLock, +// Key: "test/lock", +// Session: "adf4238a-882b-9ddc-4a9d-5b6758e4159e", +// Value: []byte("hello"), +// }, +// &KVTxnOp{ +// Verb: KVGet, +// Key: "another/key", +// }, +// } +// 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 diff --git a/vendor/github.com/hashicorp/consul/api/lock.go b/vendor/github.com/hashicorp/consul/api/lock.go index 466ef5fdf..d3187113f 100644 --- a/vendor/github.com/hashicorp/consul/api/lock.go +++ b/vendor/github.com/hashicorp/consul/api/lock.go @@ -370,7 +370,7 @@ RETRY: // 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 && IsServerError(err) { + if retries > 0 && IsRetryableError(err) { time.Sleep(l.opts.MonitorRetryTime) retries-- opts.WaitIndex = 0 diff --git a/vendor/github.com/hashicorp/consul/api/operator_area.go b/vendor/github.com/hashicorp/consul/api/operator_area.go index 7b0e461e9..a630b694c 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_area.go +++ b/vendor/github.com/hashicorp/consul/api/operator_area.go @@ -25,6 +25,10 @@ type Area struct { // 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 @@ -100,6 +104,27 @@ func (op *Operator) AreaCreate(area *Area, q *WriteOptions) (string, *WriteMeta, 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 diff --git a/vendor/github.com/hashicorp/consul/api/operator_keyring.go b/vendor/github.com/hashicorp/consul/api/operator_keyring.go index 4f91c3543..6b614296c 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_keyring.go +++ b/vendor/github.com/hashicorp/consul/api/operator_keyring.go @@ -13,6 +13,9 @@ type KeyringResponse struct { // The datacenter name this request corresponds to Datacenter string + // Segment has the network segment this request corresponds to. + Segment string + // A map of the encryption keys to the number of nodes they're installed on Keys map[string]int diff --git a/vendor/github.com/hashicorp/consul/api/operator_raft.go b/vendor/github.com/hashicorp/consul/api/operator_raft.go index 5f3c25b13..a9844df2d 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_raft.go +++ b/vendor/github.com/hashicorp/consul/api/operator_raft.go @@ -17,6 +17,9 @@ type RaftServer struct { // 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 @@ -24,7 +27,7 @@ type RaftServer struct { Voter bool } -// RaftConfigration is returned when querying for the current Raft configuration. +// 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 diff --git a/vendor/github.com/hashicorp/consul/api/operator_segment.go b/vendor/github.com/hashicorp/consul/api/operator_segment.go new file mode 100644 index 000000000..92b05d3c0 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/operator_segment.go @@ -0,0 +1,11 @@ +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/semaphore.go b/vendor/github.com/hashicorp/consul/api/semaphore.go index 9ddbdc49e..d848dfd0b 100644 --- a/vendor/github.com/hashicorp/consul/api/semaphore.go +++ b/vendor/github.com/hashicorp/consul/api/semaphore.go @@ -492,7 +492,7 @@ RETRY: // 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 && IsServerError(err) { + if retries > 0 && IsRetryableError(err) { time.Sleep(s.opts.MonitorRetryTime) retries-- opts.WaitIndex = 0 diff --git a/vendor/github.com/hashicorp/consul/consul/structs/operator.go b/vendor/github.com/hashicorp/consul/consul/structs/operator.go deleted file mode 100644 index 332d9e556..000000000 --- a/vendor/github.com/hashicorp/consul/consul/structs/operator.go +++ /dev/null @@ -1,221 +0,0 @@ -package structs - -import ( - "time" - - "github.com/hashicorp/raft" - "github.com/hashicorp/serf/serf" -) - -// AutopilotConfig holds the Autopilot configuration for a cluster. -type AutopilotConfig struct { - // CleanupDeadServers controls whether to remove dead servers when a new - // server is added to the Raft peers. - CleanupDeadServers bool - - // LastContactThreshold is the limit on the amount of time a server can go - // without leader contact before being considered unhealthy. - LastContactThreshold time.Duration - - // 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 time.Duration - - // (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 - - // RaftIndex stores the create/modify indexes of this configuration. - RaftIndex -} - -// 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 raft.ServerID - - // 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 raft.ServerAddress - - // Leader is true if this server is the current cluster leader. - Leader bool - - // 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 -} - -// RaftConfigrationResponse is returned when querying for the current Raft -// configuration. -type RaftConfigurationResponse struct { - // Servers has the list of servers in the Raft configuration. - Servers []*RaftServer - - // Index has the Raft index of this configuration. - Index uint64 -} - -// RaftRemovePeerRequest is used by the Operator endpoint to apply a Raft -// operation on a specific Raft peer by address in the form of "IP:port". -type RaftRemovePeerRequest struct { - // Datacenter is the target this request is intended for. - Datacenter string - - // Address is the peer to remove, in the form "IP:port". - Address raft.ServerAddress - - // ID is the peer ID to remove. - ID raft.ServerID - - // WriteRequest holds the ACL token to go along with this request. - WriteRequest -} - -// RequestDatacenter returns the datacenter for a given request. -func (op *RaftRemovePeerRequest) RequestDatacenter() string { - return op.Datacenter -} - -// AutopilotSetConfigRequest is used by the Operator endpoint to update the -// current Autopilot configuration of the cluster. -type AutopilotSetConfigRequest struct { - // Datacenter is the target this request is intended for. - Datacenter string - - // Config is the new Autopilot configuration to use. - Config AutopilotConfig - - // CAS controls whether to use check-and-set semantics for this request. - CAS bool - - // WriteRequest holds the ACL token to go along with this request. - WriteRequest -} - -// RequestDatacenter returns the datacenter for a given request. -func (op *AutopilotSetConfigRequest) RequestDatacenter() string { - return op.Datacenter -} - -// 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 serf.MemberStatus - - // 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 time.Duration - - // 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 -} - -// IsHealthy determines whether this ServerHealth is considered healthy -// based on the given Autopilot config -func (h *ServerHealth) IsHealthy(lastTerm uint64, leaderLastIndex uint64, autopilotConf *AutopilotConfig) bool { - if h.SerfStatus != serf.StatusAlive { - return false - } - - if h.LastContact > autopilotConf.LastContactThreshold || h.LastContact < 0 { - return false - } - - if h.LastTerm != lastTerm { - return false - } - - if leaderLastIndex > autopilotConf.MaxTrailingLogs && h.LastIndex < leaderLastIndex-autopilotConf.MaxTrailingLogs { - return false - } - - return true -} - -// IsStable returns true if the ServerHealth is in a stable, passing state -// according to the given AutopilotConfig -func (h *ServerHealth) IsStable(now time.Time, conf *AutopilotConfig) bool { - if h == nil { - return false - } - - if !h.Healthy { - return false - } - - if now.Sub(h.StableSince) < conf.ServerStabilizationTime { - return false - } - - return true -} - -// ServerStats holds miscellaneous Raft metrics for a server -type ServerStats struct { - // LastContact is the time since this node's last contact with the leader. - LastContact string - - // 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 -} - -// 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 -} diff --git a/vendor/github.com/hashicorp/consul/consul/structs/prepared_query.go b/vendor/github.com/hashicorp/consul/consul/structs/prepared_query.go deleted file mode 100644 index af535f010..000000000 --- a/vendor/github.com/hashicorp/consul/consul/structs/prepared_query.go +++ /dev/null @@ -1,257 +0,0 @@ -package structs - -// 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 - - // Failover controls what we do if there are no healthy nodes in the - // local datacenter. - Failover QueryDatacenterOptions - - // 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 - - // Near allows the query to always prefer the node nearest the given - // node. If the node does not exist, results are returned in their - // normal randomly-shuffled order. Supplying the magic "_agent" value - // is supported to sort near the agent which initiated the request. - Near string - - // 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 -} - -const ( - // QueryTemplateTypeNamePrefixMatch uses the Name field of the query as - // a prefix to select the template. - QueryTemplateTypeNamePrefixMatch = "name_prefix_match" -) - -// QueryTemplateOptions controls settings if this query is a template. -type QueryTemplateOptions struct { - // Type, if non-empty, means that this query is a template. This is - // set to one of the QueryTemplateType* constants above. - Type string - - // Regexp is an optional regular expression to use to parse the full - // name, once the prefix match has selected a template. This can be - // used to extract parts of the name and choose a service name, set - // tags, etc. - Regexp string -} - -// PreparedQuery defines a complete prepared query, and is the structure we -// maintain in the state store. -type PreparedQuery 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 - - // Template is used to configure this query as a template, which will - // respond to queries based on the Name, and then will be rendered - // before it is executed. - Template QueryTemplateOptions - - // 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 - - RaftIndex -} - -// GetACLPrefix returns the prefix to look up the prepared_query ACL policy for -// this query, and whether the prefix applies to this query. You always need to -// check the ok value before using the prefix. -func (pq *PreparedQuery) GetACLPrefix() (string, bool) { - if pq.Name != "" || pq.Template.Type != "" { - return pq.Name, true - } - - return "", false -} - -type PreparedQueries []*PreparedQuery - -type IndexedPreparedQueries struct { - Queries PreparedQueries - QueryMeta -} - -type PreparedQueryOp string - -const ( - PreparedQueryCreate PreparedQueryOp = "create" - PreparedQueryUpdate PreparedQueryOp = "update" - PreparedQueryDelete PreparedQueryOp = "delete" -) - -// QueryRequest is used to create or change prepared queries. -type PreparedQueryRequest struct { - // Datacenter is the target this request is intended for. - Datacenter string - - // Op is the operation to apply. - Op PreparedQueryOp - - // Query is the query itself. - Query *PreparedQuery - - // WriteRequest holds the ACL token to go along with this request. - WriteRequest -} - -// RequestDatacenter returns the datacenter for a given request. -func (q *PreparedQueryRequest) RequestDatacenter() string { - return q.Datacenter -} - -// PreparedQuerySpecificRequest is used to get information about a prepared -// query. -type PreparedQuerySpecificRequest struct { - // Datacenter is the target this request is intended for. - Datacenter string - - // QueryID is the ID of a query. - QueryID string - - // QueryOptions (unfortunately named here) controls the consistency - // settings for the query lookup itself, as well as the service lookups. - QueryOptions -} - -// RequestDatacenter returns the datacenter for a given request. -func (q *PreparedQuerySpecificRequest) RequestDatacenter() string { - return q.Datacenter -} - -// PreparedQueryExecuteRequest is used to execute a prepared query. -type PreparedQueryExecuteRequest struct { - // Datacenter is the target this request is intended for. - Datacenter string - - // QueryIDOrName is the ID of a query _or_ the name of one, either can - // be provided. - QueryIDOrName string - - // Limit will trim the resulting list down to the given limit. - Limit int - - // Source is used to sort the results relative to a given node using - // network coordinates. - Source QuerySource - - // Agent is used to carry around a reference to the agent which initiated - // the execute request. Used to distance-sort relative to the local node. - Agent QuerySource - - // QueryOptions (unfortunately named here) controls the consistency - // settings for the query lookup itself, as well as the service lookups. - QueryOptions -} - -// RequestDatacenter returns the datacenter for a given request. -func (q *PreparedQueryExecuteRequest) RequestDatacenter() string { - return q.Datacenter -} - -// PreparedQueryExecuteRemoteRequest is used when running a local query in a -// remote datacenter. -type PreparedQueryExecuteRemoteRequest struct { - // Datacenter is the target this request is intended for. - Datacenter string - - // Query is a copy of the query to execute. We have to ship the entire - // query over since it won't be present in the remote state store. - Query PreparedQuery - - // Limit will trim the resulting list down to the given limit. - Limit int - - // QueryOptions (unfortunately named here) controls the consistency - // settings for the the service lookups. - QueryOptions -} - -// RequestDatacenter returns the datacenter for a given request. -func (q *PreparedQueryExecuteRemoteRequest) RequestDatacenter() string { - return q.Datacenter -} - -// 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 CheckServiceNodes - - // 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 - - // QueryMeta has freshness information about the query. - QueryMeta -} - -// PreparedQueryExplainResponse has the results when explaining a query/ -type PreparedQueryExplainResponse struct { - // Query has the fully-rendered query. - Query PreparedQuery - - // QueryMeta has freshness information about the query. - QueryMeta -} diff --git a/vendor/github.com/hashicorp/consul/consul/structs/snapshot.go b/vendor/github.com/hashicorp/consul/consul/structs/snapshot.go deleted file mode 100644 index 3d65e317f..000000000 --- a/vendor/github.com/hashicorp/consul/consul/structs/snapshot.go +++ /dev/null @@ -1,40 +0,0 @@ -package structs - -type SnapshotOp int - -const ( - SnapshotSave SnapshotOp = iota - SnapshotRestore -) - -// SnapshotRequest is used as a header for a snapshot RPC request. This will -// precede any streaming data that's part of the request and is JSON-encoded on -// the wire. -type SnapshotRequest struct { - // Datacenter is the target datacenter for this request. The request - // will be forwarded if necessary. - Datacenter string - - // Token is the ACL token to use for the operation. If ACLs are enabled - // then all operations require a management token. - Token string - - // If set, any follower can service the request. Results may be - // arbitrarily stale. Only applies to SnapshotSave. - AllowStale bool - - // Op is the operation code for the RPC. - Op SnapshotOp -} - -// SnapshotResponse is used header for a snapshot RPC response. This will -// precede any streaming data that's part of the request and is JSON-encoded on -// the wire. -type SnapshotResponse struct { - // Error is the overall error status of the RPC request. - Error string - - // QueryMeta has freshness information about the server that handled the - // request. It is only filled in for a SnapshotSave. - QueryMeta -} diff --git a/vendor/github.com/hashicorp/consul/consul/structs/structs.go b/vendor/github.com/hashicorp/consul/consul/structs/structs.go deleted file mode 100644 index 0805dbf4c..000000000 --- a/vendor/github.com/hashicorp/consul/consul/structs/structs.go +++ /dev/null @@ -1,1059 +0,0 @@ -package structs - -import ( - "bytes" - "fmt" - "math/rand" - "reflect" - "time" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/types" - "github.com/hashicorp/go-msgpack/codec" - "github.com/hashicorp/serf/coordinate" - "regexp" - "strings" -) - -var ( - ErrNoLeader = fmt.Errorf("No cluster leader") - ErrNoDCPath = fmt.Errorf("No path to datacenter") - ErrNoServers = fmt.Errorf("No known Consul servers") -) - -type MessageType uint8 - -// RaftIndex is used to track the index used while creating -// or modifying a given struct type. -type RaftIndex struct { - CreateIndex uint64 - ModifyIndex uint64 -} - -const ( - RegisterRequestType MessageType = iota - DeregisterRequestType - KVSRequestType - SessionRequestType - ACLRequestType - TombstoneRequestType - CoordinateBatchUpdateType - PreparedQueryRequestType - TxnRequestType - AutopilotRequestType - AreaRequestType -) - -const ( - // IgnoreUnknownTypeFlag is set along with a MessageType - // to indicate that the message type can be safely ignored - // if it is not recognized. This is for future proofing, so - // that new commands can be added in a way that won't cause - // old servers to crash when the FSM attempts to process them. - IgnoreUnknownTypeFlag MessageType = 128 -) - -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:" -) - -const ( - // The meta key prefix reserved for Consul's internal use - metaKeyReservedPrefix = "consul-" - - // The maximum number of metadata key pairs allowed to be registered - metaMaxKeyPairs = 64 - - // The maximum allowed length of a metadata key - metaKeyMaxLength = 128 - - // The maximum allowed length of a metadata value - metaValueMaxLength = 512 -) - -var ( - // metaKeyFormat checks if a metadata key string is valid - metaKeyFormat = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`).MatchString -) - -func ValidStatus(s string) bool { - return s == HealthPassing || - s == HealthWarning || - s == HealthCritical -} - -const ( - // Client tokens have rules applied - ACLTypeClient = "client" - - // Management tokens have an always allow policy. - // They are used for token management. - ACLTypeManagement = "management" -) - -const ( - // MaxLockDelay provides a maximum LockDelay value for - // a session. Any value above this will not be respected. - MaxLockDelay = 60 * time.Second -) - -// RPCInfo is used to describe common information about query -type RPCInfo interface { - RequestDatacenter() string - IsRead() bool - AllowStaleRead() bool - ACLToken() string -} - -// QueryOptions is used to specify various flags for read queries -type QueryOptions struct { - // Token is the ACL token ID. If not provided, the 'anonymous' - // token is assumed for backwards compatibility. - Token string - - // If set, wait until query exceeds given index. Must be provided - // with MaxQueryTime. - MinQueryIndex uint64 - - // Provided with MinQueryIndex to wait for change. - MaxQueryTime time.Duration - - // If set, any follower can service the request. Results - // may be arbitrarily stale. - AllowStale bool - - // If set, the leader must verify leadership prior to - // servicing the request. Prevents a stale read. - RequireConsistent bool -} - -// QueryOption only applies to reads, so always true -func (q QueryOptions) IsRead() bool { - return true -} - -func (q QueryOptions) AllowStaleRead() bool { - return q.AllowStale -} - -func (q QueryOptions) ACLToken() string { - return q.Token -} - -type WriteRequest struct { - // Token is the ACL token ID. If not provided, the 'anonymous' - // token is assumed for backwards compatibility. - Token string -} - -// WriteRequest only applies to writes, always false -func (w WriteRequest) IsRead() bool { - return false -} - -func (w WriteRequest) AllowStaleRead() bool { - return false -} - -func (w WriteRequest) ACLToken() string { - return w.Token -} - -// QueryMeta allows a query response to include potentially -// useful metadata about a query -type QueryMeta struct { - // This is the index associated with the read - Index uint64 - - // If AllowStale is used, this is time elapsed since - // last contact between the follower and leader. This - // can be used to gauge staleness. - LastContact time.Duration - - // Used to indicate if there is a known leader node - KnownLeader bool -} - -// RegisterRequest is used for the Catalog.Register endpoint -// to register a node as providing a service. If no service -// is provided, the node is registered. -type RegisterRequest struct { - Datacenter string - ID types.NodeID - Node string - Address string - TaggedAddresses map[string]string - NodeMeta map[string]string - Service *NodeService - Check *HealthCheck - Checks HealthChecks - - // SkipNodeUpdate can be used when a register request is intended for - // updating a service and/or checks, but doesn't want to overwrite any - // node information if the node is already registered. If the node - // doesn't exist, it will still be created, but if the node exists, any - // node portion of this update will not apply. - SkipNodeUpdate bool - - WriteRequest -} - -func (r *RegisterRequest) RequestDatacenter() string { - return r.Datacenter -} - -// ChangesNode returns true if the given register request changes the given -// node, which can be nil. This only looks for changes to the node record itself, -// not any of the health checks. -func (r *RegisterRequest) ChangesNode(node *Node) bool { - // This means it's creating the node. - if node == nil { - return true - } - - // If we've been asked to skip the node update, then say there are no - // changes. - if r.SkipNodeUpdate { - return false - } - - // Check if any of the node-level fields are being changed. - if r.ID != node.ID || - r.Node != node.Node || - r.Address != node.Address || - !reflect.DeepEqual(r.TaggedAddresses, node.TaggedAddresses) || - !reflect.DeepEqual(r.NodeMeta, node.Meta) { - return true - } - - return false -} - -// DeregisterRequest is used for the Catalog.Deregister endpoint -// to deregister a node as providing a service. If no service is -// provided the entire node is deregistered. -type DeregisterRequest struct { - Datacenter string - Node string - ServiceID string - CheckID types.CheckID - WriteRequest -} - -func (r *DeregisterRequest) RequestDatacenter() string { - return r.Datacenter -} - -// QuerySource is used to pass along information about the source node -// in queries so that we can adjust the response based on its network -// coordinates. -type QuerySource struct { - Datacenter string - Node string -} - -// DCSpecificRequest is used to query about a specific DC -type DCSpecificRequest struct { - Datacenter string - NodeMetaFilters map[string]string - Source QuerySource - QueryOptions -} - -func (r *DCSpecificRequest) RequestDatacenter() string { - return r.Datacenter -} - -// ServiceSpecificRequest is used to query about a specific service -type ServiceSpecificRequest struct { - Datacenter string - NodeMetaFilters map[string]string - ServiceName string - ServiceTag string - TagFilter bool // Controls tag filtering - Source QuerySource - QueryOptions -} - -func (r *ServiceSpecificRequest) RequestDatacenter() string { - return r.Datacenter -} - -// NodeSpecificRequest is used to request the information about a single node -type NodeSpecificRequest struct { - Datacenter string - Node string - QueryOptions -} - -func (r *NodeSpecificRequest) RequestDatacenter() string { - return r.Datacenter -} - -// ChecksInStateRequest is used to query for nodes in a state -type ChecksInStateRequest struct { - Datacenter string - NodeMetaFilters map[string]string - State string - Source QuerySource - QueryOptions -} - -func (r *ChecksInStateRequest) RequestDatacenter() string { - return r.Datacenter -} - -// Used to return information about a node -type Node struct { - ID types.NodeID - Node string - Address string - TaggedAddresses map[string]string - Meta map[string]string - - RaftIndex -} -type Nodes []*Node - -// ValidateMeta validates a set of key/value pairs from the agent config -func ValidateMetadata(meta map[string]string) error { - if len(meta) > metaMaxKeyPairs { - return fmt.Errorf("Node metadata cannot contain more than %d key/value pairs", metaMaxKeyPairs) - } - - for key, value := range meta { - if err := validateMetaPair(key, value); err != nil { - return fmt.Errorf("Couldn't load metadata pair ('%s', '%s'): %s", key, value, err) - } - } - - return nil -} - -// validateMetaPair checks that the given key/value pair is in a valid format -func validateMetaPair(key, value string) error { - if key == "" { - return fmt.Errorf("Key cannot be blank") - } - if !metaKeyFormat(key) { - return fmt.Errorf("Key contains invalid characters") - } - if len(key) > metaKeyMaxLength { - return fmt.Errorf("Key is too long (limit: %d characters)", metaKeyMaxLength) - } - if strings.HasPrefix(key, metaKeyReservedPrefix) { - return fmt.Errorf("Key prefix '%s' is reserved for internal use", metaKeyReservedPrefix) - } - if len(value) > metaValueMaxLength { - return fmt.Errorf("Value is too long (limit: %d characters)", metaValueMaxLength) - } - return nil -} - -// SatisfiesMetaFilters returns true if the metadata map contains the given filters -func SatisfiesMetaFilters(meta map[string]string, filters map[string]string) bool { - for key, value := range filters { - if v, ok := meta[key]; !ok || v != value { - return false - } - } - return true -} - -// Used to return information about a provided services. -// Maps service name to available tags -type Services map[string][]string - -// ServiceNode represents a node that is part of a service. ID, Address, -// TaggedAddresses, and NodeMeta are node-related fields that are always empty -// in the state store and are filled in on the way out by parseServiceNodes(). -// This is also why PartialClone() skips them, because we know they are blank -// already so it would be a waste of time to copy them. -type ServiceNode struct { - ID types.NodeID - Node string - Address string - TaggedAddresses map[string]string - NodeMeta map[string]string - ServiceID string - ServiceName string - ServiceTags []string - ServiceAddress string - ServicePort int - ServiceEnableTagOverride bool - - RaftIndex -} - -// PartialClone() returns a clone of the given service node, minus the node- -// related fields that get filled in later, Address and TaggedAddresses. -func (s *ServiceNode) PartialClone() *ServiceNode { - tags := make([]string, len(s.ServiceTags)) - copy(tags, s.ServiceTags) - - return &ServiceNode{ - // Skip ID, see above. - Node: s.Node, - // Skip Address, see above. - // Skip TaggedAddresses, see above. - ServiceID: s.ServiceID, - ServiceName: s.ServiceName, - ServiceTags: tags, - ServiceAddress: s.ServiceAddress, - ServicePort: s.ServicePort, - ServiceEnableTagOverride: s.ServiceEnableTagOverride, - RaftIndex: RaftIndex{ - CreateIndex: s.CreateIndex, - ModifyIndex: s.ModifyIndex, - }, - } -} - -// ToNodeService converts the given service node to a node service. -func (s *ServiceNode) ToNodeService() *NodeService { - return &NodeService{ - ID: s.ServiceID, - Service: s.ServiceName, - Tags: s.ServiceTags, - Address: s.ServiceAddress, - Port: s.ServicePort, - EnableTagOverride: s.ServiceEnableTagOverride, - RaftIndex: RaftIndex{ - CreateIndex: s.CreateIndex, - ModifyIndex: s.ModifyIndex, - }, - } -} - -type ServiceNodes []*ServiceNode - -// NodeService is a service provided by a node -type NodeService struct { - ID string - Service string - Tags []string - Address string - Port int - EnableTagOverride bool - - RaftIndex -} - -// IsSame checks if one NodeService is the same as another, without looking -// at the Raft information (that's why we didn't call it IsEqual). This is -// useful for seeing if an update would be idempotent for all the functional -// parts of the structure. -func (s *NodeService) IsSame(other *NodeService) bool { - if s.ID != other.ID || - s.Service != other.Service || - !reflect.DeepEqual(s.Tags, other.Tags) || - s.Address != other.Address || - s.Port != other.Port || - s.EnableTagOverride != other.EnableTagOverride { - return false - } - - return true -} - -// ToServiceNode converts the given node service to a service node. -func (s *NodeService) ToServiceNode(node string) *ServiceNode { - return &ServiceNode{ - // Skip ID, see ServiceNode definition. - Node: node, - // Skip Address, see ServiceNode definition. - // Skip TaggedAddresses, see ServiceNode definition. - ServiceID: s.ID, - ServiceName: s.Service, - ServiceTags: s.Tags, - ServiceAddress: s.Address, - ServicePort: s.Port, - ServiceEnableTagOverride: s.EnableTagOverride, - RaftIndex: RaftIndex{ - CreateIndex: s.CreateIndex, - ModifyIndex: s.ModifyIndex, - }, - } -} - -type NodeServices struct { - Node *Node - Services map[string]*NodeService -} - -// HealthCheck represents a single check on a given node -type HealthCheck struct { - Node string - CheckID types.CheckID // Unique per-node ID - Name string // Check name - Status string // The current check status - Notes string // Additional notes with the status - Output string // Holds output of script runs - ServiceID string // optional associated service - ServiceName string // optional service name - - RaftIndex -} - -// IsSame checks if one HealthCheck is the same as another, without looking -// at the Raft information (that's why we didn't call it IsEqual). This is -// useful for seeing if an update would be idempotent for all the functional -// parts of the structure. -func (c *HealthCheck) IsSame(other *HealthCheck) bool { - if c.Node != other.Node || - c.CheckID != other.CheckID || - c.Name != other.Name || - c.Status != other.Status || - c.Notes != other.Notes || - c.Output != other.Output || - c.ServiceID != other.ServiceID || - c.ServiceName != other.ServiceName { - return false - } - - return true -} - -// Clone returns a distinct clone of the HealthCheck. -func (c *HealthCheck) Clone() *HealthCheck { - clone := new(HealthCheck) - *clone = *c - return clone -} - -// HealthChecks is a collection of HealthCheck structs. -type HealthChecks []*HealthCheck - -// CheckServiceNode is used to provide the node, its service -// definition, as well as a HealthCheck that is associated. -type CheckServiceNode struct { - Node *Node - Service *NodeService - Checks HealthChecks -} -type CheckServiceNodes []CheckServiceNode - -// Shuffle does an in-place random shuffle using the Fisher-Yates algorithm. -func (nodes CheckServiceNodes) Shuffle() { - for i := len(nodes) - 1; i > 0; i-- { - j := rand.Int31n(int32(i + 1)) - nodes[i], nodes[j] = nodes[j], nodes[i] - } -} - -// Filter removes nodes that are failing health checks (and any non-passing -// check if that option is selected). Note that this returns the filtered -// results AND modifies the receiver for performance. -func (nodes CheckServiceNodes) Filter(onlyPassing bool) CheckServiceNodes { - n := len(nodes) -OUTER: - for i := 0; i < n; i++ { - node := nodes[i] - for _, check := range node.Checks { - if check.Status == HealthCritical || - (onlyPassing && check.Status != HealthPassing) { - nodes[i], nodes[n-1] = nodes[n-1], CheckServiceNode{} - n-- - i-- - continue OUTER - } - } - } - return nodes[:n] -} - -// NodeInfo is used to dump all associated information about -// a node. This is currently used for the UI only, as it is -// rather expensive to generate. -type NodeInfo struct { - ID types.NodeID - Node string - Address string - TaggedAddresses map[string]string - Meta map[string]string - Services []*NodeService - Checks HealthChecks -} - -// NodeDump is used to dump all the nodes with all their -// associated data. This is currently used for the UI only, -// as it is rather expensive to generate. -type NodeDump []*NodeInfo - -type IndexedNodes struct { - Nodes Nodes - QueryMeta -} - -type IndexedServices struct { - Services Services - QueryMeta -} - -type IndexedServiceNodes struct { - ServiceNodes ServiceNodes - QueryMeta -} - -type IndexedNodeServices struct { - NodeServices *NodeServices - QueryMeta -} - -type IndexedHealthChecks struct { - HealthChecks HealthChecks - QueryMeta -} - -type IndexedCheckServiceNodes struct { - Nodes CheckServiceNodes - QueryMeta -} - -type IndexedNodeDump struct { - Dump NodeDump - QueryMeta -} - -// DirEntry is used to represent a directory entry. This is -// used for values in our Key-Value store. -type DirEntry struct { - LockIndex uint64 - Key string - Flags uint64 - Value []byte - Session string `json:",omitempty"` - - RaftIndex -} - -// Returns a clone of the given directory entry. -func (d *DirEntry) Clone() *DirEntry { - return &DirEntry{ - LockIndex: d.LockIndex, - Key: d.Key, - Flags: d.Flags, - Value: d.Value, - Session: d.Session, - RaftIndex: RaftIndex{ - CreateIndex: d.CreateIndex, - ModifyIndex: d.ModifyIndex, - }, - } -} - -type DirEntries []*DirEntry - -type KVSOp string - -const ( - KVSSet KVSOp = "set" - KVSDelete = "delete" - KVSDeleteCAS = "delete-cas" // Delete with check-and-set - KVSDeleteTree = "delete-tree" - KVSCAS = "cas" // Check-and-set - KVSLock = "lock" // Lock a key - KVSUnlock = "unlock" // Unlock a key - - // The following operations are only available inside of atomic - // transactions via the Txn request. - KVSGet = "get" // Read the key during the transaction. - KVSGetTree = "get-tree" // Read all keys with the given prefix during the transaction. - KVSCheckSession = "check-session" // Check the session holds the key. - KVSCheckIndex = "check-index" // Check the modify index of the key. -) - -// IsWrite returns true if the given operation alters the state store. -func (op KVSOp) IsWrite() bool { - switch op { - case KVSGet, KVSGetTree, KVSCheckSession, KVSCheckIndex: - return false - - default: - return true - } -} - -// KVSRequest is used to operate on the Key-Value store -type KVSRequest struct { - Datacenter string - Op KVSOp // Which operation are we performing - DirEnt DirEntry // Which directory entry - WriteRequest -} - -func (r *KVSRequest) RequestDatacenter() string { - return r.Datacenter -} - -// KeyRequest is used to request a key, or key prefix -type KeyRequest struct { - Datacenter string - Key string - QueryOptions -} - -func (r *KeyRequest) RequestDatacenter() string { - return r.Datacenter -} - -// KeyListRequest is used to list keys -type KeyListRequest struct { - Datacenter string - Prefix string - Seperator string - QueryOptions -} - -func (r *KeyListRequest) RequestDatacenter() string { - return r.Datacenter -} - -type IndexedDirEntries struct { - Entries DirEntries - QueryMeta -} - -type IndexedKeyList struct { - Keys []string - QueryMeta -} - -type SessionBehavior string - -const ( - SessionKeysRelease SessionBehavior = "release" - SessionKeysDelete = "delete" -) - -const ( - SessionTTLMax = 24 * time.Hour - SessionTTLMultiplier = 2 -) - -// Session is used to represent an open session in the KV store. -// This issued to associate node checks with acquired locks. -type Session struct { - ID string - Name string - Node string - Checks []types.CheckID - LockDelay time.Duration - Behavior SessionBehavior // What to do when session is invalidated - TTL string - - RaftIndex -} -type Sessions []*Session - -type SessionOp string - -const ( - SessionCreate SessionOp = "create" - SessionDestroy = "destroy" -) - -// SessionRequest is used to operate on sessions -type SessionRequest struct { - Datacenter string - Op SessionOp // Which operation are we performing - Session Session // Which session - WriteRequest -} - -func (r *SessionRequest) RequestDatacenter() string { - return r.Datacenter -} - -// SessionSpecificRequest is used to request a session by ID -type SessionSpecificRequest struct { - Datacenter string - Session string - QueryOptions -} - -func (r *SessionSpecificRequest) RequestDatacenter() string { - return r.Datacenter -} - -type IndexedSessions struct { - Sessions Sessions - QueryMeta -} - -// ACL is used to represent a token and its rules -type ACL struct { - ID string - Name string - Type string - Rules string - - RaftIndex -} -type ACLs []*ACL - -type ACLOp string - -const ( - ACLSet ACLOp = "set" - ACLForceSet = "force-set" // Deprecated, left to backwards compatibility - ACLDelete = "delete" -) - -// IsSame checks if one ACL is the same as another, without looking -// at the Raft information (that's why we didn't call it IsEqual). This is -// useful for seeing if an update would be idempotent for all the functional -// parts of the structure. -func (a *ACL) IsSame(other *ACL) bool { - if a.ID != other.ID || - a.Name != other.Name || - a.Type != other.Type || - a.Rules != other.Rules { - return false - } - - return true -} - -// ACLRequest is used to create, update or delete an ACL -type ACLRequest struct { - Datacenter string - Op ACLOp - ACL ACL - WriteRequest -} - -func (r *ACLRequest) RequestDatacenter() string { - return r.Datacenter -} - -// ACLRequests is a list of ACL change requests. -type ACLRequests []*ACLRequest - -// ACLSpecificRequest is used to request an ACL by ID -type ACLSpecificRequest struct { - Datacenter string - ACL string - QueryOptions -} - -func (r *ACLSpecificRequest) RequestDatacenter() string { - return r.Datacenter -} - -// ACLPolicyRequest is used to request an ACL by ID, conditionally -// filtering on an ID -type ACLPolicyRequest struct { - Datacenter string - ACL string - ETag string - QueryOptions -} - -func (r *ACLPolicyRequest) RequestDatacenter() string { - return r.Datacenter -} - -type IndexedACLs struct { - ACLs ACLs - QueryMeta -} - -type ACLPolicy struct { - ETag string - Parent string - Policy *acl.Policy - TTL time.Duration - QueryMeta -} - -// ACLReplicationStatus provides information about the health of the ACL -// replication system. -type ACLReplicationStatus struct { - Enabled bool - Running bool - SourceDatacenter string - ReplicatedIndex uint64 - LastSuccess time.Time - LastError time.Time -} - -// Coordinate stores a node name with its associated network coordinate. -type Coordinate struct { - Node string - Coord *coordinate.Coordinate -} - -type Coordinates []*Coordinate - -// IndexedCoordinate is used to represent a single node's coordinate from the state -// store. -type IndexedCoordinate struct { - Coord *coordinate.Coordinate - QueryMeta -} - -// IndexedCoordinates is used to represent a list of nodes and their -// corresponding raw coordinates. -type IndexedCoordinates struct { - Coordinates Coordinates - QueryMeta -} - -// DatacenterMap is used to represent a list of nodes with their raw coordinates, -// associated with a datacenter. Coordinates are only compatible between nodes in -// the same area. -type DatacenterMap struct { - Datacenter string - AreaID types.AreaID - Coordinates Coordinates -} - -// CoordinateUpdateRequest is used to update the network coordinate of a given -// node. -type CoordinateUpdateRequest struct { - Datacenter string - Node string - Coord *coordinate.Coordinate - WriteRequest -} - -// RequestDatacenter returns the datacenter for a given update request. -func (c *CoordinateUpdateRequest) RequestDatacenter() string { - return c.Datacenter -} - -// EventFireRequest is used to ask a server to fire -// a Serf event. It is a bit odd, since it doesn't depend on -// the catalog or leader. Any node can respond, so it's not quite -// like a standard write request. This is used only internally. -type EventFireRequest struct { - Datacenter string - Name string - Payload []byte - - // Not using WriteRequest so that any server can process - // the request. It is a bit unusual... - QueryOptions -} - -func (r *EventFireRequest) RequestDatacenter() string { - return r.Datacenter -} - -// EventFireResponse is used to respond to a fire request. -type EventFireResponse struct { - QueryMeta -} - -type TombstoneOp string - -const ( - TombstoneReap TombstoneOp = "reap" -) - -// TombstoneRequest is used to trigger a reaping of the tombstones -type TombstoneRequest struct { - Datacenter string - Op TombstoneOp - ReapIndex uint64 - WriteRequest -} - -func (r *TombstoneRequest) RequestDatacenter() string { - return r.Datacenter -} - -// msgpackHandle is a shared handle for encoding/decoding of structs -var msgpackHandle = &codec.MsgpackHandle{} - -// Decode is used to decode a MsgPack encoded object -func Decode(buf []byte, out interface{}) error { - return codec.NewDecoder(bytes.NewReader(buf), msgpackHandle).Decode(out) -} - -// Encode is used to encode a MsgPack object with type prefix -func Encode(t MessageType, msg interface{}) ([]byte, error) { - var buf bytes.Buffer - buf.WriteByte(uint8(t)) - err := codec.NewEncoder(&buf, msgpackHandle).Encode(msg) - return buf.Bytes(), err -} - -// CompoundResponse is an interface for gathering multiple responses. It is -// used in cross-datacenter RPC calls where more than 1 datacenter is -// expected to reply. -type CompoundResponse interface { - // Add adds a new response to the compound response - Add(interface{}) - - // New returns an empty response object which can be passed around by - // reference, and then passed to Add() later on. - New() interface{} -} - -type KeyringOp string - -const ( - KeyringList KeyringOp = "list" - KeyringInstall = "install" - KeyringUse = "use" - KeyringRemove = "remove" -) - -// KeyringRequest encapsulates a request to modify an encryption keyring. -// It can be used for install, remove, or use key type operations. -type KeyringRequest struct { - Operation KeyringOp - Key string - Datacenter string - Forwarded bool - RelayFactor uint8 - QueryOptions -} - -func (r *KeyringRequest) RequestDatacenter() string { - return r.Datacenter -} - -// KeyringResponse is a unified key response and can be used for install, -// remove, use, as well as listing key queries. -type KeyringResponse struct { - WAN bool - Datacenter string - Messages map[string]string `json:",omitempty"` - Keys map[string]int - NumNodes int - Error string `json:",omitempty"` -} - -// KeyringResponses holds multiple responses to keyring queries. Each -// datacenter replies independently, and KeyringResponses is used as a -// container for the set of all responses. -type KeyringResponses struct { - Responses []*KeyringResponse - QueryMeta -} - -func (r *KeyringResponses) Add(v interface{}) { - val := v.(*KeyringResponses) - r.Responses = append(r.Responses, val.Responses...) -} - -func (r *KeyringResponses) New() interface{} { - return new(KeyringResponses) -} diff --git a/vendor/github.com/hashicorp/consul/consul/structs/txn.go b/vendor/github.com/hashicorp/consul/consul/structs/txn.go deleted file mode 100644 index 3f8035b97..000000000 --- a/vendor/github.com/hashicorp/consul/consul/structs/txn.go +++ /dev/null @@ -1,85 +0,0 @@ -package structs - -import ( - "fmt" -) - -// TxnKVOp is used to define a single operation on the KVS inside a -// transaction -type TxnKVOp struct { - Verb KVSOp - DirEnt DirEntry -} - -// TxnKVResult is used to define the result of a single operation on the KVS -// inside a transaction. -type TxnKVResult *DirEntry - -// TxnOp is used to define a single operation inside a transaction. Only one -// of the types should be filled out per entry. -type TxnOp struct { - KV *TxnKVOp -} - -// TxnOps is a list of operations within a transaction. -type TxnOps []*TxnOp - -// TxnRequest is used to apply multiple operations to the state store in a -// single transaction -type TxnRequest struct { - Datacenter string - Ops TxnOps - WriteRequest -} - -func (r *TxnRequest) RequestDatacenter() string { - return r.Datacenter -} - -// TxnReadRequest is used as a fast path for read-only transactions that don't -// modify the state store. -type TxnReadRequest struct { - Datacenter string - Ops TxnOps - QueryOptions -} - -func (r *TxnReadRequest) RequestDatacenter() string { - return r.Datacenter -} - -// TxnError is used to return information about an error for a specific -// operation. -type TxnError struct { - OpIndex int - What string -} - -// Error returns the string representation of an atomic error. -func (e TxnError) Error() string { - return fmt.Sprintf("op %d: %s", e.OpIndex, e.What) -} - -// TxnErrors is a list of TxnError entries. -type TxnErrors []*TxnError - -// TxnResult is used to define the result of a given operation inside a -// transaction. Only one of the types should be filled out per entry. -type TxnResult struct { - KV TxnKVResult -} - -// TxnResults is a list of TxnResult entries. -type TxnResults []*TxnResult - -// TxnResponse is the structure returned by a TxnRequest. -type TxnResponse struct { - Results TxnResults - Errors TxnErrors -} - -// TxnReadResponse is the structure returned by a TxnReadRequest. -type TxnReadResponse struct { - TxnResponse - QueryMeta -} diff --git a/vendor/github.com/hashicorp/consul/lib/eof.go b/vendor/github.com/hashicorp/consul/lib/eof.go new file mode 100644 index 000000000..f77844fd6 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/lib/eof.go @@ -0,0 +1,27 @@ +package lib + +import ( + "io" + "strings" + + "github.com/hashicorp/yamux" +) + +var yamuxStreamClosed = yamux.ErrStreamClosed.Error() +var yamuxSessionShutdown = yamux.ErrSessionShutdown.Error() + +// IsErrEOF returns true if we get an EOF error from the socket itself, or +// an EOF equivalent error from yamux. +func IsErrEOF(err error) bool { + if err == io.EOF { + return true + } + + errStr := err.Error() + if strings.Contains(errStr, yamuxStreamClosed) || + strings.Contains(errStr, yamuxSessionShutdown) { + return true + } + + return false +} diff --git a/vendor/github.com/hashicorp/consul/lib/rtt.go b/vendor/github.com/hashicorp/consul/lib/rtt.go index e53a52707..a417f533c 100644 --- a/vendor/github.com/hashicorp/consul/lib/rtt.go +++ b/vendor/github.com/hashicorp/consul/lib/rtt.go @@ -18,6 +18,39 @@ func ComputeDistance(a *coordinate.Coordinate, b *coordinate.Coordinate) float64 return a.DistanceTo(b).Seconds() } +// CoordinateSet holds all the coordinates for a given node, indexed by network +// segment name. +type CoordinateSet map[string]*coordinate.Coordinate + +// Intersect tries to return a pair of coordinates which are compatible with the +// current set and a given set. We employ some special knowledge about network +// segments to avoid doing a full intersection, since this is in several hot +// paths. This might return nil for either coordinate in the output pair if an +// intersection cannot be found. The ComputeDistance function above is designed +// to deal with that. +func (cs CoordinateSet) Intersect(other CoordinateSet) (*coordinate.Coordinate, *coordinate.Coordinate) { + // Use the empty segment by default. + segment := "" + + // If we have a single segment, then let our segment take priority since + // we are possibly a client. Any node with more than one segment can only + // be a server, which means it should be in all segments. + if len(cs) == 1 { + for s, _ := range cs { + segment = s + } + } + + // Likewise for the other set. + if len(other) == 1 { + for s, _ := range other { + segment = s + } + } + + return cs[segment], other[segment] +} + // GenerateCoordinate creates a new coordinate with the given distance from the // origin. This should only be used for tests. func GenerateCoordinate(rtt time.Duration) *coordinate.Coordinate { diff --git a/vendor/github.com/hashicorp/consul/test/porter/client.go b/vendor/github.com/hashicorp/consul/test/porter/client.go new file mode 100644 index 000000000..34d3579e9 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/test/porter/client.go @@ -0,0 +1,36 @@ +package porter + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" +) + +var DefaultAddr = "127.0.0.1:7965" + +func RandomPorts(n int) ([]int, error) { + addr := os.Getenv("PORTER_ADDR") + if addr == "" { + b, err := ioutil.ReadFile("/tmp/porter.addr") + if err == nil { + addr = string(b) + } + } + if addr == "" { + addr = DefaultAddr + } + resp, err := http.Get(fmt.Sprintf("http://%s/%d", addr, n)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var p []int + err = json.Unmarshal(data, &p) + return p, err +} diff --git a/vendor/github.com/hashicorp/consul/testutil/server.go b/vendor/github.com/hashicorp/consul/testutil/server.go index 969d06a58..c01471271 100644 --- a/vendor/github.com/hashicorp/consul/testutil/server.go +++ b/vendor/github.com/hashicorp/consul/testutil/server.go @@ -27,6 +27,7 @@ import ( "testing" "time" + "github.com/hashicorp/consul/test/porter" "github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-uuid" @@ -47,9 +48,6 @@ type TestPortConfig struct { SerfLan int `json:"serf_lan,omitempty"` SerfWan int `json:"serf_wan,omitempty"` Server int `json:"server,omitempty"` - - // Deprecated - RPC int `json:"rpc,omitempty"` } // TestAddressConfig contains the bind addresses for various @@ -58,6 +56,14 @@ 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"` @@ -68,6 +74,7 @@ type TestServerConfig struct { 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"` @@ -104,8 +111,12 @@ func defaultServerConfig() *TestServerConfig { panic(err) } + ports, err := porter.RandomPorts(6) + if err != nil { + panic(err) + } return &TestServerConfig{ - NodeName: fmt.Sprintf("node%d", randomPort()), + NodeName: "node-" + nodeID, NodeID: nodeID, DisableCheckpoint: true, Performance: &TestPerformanceConfig{ @@ -117,28 +128,17 @@ func defaultServerConfig() *TestServerConfig { Bind: "127.0.0.1", Addresses: &TestAddressConfig{}, Ports: &TestPortConfig{ - DNS: randomPort(), - HTTP: randomPort(), - HTTPS: randomPort(), - SerfLan: randomPort(), - SerfWan: randomPort(), - Server: randomPort(), - RPC: randomPort(), + DNS: ports[0], + HTTP: ports[1], + HTTPS: ports[2], + SerfLan: ports[3], + SerfWan: ports[4], + Server: ports[5], }, ReadyTimeout: 10 * time.Second, } } -// randomPort asks the kernel for a random port to use. -func randomPort() int { - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - panic(err) - } - defer l.Close() - return l.Addr().(*net.TCPAddr).Port -} - // TestService is used to serialize a service definition. type TestService struct { ID string `json:",omitempty"` @@ -191,15 +191,7 @@ func NewTestServerConfig(cb ServerConfigCallback) (*TestServer, 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) { - var server *TestServer - retry.Run(t, func(r *retry.R) { - var err error - server, err = newTestServerConfigT(t, cb) - if err != nil { - r.Fatalf("failed starting test server: %v", err) - } - }) - return server, nil + return newTestServerConfigT(t, cb) } // newTestServerConfigT is the internal helper for NewTestServerConfigT. diff --git a/vendor/github.com/hashicorp/consul/testutil/server_methods.go b/vendor/github.com/hashicorp/consul/testutil/server_methods.go index 8f4b067ad..dec512054 100644 --- a/vendor/github.com/hashicorp/consul/testutil/server_methods.go +++ b/vendor/github.com/hashicorp/consul/testutil/server_methods.go @@ -25,13 +25,13 @@ const ( // JoinLAN is used to join local datacenters together. func (s *TestServer) JoinLAN(t *testing.T, addr string) { - resp := s.get(t, "/v1/agent/join/"+addr) + 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.get(t, "/v1/agent/join/"+addr+"?wan=1") + resp := s.put(t, "/v1/agent/join/"+addr+"?wan=1", nil) resp.Body.Close() } diff --git a/vendor/github.com/hashicorp/consul/types/README.md b/vendor/github.com/hashicorp/consul/types/README.md deleted file mode 100644 index da662f4a1..000000000 --- a/vendor/github.com/hashicorp/consul/types/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Consul `types` Package - -The Go language has a strong type system built into the language. The -`types` package corrals named types into a single package that is terminal in -`go`'s import graph. The `types` package should not have any downstream -dependencies. Each subsystem that defines its own set of types exists in its -own file, but all types are defined in the same package. - -# Why - -> Everything should be made as simple as possible, but not simpler. - -`string` is a useful container and underlying type for identifiers, however -the `string` type is effectively opaque to the compiler in terms of how a -given string is intended to be used. For instance, there is nothing -preventing the following from happening: - -```go -// `map` of Widgets, looked up by ID -var widgetLookup map[string]*Widget -// ... -var widgetID string = "widgetID" -w, found := widgetLookup[widgetID] - -// Bad! -var widgetName string = "name of widget" -w, found := widgetLookup[widgetName] -``` - -but this class of problem is entirely preventable: - -```go -type WidgetID string -var widgetLookup map[WidgetID]*Widget -var widgetName -``` - -TL;DR: intentions and idioms aren't statically checked by compilers. The -`types` package uses Go's strong type system to prevent this class of bug. diff --git a/vendor/github.com/hashicorp/consul/types/area.go b/vendor/github.com/hashicorp/consul/types/area.go deleted file mode 100644 index 5425434c9..000000000 --- a/vendor/github.com/hashicorp/consul/types/area.go +++ /dev/null @@ -1,9 +0,0 @@ -package types - -// AreaID is a strongly-typed string used to uniquely represent a network area, -// which is a relationship between Consul servers. -type AreaID string - -// This represents the existing WAN area that's built in to Consul. Consul -// Enterprise generalizes areas, which are represented with UUIDs. -const AreaWAN AreaID = "wan" diff --git a/vendor/github.com/hashicorp/consul/types/checks.go b/vendor/github.com/hashicorp/consul/types/checks.go deleted file mode 100644 index 25a136b4f..000000000 --- a/vendor/github.com/hashicorp/consul/types/checks.go +++ /dev/null @@ -1,5 +0,0 @@ -package types - -// CheckID is a strongly typed string used to uniquely represent a Consul -// Check on an Agent (a CheckID is not globally unique). -type CheckID string diff --git a/vendor/github.com/hashicorp/consul/types/node_id.go b/vendor/github.com/hashicorp/consul/types/node_id.go deleted file mode 100644 index c0588ed42..000000000 --- a/vendor/github.com/hashicorp/consul/types/node_id.go +++ /dev/null @@ -1,4 +0,0 @@ -package types - -// NodeID is a unique identifier for a node across space and time. -type NodeID string diff --git a/vendor/vendor.json b/vendor/vendor.json index 44a0f0159..800e15914 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -749,46 +749,34 @@ "revisionTime": "2017-10-03T21:31:50Z" }, { - "checksumSHA1": "jfELEMRhiTcppZmRH+ZwtkVS5Uw=", - "path": "github.com/hashicorp/consul/acl", - "revision": "75ca2cace08e38de8af1731ee8614d0533d5a4d4", - "revisionTime": "2017-08-10T00:46:41Z" - }, - { - "checksumSHA1": "AgdPCR9/+M0kkVpaeZ0PnATxfSc=", + "checksumSHA1": "XLfcIX2qpRr0o26aFMjCOzvw6jo=", "path": "github.com/hashicorp/consul/api", - "revision": "75ca2cace08e38de8af1731ee8614d0533d5a4d4", - "revisionTime": "2017-08-10T00:46:41Z" + "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", + "revisionTime": "2017-10-16T16:22:40Z" }, { - "checksumSHA1": "Z1N3jX/5B7GbLNfNp5GTxrsJItc=", - "path": "github.com/hashicorp/consul/consul/structs", - "revision": "e9ca44d0a1757ac9aecc6785904a701936c10e4a", - "revisionTime": "2017-04-17T18:01:43Z" - }, - { - "checksumSHA1": "X3kV+a3rz+kw6SJupDVjHmUEUCQ=", + "checksumSHA1": "tU6mtqrRxFn0gqqRC35JhD0y2rE=", "path": "github.com/hashicorp/consul/lib", - "revision": "75ca2cace08e38de8af1731ee8614d0533d5a4d4", - "revisionTime": "2017-08-10T00:46:41Z" + "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", + "revisionTime": "2017-10-16T16:22:40Z" }, { - "checksumSHA1": "++0PVBxbpylmllyCxSa7cdc6dDc=", + "checksumSHA1": "lLvSnIuLwqn3ZbX1H4dVtzKuRdU=", + "path": "github.com/hashicorp/consul/test/porter", + "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", + "revisionTime": "2017-10-16T16:22:40Z" + }, + { + "checksumSHA1": "srD5fzGnxoAqvR6oIE4JBJ1OuT8=", "path": "github.com/hashicorp/consul/testutil", - "revision": "75ca2cace08e38de8af1731ee8614d0533d5a4d4", - "revisionTime": "2017-08-10T00:46:41Z" + "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", + "revisionTime": "2017-10-16T16:22:40Z" }, { "checksumSHA1": "J8TTDc84MvAyXE/FrfgS+xc/b6s=", "path": "github.com/hashicorp/consul/testutil/retry", - "revision": "75ca2cace08e38de8af1731ee8614d0533d5a4d4", - "revisionTime": "2017-08-10T00:46:41Z" - }, - { - "checksumSHA1": "bYK/7DsyTM3YDjvc0RRUH4I+jic=", - "path": "github.com/hashicorp/consul/types", - "revision": "75ca2cace08e38de8af1731ee8614d0533d5a4d4", - "revisionTime": "2017-08-10T00:46:41Z" + "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", + "revisionTime": "2017-10-16T16:22:40Z" }, { "path": "github.com/hashicorp/errwrap", From 756737ae0a711ea8a4e735f5bb1f1e1945c18887 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Mon, 16 Oct 2017 16:58:41 -0700 Subject: [PATCH 3/5] Consul test server fork without porter/rpc.ports --- GNUmakefile | 3 +- .../hashicorp/consul/testutil/server.go | 43 +++++++++++++------ .../consul/testutil/server_methods.go | 4 +- vendor/vendor.json | 10 ++--- 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 16ac9d185..900ea4401 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -150,7 +150,8 @@ deps: ## Install build and development dependencies go get -u github.com/elazarl/go-bindata-assetfs/... go get -u github.com/hashicorp/vault go get -u github.com/a8m/tree/cmd/tree - go get -u github.com/hashicorp/consul/test/porter/cmd/porter + ## Unneeded since we use Consul's no-porter branch + ##go get -u github.com/hashicorp/consul/test/porter/cmd/porter .PHONY: check check: ## Lint the source code diff --git a/vendor/github.com/hashicorp/consul/testutil/server.go b/vendor/github.com/hashicorp/consul/testutil/server.go index c01471271..22880a869 100644 --- a/vendor/github.com/hashicorp/consul/testutil/server.go +++ b/vendor/github.com/hashicorp/consul/testutil/server.go @@ -27,7 +27,6 @@ import ( "testing" "time" - "github.com/hashicorp/consul/test/porter" "github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-uuid" @@ -48,6 +47,9 @@ type TestPortConfig struct { SerfLan int `json:"serf_lan,omitempty"` SerfWan int `json:"serf_wan,omitempty"` Server int `json:"server,omitempty"` + + // Deprecated + RPC int `json:"rpc,omitempty"` } // TestAddressConfig contains the bind addresses for various @@ -111,12 +113,8 @@ func defaultServerConfig() *TestServerConfig { panic(err) } - ports, err := porter.RandomPorts(6) - if err != nil { - panic(err) - } return &TestServerConfig{ - NodeName: "node-" + nodeID, + NodeName: fmt.Sprintf("node%d", randomPort()), NodeID: nodeID, DisableCheckpoint: true, Performance: &TestPerformanceConfig{ @@ -128,17 +126,28 @@ func defaultServerConfig() *TestServerConfig { 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], + DNS: randomPort(), + HTTP: randomPort(), + HTTPS: randomPort(), + SerfLan: randomPort(), + SerfWan: randomPort(), + Server: randomPort(), + //RPC: randomPort(), }, ReadyTimeout: 10 * time.Second, } } +// randomPort asks the kernel for a random port to use. +func randomPort() int { + l, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + panic(err) + } + defer l.Close() + return l.Addr().(*net.TCPAddr).Port +} + // TestService is used to serialize a service definition. type TestService struct { ID string `json:",omitempty"` @@ -191,7 +200,15 @@ func NewTestServerConfig(cb ServerConfigCallback) (*TestServer, 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) + var server *TestServer + retry.Run(t, func(r *retry.R) { + var err error + server, err = newTestServerConfigT(t, cb) + if err != nil { + r.Fatalf("failed starting test server: %v", err) + } + }) + return server, nil } // newTestServerConfigT is the internal helper for NewTestServerConfigT. diff --git a/vendor/github.com/hashicorp/consul/testutil/server_methods.go b/vendor/github.com/hashicorp/consul/testutil/server_methods.go index dec512054..8f4b067ad 100644 --- a/vendor/github.com/hashicorp/consul/testutil/server_methods.go +++ b/vendor/github.com/hashicorp/consul/testutil/server_methods.go @@ -25,13 +25,13 @@ const ( // 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) + resp := s.get(t, "/v1/agent/join/"+addr) 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 := s.get(t, "/v1/agent/join/"+addr+"?wan=1") resp.Body.Close() } diff --git a/vendor/vendor.json b/vendor/vendor.json index 800e15914..21fc9fdf7 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -767,16 +767,16 @@ "revisionTime": "2017-10-16T16:22:40Z" }, { - "checksumSHA1": "srD5fzGnxoAqvR6oIE4JBJ1OuT8=", + "checksumSHA1": "AZh3opzONxPrOi+4Io2+OomdKgM=", "path": "github.com/hashicorp/consul/testutil", - "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", - "revisionTime": "2017-10-16T16:22:40Z" + "revision": "745fd38728f28061c9f5bfe323d68ee25f2cd07b", + "revisionTime": "2017-10-16T23:19:35Z" }, { "checksumSHA1": "J8TTDc84MvAyXE/FrfgS+xc/b6s=", "path": "github.com/hashicorp/consul/testutil/retry", - "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", - "revisionTime": "2017-10-16T16:22:40Z" + "revision": "745fd38728f28061c9f5bfe323d68ee25f2cd07b", + "revisionTime": "2017-10-16T23:19:35Z" }, { "path": "github.com/hashicorp/errwrap", From a52cb34ab8f3b61746c63b436043d9a5363f0cff Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Mon, 16 Oct 2017 17:35:47 -0700 Subject: [PATCH 4/5] Don't set Interval on TTL health checks --- command/agent/consul/client.go | 2 ++ command/agent/consul/int_test.go | 47 ++++++++++++-------------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/command/agent/consul/client.go b/command/agent/consul/client.go index 1f8dba93d..47a04da7d 100644 --- a/command/agent/consul/client.go +++ b/command/agent/consul/client.go @@ -1064,6 +1064,8 @@ func createCheckReg(serviceID, checkID string, check *structs.ServiceCheck, host chkReg.TCP = net.JoinHostPort(host, strconv.Itoa(port)) case structs.ServiceCheckScript: chkReg.TTL = (check.Interval + ttlCheckBuffer).String() + // As of Consul 1.0.0 setting TTL and Interval is a 400 + chkReg.Interval = "" default: return nil, fmt.Errorf("check type %+q not valid", check.Type) } diff --git a/command/agent/consul/int_test.go b/command/agent/consul/int_test.go index 0d4087707..9295a696c 100644 --- a/command/agent/consul/int_test.go +++ b/command/agent/consul/int_test.go @@ -19,6 +19,7 @@ import ( "github.com/hashicorp/nomad/command/agent/consul" "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/structs" + "github.com/stretchr/testify/assert" ) func testLogger() *log.Logger { @@ -37,6 +38,8 @@ func TestConsul_Integration(t *testing.T) { if testing.Short() { t.Skip("-short set; skipping") } + assert := assert.New(t) + // Create an embedded Consul server testconsul, err := testutil.NewTestServerConfig(func(c *testutil.TestServerConfig) { // If -v wasn't specified squelch consul logging @@ -128,9 +131,8 @@ func TestConsul_Integration(t *testing.T) { taskDir := allocDir.NewTaskDir(task.Name) vclient := vaultclient.NewMockVaultClient() consulClient, err := consulapi.NewClient(consulConfig) - if err != nil { - t.Fatalf("error creating consul client: %v", err) - } + assert.Nil(err) + serviceClient := consul.NewServiceClient(consulClient.Agent(), true, logger) defer serviceClient.Shutdown() // just-in-case cleanup consulRan := make(chan struct{}) @@ -154,9 +156,7 @@ func TestConsul_Integration(t *testing.T) { // Block waiting for the service to appear catalog := consulClient.Catalog() res, meta, err := catalog.Service("httpd2", "test", nil) - if err != nil { - t.Fatalf("bad: %v", err) - } + assert.Nil(err) for i := 0; len(res) == 0 && i < 10; i++ { //Expected initial request to fail, do a blocking query @@ -165,32 +165,25 @@ func TestConsul_Integration(t *testing.T) { t.Fatalf("error querying for service: %v", err) } } - if len(res) != 1 { - t.Fatalf("expected 1 service but found %d:\n%#v", len(res), res) - } + assert.Len(res, 1) + + // Truncate results res = res[:] // Assert the service with the checks exists for i := 0; len(res) == 0 && i < 10; i++ { res, meta, err = catalog.Service("httpd", "http", &consulapi.QueryOptions{WaitIndex: meta.LastIndex + 1, WaitTime: 3 * time.Second}) - if err != nil { - t.Fatalf("error querying for service: %v", err) - } - } - if len(res) != 1 { - t.Fatalf("exepcted 1 service but found %d:\n%#v", len(res), res) + assert.Nil(err) } + assert.Len(res, 1) // Assert the script check passes (mock_driver script checks always // pass) after having time to run once time.Sleep(2 * time.Second) checks, _, err := consulClient.Health().Checks("httpd", nil) - if err != nil { - t.Fatalf("error querying checks: %v", err) - } - if expected := 2; len(checks) != expected { - t.Fatalf("expected %d checks but found %d:\n%#v", expected, len(checks), checks) - } + assert.Nil(err) + assert.Len(checks, 2) + for _, check := range checks { if expected := "httpd"; check.ServiceName != expected { t.Fatalf("expected checks to be for %q but found service name = %q", expected, check.ServiceName) @@ -244,13 +237,7 @@ func TestConsul_Integration(t *testing.T) { // Ensure Consul is clean services, _, err := catalog.Services(nil) - if err != nil { - t.Fatalf("error query services: %v", err) - } - if len(services) != 1 { - t.Fatalf("expected only 1 service in Consul but found %d:\n%#v", len(services), services) - } - if _, ok := services["consul"]; !ok { - t.Fatalf(`expected only the "consul" key in Consul but found: %#v`, services) - } + assert.Nil(err) + assert.Len(services, 1) + assert.Contains(services, "consul") } From eec7bae1a0dc51567b33d05767399c80a59965c9 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Tue, 17 Oct 2017 09:56:54 -0700 Subject: [PATCH 5/5] No need to leave this commented out code in --- GNUmakefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 900ea4401..996302bb0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -150,8 +150,6 @@ deps: ## Install build and development dependencies go get -u github.com/elazarl/go-bindata-assetfs/... go get -u github.com/hashicorp/vault go get -u github.com/a8m/tree/cmd/tree - ## Unneeded since we use Consul's no-porter branch - ##go get -u github.com/hashicorp/consul/test/porter/cmd/porter .PHONY: check check: ## Lint the source code