mirror of https://github.com/status-im/consul.git
Enable looking up consul nodes by their node ID.
Assuming the following output from a consul agent: ``` ==> Consul agent running! Version: 'v0.7.3-43-gc5e140c-dev (c5e140c+CHANGES)' Node ID: '40e4a748-2192-161a-0510-9bf59fe950b5' Node name: 'myhost' ``` it is now possible to lookup nodes by their Node Name or Node ID, or a prefix match of the Node ID, with the following caveats re: the prefix match: 1) first eight digits of the Node ID are a required minimum (eight was chosen as an arbitrary number) 2) the length of the Node ID must be an even number or no result will be returned. ``` % dig @127.0.0.1 -p 8600 myhost.node.dc1.consul. myhost.node.dc1.consul. 0 IN A 127.0.0.1 % dig @127.0.0.1 -p 8600 40e4a748-2192-161a-0510-9bf59fe950b5.node.dc1.consul. 40e4a748-2192-161a-0510-9bf59fe950b5.node.dc1.consul. 0 IN A 127.0.0.1 % dig @127.0.0.1 -p 8600 40e4a748.node.dc1.consul. 40e4a748.node.dc1.consul. 0 IN A 127.0.0.1 % dig @127.0.0.1 -p 8600 40e4a74821.node.dc1.consul. 40e4a74821.node.dc1.consul. 0 IN A 127.0.0.1 % dig @127.0.0.1 -p 8600 40e4a748-21.node.dc1.consul. 40e4a748-21.node.dc1.consul. 0 IN A 127.0.0.1 ```
This commit is contained in:
parent
c5e140c79d
commit
f3f3f73e6d
|
@ -9,6 +9,13 @@ import (
|
||||||
"github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// minUUIDLookupLen is used as a minimum length of a node name required before
|
||||||
|
// we test to see if the name is actually a UUID and perform an ID-based node
|
||||||
|
// lookup.
|
||||||
|
minUUIDLookupLen = 8
|
||||||
|
)
|
||||||
|
|
||||||
// Nodes is used to pull the full list of nodes for use during snapshots.
|
// Nodes is used to pull the full list of nodes for use during snapshots.
|
||||||
func (s *StateSnapshot) Nodes() (memdb.ResultIterator, error) {
|
func (s *StateSnapshot) Nodes() (memdb.ResultIterator, error) {
|
||||||
iter, err := s.tx.Get("nodes", "id")
|
iter, err := s.tx.Get("nodes", "id")
|
||||||
|
@ -151,7 +158,7 @@ func (s *StateStore) ensureNodeTxn(tx *memdb.Txn, idx uint64, node *structs.Node
|
||||||
// Check for an existing node
|
// Check for an existing node
|
||||||
existing, err := tx.First("nodes", "id", node.Node)
|
existing, err := tx.First("nodes", "id", node.Node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("node lookup failed: %s", err)
|
return fmt.Errorf("node name lookup failed: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the indexes
|
// Get the indexes
|
||||||
|
@ -174,7 +181,7 @@ func (s *StateStore) ensureNodeTxn(tx *memdb.Txn, idx uint64, node *structs.Node
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNode is used to retrieve a node registration by node ID.
|
// GetNode is used to retrieve a node registration by node name ID.
|
||||||
func (s *StateStore) GetNode(id string) (uint64, *structs.Node, error) {
|
func (s *StateStore) GetNode(id string) (uint64, *structs.Node, error) {
|
||||||
tx := s.db.Txn(false)
|
tx := s.db.Txn(false)
|
||||||
defer tx.Abort()
|
defer tx.Abort()
|
||||||
|
@ -193,6 +200,25 @@ func (s *StateStore) GetNode(id string) (uint64, *structs.Node, error) {
|
||||||
return idx, nil, nil
|
return idx, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNodeID is used to retrieve a node registration by node ID.
|
||||||
|
func (s *StateStore) GetNodeID(id types.NodeID) (uint64, *structs.Node, error) {
|
||||||
|
tx := s.db.Txn(false)
|
||||||
|
defer tx.Abort()
|
||||||
|
|
||||||
|
// Get the table index.
|
||||||
|
idx := maxIndexTxn(tx, "nodes")
|
||||||
|
|
||||||
|
// Retrieve the node from the state store
|
||||||
|
node, err := tx.First("nodes", "uuid", string(id))
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("node lookup failed: %s", err)
|
||||||
|
}
|
||||||
|
if node != nil {
|
||||||
|
return idx, node.(*structs.Node), nil
|
||||||
|
}
|
||||||
|
return idx, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Nodes is used to return all of the known nodes.
|
// Nodes is used to return all of the known nodes.
|
||||||
func (s *StateStore) Nodes(ws memdb.WatchSet) (uint64, structs.Nodes, error) {
|
func (s *StateStore) Nodes(ws memdb.WatchSet) (uint64, structs.Nodes, error) {
|
||||||
tx := s.db.Txn(false)
|
tx := s.db.Txn(false)
|
||||||
|
@ -662,15 +688,34 @@ func (s *StateStore) NodeServices(ws memdb.WatchSet, nodeName string) (uint64, *
|
||||||
// Get the table index.
|
// Get the table index.
|
||||||
idx := maxIndexTxn(tx, "nodes", "services")
|
idx := maxIndexTxn(tx, "nodes", "services")
|
||||||
|
|
||||||
// Query the node
|
// Query the node by node name
|
||||||
watchCh, n, err := tx.FirstWatch("nodes", "id", nodeName)
|
watchCh, n, err := tx.FirstWatch("nodes", "id", nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, fmt.Errorf("node lookup failed: %s", err)
|
return 0, nil, fmt.Errorf("node lookup failed: %s", err)
|
||||||
}
|
}
|
||||||
ws.Add(watchCh)
|
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return 0, nil, nil
|
if len(nodeName) >= minUUIDLookupLen {
|
||||||
|
// Attempt to lookup the node by it's node ID
|
||||||
|
var idWatchCh <-chan struct{}
|
||||||
|
idWatchCh, n, err = tx.FirstWatch("nodes", "uuid_prefix", nodeName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, fmt.Errorf("node ID lookup failed: %s", err)
|
||||||
|
}
|
||||||
|
if n == nil {
|
||||||
|
ws.Add(watchCh)
|
||||||
|
return 0, nil, nil
|
||||||
|
} else {
|
||||||
|
ws.Add(idWatchCh)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ws.Add(watchCh)
|
||||||
|
return 0, nil, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ws.Add(watchCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
node := n.(*structs.Node)
|
node := n.(*structs.Node)
|
||||||
|
|
||||||
// Read all of the services
|
// Read all of the services
|
||||||
|
|
|
@ -10,14 +10,23 @@ import (
|
||||||
"github.com/hashicorp/consul/lib"
|
"github.com/hashicorp/consul/lib"
|
||||||
"github.com/hashicorp/consul/types"
|
"github.com/hashicorp/consul/types"
|
||||||
"github.com/hashicorp/go-memdb"
|
"github.com/hashicorp/go-memdb"
|
||||||
|
uuid "github.com/hashicorp/go-uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func makeRandomNodeID(t *testing.T) types.NodeID {
|
||||||
|
id, err := uuid.GenerateUUID()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
return types.NodeID(id)
|
||||||
|
}
|
||||||
|
|
||||||
func TestStateStore_EnsureRegistration(t *testing.T) {
|
func TestStateStore_EnsureRegistration(t *testing.T) {
|
||||||
s := testStateStore(t)
|
s := testStateStore(t)
|
||||||
|
|
||||||
// Start with just a node.
|
// Start with just a node.
|
||||||
req := &structs.RegisterRequest{
|
req := &structs.RegisterRequest{
|
||||||
ID: types.NodeID("40e4a748-2192-161a-0510-9bf59fe950b5"),
|
ID: makeRandomNodeID(t),
|
||||||
Node: "node1",
|
Node: "node1",
|
||||||
Address: "1.2.3.4",
|
Address: "1.2.3.4",
|
||||||
TaggedAddresses: map[string]string{
|
TaggedAddresses: map[string]string{
|
||||||
|
@ -27,6 +36,7 @@ func TestStateStore_EnsureRegistration(t *testing.T) {
|
||||||
"somekey": "somevalue",
|
"somekey": "somevalue",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
nodeID := req.ID
|
||||||
if err := s.EnsureRegistration(1, req); err != nil {
|
if err := s.EnsureRegistration(1, req); err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +47,7 @@ func TestStateStore_EnsureRegistration(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
}
|
}
|
||||||
if out.ID != types.NodeID("40e4a748-2192-161a-0510-9bf59fe950b5") ||
|
if out.ID != nodeID ||
|
||||||
out.Node != "node1" || out.Address != "1.2.3.4" ||
|
out.Node != "node1" || out.Address != "1.2.3.4" ||
|
||||||
len(out.TaggedAddresses) != 1 ||
|
len(out.TaggedAddresses) != 1 ||
|
||||||
out.TaggedAddresses["hello"] != "world" ||
|
out.TaggedAddresses["hello"] != "world" ||
|
||||||
|
@ -45,6 +55,13 @@ func TestStateStore_EnsureRegistration(t *testing.T) {
|
||||||
out.CreateIndex != 1 || out.ModifyIndex != 1 {
|
out.CreateIndex != 1 || out.ModifyIndex != 1 {
|
||||||
t.Fatalf("bad node returned: %#v", out)
|
t.Fatalf("bad node returned: %#v", out)
|
||||||
}
|
}
|
||||||
|
_, out2, err := s.GetNodeID(nodeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(out, out2) {
|
||||||
|
t.Fatalf("bad node returned: %#v -- %#v", out, out2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
verifyNode()
|
verifyNode()
|
||||||
|
|
||||||
|
@ -183,6 +200,7 @@ func TestStateStore_EnsureRegistration_Restore(t *testing.T) {
|
||||||
|
|
||||||
// Start with just a node.
|
// Start with just a node.
|
||||||
req := &structs.RegisterRequest{
|
req := &structs.RegisterRequest{
|
||||||
|
ID: makeRandomNodeID(t),
|
||||||
Node: "node1",
|
Node: "node1",
|
||||||
Address: "1.2.3.4",
|
Address: "1.2.3.4",
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,14 @@ func nodesTableSchema() *memdb.TableSchema {
|
||||||
Lowercase: true,
|
Lowercase: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"uuid": &memdb.IndexSchema{
|
||||||
|
Name: "uuid",
|
||||||
|
AllowMissing: false,
|
||||||
|
Unique: true,
|
||||||
|
Indexer: &memdb.UUIDFieldIndex{
|
||||||
|
Field: "ID",
|
||||||
|
},
|
||||||
|
},
|
||||||
"meta": &memdb.IndexSchema{
|
"meta": &memdb.IndexSchema{
|
||||||
Name: "meta",
|
Name: "meta",
|
||||||
AllowMissing: true,
|
AllowMissing: true,
|
||||||
|
|
Loading…
Reference in New Issue