...

Source file src/k8s.io/kubernetes/test/e2e/node/runtimeclass.go

Documentation: k8s.io/kubernetes/test/e2e/node

     1  /*
     2  Copyright 2019 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 node
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"k8s.io/pod-security-admission/api"
    24  
    25  	v1 "k8s.io/api/core/v1"
    26  	nodev1 "k8s.io/api/node/v1"
    27  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/util/uuid"
    30  	runtimeclasstest "k8s.io/kubernetes/pkg/kubelet/runtimeclass/testing"
    31  	"k8s.io/kubernetes/test/e2e/framework"
    32  	e2enode "k8s.io/kubernetes/test/e2e/framework/node"
    33  	e2eruntimeclass "k8s.io/kubernetes/test/e2e/framework/node/runtimeclass"
    34  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    35  	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
    36  	"k8s.io/kubernetes/test/e2e/scheduling"
    37  
    38  	"github.com/onsi/ginkgo/v2"
    39  	"github.com/onsi/gomega"
    40  )
    41  
    42  var _ = SIGDescribe("RuntimeClass", func() {
    43  	f := framework.NewDefaultFramework("runtimeclass")
    44  	f.NamespacePodSecurityLevel = api.LevelPrivileged
    45  
    46  	ginkgo.It("should reject a Pod requesting a RuntimeClass with conflicting node selector", func(ctx context.Context) {
    47  		labelFooName := "foo-" + string(uuid.NewUUID())
    48  
    49  		scheduling := &nodev1.Scheduling{
    50  			NodeSelector: map[string]string{
    51  				labelFooName: "conflict",
    52  			},
    53  		}
    54  
    55  		runtimeClass := newRuntimeClass(f.Namespace.Name, "conflict-runtimeclass")
    56  		runtimeClass.Scheduling = scheduling
    57  		rc, err := f.ClientSet.NodeV1().RuntimeClasses().Create(ctx, runtimeClass, metav1.CreateOptions{})
    58  		framework.ExpectNoError(err, "failed to create RuntimeClass resource")
    59  
    60  		pod := e2eruntimeclass.NewRuntimeClassPod(rc.GetName())
    61  		pod.Spec.NodeSelector = map[string]string{
    62  			labelFooName: "bar",
    63  		}
    64  		_, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(ctx, pod, metav1.CreateOptions{})
    65  		if !apierrors.IsForbidden(err) {
    66  			framework.Failf("expected 'forbidden' as error, got instead: %v", err)
    67  		}
    68  	})
    69  
    70  	f.It("should run a Pod requesting a RuntimeClass with scheduling with taints", f.WithSerial(), func(ctx context.Context) {
    71  		labelFooName := "foo-" + string(uuid.NewUUID())
    72  		labelFizzName := "fizz-" + string(uuid.NewUUID())
    73  
    74  		nodeName := scheduling.GetNodeThatCanRunPod(ctx, f)
    75  		nodeSelector := map[string]string{
    76  			labelFooName:  "bar",
    77  			labelFizzName: "buzz",
    78  		}
    79  		tolerations := []v1.Toleration{
    80  			{
    81  				Key:      labelFooName,
    82  				Operator: v1.TolerationOpEqual,
    83  				Value:    "bar",
    84  				Effect:   v1.TaintEffectNoSchedule,
    85  			},
    86  		}
    87  		scheduling := &nodev1.Scheduling{
    88  			NodeSelector: nodeSelector,
    89  			Tolerations:  tolerations,
    90  		}
    91  
    92  		ginkgo.By("Trying to apply a label on the found node.")
    93  		for key, value := range nodeSelector {
    94  			e2enode.AddOrUpdateLabelOnNode(f.ClientSet, nodeName, key, value)
    95  			e2enode.ExpectNodeHasLabel(ctx, f.ClientSet, nodeName, key, value)
    96  			ginkgo.DeferCleanup(e2enode.RemoveLabelOffNode, f.ClientSet, nodeName, key)
    97  		}
    98  
    99  		ginkgo.By("Trying to apply taint on the found node.")
   100  		taint := v1.Taint{
   101  			Key:    labelFooName,
   102  			Value:  "bar",
   103  			Effect: v1.TaintEffectNoSchedule,
   104  		}
   105  		e2enode.AddOrUpdateTaintOnNode(ctx, f.ClientSet, nodeName, taint)
   106  		e2enode.ExpectNodeHasTaint(ctx, f.ClientSet, nodeName, &taint)
   107  		ginkgo.DeferCleanup(e2enode.RemoveTaintOffNode, f.ClientSet, nodeName, taint)
   108  
   109  		ginkgo.By("Trying to create runtimeclass and pod")
   110  		runtimeClass := newRuntimeClass(f.Namespace.Name, "non-conflict-runtimeclass")
   111  		runtimeClass.Scheduling = scheduling
   112  		rc, err := f.ClientSet.NodeV1().RuntimeClasses().Create(ctx, runtimeClass, metav1.CreateOptions{})
   113  		framework.ExpectNoError(err, "failed to create RuntimeClass resource")
   114  
   115  		pod := e2eruntimeclass.NewRuntimeClassPod(rc.GetName())
   116  		pod.Spec.NodeSelector = map[string]string{
   117  			labelFooName: "bar",
   118  		}
   119  		pod = e2epod.NewPodClient(f).Create(ctx, pod)
   120  
   121  		framework.ExpectNoError(e2epod.WaitForPodNotPending(ctx, f.ClientSet, f.Namespace.Name, pod.Name))
   122  
   123  		// check that pod got scheduled on specified node.
   124  		scheduledPod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(ctx, pod.Name, metav1.GetOptions{})
   125  		framework.ExpectNoError(err)
   126  		gomega.Expect(nodeName).To(gomega.Equal(scheduledPod.Spec.NodeName))
   127  		gomega.Expect(nodeSelector).To(gomega.Equal(pod.Spec.NodeSelector))
   128  		gomega.Expect(pod.Spec.Tolerations).To(gomega.ContainElement(tolerations[0]))
   129  	})
   130  
   131  	ginkgo.It("should run a Pod requesting a RuntimeClass with scheduling without taints ", func(ctx context.Context) {
   132  		if err := e2eruntimeclass.NodeSupportsPreconfiguredRuntimeClassHandler(ctx, f); err != nil {
   133  			e2eskipper.Skipf("Skipping test as node does not have E2E runtime class handler preconfigured in container runtime config: %v", err)
   134  		}
   135  
   136  		labelFooName := "foo-" + string(uuid.NewUUID())
   137  		labelFizzName := "fizz-" + string(uuid.NewUUID())
   138  
   139  		nodeName := scheduling.GetNodeThatCanRunPod(ctx, f)
   140  		nodeSelector := map[string]string{
   141  			labelFooName:  "bar",
   142  			labelFizzName: "buzz",
   143  		}
   144  		scheduling := &nodev1.Scheduling{
   145  			NodeSelector: nodeSelector,
   146  		}
   147  
   148  		ginkgo.By("Trying to apply a label on the found node.")
   149  		for key, value := range nodeSelector {
   150  			e2enode.AddOrUpdateLabelOnNode(f.ClientSet, nodeName, key, value)
   151  			e2enode.ExpectNodeHasLabel(ctx, f.ClientSet, nodeName, key, value)
   152  			ginkgo.DeferCleanup(e2enode.RemoveLabelOffNode, f.ClientSet, nodeName, key)
   153  		}
   154  
   155  		ginkgo.By("Trying to create runtimeclass and pod")
   156  		runtimeClass := newRuntimeClass(f.Namespace.Name, "non-conflict-runtimeclass")
   157  		runtimeClass.Scheduling = scheduling
   158  		rc, err := f.ClientSet.NodeV1().RuntimeClasses().Create(ctx, runtimeClass, metav1.CreateOptions{})
   159  		framework.ExpectNoError(err, "failed to create RuntimeClass resource")
   160  
   161  		pod := e2eruntimeclass.NewRuntimeClassPod(rc.GetName())
   162  		pod.Spec.NodeSelector = map[string]string{
   163  			labelFooName: "bar",
   164  		}
   165  		pod = e2epod.NewPodClient(f).Create(ctx, pod)
   166  
   167  		framework.ExpectNoError(e2epod.WaitForPodNotPending(ctx, f.ClientSet, f.Namespace.Name, pod.Name))
   168  
   169  		// check that pod got scheduled on specified node.
   170  		scheduledPod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(ctx, pod.Name, metav1.GetOptions{})
   171  		framework.ExpectNoError(err)
   172  		gomega.Expect(nodeName).To(gomega.Equal(scheduledPod.Spec.NodeName))
   173  		gomega.Expect(nodeSelector).To(gomega.Equal(pod.Spec.NodeSelector))
   174  	})
   175  })
   176  
   177  // newRuntimeClass returns a test runtime class.
   178  func newRuntimeClass(namespace, name string) *nodev1.RuntimeClass {
   179  	uniqueName := fmt.Sprintf("%s-%s", namespace, name)
   180  	return runtimeclasstest.NewRuntimeClass(uniqueName, e2eruntimeclass.PreconfiguredRuntimeClassHandler)
   181  }
   182  

View as plain text