This commit is contained in:
Alex Dadgar 2018-10-08 16:58:19 -07:00
parent 87cacb427f
commit a2a56a930c
2 changed files with 303 additions and 0 deletions

View File

@ -840,6 +840,11 @@ func (r *Resources) Diff(other *Resources, contextual bool) *ObjectDiff {
diff.Objects = append(diff.Objects, nDiffs...)
}
// Requested Devices diff
if nDiffs := requestedDevicesDiffs(r.Devices, other.Devices, contextual); nDiffs != nil {
diff.Objects = append(diff.Objects, nDiffs...)
}
return diff
}
@ -975,6 +980,67 @@ func portDiffs(old, new []Port, dynamic bool, contextual bool) []*ObjectDiff {
}
// Diff returns a diff of two requested devices. If contextual diff is enabled,
// non-changed fields will still be returned.
func (r *RequestedDevice) Diff(other *RequestedDevice, contextual bool) *ObjectDiff {
diff := &ObjectDiff{Type: DiffTypeNone, Name: "Device"}
var oldPrimitiveFlat, newPrimitiveFlat map[string]string
if reflect.DeepEqual(r, other) {
return nil
} else if r == nil {
diff.Type = DiffTypeAdded
newPrimitiveFlat = flatmap.Flatten(other, nil, true)
} else if other == nil {
diff.Type = DiffTypeDeleted
oldPrimitiveFlat = flatmap.Flatten(r, nil, true)
} else {
diff.Type = DiffTypeEdited
oldPrimitiveFlat = flatmap.Flatten(r, nil, true)
newPrimitiveFlat = flatmap.Flatten(other, nil, true)
}
// Diff the primitive fields.
diff.Fields = fieldDiffs(oldPrimitiveFlat, newPrimitiveFlat, contextual)
return diff
}
// requestedDevicesDiffs diffs a set of RequestedDevices. If contextual diff is enabled,
// non-changed fields will still be returned.
func requestedDevicesDiffs(old, new []*RequestedDevice, contextual bool) []*ObjectDiff {
makeSet := func(devices []*RequestedDevice) map[string]*RequestedDevice {
deviceMap := make(map[string]*RequestedDevice, len(devices))
for _, d := range devices {
deviceMap[d.Name] = d
}
return deviceMap
}
oldSet := makeSet(old)
newSet := makeSet(new)
var diffs []*ObjectDiff
for k, oldV := range oldSet {
newV := newSet[k]
if diff := oldV.Diff(newV, contextual); diff != nil {
diffs = append(diffs, diff)
}
}
for k, newV := range newSet {
if oldV, ok := oldSet[k]; !ok {
if diff := oldV.Diff(newV, contextual); diff != nil {
diffs = append(diffs, diff)
}
}
}
sort.Sort(ObjectDiffs(diffs))
return diffs
}
// configDiff returns the diff of two Task Config objects. If contextual diff is
// enabled, all fields will be returned, even if no diff occurred.
func configDiff(old, new map[string]interface{}, contextual bool) *ObjectDiff {

View File

@ -3428,6 +3428,243 @@ func TestTaskDiff(t *testing.T) {
},
},
},
{
Name: "Device Resources edited",
Old: &Task{
Resources: &Resources{
Devices: []*RequestedDevice{
{
Name: "foo",
Count: 2,
},
{
Name: "bar",
Count: 2,
},
{
Name: "baz",
Count: 2,
},
},
},
},
New: &Task{
Resources: &Resources{
Devices: []*RequestedDevice{
{
Name: "foo",
Count: 2,
},
{
Name: "bar",
Count: 3,
},
{
Name: "bam",
Count: 2,
},
},
},
},
Expected: &TaskDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "Resources",
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "Device",
Fields: []*FieldDiff{
{
Type: DiffTypeEdited,
Name: "Count",
Old: "2",
New: "3",
},
},
},
{
Type: DiffTypeAdded,
Name: "Device",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "Count",
Old: "",
New: "2",
},
{
Type: DiffTypeAdded,
Name: "Name",
Old: "",
New: "bam",
},
},
},
{
Type: DiffTypeDeleted,
Name: "Device",
Fields: []*FieldDiff{
{
Type: DiffTypeDeleted,
Name: "Count",
Old: "2",
New: "",
},
{
Type: DiffTypeDeleted,
Name: "Name",
Old: "baz",
New: "",
},
},
},
},
},
},
},
},
{
Name: "Device Resources edited with context",
Contextual: true,
Old: &Task{
Resources: &Resources{
CPU: 100,
MemoryMB: 100,
DiskMB: 100,
IOPS: 100,
Devices: []*RequestedDevice{
{
Name: "foo",
Count: 2,
},
{
Name: "bar",
Count: 2,
},
{
Name: "baz",
Count: 2,
},
},
},
},
New: &Task{
Resources: &Resources{
CPU: 100,
MemoryMB: 100,
DiskMB: 100,
IOPS: 100,
Devices: []*RequestedDevice{
{
Name: "foo",
Count: 2,
},
{
Name: "bar",
Count: 3,
},
{
Name: "bam",
Count: 2,
},
},
},
},
Expected: &TaskDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "Resources",
Fields: []*FieldDiff{
{
Type: DiffTypeNone,
Name: "CPU",
Old: "100",
New: "100",
},
{
Type: DiffTypeNone,
Name: "DiskMB",
Old: "100",
New: "100",
},
{
Type: DiffTypeNone,
Name: "IOPS",
Old: "100",
New: "100",
},
{
Type: DiffTypeNone,
Name: "MemoryMB",
Old: "100",
New: "100",
},
},
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "Device",
Fields: []*FieldDiff{
{
Type: DiffTypeEdited,
Name: "Count",
Old: "2",
New: "3",
},
{
Type: DiffTypeNone,
Name: "Name",
Old: "bar",
New: "bar",
},
},
},
{
Type: DiffTypeAdded,
Name: "Device",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "Count",
Old: "",
New: "2",
},
{
Type: DiffTypeAdded,
Name: "Name",
Old: "",
New: "bam",
},
},
},
{
Type: DiffTypeDeleted,
Name: "Device",
Fields: []*FieldDiff{
{
Type: DiffTypeDeleted,
Name: "Count",
Old: "2",
New: "",
},
{
Type: DiffTypeDeleted,
Name: "Name",
Old: "baz",
New: "",
},
},
},
},
},
},
},
},
{
Name: "Config same",
Old: &Task{