k8s.io/apimachinery@v0.29.2/pkg/util/managedfields/internal/testing/testfieldmanager.go (about) 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 testing 18 19 import ( 20 "errors" 21 "fmt" 22 23 "k8s.io/apimachinery/pkg/api/meta" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apimachinery/pkg/runtime/schema" 28 "k8s.io/apimachinery/pkg/util/managedfields" 29 "k8s.io/apimachinery/pkg/util/managedfields/internal" 30 ) 31 32 // FakeObjectCreater implements ObjectCreater, it can create empty 33 // objects (unstructured) of the given GVK. 34 type FakeObjectCreater struct{} 35 36 func (f *FakeObjectCreater) New(gvk schema.GroupVersionKind) (runtime.Object, error) { 37 u := unstructured.Unstructured{Object: map[string]interface{}{}} 38 u.SetAPIVersion(gvk.GroupVersion().String()) 39 u.SetKind(gvk.Kind) 40 return &u, nil 41 } 42 43 // FakeObjectConvertor implements runtime.ObjectConvertor but it 44 // actually does nothing but return its input. 45 type FakeObjectConvertor struct{} 46 47 //nolint:staticcheck,ineffassign // SA4009 backwards compatibility 48 func (c *FakeObjectConvertor) Convert(in, out, context interface{}) error { 49 out = in 50 return nil 51 } 52 53 func (c *FakeObjectConvertor) ConvertToVersion(in runtime.Object, _ runtime.GroupVersioner) (runtime.Object, error) { 54 return in, nil 55 } 56 57 func (c *FakeObjectConvertor) ConvertFieldLabel(_ schema.GroupVersionKind, _, _ string) (string, string, error) { 58 return "", "", errors.New("not implemented") 59 } 60 61 // FakeObjectDefaulter implements runtime.Defaulter, but it actually 62 // does nothing. 63 type FakeObjectDefaulter struct{} 64 65 func (d *FakeObjectDefaulter) Default(in runtime.Object) {} 66 67 type TestFieldManagerImpl struct { 68 fieldManager *internal.FieldManager 69 apiVersion string 70 emptyObj runtime.Object 71 liveObj runtime.Object 72 } 73 74 // APIVersion of the object that we're tracking. 75 func (f *TestFieldManagerImpl) APIVersion() string { 76 return f.apiVersion 77 } 78 79 // Reset resets the state of the liveObject by resetting it to an empty object. 80 func (f *TestFieldManagerImpl) Reset() { 81 f.liveObj = f.emptyObj.DeepCopyObject() 82 } 83 84 // Live returns a copy of the current liveObject. 85 func (f *TestFieldManagerImpl) Live() runtime.Object { 86 return f.liveObj.DeepCopyObject() 87 } 88 89 // Apply applies the given object on top of the current liveObj, for the 90 // given manager and force flag. 91 func (f *TestFieldManagerImpl) Apply(obj runtime.Object, manager string, force bool) error { 92 out, err := f.fieldManager.Apply(f.liveObj, obj, manager, force) 93 if err == nil { 94 f.liveObj = out 95 } 96 return err 97 } 98 99 // Update will updates the managed fields in the liveObj based on the 100 // changes performed by the update. 101 func (f *TestFieldManagerImpl) Update(obj runtime.Object, manager string) error { 102 out, err := f.fieldManager.Update(f.liveObj, obj, manager) 103 if err == nil { 104 f.liveObj = out 105 } 106 return err 107 } 108 109 // ManagedFields returns the list of existing managed fields for the 110 // liveObj. 111 func (f *TestFieldManagerImpl) ManagedFields() []metav1.ManagedFieldsEntry { 112 accessor, err := meta.Accessor(f.liveObj) 113 if err != nil { 114 panic(fmt.Errorf("couldn't get accessor: %v", err)) 115 } 116 117 return accessor.GetManagedFields() 118 } 119 120 // NewTestFieldManager creates a new manager for the given GVK. 121 func NewTestFieldManagerImpl(typeConverter managedfields.TypeConverter, gvk schema.GroupVersionKind, subresource string, chainFieldManager func(internal.Manager) internal.Manager) *TestFieldManagerImpl { 122 f, err := internal.NewStructuredMergeManager( 123 typeConverter, 124 &FakeObjectConvertor{}, 125 &FakeObjectDefaulter{}, 126 gvk.GroupVersion(), 127 gvk.GroupVersion(), 128 nil, 129 ) 130 if err != nil { 131 panic(err) 132 } 133 live := &unstructured.Unstructured{} 134 live.SetKind(gvk.Kind) 135 live.SetAPIVersion(gvk.GroupVersion().String()) 136 // This is different from `internal.NewDefaultFieldManager` because: 137 // 1. We don't want to create a `internal.FieldManager` 138 // 2. We don't want to use the CapManager that is tested separately with 139 // a smaller than the default cap. 140 f = internal.NewVersionCheckManager( 141 internal.NewLastAppliedUpdater( 142 internal.NewLastAppliedManager( 143 internal.NewProbabilisticSkipNonAppliedManager( 144 internal.NewBuildManagerInfoManager( 145 internal.NewManagedFieldsUpdater( 146 internal.NewStripMetaManager(f), 147 ), gvk.GroupVersion(), subresource, 148 ), &FakeObjectCreater{}, internal.DefaultTrackOnCreateProbability, 149 ), typeConverter, &FakeObjectConvertor{}, gvk.GroupVersion(), 150 ), 151 ), gvk, 152 ) 153 if chainFieldManager != nil { 154 f = chainFieldManager(f) 155 } 156 return &TestFieldManagerImpl{ 157 fieldManager: internal.NewFieldManager(f, subresource), 158 apiVersion: gvk.GroupVersion().String(), 159 emptyObj: live, 160 liveObj: live.DeepCopyObject(), 161 } 162 }