From 92191298d0480876c02f339e698b8e0d14e19310 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Sun, 6 Sep 2015 21:27:07 -0700 Subject: [PATCH] consul/state: implement acl delete --- consul/state/state_store.go | 37 ++++++++++++++++++++++++++++++ consul/state/state_store_test.go | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/consul/state/state_store.go b/consul/state/state_store.go index e6b47a2d26..79150aaf4b 100644 --- a/consul/state/state_store.go +++ b/consul/state/state_store.go @@ -1246,3 +1246,40 @@ func (s *StateStore) ACLGet(aclID string) (*structs.ACL, error) { } return nil, nil } + +// ACLDelete is used to remove an existing ACL from the state store. If +// the ACL does not exist this is a no-op and no error is returned. +func (s *StateStore) ACLDelete(idx uint64, aclID string) error { + tx := s.db.Txn(true) + defer tx.Abort() + + // Call the ACL delete + if err := s.aclDeleteTxn(idx, aclID, tx); err != nil { + return err + } + + tx.Commit() + return nil +} + +// aclDeleteTxn is used to delete an ACL from the state store within +// an existing transaction. +func (s *StateStore) aclDeleteTxn(idx uint64, aclID string, tx *memdb.Txn) error { + // Look up the existing ACL + acl, err := tx.First("acls", "id", aclID) + if err != nil { + return fmt.Errorf("failed acl lookup: %s", err) + } + if acl == nil { + return nil + } + + // Delete the ACL from the state store and update indexes + if err := tx.Delete("acls", acl); err != nil { + return fmt.Errorf("failed deleting acl: %s", err) + } + if err := tx.Insert("index", &IndexEntry{"acls", idx}); err != nil { + return fmt.Errorf("failed updating index: %s", err) + } + return nil +} diff --git a/consul/state/state_store_test.go b/consul/state/state_store_test.go index e3a423ecf3..5a9369dbcc 100644 --- a/consul/state/state_store_test.go +++ b/consul/state/state_store_test.go @@ -1565,3 +1565,42 @@ func TestStateStore_ACLSet(t *testing.T) { t.Fatalf("bad: %#v", acl) } } + +func TestStateStore_ACLDelete(t *testing.T) { + s := testStateStore(t) + + // Calling delete on an ACL which doesn't exist returns nil + if err := s.ACLDelete(1, "nope"); err != nil { + t.Fatalf("err: %s", err) + } + + // Index isn't updated if nothing is deleted + if idx := s.maxIndex("acls"); idx != 0 { + t.Fatalf("bad index: %d", idx) + } + + // Insert an ACL + if err := s.ACLSet(1, &structs.ACL{ID: "acl1"}); err != nil { + t.Fatalf("err: %s", err) + } + + // Delete the ACL and check that the index was updated + if err := s.ACLDelete(2, "acl1"); err != nil { + t.Fatalf("err: %s", err) + } + if idx := s.maxIndex("acls"); idx != 2 { + t.Fatalf("bad index: %d", idx) + } + + tx := s.db.Txn(false) + defer tx.Abort() + + // Check that the ACL was really deleted + result, err := tx.First("acls", "id", "acl1") + if err != nil { + t.Fatalf("err: %s", err) + } + if result != nil { + t.Fatalf("expected nil, got: %#v", result) + } +}