strip selected fields from managedFields

refactor fieldstrip and update tests

add checks and remove empty fields

shorten test and check for nil manager

fix gofmt

panic on nil manager
pull/564/head
Kevin Wiesmüller 2019-02-03 22:22:10 +01:00
parent f7c4389b79
commit 9082cac482
2 changed files with 93 additions and 4 deletions

View File

@ -51,6 +51,7 @@ func NewFieldManager(models openapiproto.Models, objectConverter runtime.ObjectC
if err != nil {
return nil, err
}
return &FieldManager{
typeConverter: typeConverter,
objectConverter: objectConverter,
@ -130,6 +131,7 @@ func (f *FieldManager) Update(liveObj, newObj runtime.Object, manager string) (r
if err != nil {
return nil, fmt.Errorf("failed to update ManagedFields: %v", err)
}
managed = f.stripFields(managed, manager)
if err := internal.EncodeObjectManagedFields(newObj, managed); err != nil {
return nil, fmt.Errorf("failed to encode managed fields: %v", err)
@ -180,6 +182,7 @@ func (f *FieldManager) Apply(liveObj runtime.Object, patch []byte, force bool) (
}
return nil, err
}
managed = f.stripFields(managed, manager)
newObj, err := f.typeConverter.TypedToObject(newObjTyped)
if err != nil {
@ -223,3 +226,31 @@ func (f *FieldManager) buildManagerInfo(prefix string, operation metav1.ManagedF
}
return internal.BuildManagerIdentifier(&managerInfo)
}
// stripSet is the list of fields that should never be part of a mangedFields.
var stripSet = fieldpath.NewSet(
fieldpath.MakePathOrDie("apiVersion"),
fieldpath.MakePathOrDie("kind"),
fieldpath.MakePathOrDie("metadata", "name"),
fieldpath.MakePathOrDie("metadata", "namespace"),
fieldpath.MakePathOrDie("metadata", "creationTimestamp"),
fieldpath.MakePathOrDie("metadata", "selfLink"),
fieldpath.MakePathOrDie("metadata", "uid"),
fieldpath.MakePathOrDie("metadata", "resourceVersion"),
)
// stripFields removes a predefined set of paths found in typed from managed and returns the updated ManagedFields
func (f *FieldManager) stripFields(managed fieldpath.ManagedFields, manager string) fieldpath.ManagedFields {
vs, ok := managed[manager]
if ok {
if vs == nil {
panic(fmt.Sprintf("Found unexpected nil manager which should never happen: %s", manager))
}
vs.Set = vs.Set.Difference(stripSet)
if vs.Set.Empty() {
delete(managed, manager)
}
}
return managed
}

View File

@ -223,7 +223,11 @@ func TestApplyManagedFields(t *testing.T) {
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "test-cm"
"name": "test-cm",
"namespace": "default",
"labels": {
"test-label": "test"
}
},
"data": {
"key": "value"
@ -267,16 +271,19 @@ func TestApplyManagedFields(t *testing.T) {
"uid": "` + string(accessor.GetUID()) + `",
"resourceVersion": "` + accessor.GetResourceVersion() + `",
"creationTimestamp": "` + accessor.GetCreationTimestamp().UTC().Format(time.RFC3339) + `",
"labels": {
"test-label": "test"
},
"managedFields": [
{
"manager": "apply",
"operation": "Apply",
"apiVersion": "v1",
"fields": {
"f:apiVersion": {},
"f:kind": {},
"f:metadata": {
"f:name": {}
"f:labels": {
"f:test-label": {}
}
}
}
},
@ -302,3 +309,54 @@ func TestApplyManagedFields(t *testing.T) {
t.Fatalf("Expected:\n%v\nGot:\n%v", string(expected), string(actual))
}
}
// TestApplyRemovesEmptyManagedFields there are no empty managers in managedFields
func TestApplyRemovesEmptyManagedFields(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
_, client, closeFn := setup(t)
defer closeFn()
obj := []byte(`{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "test-cm",
"namespace": "default"
}
}`)
_, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
Namespace("default").
Resource("configmaps").
Name("test-cm").
Body(obj).
Do().
Get()
if err != nil {
t.Fatalf("Failed to create object using Apply patch: %v", err)
}
_, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
Namespace("default").
Resource("configmaps").
Name("test-cm").
Body(obj).Do().Get()
if err != nil {
t.Fatalf("Failed to patch object: %v", err)
}
object, err := client.CoreV1().RESTClient().Get().Namespace("default").Resource("configmaps").Name("test-cm").Do().Get()
if err != nil {
t.Fatalf("Failed to retrieve object: %v", err)
}
accessor, err := meta.Accessor(object)
if err != nil {
t.Fatalf("Failed to get meta accessor: %v", err)
}
if managed := accessor.GetManagedFields(); managed != nil {
t.Fatalf("Object contains unexpected managedFields: %v", managed)
}
}