k8s.io/apiserver@v0.31.1/pkg/endpoints/handlers/fieldmanager/admission_test.go (about) 1 /* 2 Copyright 2021 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 fieldmanager_test 18 19 import ( 20 "context" 21 "reflect" 22 "testing" 23 24 v1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/api/meta" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/runtime/schema" 28 "k8s.io/apiserver/pkg/admission" 29 "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager" 30 "sigs.k8s.io/structured-merge-diff/v4/fieldpath" 31 ) 32 33 func TestAdmission(t *testing.T) { 34 wrap := &mockAdmissionController{} 35 ac := fieldmanager.NewManagedFieldsValidatingAdmissionController(wrap) 36 now := metav1.Now() 37 38 validFieldsV1 := metav1.FieldsV1{} 39 var err error 40 validFieldsV1.Raw, err = fieldpath.NewSet(fieldpath.MakePathOrDie("metadata", "labels", "test-label")).ToJSON() 41 if err != nil { 42 t.Fatal(err) 43 } 44 validManagedFieldsEntry := metav1.ManagedFieldsEntry{ 45 APIVersion: "v1", 46 Operation: metav1.ManagedFieldsOperationApply, 47 Time: &now, 48 Manager: "test", 49 FieldsType: "FieldsV1", 50 FieldsV1: &validFieldsV1, 51 } 52 53 managedFieldsMutators := map[string]func(in metav1.ManagedFieldsEntry) (out metav1.ManagedFieldsEntry, shouldReset bool){ 54 "invalid APIVersion": func(managedFields metav1.ManagedFieldsEntry) (metav1.ManagedFieldsEntry, bool) { 55 managedFields.APIVersion = "" 56 return managedFields, true 57 }, 58 "invalid Operation": func(managedFields metav1.ManagedFieldsEntry) (metav1.ManagedFieldsEntry, bool) { 59 managedFields.Operation = "invalid operation" 60 return managedFields, true 61 }, 62 "invalid fieldsType": func(managedFields metav1.ManagedFieldsEntry) (metav1.ManagedFieldsEntry, bool) { 63 managedFields.FieldsType = "invalid fieldsType" 64 return managedFields, true 65 }, 66 "invalid fieldsV1": func(managedFields metav1.ManagedFieldsEntry) (metav1.ManagedFieldsEntry, bool) { 67 managedFields.FieldsV1 = &metav1.FieldsV1{Raw: []byte("{invalid}")} 68 return managedFields, true 69 }, 70 "invalid manager": func(managedFields metav1.ManagedFieldsEntry) (metav1.ManagedFieldsEntry, bool) { 71 managedFields.Manager = "" 72 return managedFields, false 73 }, 74 } 75 76 for name, mutate := range managedFieldsMutators { 77 t.Run(name, func(t *testing.T) { 78 mutated, shouldReset := mutate(validManagedFieldsEntry) 79 validEntries := []metav1.ManagedFieldsEntry{validManagedFieldsEntry} 80 mutatedEntries := []metav1.ManagedFieldsEntry{mutated} 81 82 obj := &v1.ConfigMap{} 83 obj.SetManagedFields(validEntries) 84 85 wrap.admit = replaceManagedFields(mutatedEntries) 86 87 attrs := admission.NewAttributesRecord(obj, obj, schema.GroupVersionKind{}, "default", "", schema.GroupVersionResource{}, "", admission.Update, nil, false, nil) 88 if err := ac.(admission.MutationInterface).Admit(context.TODO(), attrs, nil); err != nil { 89 t.Fatal(err) 90 } 91 92 if shouldReset && !reflect.DeepEqual(obj.GetManagedFields(), validEntries) { 93 t.Fatalf("expected: \n%v\ngot:\n%v", validEntries, obj.GetManagedFields()) 94 } 95 if !shouldReset && reflect.DeepEqual(obj.GetManagedFields(), validEntries) { 96 t.Fatalf("expected: \n%v\ngot:\n%v", mutatedEntries, obj.GetManagedFields()) 97 } 98 }) 99 } 100 } 101 102 func replaceManagedFields(with []metav1.ManagedFieldsEntry) func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { 103 return func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { 104 objectMeta, err := meta.Accessor(a.GetObject()) 105 if err != nil { 106 return err 107 } 108 objectMeta.SetManagedFields(with) 109 return nil 110 } 111 } 112 113 type mockAdmissionController struct { 114 admit func(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error 115 } 116 117 func (c *mockAdmissionController) Handles(operation admission.Operation) bool { 118 return true 119 } 120 121 func (c *mockAdmissionController) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error { 122 return c.admit(ctx, a, o) 123 }