diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go index ec91d772fbc..71a4eff8e80 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go @@ -110,23 +110,22 @@ func newDefaultFieldManager(f Manager, typeConverter TypeConverter, objectConver return NewFieldManager(f, ignoreManagedFieldsFromRequestObject) } -func decodeLiveManagedFields(liveObj runtime.Object) (Managed, error) { +// DecodeManagedFields converts ManagedFields from the wire format (api format) +// to the format used by sigs.k8s.io/structured-merge-diff +func DecodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (Managed, error) { + return internal.DecodeManagedFields(encodedManagedFields) +} + +func decodeLiveOrNew(liveObj, newObj runtime.Object, ignoreManagedFieldsFromRequestObject bool) (Managed, error) { liveAccessor, err := meta.Accessor(liveObj) if err != nil { return nil, err } - managed, err := internal.DecodeObjectManagedFields(liveAccessor.GetManagedFields()) - if err != nil { - return internal.NewEmptyManaged(), nil - } - return managed, nil -} -func decodeManagedFields(liveObj, newObj runtime.Object, ignoreManagedFieldsFromRequestObject bool) (Managed, error) { // We take the managedFields of the live object in case the request tries to // manually set managedFields via a subresource. if ignoreManagedFieldsFromRequestObject { - return decodeLiveManagedFields(liveObj) + return emptyManagedFieldsOnErr(DecodeManagedFields(liveAccessor.GetManagedFields())) } // If the object doesn't have metadata, we should just return without trying to @@ -140,14 +139,20 @@ func decodeManagedFields(liveObj, newObj runtime.Object, ignoreManagedFieldsFrom return internal.NewEmptyManaged(), nil } - managed, err := internal.DecodeObjectManagedFields(newAccessor.GetManagedFields()) // If the managed field is empty or we failed to decode it, // let's try the live object. This is to prevent clients who // don't understand managedFields from deleting it accidentally. + managed, err := DecodeManagedFields(newAccessor.GetManagedFields()) if err != nil || len(managed.Fields()) == 0 { - return decodeLiveManagedFields(liveObj) + return emptyManagedFieldsOnErr(DecodeManagedFields(liveAccessor.GetManagedFields())) } + return managed, nil +} +func emptyManagedFieldsOnErr(managed Managed, err error) (Managed, error) { + if err != nil { + return internal.NewEmptyManaged(), nil + } return managed, nil } @@ -157,7 +162,7 @@ func decodeManagedFields(liveObj, newObj runtime.Object, ignoreManagedFieldsFrom func (f *FieldManager) Update(liveObj, newObj runtime.Object, manager string) (object runtime.Object, err error) { // First try to decode the managed fields provided in the update, // This is necessary to allow directly updating managed fields. - managed, err := decodeManagedFields(liveObj, newObj, f.ignoreManagedFieldsFromRequestObject) + managed, err := decodeLiveOrNew(liveObj, newObj, f.ignoreManagedFieldsFromRequestObject) if err != nil { return newObj, nil } @@ -219,7 +224,7 @@ func (f *FieldManager) Apply(liveObj, appliedObj runtime.Object, manager string, } // Decode the managed fields in the live object, since it isn't allowed in the patch. - managed, err := internal.DecodeObjectManagedFields(accessor.GetManagedFields()) + managed, err := DecodeManagedFields(accessor.GetManagedFields()) if err != nil { return nil, fmt.Errorf("failed to decode managed fields: %v", err) } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields.go index 9a625e2acf7..652ba64a839 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields.go @@ -77,15 +77,6 @@ func RemoveObjectManagedFields(obj runtime.Object) { accessor.SetManagedFields(nil) } -// DecodeObjectManagedFields extracts and converts the objects ManagedFields into a fieldpath.ManagedFields. -func DecodeObjectManagedFields(from []metav1.ManagedFieldsEntry) (ManagedInterface, error) { - managed, err := decodeManagedFields(from) - if err != nil { - return nil, fmt.Errorf("failed to convert managed fields from API: %v", err) - } - return &managed, nil -} - // EncodeObjectManagedFields converts and stores the fieldpathManagedFields into the objects ManagedFields func EncodeObjectManagedFields(obj runtime.Object, managed ManagedInterface) error { accessor, err := meta.Accessor(obj) @@ -102,9 +93,10 @@ func EncodeObjectManagedFields(obj runtime.Object, managed ManagedInterface) err return nil } -// decodeManagedFields converts ManagedFields from the wire format (api format) +// DecodeManagedFields converts ManagedFields from the wire format (api format) // to the format used by sigs.k8s.io/structured-merge-diff -func decodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (managed managedStruct, err error) { +func DecodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (ManagedInterface, error) { + managed := managedStruct{} managed.fields = make(fieldpath.ManagedFields, len(encodedManagedFields)) managed.times = make(map[string]*metav1.Time, len(encodedManagedFields)) @@ -113,21 +105,21 @@ func decodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (mana case "FieldsV1": // Valid case. case "": - return managedStruct{}, fmt.Errorf("missing fieldsType in managed fields entry %d", i) + return nil, fmt.Errorf("missing fieldsType in managed fields entry %d", i) default: - return managedStruct{}, fmt.Errorf("invalid fieldsType %q in managed fields entry %d", encodedVersionedSet.FieldsType, i) + return nil, fmt.Errorf("invalid fieldsType %q in managed fields entry %d", encodedVersionedSet.FieldsType, i) } manager, err := BuildManagerIdentifier(&encodedVersionedSet) if err != nil { - return managedStruct{}, fmt.Errorf("error decoding manager from %v: %v", encodedVersionedSet, err) + return nil, fmt.Errorf("error decoding manager from %v: %v", encodedVersionedSet, err) } managed.fields[manager], err = decodeVersionedSet(&encodedVersionedSet) if err != nil { - return managedStruct{}, fmt.Errorf("error decoding versioned set from %v: %v", encodedVersionedSet, err) + return nil, fmt.Errorf("error decoding versioned set from %v: %v", encodedVersionedSet, err) } managed.times[manager] = encodedVersionedSet.Time } - return managed, nil + return &managed, nil } // BuildManagerIdentifier creates a manager identifier string from a ManagedFieldsEntry diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields_test.go index 68a6fa5a2b7..1ca4d4b0ba0 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/managedfields_test.go @@ -40,7 +40,7 @@ func TestHasFieldsType(t *testing.T) { `), &unmarshaled); err != nil { t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) } - if _, err := decodeManagedFields(unmarshaled); err != nil { + if _, err := DecodeManagedFields(unmarshaled); err != nil { t.Fatalf("did not expect decoding error but got: %v", err) } @@ -54,7 +54,7 @@ func TestHasFieldsType(t *testing.T) { `), &unmarshaled); err != nil { t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) } - if _, err := decodeManagedFields(unmarshaled); err == nil { + if _, err := DecodeManagedFields(unmarshaled); err == nil { t.Fatal("Expect decoding error but got none") } @@ -67,7 +67,7 @@ func TestHasFieldsType(t *testing.T) { `), &unmarshaled); err != nil { t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) } - if _, err := decodeManagedFields(unmarshaled); err == nil { + if _, err := DecodeManagedFields(unmarshaled); err == nil { t.Fatal("Expect decoding error but got none") } } @@ -189,11 +189,11 @@ func TestRoundTripManagedFields(t *testing.T) { if err := yaml.Unmarshal([]byte(test), &unmarshaled); err != nil { t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) } - decoded, err := decodeManagedFields(unmarshaled) + decoded, err := DecodeManagedFields(unmarshaled) if err != nil { t.Fatalf("did not expect decoding error but got: %v", err) } - encoded, err := encodeManagedFields(&decoded) + encoded, err := encodeManagedFields(decoded) if err != nil { t.Fatalf("did not expect encoding error but got: %v", err) }