diff --git a/consul/state/state_store.go b/consul/state/state_store.go index b31d521cc..4d11a072e 100644 --- a/consul/state/state_store.go +++ b/consul/state/state_store.go @@ -119,6 +119,40 @@ func (s *StateStore) Nodes() (structs.Nodes, error) { return results, nil } +// DeleteNode is used to delete a given node by its ID. +func (s *StateStore) DeleteNode(idx uint64, nodeID string) error { + tx := s.db.Txn(true) + defer tx.Abort() + + // Call the node deletion. + if err := s.deleteNodeTxn(idx, nodeID, tx); err != nil { + return err + } + + tx.Commit() + return nil +} + +func (s *StateStore) deleteNodeTxn(idx uint64, nodeID string, tx *memdb.Txn) error { + // Look up the node + node, err := tx.First("nodes", "id", nodeID) + if err != nil { + return fmt.Errorf("node lookup failed: %s", err) + } + + // Delete the node and update the index + if err := tx.Delete("nodes", node); err != nil { + return fmt.Errorf("failed deleting node: %s", err) + } + if err := tx.Insert("index", &IndexEntry{"nodes", idx}); err != nil { + return fmt.Errorf("failed updating index: %s", err) + } + + // TODO: session invalidation + // TODO: watch trigger + return nil +} + // EnsureService is called to upsert creation of a given NodeService. func (s *StateStore) EnsureService(idx uint64, node string, svc *structs.NodeService) error { tx := s.db.Txn(true) diff --git a/consul/state/state_store_test.go b/consul/state/state_store_test.go index 29e2b39c4..c60fc2d18 100644 --- a/consul/state/state_store_test.go +++ b/consul/state/state_store_test.go @@ -124,6 +124,31 @@ func TestStateStore_GetNodes(t *testing.T) { } } +func TestStateStore_DeleteNode(t *testing.T) { + s := testStateStore(t) + + // Create a node + node := &structs.Node{Node: "node1", Address: "1.1.1.1"} + if err := s.EnsureNode(1, node); err != nil { + t.Fatalf("err: %s", err) + } + + // The node exists + if n, err := s.GetNode("node1"); err != nil || n == nil { + t.Fatalf("bad: %#v (%#v)", n, err) + } + + // Delete the node + if err := s.DeleteNode(2, "node1"); err != nil { + t.Fatalf("err: %s", err) + } + + // The node is now gone + if n, err := s.GetNode("node1"); err != nil || n != nil { + t.Fatalf("bad: %#v (%#v)", node, err) + } +} + func TestStateStore_EnsureService_NodeServices(t *testing.T) { s := testStateStore(t)