Skip to content

Commit 97bbf07

Browse files
authored
Merge pull request kubernetes#114977 from apelisse/simplify-fieldmanager-test
fieldmanagertest: Reduce API surface of the test package
2 parents 7372e7e + 7899157 commit 97bbf07

File tree

8 files changed

+274
-224
lines changed

8 files changed

+274
-224
lines changed

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager_test.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ var fakeTypeConverter = func() fieldmanager.TypeConverter {
6363
// TestUpdateApplyConflict tests that applying to an object, which
6464
// wasn't created by apply, will give conflicts
6565
func TestUpdateApplyConflict(t *testing.T) {
66-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
66+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
6767

6868
patch := []byte(`{
6969
"apiVersion": "apps/v1",
@@ -124,7 +124,7 @@ func TestUpdateApplyConflict(t *testing.T) {
124124
}
125125

126126
func TestApplyStripsFields(t *testing.T) {
127-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
127+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
128128

129129
newObj := &unstructured.Unstructured{
130130
Object: map[string]interface{}{
@@ -156,7 +156,7 @@ func TestApplyStripsFields(t *testing.T) {
156156
}
157157

158158
func TestVersionCheck(t *testing.T) {
159-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
159+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
160160

161161
appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
162162
if err := yaml.Unmarshal([]byte(`{
@@ -196,7 +196,7 @@ func TestVersionCheck(t *testing.T) {
196196
}
197197
}
198198
func TestVersionCheckDoesNotPanic(t *testing.T) {
199-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
199+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
200200

201201
appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
202202
if err := yaml.Unmarshal([]byte(`{
@@ -235,7 +235,7 @@ func TestVersionCheckDoesNotPanic(t *testing.T) {
235235
}
236236

237237
func TestApplyDoesNotStripLabels(t *testing.T) {
238-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
238+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
239239

240240
appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
241241
if err := yaml.Unmarshal([]byte(`{
@@ -289,7 +289,7 @@ func TestApplyNewObject(t *testing.T) {
289289

290290
for _, test := range tests {
291291
t.Run(test.gvk.String(), func(t *testing.T) {
292-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, test.gvk)
292+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, test.gvk)
293293

294294
appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
295295
if err := yaml.Unmarshal(test.obj, &appliedObj.Object); err != nil {
@@ -327,7 +327,7 @@ func BenchmarkNewObject(b *testing.B) {
327327
}
328328
for _, test := range tests {
329329
b.Run(test.gvk.Kind, func(b *testing.B) {
330-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, test.gvk)
330+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, test.gvk)
331331

332332
decoder := serializer.NewCodecFactory(scheme).UniversalDecoder(test.gvk.GroupVersion())
333333
newObj, err := runtime.Decode(decoder, test.obj)
@@ -540,7 +540,7 @@ func BenchmarkCompare(b *testing.B) {
540540
}
541541

542542
func BenchmarkRepeatedUpdate(b *testing.B) {
543-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
543+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
544544
podBytes := getObjectBytes("pod.yaml")
545545

546546
var obj *corev1.Pod
@@ -579,7 +579,7 @@ func BenchmarkRepeatedUpdate(b *testing.B) {
579579
}
580580

581581
func TestApplyFailsWithManagedFields(t *testing.T) {
582-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
582+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
583583

584584
appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
585585
if err := yaml.Unmarshal([]byte(`{
@@ -604,7 +604,7 @@ func TestApplyFailsWithManagedFields(t *testing.T) {
604604
}
605605

606606
func TestApplySuccessWithNoManagedFields(t *testing.T) {
607-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
607+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
608608

609609
appliedObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
610610
if err := yaml.Unmarshal([]byte(`{
@@ -627,7 +627,7 @@ func TestApplySuccessWithNoManagedFields(t *testing.T) {
627627

628628
// Run an update and apply, and make sure that nothing has changed.
629629
func TestNoOpChanges(t *testing.T) {
630-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
630+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
631631

632632
obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
633633
if err := yaml.Unmarshal([]byte(`{
@@ -678,7 +678,7 @@ func TestNoOpChanges(t *testing.T) {
678678
// Tests that one can reset the managedFields by sending either an empty
679679
// list
680680
func TestResetManagedFieldsEmptyList(t *testing.T) {
681-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
681+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
682682

683683
obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
684684
if err := yaml.Unmarshal([]byte(`{
@@ -719,7 +719,7 @@ func TestResetManagedFieldsEmptyList(t *testing.T) {
719719

720720
// Tests that one can reset the managedFields by sending either a list with one empty item.
721721
func TestResetManagedFieldsEmptyItem(t *testing.T) {
722-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
722+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"))
723723

724724
obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
725725
if err := yaml.Unmarshal([]byte(`{
@@ -759,7 +759,7 @@ func TestResetManagedFieldsEmptyItem(t *testing.T) {
759759
}
760760

761761
func TestServerSideApplyWithInvalidLastApplied(t *testing.T) {
762-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
762+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
763763

764764
// create object with client-side apply
765765
newObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
@@ -838,7 +838,7 @@ spec:
838838
}
839839

840840
func TestInteropForClientSideApplyAndServerSideApply(t *testing.T) {
841-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
841+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
842842

843843
// create object with client-side apply
844844
newObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
@@ -922,7 +922,7 @@ spec:
922922
}
923923

924924
func TestNoTrackManagedFieldsForClientSideApply(t *testing.T) {
925-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
925+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
926926

927927
// create object
928928
newObj := &unstructured.Unstructured{Object: map[string]interface{}{}}
@@ -1102,7 +1102,7 @@ func getLastApplied(obj runtime.Object) (string, error) {
11021102
}
11031103

11041104
func TestUpdateViaSubresources(t *testing.T) {
1105-
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"), "scale", nil)
1105+
f := fieldmanagertest.NewTestFieldManagerSubresource(fakeTypeConverter, schema.FromAPIVersionAndKind("v1", "Pod"), "scale")
11061106

11071107
obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
11081108
if err := yaml.Unmarshal([]byte(`{
@@ -1157,7 +1157,7 @@ func TestUpdateViaSubresources(t *testing.T) {
11571157
// Ensures that a no-op Apply does not mutate managed fields
11581158
func TestApplyDoesNotChangeManagedFields(t *testing.T) {
11591159
originalManagedFields := []metav1.ManagedFieldsEntry{}
1160-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter,
1160+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter,
11611161
schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
11621162
newObj := &unstructured.Unstructured{
11631163
Object: map[string]interface{}{},
@@ -1251,7 +1251,7 @@ func TestApplyDoesNotChangeManagedFields(t *testing.T) {
12511251
// Ensures that a no-op Update does not mutate managed fields
12521252
func TestUpdateDoesNotChangeManagedFields(t *testing.T) {
12531253
originalManagedFields := []metav1.ManagedFieldsEntry{}
1254-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter,
1254+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter,
12551255
schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
12561256
newObj := &unstructured.Unstructured{
12571257
Object: map[string]interface{}{},
@@ -1323,7 +1323,7 @@ func TestUpdateDoesNotChangeManagedFields(t *testing.T) {
13231323
// This test makes sure that the liveObject during a patch does not mutate
13241324
// its managed fields.
13251325
func TestLiveObjectManagedFieldsNotRemoved(t *testing.T) {
1326-
f := fieldmanagertest.NewDefaultTestFieldManager(fakeTypeConverter,
1326+
f := fieldmanagertest.NewTestFieldManager(fakeTypeConverter,
13271327
schema.FromAPIVersionAndKind("apps/v1", "Deployment"))
13281328
newObj := &unstructured.Unstructured{
13291329
Object: map[string]interface{}{},

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanagertest/testfieldmanager.go

Lines changed: 29 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -17,73 +17,13 @@ limitations under the License.
1717
package fieldmanagertest
1818

1919
import (
20-
"errors"
21-
"fmt"
22-
23-
"k8s.io/apimachinery/pkg/api/meta"
2420
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2621
"k8s.io/apimachinery/pkg/runtime"
2722
"k8s.io/apimachinery/pkg/runtime/schema"
2823
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
29-
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
30-
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
31-
"sigs.k8s.io/structured-merge-diff/v4/merge"
32-
"sigs.k8s.io/structured-merge-diff/v4/typed"
24+
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/testing"
3325
)
3426

35-
type fakeObjectConvertor struct {
36-
converter merge.Converter
37-
apiVersion fieldpath.APIVersion
38-
}
39-
40-
//nolint:staticcheck,ineffassign // SA4009 backwards compatibility
41-
func (c *fakeObjectConvertor) Convert(in, out, context interface{}) error {
42-
if typedValue, ok := in.(*typed.TypedValue); ok {
43-
var err error
44-
out, err = c.converter.Convert(typedValue, c.apiVersion)
45-
return err
46-
}
47-
return nil
48-
}
49-
50-
func (c *fakeObjectConvertor) ConvertToVersion(in runtime.Object, _ runtime.GroupVersioner) (runtime.Object, error) {
51-
return in, nil
52-
}
53-
54-
func (c *fakeObjectConvertor) ConvertFieldLabel(_ schema.GroupVersionKind, _, _ string) (string, string, error) {
55-
return "", "", errors.New("not implemented")
56-
}
57-
58-
type fakeObjectDefaulter struct{}
59-
60-
func (d *fakeObjectDefaulter) Default(in runtime.Object) {}
61-
62-
type sameVersionConverter struct{}
63-
64-
func (sameVersionConverter) Convert(object *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) {
65-
return object, nil
66-
}
67-
68-
func (sameVersionConverter) IsMissingVersionError(error) bool {
69-
return false
70-
}
71-
72-
// NewFakeObjectCreater implements ObjectCreater, it can create empty
73-
// objects (unstructured) of the given GVK.
74-
func NewFakeObjectCreater() runtime.ObjectCreater {
75-
return &fakeObjectCreater{}
76-
}
77-
78-
type fakeObjectCreater struct{}
79-
80-
func (f *fakeObjectCreater) New(gvk schema.GroupVersionKind) (runtime.Object, error) {
81-
u := unstructured.Unstructured{Object: map[string]interface{}{}}
82-
u.SetAPIVersion(gvk.GroupVersion().String())
83-
u.SetKind(gvk.Kind)
84-
return &u, nil
85-
}
86-
8727
// TestFieldManager is a FieldManager that can be used in test to
8828
// simulate the behavior of Server-Side Apply and field tracking. This
8929
// also has a few methods to get a sense of the state of the object.
@@ -95,105 +35,32 @@ func (f *fakeObjectCreater) New(gvk schema.GroupVersionKind) (runtime.Object, er
9535
// You can use this rather than NewDefaultTestFieldManager if you want
9636
// to specify either a sub-resource, or a set of modified Manager to
9737
// test them specifically.
98-
type TestFieldManager struct {
99-
fieldManager *internal.FieldManager
100-
apiVersion string
101-
emptyObj runtime.Object
102-
liveObj runtime.Object
103-
}
104-
105-
// NewDefaultTestFieldManager returns a new TestFieldManager built for
106-
// the given gvk, on the main resource.
107-
func NewDefaultTestFieldManager(typeConverter fieldmanager.TypeConverter, gvk schema.GroupVersionKind) TestFieldManager {
108-
return NewTestFieldManager(typeConverter, gvk, "", nil)
109-
}
110-
111-
// NewTestFieldManager creates a new manager for the given GVK.
112-
func NewTestFieldManager(typeConverter fieldmanager.TypeConverter, gvk schema.GroupVersionKind, subresource string, chainFieldManager func(internal.Manager) internal.Manager) TestFieldManager {
113-
apiVersion := fieldpath.APIVersion(gvk.GroupVersion().String())
114-
objectConverter := &fakeObjectConvertor{sameVersionConverter{}, apiVersion}
115-
f, err := internal.NewStructuredMergeManager(
116-
typeConverter,
117-
objectConverter,
118-
&fakeObjectDefaulter{},
119-
gvk.GroupVersion(),
120-
gvk.GroupVersion(),
121-
nil,
122-
)
123-
if err != nil {
124-
panic(err)
125-
}
126-
live := &unstructured.Unstructured{}
127-
live.SetKind(gvk.Kind)
128-
live.SetAPIVersion(gvk.GroupVersion().String())
129-
// This is different from `internal.NewDefaultFieldManager` because:
130-
// 1. We don't want to create a `internal.FieldManager`
131-
// 2. We don't want to use the CapManager that is tested separately with
132-
// a smaller than the default cap.
133-
f = internal.NewLastAppliedUpdater(
134-
internal.NewLastAppliedManager(
135-
internal.NewProbabilisticSkipNonAppliedManager(
136-
internal.NewBuildManagerInfoManager(
137-
internal.NewManagedFieldsUpdater(
138-
internal.NewStripMetaManager(f),
139-
), gvk.GroupVersion(), subresource,
140-
), NewFakeObjectCreater(), gvk, internal.DefaultTrackOnCreateProbability,
141-
), typeConverter, objectConverter, gvk.GroupVersion(),
142-
),
143-
)
144-
if chainFieldManager != nil {
145-
f = chainFieldManager(f)
146-
}
147-
return TestFieldManager{
148-
fieldManager: internal.NewFieldManager(f, subresource),
149-
apiVersion: gvk.GroupVersion().String(),
150-
emptyObj: live,
151-
liveObj: live.DeepCopyObject(),
152-
}
153-
}
154-
155-
// APIVersion of the object that we're tracking.
156-
func (f *TestFieldManager) APIVersion() string {
157-
return f.apiVersion
158-
}
159-
160-
// Reset resets the state of the liveObject by resetting it to an empty object.
161-
func (f *TestFieldManager) Reset() {
162-
f.liveObj = f.emptyObj.DeepCopyObject()
163-
}
164-
165-
// Live returns a copy of the current liveObject.
166-
func (f *TestFieldManager) Live() runtime.Object {
167-
return f.liveObj.DeepCopyObject()
168-
}
169-
170-
// Apply applies the given object on top of the current liveObj, for the
171-
// given manager and force flag.
172-
func (f *TestFieldManager) Apply(obj runtime.Object, manager string, force bool) error {
173-
out, err := f.fieldManager.Apply(f.liveObj, obj, manager, force)
174-
if err == nil {
175-
f.liveObj = out
176-
}
177-
return err
178-
}
179-
180-
// Update will updates the managed fields in the liveObj based on the
181-
// changes performed by the update.
182-
func (f *TestFieldManager) Update(obj runtime.Object, manager string) error {
183-
out, err := f.fieldManager.Update(f.liveObj, obj, manager)
184-
if err == nil {
185-
f.liveObj = out
186-
}
187-
return err
188-
}
189-
190-
// ManagedFields returns the list of existing managed fields for the
191-
// liveObj.
192-
func (f *TestFieldManager) ManagedFields() []metav1.ManagedFieldsEntry {
193-
accessor, err := meta.Accessor(f.liveObj)
194-
if err != nil {
195-
panic(fmt.Errorf("couldn't get accessor: %v", err))
196-
}
197-
198-
return accessor.GetManagedFields()
38+
type TestFieldManager interface {
39+
// APIVersion of the object that we're tracking.
40+
APIVersion() string
41+
// Reset resets the state of the liveObject by resetting it to an empty object.
42+
Reset()
43+
// Live returns a copy of the current liveObject.
44+
Live() runtime.Object
45+
// Apply applies the given object on top of the current liveObj, for the
46+
// given manager and force flag.
47+
Apply(obj runtime.Object, manager string, force bool) error
48+
// Update will updates the managed fields in the liveObj based on the
49+
// changes performed by the update.
50+
Update(obj runtime.Object, manager string) error
51+
// ManagedFields returns the list of existing managed fields for the
52+
// liveObj.
53+
ManagedFields() []metav1.ManagedFieldsEntry
54+
}
55+
56+
// NewTestFieldManager returns a new TestFieldManager built for the
57+
// given gvk, on the main resource.
58+
func NewTestFieldManager(typeConverter fieldmanager.TypeConverter, gvk schema.GroupVersionKind) TestFieldManager {
59+
return testing.NewTestFieldManagerImpl(typeConverter, gvk, "", nil)
60+
}
61+
62+
// NewTestFieldManagerSubresource returns a new TestFieldManager built
63+
// for the given gvk, on the given sub-resource.
64+
func NewTestFieldManagerSubresource(typeConverter fieldmanager.TypeConverter, gvk schema.GroupVersionKind, subresource string) TestFieldManager {
65+
return testing.NewTestFieldManagerImpl(typeConverter, gvk, subresource, nil)
19966
}

0 commit comments

Comments
 (0)