diff --git a/consul/acl_replication.go b/consul/acl_replication.go index c7a5f3dd13..c59077543e 100644 --- a/consul/acl_replication.go +++ b/consul/acl_replication.go @@ -10,30 +10,11 @@ import ( "github.com/hashicorp/consul/lib" ) -// aclIDSorter is used to make sure a given list of ACLs is sorted by token ID. -// This should always be true, but since this is crucial for correctness and we -// are accepting input from another server, we sort to make sure. -type aclIDSorter struct { - acls structs.ACLs -} - -// See sort.Interface. -func (a *aclIDSorter) Len() int { - return len(a.acls) -} - -// See sort.Interface. -func (a *aclIDSorter) Swap(i, j int) { - a.acls[i], a.acls[j] = a.acls[j], a.acls[i] -} - -// See sort.Interface. -func (a *aclIDSorter) Less(i, j int) bool { - return a.acls[i].ID < a.acls[j].ID -} - // aclIterator simplifies the algorithm below by providing a basic iterator that -// moves through a list of ACLs and returns nil when it's exhausted. +// moves through a list of ACLs and returns nil when it's exhausted. It also has +// methods for pre-sorting the ACLs being iterated over by ID, which should +// already be true, but since this is crucial for correctness and we are taking +// input from other servers, we sort to make sure. type aclIterator struct { acls structs.ACLs @@ -46,6 +27,21 @@ func newACLIterator(acls structs.ACLs) *aclIterator { return &aclIterator{acls: acls} } +// See sort.Interface. +func (a *aclIterator) Len() int { + return len(a.acls) +} + +// See sort.Interface. +func (a *aclIterator) Swap(i, j int) { + a.acls[i], a.acls[j] = a.acls[j], a.acls[i] +} + +// See sort.Interface. +func (a *aclIterator) Less(i, j int) bool { + return a.acls[i].ID < a.acls[j].ID +} + // Front returns the item at index position, or nil if the list is exhausted. func (a *aclIterator) Front() *structs.ACL { if a.index < len(a.acls) { @@ -72,12 +68,12 @@ func reconcileACLs(local, remote structs.ACLs, lastRemoteIndex uint64) structs.A // version of Consul, and sorted-ness is kind of a subtle property of // the state store indexing, it's prudent to make sure things are sorted // before we begin. - sort.Sort(&aclIDSorter{local}) - sort.Sort(&aclIDSorter{remote}) + localIter, remoteIter := newACLIterator(local), newACLIterator(remote) + sort.Sort(localIter) + sort.Sort(remoteIter) // Run through both lists and reconcile them. var changes structs.ACLRequests - localIter, remoteIter := newACLIterator(local), newACLIterator(remote) for localIter.Front() != nil || remoteIter.Front() != nil { // If the local list is exhausted, then process this as a remote // add. We know from the loop condition that there's something diff --git a/consul/acl_replication_test.go b/consul/acl_replication_test.go index 0f60fc69a8..6bb0bb9602 100644 --- a/consul/acl_replication_test.go +++ b/consul/acl_replication_test.go @@ -21,7 +21,7 @@ func TestACLReplication_Sorter(t *testing.T) { &structs.ACL{ID: "c"}, } - sorter := &aclIDSorter{acls} + sorter := &aclIterator{acls, 0} if len := sorter.Len(); len != 3 { t.Fatalf("bad: %d", len) }