diff --git a/nomad/structs/funcs.go b/nomad/structs/funcs.go index 56b26d510..fd5644ad1 100644 --- a/nomad/structs/funcs.go +++ b/nomad/structs/funcs.go @@ -2,6 +2,8 @@ package structs import ( crand "crypto/rand" + "crypto/sha1" + "encoding/binary" "fmt" "math" "strings" @@ -255,3 +257,14 @@ func DenormalizeAllocationJobs(job *Job, allocs []*Allocation) { func AllocName(job, group string, idx uint) string { return fmt.Sprintf("%s.%s[%d]", job, group, idx) } + +// ACLPolicyListHash returns a consistent hash for a set of policies. +func ACLPolicyListHash(policies []*ACLPolicy) string { + cacheKeyHash := sha1.New() + for _, policy := range policies { + cacheKeyHash.Write([]byte(policy.Name)) + binary.Write(cacheKeyHash, binary.BigEndian, policy.ModifyIndex) + } + cacheKey := string(cacheKeyHash.Sum(nil)) + return cacheKey +} diff --git a/nomad/structs/funcs_test.go b/nomad/structs/funcs_test.go index 9377a8a6c..a81c4da7a 100644 --- a/nomad/structs/funcs_test.go +++ b/nomad/structs/funcs_test.go @@ -4,6 +4,8 @@ import ( "fmt" "regexp" "testing" + + "github.com/stretchr/testify/assert" ) func TestRemoveAllocs(t *testing.T) { @@ -269,3 +271,49 @@ func TestGenerateUUID(t *testing.T) { } } } + +func TestACLPolicyListHash(t *testing.T) { + h1 := ACLPolicyListHash(nil) + assert.NotEqual(t, "", h1) + + p1 := &ACLPolicy{ + Name: fmt.Sprintf("policy-%s", GenerateUUID()), + Description: "Super cool policy!", + Rules: ` + namespace "default" { + policy = "write" + } + node { + policy = "read" + } + agent { + policy = "read" + } + `, + CreateIndex: 10, + ModifyIndex: 20, + } + + h2 := ACLPolicyListHash([]*ACLPolicy{p1}) + assert.NotEqual(t, "", h2) + assert.NotEqual(t, h1, h2) + + // Create P2 as copy of P1 with new name + p2 := &ACLPolicy{} + *p2 = *p1 + p2.Name = fmt.Sprintf("policy-%s", GenerateUUID()) + + h3 := ACLPolicyListHash([]*ACLPolicy{p1, p2}) + assert.NotEqual(t, "", h3) + assert.NotEqual(t, h2, h3) + + h4 := ACLPolicyListHash([]*ACLPolicy{p2}) + assert.NotEqual(t, "", h4) + assert.NotEqual(t, h3, h4) + + // ModifyIndex should change the hash + p2.ModifyIndex++ + h5 := ACLPolicyListHash([]*ACLPolicy{p2}) + assert.NotEqual(t, "", h5) + assert.NotEqual(t, h4, h5) +}