This commit is contained in:
Alex Dadgar 2016-12-15 15:40:18 -08:00
parent bf1e157bd8
commit d8de7b59a5
2 changed files with 404 additions and 0 deletions

View File

@ -130,6 +130,12 @@ func (j *Job) Diff(other *Job, contextual bool) (*JobDiff, error) {
diff.Objects = append(diff.Objects, pDiff)
}
// Constructor diff
// Vault diff
if cDiff := constructorDiff(j.Constructor, other.Constructor, contextual); cDiff != nil {
diff.Objects = append(diff.Objects, cDiff)
}
return diff, nil
}
@ -370,6 +376,12 @@ func (t *Task) Diff(other *Task, contextual bool) (*TaskDiff, error) {
diff.Objects = append(diff.Objects, lDiff)
}
// Dispatch Input diff
dDiff := primitiveObjectDiff(t.DispatchInput, other.DispatchInput, nil, "DispatchInput", contextual)
if dDiff != nil {
diff.Objects = append(diff.Objects, dDiff)
}
// Artifacts diff
diffs := primitiveObjectSetDiff(
interfaceSlice(t.Artifacts),
@ -629,6 +641,43 @@ func vaultDiff(old, new *Vault, contextual bool) *ObjectDiff {
return diff
}
// constructorDiff returns the diff of two constructor objects. If contextual
// diff is enabled, all fields will be returned, even if no diff occurred.
func constructorDiff(old, new *ConstructorConfig, contextual bool) *ObjectDiff {
diff := &ObjectDiff{Type: DiffTypeNone, Name: "Constructor"}
var oldPrimitiveFlat, newPrimitiveFlat map[string]string
if reflect.DeepEqual(old, new) {
return nil
} else if old == nil {
old = &ConstructorConfig{}
diff.Type = DiffTypeAdded
newPrimitiveFlat = flatmap.Flatten(new, nil, true)
} else if new == nil {
new = &ConstructorConfig{}
diff.Type = DiffTypeDeleted
oldPrimitiveFlat = flatmap.Flatten(old, nil, true)
} else {
diff.Type = DiffTypeEdited
oldPrimitiveFlat = flatmap.Flatten(old, nil, true)
newPrimitiveFlat = flatmap.Flatten(new, nil, true)
}
// Diff the primitive fields.
diff.Fields = fieldDiffs(oldPrimitiveFlat, newPrimitiveFlat, contextual)
// Meta diffs
if optionalDiff := stringSetDiff(old.MetaOptional, new.MetaOptional, "OptionalMeta", contextual); optionalDiff != nil {
diff.Objects = append(diff.Objects, optionalDiff)
}
if requiredDiff := stringSetDiff(old.MetaRequired, new.MetaRequired, "RequiredMeta", contextual); requiredDiff != nil {
diff.Objects = append(diff.Objects, requiredDiff)
}
return diff
}
// Diff returns a diff of two resource objects. If contextual diff is enabled,
// non-changed fields will still be returned.
func (r *Resources) Diff(other *Resources, contextual bool) *ObjectDiff {

View File

@ -877,6 +877,247 @@ func TestJobDiff(t *testing.T) {
},
},
},
{
// Constructor added
Old: &Job{},
New: &Job{
Constructor: &ConstructorConfig{
Payload: DispatchPayloadRequired,
MetaOptional: []string{"foo"},
MetaRequired: []string{"bar"},
},
},
Expected: &JobDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeAdded,
Name: "Constructor",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "Payload",
Old: "",
New: DispatchPayloadRequired,
},
},
Objects: []*ObjectDiff{
{
Type: DiffTypeAdded,
Name: "OptionalMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "OptionalMeta",
Old: "",
New: "foo",
},
},
},
{
Type: DiffTypeAdded,
Name: "RequiredMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "RequiredMeta",
Old: "",
New: "bar",
},
},
},
},
},
},
},
},
{
// Constructor deleted
Old: &Job{
Constructor: &ConstructorConfig{
Payload: DispatchPayloadRequired,
MetaOptional: []string{"foo"},
MetaRequired: []string{"bar"},
},
},
New: &Job{},
Expected: &JobDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeDeleted,
Name: "Constructor",
Fields: []*FieldDiff{
{
Type: DiffTypeDeleted,
Name: "Payload",
Old: DispatchPayloadRequired,
New: "",
},
},
Objects: []*ObjectDiff{
{
Type: DiffTypeDeleted,
Name: "OptionalMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeDeleted,
Name: "OptionalMeta",
Old: "foo",
New: "",
},
},
},
{
Type: DiffTypeDeleted,
Name: "RequiredMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeDeleted,
Name: "RequiredMeta",
Old: "bar",
New: "",
},
},
},
},
},
},
},
},
{
// Constructor edited
Old: &Job{
Constructor: &ConstructorConfig{
Payload: DispatchPayloadRequired,
MetaOptional: []string{"foo"},
MetaRequired: []string{"bar"},
},
},
New: &Job{
Constructor: &ConstructorConfig{
Payload: DispatchPayloadOptional,
MetaOptional: []string{"bam"},
MetaRequired: []string{"bang"},
},
},
Expected: &JobDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "Constructor",
Fields: []*FieldDiff{
{
Type: DiffTypeEdited,
Name: "Payload",
Old: DispatchPayloadRequired,
New: DispatchPayloadOptional,
},
},
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "OptionalMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "OptionalMeta",
Old: "",
New: "bam",
},
{
Type: DiffTypeDeleted,
Name: "OptionalMeta",
Old: "foo",
New: "",
},
},
},
{
Type: DiffTypeEdited,
Name: "RequiredMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "RequiredMeta",
Old: "",
New: "bang",
},
{
Type: DiffTypeDeleted,
Name: "RequiredMeta",
Old: "bar",
New: "",
},
},
},
},
},
},
},
},
{
// Constructor edited with context
Contextual: true,
Old: &Job{
Constructor: &ConstructorConfig{
Payload: DispatchPayloadRequired,
MetaOptional: []string{"foo"},
MetaRequired: []string{"bar"},
},
},
New: &Job{
Constructor: &ConstructorConfig{
Payload: DispatchPayloadOptional,
MetaOptional: []string{"foo"},
MetaRequired: []string{"bar"},
},
},
Expected: &JobDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "Constructor",
Fields: []*FieldDiff{
{
Type: DiffTypeEdited,
Name: "Payload",
Old: DispatchPayloadRequired,
New: DispatchPayloadOptional,
},
},
Objects: []*ObjectDiff{
{
Type: DiffTypeNone,
Name: "OptionalMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeNone,
Name: "OptionalMeta",
Old: "foo",
New: "foo",
},
},
},
{
Type: DiffTypeNone,
Name: "RequiredMeta",
Fields: []*FieldDiff{
{
Type: DiffTypeNone,
Name: "RequiredMeta",
Old: "bar",
New: "bar",
},
},
},
},
},
},
},
},
}
for i, c := range cases {
@ -3424,6 +3665,120 @@ func TestTaskDiff(t *testing.T) {
},
},
},
{
// DispatchInput added
Old: &Task{},
New: &Task{
DispatchInput: &DispatchInputConfig{
File: "foo",
},
},
Expected: &TaskDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeAdded,
Name: "DispatchInput",
Fields: []*FieldDiff{
{
Type: DiffTypeAdded,
Name: "File",
Old: "",
New: "foo",
},
},
},
},
},
},
{
// DispatchInput deleted
Old: &Task{
DispatchInput: &DispatchInputConfig{
File: "foo",
},
},
New: &Task{},
Expected: &TaskDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeDeleted,
Name: "DispatchInput",
Fields: []*FieldDiff{
{
Type: DiffTypeDeleted,
Name: "File",
Old: "foo",
New: "",
},
},
},
},
},
},
{
// Dispatch input edited
Old: &Task{
DispatchInput: &DispatchInputConfig{
File: "foo",
},
},
New: &Task{
DispatchInput: &DispatchInputConfig{
File: "bar",
},
},
Expected: &TaskDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "DispatchInput",
Fields: []*FieldDiff{
{
Type: DiffTypeEdited,
Name: "File",
Old: "foo",
New: "bar",
},
},
},
},
},
},
{
// DispatchInput edited with context. Place holder for if more
// fields are added
Contextual: true,
Old: &Task{
DispatchInput: &DispatchInputConfig{
File: "foo",
},
},
New: &Task{
DispatchInput: &DispatchInputConfig{
File: "bar",
},
},
Expected: &TaskDiff{
Type: DiffTypeEdited,
Objects: []*ObjectDiff{
{
Type: DiffTypeEdited,
Name: "DispatchInput",
Fields: []*FieldDiff{
{
Type: DiffTypeEdited,
Name: "File",
Old: "foo",
New: "bar",
},
},
},
},
},
},
}
for i, c := range cases {