From 8a8aef05034fc5270e44221f48eb43eb8cde0aff Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Mon, 24 Aug 2015 18:52:31 -0700 Subject: [PATCH] consul/state: add service delete functions --- consul/state/state_store.go | 39 ++++++++++++++++++++++++++++ consul/state/state_store_test.go | 44 +++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/consul/state/state_store.go b/consul/state/state_store.go index 4d11a072e4..44c1f8472d 100644 --- a/consul/state/state_store.go +++ b/consul/state/state_store.go @@ -133,6 +133,8 @@ func (s *StateStore) DeleteNode(idx uint64, nodeID string) error { return nil } +// deleteNodeTxn is the inner method used for removing a node from +// the store within a given transaction. func (s *StateStore) deleteNodeTxn(idx uint64, nodeID string, tx *memdb.Txn) error { // Look up the node node, err := tx.First("nodes", "id", nodeID) @@ -263,3 +265,40 @@ func (s *StateStore) NodeServices(nodeID string) (*structs.NodeServices, error) return ns, nil } + +// DeleteNodeService is used to delete a given service associated +// with the given node. +func (s *StateStore) DeleteNodeService(idx uint64, nodeID, serviceID string) error { + tx := s.db.Txn(true) + defer tx.Abort() + + // Call the service deletion + if err := s.deleteNodeServiceTxn(idx, nodeID, serviceID, tx); err != nil { + return err + } + + tx.Commit() + return nil +} + +// deleteNodeServiceTxn is the inner method called to remove a service +// registration within an existing transaction. +func (s *StateStore) deleteNodeServiceTxn(idx uint64, nodeID, serviceID string, tx *memdb.Txn) error { + // Look up the service + service, err := tx.First("services", "id", nodeID, serviceID) + if err != nil { + return fmt.Errorf("failed service lookup: %s", err) + } + + // Delete the service and update the index + if err := tx.Delete("services", service); err != nil { + return fmt.Errorf("failed deleting service: %s", err) + } + if err := tx.Insert("index", &IndexEntry{"services", idx}); err != nil { + return fmt.Errorf("failed updating index: %s", err) + } + + // TODO: session invalidation + // TODO: watch trigger + return nil +} diff --git a/consul/state/state_store_test.go b/consul/state/state_store_test.go index c60fc2d18b..678f2dc343 100644 --- a/consul/state/state_store_test.go +++ b/consul/state/state_store_test.go @@ -145,7 +145,7 @@ func TestStateStore_DeleteNode(t *testing.T) { // The node is now gone if n, err := s.GetNode("node1"); err != nil || n != nil { - t.Fatalf("bad: %#v (%#v)", node, err) + t.Fatalf("bad: %#v (err: %#v)", node, err) } } @@ -226,3 +226,45 @@ func TestStateStore_EnsureService_NodeServices(t *testing.T) { t.Fatalf("bad index: %d, %d", out.CreateIndex, out.ModifyIndex) } } + +func TestStateStore_DeleteNodeService(t *testing.T) { + s := testStateStore(t) + + // Register 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) + } + + // Create a service + service := &structs.NodeService{ + ID: "service1", + Service: "redis", + Tags: []string{"prod"}, + Address: "1.1.1.1", + Port: 1111, + } + if err := s.EnsureService(2, "node1", service); err != nil { + t.Fatalf("err: %s", err) + } + + // The service exists + ns, err := s.NodeServices("node1") + if err != nil || ns == nil || len(ns.Services) != 1 { + t.Fatalf("bad: %#v (err: %#v)", ns, err) + } + + // Delete the service + if err := s.DeleteNodeService(3, "node1", "service1"); err != nil { + t.Fatalf("err: %s", err) + } + + // The service doesn't exist. + ns, err = s.NodeServices("node1") + if err != nil || ns == nil || len(ns.Services) != 0 { + t.Fatalf("bad: %#v (err: %#v)", ns, err) + } +}