...

Source file src/k8s.io/apimachinery/pkg/util/managedfields/internal/fieldmanager.go

Documentation: k8s.io/apimachinery/pkg/util/managedfields/internal

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package internal
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"time"
    23  
    24  	"k8s.io/apimachinery/pkg/api/meta"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	"k8s.io/apimachinery/pkg/runtime/schema"
    28  	"k8s.io/klog/v2"
    29  	"sigs.k8s.io/structured-merge-diff/v4/merge"
    30  )
    31  
    32  // DefaultMaxUpdateManagers defines the default maximum retained number of managedFields entries from updates
    33  // if the number of update managers exceeds this, the oldest entries will be merged until the number is below the maximum.
    34  // TODO(jennybuckley): Determine if this is really the best value. Ideally we wouldn't unnecessarily merge too many entries.
    35  const DefaultMaxUpdateManagers int = 10
    36  
    37  // DefaultTrackOnCreateProbability defines the default probability that the field management of an object
    38  // starts being tracked from the object's creation, instead of from the first time the object is applied to.
    39  const DefaultTrackOnCreateProbability float32 = 1
    40  
    41  var atMostEverySecond = NewAtMostEvery(time.Second)
    42  
    43  // FieldManager updates the managed fields and merges applied
    44  // configurations.
    45  type FieldManager struct {
    46  	fieldManager Manager
    47  	subresource  string
    48  }
    49  
    50  // NewFieldManager creates a new FieldManager that decodes, manages, then re-encodes managedFields
    51  // on update and apply requests.
    52  func NewFieldManager(f Manager, subresource string) *FieldManager {
    53  	return &FieldManager{fieldManager: f, subresource: subresource}
    54  }
    55  
    56  // newDefaultFieldManager is a helper function which wraps a Manager with certain default logic.
    57  func NewDefaultFieldManager(f Manager, typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, subresource string) *FieldManager {
    58  	return NewFieldManager(
    59  		NewVersionCheckManager(
    60  			NewLastAppliedUpdater(
    61  				NewLastAppliedManager(
    62  					NewProbabilisticSkipNonAppliedManager(
    63  						NewCapManagersManager(
    64  							NewBuildManagerInfoManager(
    65  								NewManagedFieldsUpdater(
    66  									NewStripMetaManager(f),
    67  								), kind.GroupVersion(), subresource,
    68  							), DefaultMaxUpdateManagers,
    69  						), objectCreater, DefaultTrackOnCreateProbability,
    70  					), typeConverter, objectConverter, kind.GroupVersion(),
    71  				),
    72  			), kind,
    73  		), subresource,
    74  	)
    75  }
    76  
    77  func decodeLiveOrNew(liveObj, newObj runtime.Object, ignoreManagedFieldsFromRequestObject bool) (Managed, error) {
    78  	liveAccessor, err := meta.Accessor(liveObj)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	// We take the managedFields of the live object in case the request tries to
    84  	// manually set managedFields via a subresource.
    85  	if ignoreManagedFieldsFromRequestObject {
    86  		return emptyManagedFieldsOnErr(DecodeManagedFields(liveAccessor.GetManagedFields()))
    87  	}
    88  
    89  	// If the object doesn't have metadata, we should just return without trying to
    90  	// set the managedFields at all, so creates/updates/patches will work normally.
    91  	newAccessor, err := meta.Accessor(newObj)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	if isResetManagedFields(newAccessor.GetManagedFields()) {
    97  		return NewEmptyManaged(), nil
    98  	}
    99  
   100  	// If the managed field is empty or we failed to decode it,
   101  	// let's try the live object. This is to prevent clients who
   102  	// don't understand managedFields from deleting it accidentally.
   103  	managed, err := DecodeManagedFields(newAccessor.GetManagedFields())
   104  	if err != nil || len(managed.Fields()) == 0 {
   105  		return emptyManagedFieldsOnErr(DecodeManagedFields(liveAccessor.GetManagedFields()))
   106  	}
   107  	return managed, nil
   108  }
   109  
   110  func emptyManagedFieldsOnErr(managed Managed, err error) (Managed, error) {
   111  	if err != nil {
   112  		return NewEmptyManaged(), nil
   113  	}
   114  	return managed, nil
   115  }
   116  
   117  // Update is used when the object has already been merged (non-apply
   118  // use-case), and simply updates the managed fields in the output
   119  // object.
   120  func (f *FieldManager) Update(liveObj, newObj runtime.Object, manager string) (object runtime.Object, err error) {
   121  	// First try to decode the managed fields provided in the update,
   122  	// This is necessary to allow directly updating managed fields.
   123  	isSubresource := f.subresource != ""
   124  	managed, err := decodeLiveOrNew(liveObj, newObj, isSubresource)
   125  	if err != nil {
   126  		return newObj, nil
   127  	}
   128  
   129  	RemoveObjectManagedFields(newObj)
   130  
   131  	if object, managed, err = f.fieldManager.Update(liveObj, newObj, managed, manager); err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	if err = EncodeObjectManagedFields(object, managed); err != nil {
   136  		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
   137  	}
   138  
   139  	return object, nil
   140  }
   141  
   142  // UpdateNoErrors is the same as Update, but it will not return
   143  // errors. If an error happens, the object is returned with
   144  // managedFields cleared.
   145  func (f *FieldManager) UpdateNoErrors(liveObj, newObj runtime.Object, manager string) runtime.Object {
   146  	obj, err := f.Update(liveObj, newObj, manager)
   147  	if err != nil {
   148  		atMostEverySecond.Do(func() {
   149  			ns, name := "unknown", "unknown"
   150  			if accessor, err := meta.Accessor(newObj); err == nil {
   151  				ns = accessor.GetNamespace()
   152  				name = accessor.GetName()
   153  			}
   154  
   155  			klog.ErrorS(err, "[SHOULD NOT HAPPEN] failed to update managedFields", "versionKind",
   156  				newObj.GetObjectKind().GroupVersionKind(), "namespace", ns, "name", name)
   157  		})
   158  		// Explicitly remove managedFields on failure, so that
   159  		// we can't have garbage in it.
   160  		RemoveObjectManagedFields(newObj)
   161  		return newObj
   162  	}
   163  	return obj
   164  }
   165  
   166  // Returns true if the managedFields indicate that the user is trying to
   167  // reset the managedFields, i.e. if the list is non-nil but empty, or if
   168  // the list has one empty item.
   169  func isResetManagedFields(managedFields []metav1.ManagedFieldsEntry) bool {
   170  	if len(managedFields) == 0 {
   171  		return managedFields != nil
   172  	}
   173  
   174  	if len(managedFields) == 1 {
   175  		return reflect.DeepEqual(managedFields[0], metav1.ManagedFieldsEntry{})
   176  	}
   177  
   178  	return false
   179  }
   180  
   181  // Apply is used when server-side apply is called, as it merges the
   182  // object and updates the managed fields.
   183  func (f *FieldManager) Apply(liveObj, appliedObj runtime.Object, manager string, force bool) (object runtime.Object, err error) {
   184  	// If the object doesn't have metadata, apply isn't allowed.
   185  	accessor, err := meta.Accessor(liveObj)
   186  	if err != nil {
   187  		return nil, fmt.Errorf("couldn't get accessor: %v", err)
   188  	}
   189  
   190  	// Decode the managed fields in the live object, since it isn't allowed in the patch.
   191  	managed, err := DecodeManagedFields(accessor.GetManagedFields())
   192  	if err != nil {
   193  		return nil, fmt.Errorf("failed to decode managed fields: %v", err)
   194  	}
   195  
   196  	object, managed, err = f.fieldManager.Apply(liveObj, appliedObj, managed, manager, force)
   197  	if err != nil {
   198  		if conflicts, ok := err.(merge.Conflicts); ok {
   199  			return nil, NewConflictError(conflicts)
   200  		}
   201  		return nil, err
   202  	}
   203  
   204  	if err = EncodeObjectManagedFields(object, managed); err != nil {
   205  		return nil, fmt.Errorf("failed to encode managed fields: %v", err)
   206  	}
   207  
   208  	return object, nil
   209  }
   210  

View as plain text