@@ -18,247 +18,40 @@ package fieldmanager
1818
1919import (
2020 "fmt"
21- "reflect"
22- "time"
2321
24- "k8s.io/apimachinery/pkg/api/meta"
2522 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2623 "k8s.io/apimachinery/pkg/runtime"
2724 "k8s.io/apimachinery/pkg/runtime/schema"
2825 "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
29- "k8s.io/klog/v2"
3026 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
31- "sigs.k8s.io/structured-merge-diff/v4/merge"
3227)
3328
34- // DefaultMaxUpdateManagers defines the default maximum retained number of managedFields entries from updates
35- // if the number of update managers exceeds this, the oldest entries will be merged until the number is below the maximum.
36- // TODO(jennybuckley): Determine if this is really the best value. Ideally we wouldn't unnecessarily merge too many entries.
37- const DefaultMaxUpdateManagers int = 10
38-
39- // DefaultTrackOnCreateProbability defines the default probability that the field management of an object
40- // starts being tracked from the object's creation, instead of from the first time the object is applied to.
41- const DefaultTrackOnCreateProbability float32 = 1
42-
43- var atMostEverySecond = internal .NewAtMostEvery (time .Second )
44-
45- // Managed groups a fieldpath.ManagedFields together with the timestamps associated with each operation.
46- type Managed interface {
47- // Fields gets the fieldpath.ManagedFields.
48- Fields () fieldpath.ManagedFields
49-
50- // Times gets the timestamps associated with each operation.
51- Times () map [string ]* metav1.Time
52- }
53-
54- // Manager updates the managed fields and merges applied configurations.
55- type Manager interface {
56- // Update is used when the object has already been merged (non-apply
57- // use-case), and simply updates the managed fields in the output
58- // object.
59- // * `liveObj` is not mutated by this function
60- // * `newObj` may be mutated by this function
61- // Returns the new object with managedFields removed, and the object's new
62- // proposed managedFields separately.
63- Update (liveObj , newObj runtime.Object , managed Managed , manager string ) (runtime.Object , Managed , error )
64-
65- // Apply is used when server-side apply is called, as it merges the
66- // object and updates the managed fields.
67- // * `liveObj` is not mutated by this function
68- // * `newObj` may be mutated by this function
69- // Returns the new object with managedFields removed, and the object's new
70- // proposed managedFields separately.
71- Apply (liveObj , appliedObj runtime.Object , managed Managed , fieldManager string , force bool ) (runtime.Object , Managed , error )
72- }
73-
74- // FieldManager updates the managed fields and merge applied
29+ // FieldManager updates the managed fields and merges applied
7530// configurations.
76- type FieldManager struct {
77- fieldManager Manager
78- subresource string
79- }
80-
81- // NewFieldManager creates a new FieldManager that decodes, manages, then re-encodes managedFields
82- // on update and apply requests.
83- func NewFieldManager (f Manager , subresource string ) * FieldManager {
84- return & FieldManager {fieldManager : f , subresource : subresource }
85- }
31+ type FieldManager = internal.FieldManager
8632
8733// NewDefaultFieldManager creates a new FieldManager that merges apply requests
8834// and update managed fields for other types of requests.
8935func NewDefaultFieldManager (typeConverter TypeConverter , objectConverter runtime.ObjectConvertor , objectDefaulter runtime.ObjectDefaulter , objectCreater runtime.ObjectCreater , kind schema.GroupVersionKind , hub schema.GroupVersion , subresource string , resetFields map [fieldpath.APIVersion ]* fieldpath.Set ) (* FieldManager , error ) {
90- f , err := NewStructuredMergeManager (typeConverter , objectConverter , objectDefaulter , kind .GroupVersion (), hub , resetFields )
36+ f , err := internal . NewStructuredMergeManager (typeConverter , objectConverter , objectDefaulter , kind .GroupVersion (), hub , resetFields )
9137 if err != nil {
9238 return nil , fmt .Errorf ("failed to create field manager: %v" , err )
9339 }
94- return newDefaultFieldManager (f , typeConverter , objectConverter , objectCreater , kind , subresource ), nil
40+ return internal . NewDefaultFieldManager (f , typeConverter , objectConverter , objectCreater , kind , subresource ), nil
9541}
9642
9743// NewDefaultCRDFieldManager creates a new FieldManager specifically for
9844// CRDs. This allows for the possibility of fields which are not defined
9945// in models, as well as having no models defined at all.
10046func NewDefaultCRDFieldManager (typeConverter TypeConverter , objectConverter runtime.ObjectConvertor , objectDefaulter runtime.ObjectDefaulter , objectCreater runtime.ObjectCreater , kind schema.GroupVersionKind , hub schema.GroupVersion , subresource string , resetFields map [fieldpath.APIVersion ]* fieldpath.Set ) (_ * FieldManager , err error ) {
101- f , err := NewCRDStructuredMergeManager (typeConverter , objectConverter , objectDefaulter , kind .GroupVersion (), hub , resetFields )
47+ f , err := internal . NewCRDStructuredMergeManager (typeConverter , objectConverter , objectDefaulter , kind .GroupVersion (), hub , resetFields )
10248 if err != nil {
10349 return nil , fmt .Errorf ("failed to create field manager: %v" , err )
10450 }
105- return newDefaultFieldManager (f , typeConverter , objectConverter , objectCreater , kind , subresource ), nil
106- }
107-
108- // newDefaultFieldManager is a helper function which wraps a Manager with certain default logic.
109- func newDefaultFieldManager (f Manager , typeConverter TypeConverter , objectConverter runtime.ObjectConvertor , objectCreater runtime.ObjectCreater , kind schema.GroupVersionKind , subresource string ) * FieldManager {
110- return NewFieldManager (
111- NewLastAppliedUpdater (
112- NewLastAppliedManager (
113- NewProbabilisticSkipNonAppliedManager (
114- NewCapManagersManager (
115- NewBuildManagerInfoManager (
116- NewManagedFieldsUpdater (
117- NewStripMetaManager (f ),
118- ), kind .GroupVersion (), subresource ,
119- ), DefaultMaxUpdateManagers ,
120- ), objectCreater , kind , DefaultTrackOnCreateProbability ,
121- ), typeConverter , objectConverter , kind .GroupVersion ()),
122- ), subresource ,
123- )
124- }
125-
126- // DecodeManagedFields converts ManagedFields from the wire format (api format)
127- // to the format used by sigs.k8s.io/structured-merge-diff
128- func DecodeManagedFields (encodedManagedFields []metav1.ManagedFieldsEntry ) (Managed , error ) {
129- return internal .DecodeManagedFields (encodedManagedFields )
130- }
131-
132- func decodeLiveOrNew (liveObj , newObj runtime.Object , ignoreManagedFieldsFromRequestObject bool ) (Managed , error ) {
133- liveAccessor , err := meta .Accessor (liveObj )
134- if err != nil {
135- return nil , err
136- }
137-
138- // We take the managedFields of the live object in case the request tries to
139- // manually set managedFields via a subresource.
140- if ignoreManagedFieldsFromRequestObject {
141- return emptyManagedFieldsOnErr (DecodeManagedFields (liveAccessor .GetManagedFields ()))
142- }
143-
144- // If the object doesn't have metadata, we should just return without trying to
145- // set the managedFields at all, so creates/updates/patches will work normally.
146- newAccessor , err := meta .Accessor (newObj )
147- if err != nil {
148- return nil , err
149- }
150-
151- if isResetManagedFields (newAccessor .GetManagedFields ()) {
152- return internal .NewEmptyManaged (), nil
153- }
154-
155- // If the managed field is empty or we failed to decode it,
156- // let's try the live object. This is to prevent clients who
157- // don't understand managedFields from deleting it accidentally.
158- managed , err := DecodeManagedFields (newAccessor .GetManagedFields ())
159- if err != nil || len (managed .Fields ()) == 0 {
160- return emptyManagedFieldsOnErr (DecodeManagedFields (liveAccessor .GetManagedFields ()))
161- }
162- return managed , nil
163- }
164-
165- func emptyManagedFieldsOnErr (managed Managed , err error ) (Managed , error ) {
166- if err != nil {
167- return internal .NewEmptyManaged (), nil
168- }
169- return managed , nil
51+ return internal .NewDefaultFieldManager (f , typeConverter , objectConverter , objectCreater , kind , subresource ), nil
17052}
17153
172- // Update is used when the object has already been merged (non-apply
173- // use-case), and simply updates the managed fields in the output
174- // object.
175- func (f * FieldManager ) Update (liveObj , newObj runtime.Object , manager string ) (object runtime.Object , err error ) {
176- // First try to decode the managed fields provided in the update,
177- // This is necessary to allow directly updating managed fields.
178- isSubresource := f .subresource != ""
179- managed , err := decodeLiveOrNew (liveObj , newObj , isSubresource )
180- if err != nil {
181- return newObj , nil
182- }
183-
184- internal .RemoveObjectManagedFields (newObj )
185-
186- if object , managed , err = f .fieldManager .Update (liveObj , newObj , managed , manager ); err != nil {
187- return nil , err
188- }
189-
190- if err = internal .EncodeObjectManagedFields (object , managed ); err != nil {
191- return nil , fmt .Errorf ("failed to encode managed fields: %v" , err )
192- }
193-
194- return object , nil
195- }
196-
197- // UpdateNoErrors is the same as Update, but it will not return
198- // errors. If an error happens, the object is returned with
199- // managedFields cleared.
200- func (f * FieldManager ) UpdateNoErrors (liveObj , newObj runtime.Object , manager string ) runtime.Object {
201- obj , err := f .Update (liveObj , newObj , manager )
202- if err != nil {
203- atMostEverySecond .Do (func () {
204- ns , name := "unknown" , "unknown"
205- if accessor , err := meta .Accessor (newObj ); err == nil {
206- ns = accessor .GetNamespace ()
207- name = accessor .GetName ()
208- }
209-
210- klog .ErrorS (err , "[SHOULD NOT HAPPEN] failed to update managedFields" , "VersionKind" ,
211- newObj .GetObjectKind ().GroupVersionKind (), "namespace" , ns , "name" , name )
212- })
213- // Explicitly remove managedFields on failure, so that
214- // we can't have garbage in it.
215- internal .RemoveObjectManagedFields (newObj )
216- return newObj
217- }
218- return obj
219- }
220-
221- // Returns true if the managedFields indicate that the user is trying to
222- // reset the managedFields, i.e. if the list is non-nil but empty, or if
223- // the list has one empty item.
224- func isResetManagedFields (managedFields []metav1.ManagedFieldsEntry ) bool {
225- if len (managedFields ) == 0 {
226- return managedFields != nil
227- }
228-
229- if len (managedFields ) == 1 {
230- return reflect .DeepEqual (managedFields [0 ], metav1.ManagedFieldsEntry {})
231- }
232-
233- return false
234- }
235-
236- // Apply is used when server-side apply is called, as it merges the
237- // object and updates the managed fields.
238- func (f * FieldManager ) Apply (liveObj , appliedObj runtime.Object , manager string , force bool ) (object runtime.Object , err error ) {
239- // If the object doesn't have metadata, apply isn't allowed.
240- accessor , err := meta .Accessor (liveObj )
241- if err != nil {
242- return nil , fmt .Errorf ("couldn't get accessor: %v" , err )
243- }
244-
245- // Decode the managed fields in the live object, since it isn't allowed in the patch.
246- managed , err := DecodeManagedFields (accessor .GetManagedFields ())
247- if err != nil {
248- return nil , fmt .Errorf ("failed to decode managed fields: %v" , err )
249- }
250-
251- object , managed , err = f .fieldManager .Apply (liveObj , appliedObj , managed , manager , force )
252- if err != nil {
253- if conflicts , ok := err .(merge.Conflicts ); ok {
254- return nil , internal .NewConflictError (conflicts )
255- }
256- return nil , err
257- }
258-
259- if err = internal .EncodeObjectManagedFields (object , managed ); err != nil {
260- return nil , fmt .Errorf ("failed to encode managed fields: %v" , err )
261- }
262-
263- return object , nil
54+ func ValidateManagedFields (encodedManagedFields []metav1.ManagedFieldsEntry ) error {
55+ _ , err := internal .DecodeManagedFields (encodedManagedFields )
56+ return err
26457}
0 commit comments