Merge pull request #74721 from kwiesmueller/sort-fieldmanagers

implement managedFields sorting

Kubernetes-commit: c2e1d994b0c8946f20b36b0bb0a2f0c2fd71d0da
This commit is contained in:
Kubernetes Publisher 2019-03-05 14:54:01 -08:00
commit 3174b25959
3 changed files with 418 additions and 285 deletions

570
Godeps/Godeps.json generated

File diff suppressed because it is too large Load Diff

View File

@ -146,6 +146,27 @@ func encodeManagedFields(managedFields fieldpath.ManagedFields) (encodedManagedF
}
encodedManagedFields = append(encodedManagedFields, *v)
}
return sortEncodedManagedFields(encodedManagedFields)
}
func sortEncodedManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (sortedManagedFields []metav1.ManagedFieldsEntry, err error) {
sort.Slice(encodedManagedFields, func(i, j int) bool {
p, q := encodedManagedFields[i], encodedManagedFields[j]
if p.Operation != q.Operation {
return p.Operation < q.Operation
}
if p.Time == nil || q.Time == nil {
return false
}
if !p.Time.Equal(q.Time) {
return p.Time.Before(q.Time)
}
return p.Manager < q.Manager
})
return encodedManagedFields, nil
}

View File

@ -17,8 +17,10 @@ limitations under the License.
package internal
import (
"fmt"
"reflect"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -198,3 +200,113 @@ time: "2001-02-03T04:05:06Z"
})
}
}
func TestSortEncodedManagedFields(t *testing.T) {
tests := []struct {
name string
managedFields []metav1.ManagedFieldsEntry
expected []metav1.ManagedFieldsEntry
}{
{
name: "empty",
managedFields: []metav1.ManagedFieldsEntry{},
expected: []metav1.ManagedFieldsEntry{},
},
{
name: "nil",
managedFields: nil,
expected: nil,
},
{
name: "remains untouched",
managedFields: []metav1.ManagedFieldsEntry{
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "a", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
},
expected: []metav1.ManagedFieldsEntry{
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "a", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
},
},
{
name: "apply first",
managedFields: []metav1.ManagedFieldsEntry{
{Manager: "a", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
},
expected: []metav1.ManagedFieldsEntry{
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "a", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
},
},
{
name: "newest last",
managedFields: []metav1.ManagedFieldsEntry{
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
{Manager: "b", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
},
expected: []metav1.ManagedFieldsEntry{
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "b", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
},
},
{
name: "manager last",
managedFields: []metav1.ManagedFieldsEntry{
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "d", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "b", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
},
expected: []metav1.ManagedFieldsEntry{
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "b", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "d", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
},
},
{
name: "manager sorted",
managedFields: []metav1.ManagedFieldsEntry{
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "f", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
{Manager: "d", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
{Manager: "e", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
{Manager: "b", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
},
expected: []metav1.ManagedFieldsEntry{
{Manager: "a", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "b", Operation: metav1.ManagedFieldsOperationApply, Time: nil},
{Manager: "c", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2001-01-01T01:00:00Z")},
{Manager: "d", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
{Manager: "e", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
{Manager: "f", Operation: metav1.ManagedFieldsOperationUpdate, Time: parseTimeOrPanic("2002-01-01T01:00:00Z")},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
sorted, err := sortEncodedManagedFields(test.managedFields)
if err != nil {
t.Fatalf("did not expect error when sorting but got: %v", err)
}
if !reflect.DeepEqual(sorted, test.expected) {
t.Fatalf("expected:\n%v\nbut got:\n%v", test.expected, sorted)
}
})
}
}
func parseTimeOrPanic(s string) *metav1.Time {
t, err := time.Parse(time.RFC3339, s)
if err != nil {
panic(fmt.Sprintf("failed to parse time %s, got: %v", s, err))
}
return &metav1.Time{Time: t.UTC()}
}