diff --git a/nomad/leader.go b/nomad/leader.go index 825dd9b4f..d35743a6f 100644 --- a/nomad/leader.go +++ b/nomad/leader.go @@ -1,6 +1,7 @@ package nomad import ( + "bytes" "context" "errors" "fmt" @@ -770,7 +771,7 @@ ERR_WAIT: // be deleted or updated. func diffACLPolicies(state *state.StateStore, minIndex uint64, remoteList []*structs.ACLPolicyListStub) (delete []string, update []string) { // Construct a set of the local and remote policies - local := make(map[string]struct{}) + local := make(map[string][]byte) remote := make(map[string]struct{}) // Add all the local policies @@ -784,7 +785,7 @@ func diffACLPolicies(state *state.StateStore, minIndex uint64, remoteList []*str break } policy := raw.(*structs.ACLPolicy) - local[policy.Name] = struct{}{} + local[policy.Name] = policy.Hash } // Iterate over the remote policies @@ -792,14 +793,11 @@ func diffACLPolicies(state *state.StateStore, minIndex uint64, remoteList []*str remote[rp.Name] = struct{}{} // Check if the policy is missing locally - if _, ok := local[rp.Name]; !ok { + if localHash, ok := local[rp.Name]; !ok { update = append(update, rp.Name) - // Check if policy is newer remotely - // TODO: Eventually would be nice to use a policy - // hash or something to avoid fetching policies that - // are unchanged. - } else if rp.ModifyIndex > minIndex { + // Check if policy is newer remotely and there is a hash mis-match. + } else if rp.ModifyIndex > minIndex && !bytes.Equal(localHash, rp.Hash) { update = append(update, rp.Name) } } @@ -915,7 +913,7 @@ ERR_WAIT: // be deleted or updated. func diffACLTokens(state *state.StateStore, minIndex uint64, remoteList []*structs.ACLTokenListStub) (delete []string, update []string) { // Construct a set of the local and remote policies - local := make(map[string]struct{}) + local := make(map[string][]byte) remote := make(map[string]struct{}) // Add all the local global tokens @@ -929,7 +927,7 @@ func diffACLTokens(state *state.StateStore, minIndex uint64, remoteList []*struc break } token := raw.(*structs.ACLToken) - local[token.AccessorID] = struct{}{} + local[token.AccessorID] = token.Hash } // Iterate over the remote tokens @@ -937,14 +935,11 @@ func diffACLTokens(state *state.StateStore, minIndex uint64, remoteList []*struc remote[rp.AccessorID] = struct{}{} // Check if the token is missing locally - if _, ok := local[rp.AccessorID]; !ok { + if localHash, ok := local[rp.AccessorID]; !ok { update = append(update, rp.AccessorID) - // Check if token is newer remotely - // TODO: Eventually would be nice to use an object - // hash or something to avoid fetching tokens that - // are unchanged. - } else if rp.ModifyIndex > minIndex { + // Check if policy is newer remotely and there is a hash mis-match. + } else if rp.ModifyIndex > minIndex && !bytes.Equal(localHash, rp.Hash) { update = append(update, rp.AccessorID) } } diff --git a/nomad/leader_test.go b/nomad/leader_test.go index c6827566f..8b3381d56 100644 --- a/nomad/leader_test.go +++ b/nomad/leader_test.go @@ -683,6 +683,7 @@ func TestLeader_DiffACLPolicies(t *testing.T) { p2Stub.ModifyIndex = 50 // Ignored, same index p3Stub := p3.Stub() p3Stub.ModifyIndex = 100 // Updated, higher index + p3Stub.Hash = []byte{0, 1, 2, 3} p4 := mock.ACLPolicy() remoteList := []*structs.ACLPolicyListStub{ p2Stub, @@ -759,6 +760,7 @@ func TestLeader_DiffACLTokens(t *testing.T) { p2Stub.ModifyIndex = 50 // Ignored, same index p3Stub := p3.Stub() p3Stub.ModifyIndex = 100 // Updated, higher index + p3Stub.Hash = []byte{0, 1, 2, 3} p4 := mock.ACLToken() p4.Global = true remoteList := []*structs.ACLTokenListStub{ diff --git a/nomad/mock/mock.go b/nomad/mock/mock.go index ca22302f2..115021e96 100644 --- a/nomad/mock/mock.go +++ b/nomad/mock/mock.go @@ -339,7 +339,7 @@ func PlanResult() *structs.PlanResult { } func ACLPolicy() *structs.ACLPolicy { - return &structs.ACLPolicy{ + ap := &structs.ACLPolicy{ Name: fmt.Sprintf("policy-%s", structs.GenerateUUID()), Description: "Super cool policy!", Rules: ` @@ -356,10 +356,12 @@ func ACLPolicy() *structs.ACLPolicy { CreateIndex: 10, ModifyIndex: 20, } + ap.SetHash() + return ap } func ACLToken() *structs.ACLToken { - return &structs.ACLToken{ + tk := &structs.ACLToken{ AccessorID: structs.GenerateUUID(), SecretID: structs.GenerateUUID(), Name: "my cool token " + structs.GenerateUUID(), @@ -370,6 +372,8 @@ func ACLToken() *structs.ACLToken { CreateIndex: 10, ModifyIndex: 20, } + tk.SetHash() + return tk } func ACLManagementToken() *structs.ACLToken {