sigs.k8s.io/kueue@v0.6.2/test/integration/webhook/resourceflavor_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6      http://www.apache.org/licenses/LICENSE-2.0
     7  Unless required by applicable law or agreed to in writing, software
     8  distributed under the License is distributed on an "AS IS" BASIS,
     9  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  See the License for the specific language governing permissions and
    11  limitations under the License.
    12  */
    13  
    14  package webhook
    15  
    16  import (
    17  	"fmt"
    18  
    19  	"github.com/onsi/ginkgo/v2"
    20  	"github.com/onsi/gomega"
    21  	corev1 "k8s.io/api/core/v1"
    22  	"k8s.io/apimachinery/pkg/api/errors"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"sigs.k8s.io/controller-runtime/pkg/client"
    25  	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    26  
    27  	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
    28  	"sigs.k8s.io/kueue/pkg/util/testing"
    29  	"sigs.k8s.io/kueue/test/util"
    30  )
    31  
    32  const (
    33  	nodeSelectorMaxProperties = 8
    34  	taintsMaxItems            = 8
    35  )
    36  
    37  var _ = ginkgo.Describe("ResourceFlavor Webhook", func() {
    38  	var ns *corev1.Namespace
    39  
    40  	ginkgo.BeforeEach(func() {
    41  		ns = &corev1.Namespace{
    42  			ObjectMeta: metav1.ObjectMeta{
    43  				GenerateName: "core-",
    44  			},
    45  		}
    46  		gomega.Expect(k8sClient.Create(ctx, ns)).To(gomega.Succeed())
    47  	})
    48  
    49  	ginkgo.AfterEach(func() {
    50  		gomega.Expect(util.DeleteNamespace(ctx, k8sClient, ns)).To(gomega.Succeed())
    51  	})
    52  
    53  	ginkgo.When("Creating a ResourceFlavor", func() {
    54  		ginkgo.It("Should have a finalizer", func() {
    55  			ginkgo.By("Creating a new resourceFlavor")
    56  			resourceFlavor := testing.MakeResourceFlavor("resource-flavor").Obj()
    57  			gomega.Expect(k8sClient.Create(ctx, resourceFlavor)).Should(gomega.Succeed())
    58  			defer func() {
    59  				var rf kueue.ResourceFlavor
    60  				gomega.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(resourceFlavor), &rf)).Should(gomega.Succeed())
    61  				controllerutil.RemoveFinalizer(&rf, kueue.ResourceInUseFinalizerName)
    62  				gomega.Expect(k8sClient.Update(ctx, &rf)).Should(gomega.Succeed())
    63  				util.ExpectResourceFlavorToBeDeleted(ctx, k8sClient, resourceFlavor, true)
    64  			}()
    65  
    66  			var created kueue.ResourceFlavor
    67  			gomega.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(resourceFlavor), &created)).Should(gomega.Succeed())
    68  			gomega.Expect(created.GetFinalizers()).Should(gomega.Equal([]string{kueue.ResourceInUseFinalizerName}))
    69  		})
    70  	})
    71  
    72  	ginkgo.When("Creating a ResourceFlavor with invalid taints", func() {
    73  		ginkgo.It("Should fail to create", func() {
    74  			ginkgo.By("Creating a new resourceFlavor")
    75  			resourceFlavor := testing.MakeResourceFlavor("resource-flavor").Taint(corev1.Taint{
    76  				Key:    "@foo",
    77  				Value:  "bar",
    78  				Effect: corev1.TaintEffectNoSchedule,
    79  			}).Obj()
    80  			err := k8sClient.Create(ctx, resourceFlavor)
    81  			gomega.Expect(err).To(gomega.HaveOccurred())
    82  			gomega.Expect(errors.IsForbidden(err)).To(gomega.BeTrue(), "error: %v", err)
    83  		})
    84  	})
    85  
    86  	ginkgo.DescribeTable("invalid number of properties", func(taintsCount int, nodeSelectorCount int, isInvalid bool) {
    87  		rf := testing.MakeResourceFlavor("resource-flavor")
    88  		for i := 0; i < taintsCount; i++ {
    89  			rf = rf.Taint(corev1.Taint{
    90  				Key:    fmt.Sprintf("t%d", i),
    91  				Effect: corev1.TaintEffectNoExecute,
    92  			})
    93  		}
    94  		for i := 0; i < nodeSelectorCount; i++ {
    95  			rf = rf.Label(fmt.Sprintf("l%d", i), "")
    96  		}
    97  		resourceFlavor := rf.Obj()
    98  		err := k8sClient.Create(ctx, resourceFlavor)
    99  		if isInvalid {
   100  			gomega.Expect(err).To(gomega.HaveOccurred())
   101  			gomega.Expect(errors.IsInvalid(err)).To(gomega.BeTrue(), "error: %v", err)
   102  		} else {
   103  			gomega.Expect(err).To(gomega.Succeed())
   104  			defer func() {
   105  				var rf kueue.ResourceFlavor
   106  				gomega.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(resourceFlavor), &rf)).To(gomega.Succeed())
   107  				controllerutil.RemoveFinalizer(&rf, kueue.ResourceInUseFinalizerName)
   108  				gomega.Expect(k8sClient.Update(ctx, &rf)).Should(gomega.Succeed())
   109  				util.ExpectResourceFlavorToBeDeleted(ctx, k8sClient, resourceFlavor, true)
   110  			}()
   111  		}
   112  	},
   113  		ginkgo.Entry("invalid number of taint", taintsMaxItems+1, 0, true),
   114  		ginkgo.Entry("invalid number of nodeSelector", 0, nodeSelectorMaxProperties+1, true),
   115  		ginkgo.Entry("valid number of nodeSelector and taint", taintsMaxItems, nodeSelectorMaxProperties, false),
   116  	)
   117  
   118  	ginkgo.When("Updating a ResourceFlavor with invalid taints", func() {
   119  		ginkgo.It("Should fail to update", func() {
   120  			ginkgo.By("Creating a new resourceFlavor")
   121  			resourceFlavor := testing.MakeResourceFlavor("resource-flavor").Obj()
   122  			gomega.Expect(k8sClient.Create(ctx, resourceFlavor)).Should(gomega.Succeed())
   123  			defer func() {
   124  				var rf kueue.ResourceFlavor
   125  				gomega.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(resourceFlavor), &rf)).To(gomega.Succeed())
   126  				controllerutil.RemoveFinalizer(&rf, kueue.ResourceInUseFinalizerName)
   127  				gomega.Expect(k8sClient.Update(ctx, &rf)).Should(gomega.Succeed())
   128  				util.ExpectResourceFlavorToBeDeleted(ctx, k8sClient, resourceFlavor, true)
   129  			}()
   130  
   131  			var created kueue.ResourceFlavor
   132  			gomega.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(resourceFlavor), &created)).To(gomega.Succeed())
   133  			created.Spec.NodeTaints = []corev1.Taint{{
   134  				Key:    "foo",
   135  				Value:  "bar",
   136  				Effect: "Invalid",
   137  			}}
   138  
   139  			ginkgo.By("Updating the resourceFlavor with invalid labels")
   140  			err := k8sClient.Update(ctx, &created)
   141  			gomega.Expect(err).To(gomega.HaveOccurred())
   142  			gomega.Expect(errors.IsForbidden(err)).To(gomega.BeTrue(), "error: %v", err)
   143  		})
   144  	})
   145  })