diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go index 54a4eae00f6..05d3123f41d 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go @@ -192,6 +192,11 @@ func (f *FieldManager) Apply(liveObj runtime.Object, patch []byte, fieldManager if err := yaml.Unmarshal(patch, &patchObj.Object); err != nil { return nil, fmt.Errorf("error decoding YAML: %v", err) } + + if patchObj.GetManagedFields() != nil { + return nil, fmt.Errorf("managed fields must be nil but was %v", patchObj.GetManagedFields()) + } + if patchObj.GetAPIVersion() != f.groupVersion.String() { return nil, errors.NewBadRequest( diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager_test.go index 3a3fded4ef4..7b747dcb084 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager_test.go @@ -22,6 +22,8 @@ import ( "net/http" "testing" + "time" + corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -104,37 +106,36 @@ func TestApplyStripsFields(t *testing.T) { obj := &corev1.Pod{} obj.ObjectMeta.ManagedFields = []metav1.ManagedFieldsEntry{{}} - newObj, err := f.Apply(obj, []byte(`{ - "apiVersion": "apps/v1", - "kind": "Deployment", - "metadata": { - "name": "b", - "namespace": "b", - "creationTimestamp": "2016-05-19T09:59:00Z", - "selfLink": "b", - "uid": "b", - "clusterName": "b", - "generation": 0, - "managedFields": [{ - "manager": "apply", - "operation": "Apply", - "apiVersion": "apps/v1", - "fields": { - "f:metadata": { - "f:labels": { - "f:test-label": {} - } - } - } - }], - "resourceVersion": "b" - } - }`), "fieldmanager_test", false) + newObj := &corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "b", + Namespace: "b", + CreationTimestamp: metav1.NewTime(time.Now()), + SelfLink: "b", + UID: "b", + ClusterName: "b", + Generation: 0, + ManagedFields: []metav1.ManagedFieldsEntry{ + { + Manager: "update", + Operation: metav1.ManagedFieldsOperationApply, + APIVersion: "apps/v1", + }, + }, + ResourceVersion: "b", + }, + } + + updatedObj, err := f.Update(obj, newObj, "fieldmanager_test") if err != nil { t.Fatalf("failed to apply object: %v", err) } - accessor, err := meta.Accessor(newObj) + accessor, err := meta.Accessor(updatedObj) if err != nil { t.Fatalf("couldn't get accessor: %v", err) } @@ -468,3 +469,41 @@ func BenchmarkRepeatedUpdate(b *testing.B) { } } } + +func TestApplyFailsWithManagedFields(t *testing.T) { + f := NewTestFieldManager() + + _, err := f.Apply(&corev1.Pod{}, []byte(`{ + "apiVersion": "apps/v1", + "kind": "Pod", + "metadata": { + "managedFields": [ + { + "manager": "test", + } + ] + } + }`), "fieldmanager_test", false) + + if err == nil { + t.Fatalf("successfully applied with set managed fields") + } +} + +func TestApplySuccessWithNoManagedFields(t *testing.T) { + f := NewTestFieldManager() + + _, err := f.Apply(&corev1.Pod{}, []byte(`{ + "apiVersion": "apps/v1", + "kind": "Pod", + "metadata": { + "labels": { + "a": "b" + }, + } + }`), "fieldmanager_test", false) + + if err != nil { + t.Fatalf("failed to apply object: %v", err) + } +}