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  })