fieldmanager.go 7.2 KB

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