export and cleanup managedFields decoding

This commit is contained in:
Kevin Wiesmueller 2021-02-26 17:47:52 +01:00
parent f86b59ab79
commit 589ca1be1c
3 changed files with 31 additions and 34 deletions

View File

@ -110,23 +110,22 @@ func newDefaultFieldManager(f Manager, typeConverter TypeConverter, objectConver
return NewFieldManager(f, ignoreManagedFieldsFromRequestObject) 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) liveAccessor, err := meta.Accessor(liveObj)
if err != nil { if err != nil {
return nil, err 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 // We take the managedFields of the live object in case the request tries to
// manually set managedFields via a subresource. // manually set managedFields via a subresource.
if ignoreManagedFieldsFromRequestObject { if ignoreManagedFieldsFromRequestObject {
return decodeLiveManagedFields(liveObj) return emptyManagedFieldsOnErr(DecodeManagedFields(liveAccessor.GetManagedFields()))
} }
// If the object doesn't have metadata, we should just return without trying to // 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 return internal.NewEmptyManaged(), nil
} }
managed, err := internal.DecodeObjectManagedFields(newAccessor.GetManagedFields())
// If the managed field is empty or we failed to decode it, // If the managed field is empty or we failed to decode it,
// let's try the live object. This is to prevent clients who // let's try the live object. This is to prevent clients who
// don't understand managedFields from deleting it accidentally. // don't understand managedFields from deleting it accidentally.
managed, err := DecodeManagedFields(newAccessor.GetManagedFields())
if err != nil || len(managed.Fields()) == 0 { 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 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) { 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, // First try to decode the managed fields provided in the update,
// This is necessary to allow directly updating managed fields. // 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 { if err != nil {
return newObj, 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. // 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 { if err != nil {
return nil, fmt.Errorf("failed to decode managed fields: %v", err) return nil, fmt.Errorf("failed to decode managed fields: %v", err)
} }

View File

@ -77,15 +77,6 @@ func RemoveObjectManagedFields(obj runtime.Object) {
accessor.SetManagedFields(nil) 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 // EncodeObjectManagedFields converts and stores the fieldpathManagedFields into the objects ManagedFields
func EncodeObjectManagedFields(obj runtime.Object, managed ManagedInterface) error { func EncodeObjectManagedFields(obj runtime.Object, managed ManagedInterface) error {
accessor, err := meta.Accessor(obj) accessor, err := meta.Accessor(obj)
@ -102,9 +93,10 @@ func EncodeObjectManagedFields(obj runtime.Object, managed ManagedInterface) err
return nil 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 // 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.fields = make(fieldpath.ManagedFields, len(encodedManagedFields))
managed.times = make(map[string]*metav1.Time, len(encodedManagedFields)) managed.times = make(map[string]*metav1.Time, len(encodedManagedFields))
@ -113,21 +105,21 @@ func decodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (mana
case "FieldsV1": case "FieldsV1":
// Valid case. // Valid case.
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: 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) manager, err := BuildManagerIdentifier(&encodedVersionedSet)
if err != nil { 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) managed.fields[manager], err = decodeVersionedSet(&encodedVersionedSet)
if err != nil { 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 managed.times[manager] = encodedVersionedSet.Time
} }
return managed, nil return &managed, nil
} }
// BuildManagerIdentifier creates a manager identifier string from a ManagedFieldsEntry // BuildManagerIdentifier creates a manager identifier string from a ManagedFieldsEntry

View File

@ -40,7 +40,7 @@ func TestHasFieldsType(t *testing.T) {
`), &unmarshaled); err != nil { `), &unmarshaled); err != nil {
t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) 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) t.Fatalf("did not expect decoding error but got: %v", err)
} }
@ -54,7 +54,7 @@ func TestHasFieldsType(t *testing.T) {
`), &unmarshaled); err != nil { `), &unmarshaled); err != nil {
t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) 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") t.Fatal("Expect decoding error but got none")
} }
@ -67,7 +67,7 @@ func TestHasFieldsType(t *testing.T) {
`), &unmarshaled); err != nil { `), &unmarshaled); err != nil {
t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) 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") 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 { if err := yaml.Unmarshal([]byte(test), &unmarshaled); err != nil {
t.Fatalf("did not expect yaml unmarshalling error but got: %v", err) t.Fatalf("did not expect yaml unmarshalling error but got: %v", err)
} }
decoded, err := decodeManagedFields(unmarshaled) decoded, err := DecodeManagedFields(unmarshaled)
if err != nil { if err != nil {
t.Fatalf("did not expect decoding error but got: %v", err) t.Fatalf("did not expect decoding error but got: %v", err)
} }
encoded, err := encodeManagedFields(&decoded) encoded, err := encodeManagedFields(decoded)
if err != nil { if err != nil {
t.Fatalf("did not expect encoding error but got: %v", err) t.Fatalf("did not expect encoding error but got: %v", err)
} }