client: alloc diffing

This commit is contained in:
Armon Dadgar 2015-08-23 14:47:51 -07:00
parent 811d6d85e1
commit 1dfa7296c1
2 changed files with 106 additions and 0 deletions

View File

@ -4,10 +4,74 @@ import (
crand "crypto/rand"
"fmt"
"time"
"github.com/hashicorp/nomad/nomad/structs"
)
import "math/rand"
type allocTuple struct {
exist, updated *structs.Allocation
}
// diffResult is used to return the sets that result from a diff
type diffResult struct {
added []*structs.Allocation
removed []*structs.Allocation
updated []allocTuple
ignore []*structs.Allocation
}
func (d *diffResult) GoString() string {
return fmt.Sprintf("allocs: (added %d) (removed %d) (updated %d) (ignore %d)",
len(d.added), len(d.removed), len(d.updated), len(d.ignore))
}
// diffAllocs is used to diff the existing and updated allocations
// to see what has happened.
func diffAllocs(existing, updated []*structs.Allocation) *diffResult {
result := &diffResult{}
// Index the updated allocations by id
idx := make(map[string]*structs.Allocation)
for _, update := range updated {
idx[update.ID] = update
}
// Scan the existing allocations
existIdx := make(map[string]struct{})
for _, exist := range existing {
// Mark this as existing
existIdx[exist.ID] = struct{}{}
// Check for presence in the new set
update, ok := idx[exist.ID]
// If not present, removed
if !ok {
result.removed = append(result.removed, exist)
continue
}
// Check for an update
if update.ModifyIndex > exist.ModifyIndex {
result.updated = append(result.updated, allocTuple{exist, update})
continue
}
// Ignore this
result.ignore = append(result.ignore, exist)
}
// Scan the updated allocations for any that are new
for _, update := range updated {
if _, ok := existIdx[update.ID]; !ok {
result.added = append(result.added, update)
}
}
return result
}
// generateUUID is used to generate a random UUID
func generateUUID() string {
buf := make([]byte, 16)

View File

@ -5,8 +5,50 @@ import (
"regexp"
"testing"
"time"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
)
func TestDiffAllocs(t *testing.T) {
alloc1 := mock.Alloc() // Ignore
alloc2 := mock.Alloc() // Update
alloc2u := new(structs.Allocation)
*alloc2u = *alloc2
alloc2u.ModifyIndex += 1
alloc3 := mock.Alloc() // Remove
alloc4 := mock.Alloc() // Add
exist := []*structs.Allocation{
alloc1,
alloc2,
alloc3,
}
updated := []*structs.Allocation{
alloc1,
alloc2u,
alloc4,
}
result := diffAllocs(exist, updated)
if len(result.ignore) != 1 || result.ignore[0] != alloc1 {
t.Fatalf("Bad: %#v", result.ignore)
}
if len(result.added) != 1 || result.added[0] != alloc4 {
t.Fatalf("Bad: %#v", result.added)
}
if len(result.removed) != 1 || result.removed[0] != alloc3 {
t.Fatalf("Bad: %#v", result.removed)
}
if len(result.updated) != 1 {
t.Fatalf("Bad: %#v", result.updated)
}
if result.updated[0].exist != alloc2 || result.updated[0].updated != alloc2u {
t.Fatalf("Bad: %#v", result.updated)
}
}
func TestGenerateUUID(t *testing.T) {
prev := generateUUID()
for i := 0; i < 100; i++ {