export and cleanup managedFields decoding

Kubernetes-commit: 589ca1be1c9e75b1730feacd1af6e2c817f693ac
This commit is contained in:
Kevin Wiesmueller 2021-02-26 17:47:52 +01:00 committed by Kubernetes Publisher
parent 82e671a5f8
commit f9c68c0e80
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)
}
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)
}

View File

@ -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

View File

@ -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)
}