github.com/oam-dev/kubevela@v1.9.11/pkg/webhook/core.oam.dev/v1beta1/traitdefinition/validating_handler_test.go (about) 1 /* 2 Copyright 2021 The KubeVela 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 traitdefinition 18 19 import ( 20 "context" 21 "encoding/json" 22 "testing" 23 24 . "github.com/onsi/ginkgo/v2" 25 . "github.com/onsi/gomega" 26 "github.com/pkg/errors" 27 admissionv1 "k8s.io/api/admission/v1" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/apimachinery/pkg/runtime" 30 "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 31 32 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" 33 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" 34 ) 35 36 var handler ValidatingHandler 37 var req admission.Request 38 var reqResource metav1.GroupVersionResource 39 var decoder *admission.Decoder 40 var td v1beta1.TraitDefinition 41 var tdRaw []byte 42 var scheme = runtime.NewScheme() 43 var validCueTemplate string 44 var inValidCueTemplate string 45 46 func TestTraitdefinition(t *testing.T) { 47 RegisterFailHandler(Fail) 48 RunSpecs(t, "Traitdefinition Suite") 49 } 50 51 var _ = BeforeSuite(func() { 52 53 validCueTemplate = "{hello: 'world'}" 54 inValidCueTemplate = "{hello: world}" 55 56 td = v1beta1.TraitDefinition{} 57 td.SetGroupVersionKind(v1beta1.TraitDefinitionGroupVersionKind) 58 59 var err error 60 decoder, err = admission.NewDecoder(scheme) 61 Expect(err).Should(BeNil()) 62 }) 63 64 var _ = Describe("Test TraitDefinition validating handler", func() { 65 BeforeEach(func() { 66 reqResource = metav1.GroupVersionResource{ 67 Group: v1beta1.Group, 68 Version: v1beta1.Version, 69 Resource: "traitdefinitions"} 70 handler = ValidatingHandler{} 71 handler.InjectDecoder(decoder) 72 }) 73 74 It("Test wrong resource of admission request", func() { 75 wrongReqResource := metav1.GroupVersionResource{ 76 Group: v1beta1.Group, 77 Version: v1beta1.Version, 78 Resource: "foos"} 79 req = admission.Request{ 80 AdmissionRequest: admissionv1.AdmissionRequest{ 81 Operation: admissionv1.Create, 82 Resource: wrongReqResource, 83 Object: runtime.RawExtension{Raw: []byte("")}, 84 }, 85 } 86 resp := handler.Handle(context.TODO(), req) 87 Expect(resp.Allowed).Should(BeFalse()) 88 }) 89 90 It("Test bad admission request", func() { 91 req = admission.Request{ 92 AdmissionRequest: admissionv1.AdmissionRequest{ 93 Operation: admissionv1.Create, 94 Resource: reqResource, 95 Object: runtime.RawExtension{Raw: []byte("bad request")}, 96 }, 97 } 98 resp := handler.Handle(context.TODO(), req) 99 Expect(resp.Allowed).Should(BeFalse()) 100 }) 101 102 Context("Test create/update operation admission request", func() { 103 var mockValidator TraitDefValidatorFn 104 It("Test validation passed", func() { 105 // mock a validator that always validates successfully 106 mockValidator = func(_ context.Context, _ v1beta1.TraitDefinition) error { 107 return nil 108 } 109 handler.Validators = []TraitDefValidator{ 110 TraitDefValidatorFn(mockValidator), 111 } 112 tdRaw, _ = json.Marshal(td) 113 req = admission.Request{ 114 AdmissionRequest: admissionv1.AdmissionRequest{ 115 Operation: admissionv1.Create, 116 Resource: reqResource, 117 Object: runtime.RawExtension{Raw: tdRaw}, 118 }, 119 } 120 resp := handler.Handle(context.TODO(), req) 121 Expect(resp.Allowed).Should(BeTrue()) 122 }) 123 It("Test validation failed", func() { 124 // mock a validator that always failed 125 mockValidator = func(_ context.Context, _ v1beta1.TraitDefinition) error { 126 return errors.New("mock validator error") 127 } 128 handler.Validators = []TraitDefValidator{ 129 TraitDefValidatorFn(mockValidator), 130 } 131 tdRaw, _ = json.Marshal(td) 132 req = admission.Request{ 133 AdmissionRequest: admissionv1.AdmissionRequest{ 134 Operation: admissionv1.Create, 135 Resource: reqResource, 136 Object: runtime.RawExtension{Raw: tdRaw}, 137 }, 138 } 139 resp := handler.Handle(context.TODO(), req) 140 Expect(resp.Allowed).Should(BeFalse()) 141 Expect(resp.Result.Reason).Should(Equal(metav1.StatusReason("mock validator error"))) 142 }) 143 It("Test cue template validation passed", func() { 144 td.Spec = v1beta1.TraitDefinitionSpec{ 145 Schematic: &common.Schematic{ 146 CUE: &common.CUE{ 147 Template: validCueTemplate, 148 }, 149 }, 150 } 151 tdRaw, _ = json.Marshal(td) 152 153 req = admission.Request{ 154 AdmissionRequest: admissionv1.AdmissionRequest{ 155 Operation: admissionv1.Create, 156 Resource: reqResource, 157 Object: runtime.RawExtension{Raw: tdRaw}, 158 }, 159 } 160 resp := handler.Handle(context.TODO(), req) 161 Expect(resp.Allowed).Should(BeTrue()) 162 }) 163 It("Test cue template validation failed", func() { 164 td.Spec = v1beta1.TraitDefinitionSpec{ 165 Schematic: &common.Schematic{ 166 CUE: &common.CUE{ 167 Template: inValidCueTemplate, 168 }, 169 }, 170 } 171 tdRaw, _ = json.Marshal(td) 172 173 req = admission.Request{ 174 AdmissionRequest: admissionv1.AdmissionRequest{ 175 Operation: admissionv1.Create, 176 Resource: reqResource, 177 Object: runtime.RawExtension{Raw: tdRaw}, 178 }, 179 } 180 resp := handler.Handle(context.TODO(), req) 181 Expect(resp.Allowed).Should(BeFalse()) 182 }) 183 }) 184 })