...

Source file src/k8s.io/kubernetes/test/integration/scheduler/eventhandler/eventhandler_test.go

Documentation: k8s.io/kubernetes/test/integration/scheduler/eventhandler

     1  /*
     2  Copyright 2023 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 eventhandler
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/runtime"
    26  	"k8s.io/component-helpers/scheduling/corev1"
    27  	configv1 "k8s.io/kube-scheduler/config/v1"
    28  	"k8s.io/kubernetes/pkg/scheduler"
    29  	configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing"
    30  	"k8s.io/kubernetes/pkg/scheduler/framework"
    31  	frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
    32  	st "k8s.io/kubernetes/pkg/scheduler/testing"
    33  	schedulerutils "k8s.io/kubernetes/test/integration/scheduler"
    34  	testutils "k8s.io/kubernetes/test/integration/util"
    35  	"k8s.io/utils/ptr"
    36  )
    37  
    38  var _ framework.FilterPlugin = &fooPlugin{}
    39  
    40  type fooPlugin struct {
    41  }
    42  
    43  func (pl *fooPlugin) Name() string {
    44  	return "foo"
    45  }
    46  
    47  func (pl *fooPlugin) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
    48  	taints := nodeInfo.Node().Spec.Taints
    49  	if len(taints) == 0 {
    50  		return nil
    51  	}
    52  
    53  	if corev1.TolerationsTolerateTaint(pod.Spec.Tolerations, &nodeInfo.Node().Spec.Taints[0]) {
    54  		return nil
    55  	}
    56  	return framework.NewStatus(framework.Unschedulable)
    57  }
    58  
    59  func (pl *fooPlugin) EventsToRegister() []framework.ClusterEventWithHint {
    60  	return []framework.ClusterEventWithHint{
    61  		{Event: framework.ClusterEvent{Resource: framework.Node, ActionType: framework.UpdateNodeTaint}},
    62  	}
    63  }
    64  
    65  // newPlugin returns a plugin factory with specified Plugin.
    66  func newPlugin(plugin framework.Plugin) frameworkruntime.PluginFactory {
    67  	return func(_ context.Context, _ runtime.Object, fh framework.Handle) (framework.Plugin, error) {
    68  		return plugin, nil
    69  	}
    70  }
    71  
    72  func TestUpdateNodeEvent(t *testing.T) {
    73  	testContext := testutils.InitTestAPIServer(t, "test-event", nil)
    74  
    75  	taints := []v1.Taint{{Key: v1.TaintNodeUnschedulable, Value: "", Effect: v1.TaintEffectNoSchedule}}
    76  	nodeWrapper := st.MakeNode().Name("node-0").Label("kubernetes.io/hostname", "node-0").Taints(taints).Obj()
    77  	podWrapper := testutils.InitPausePod(&testutils.PausePodConfig{Name: "test-pod", Namespace: testContext.NS.Name})
    78  	fooPlugin := &fooPlugin{}
    79  
    80  	registry := frameworkruntime.Registry{
    81  		fooPlugin.Name(): newPlugin(fooPlugin),
    82  	}
    83  
    84  	// Setup plugins for testing.
    85  	cfg := configtesting.V1ToInternalWithDefaults(t, configv1.KubeSchedulerConfiguration{
    86  		Profiles: []configv1.KubeSchedulerProfile{{
    87  			SchedulerName: ptr.To[string](v1.DefaultSchedulerName),
    88  			Plugins: &configv1.Plugins{
    89  				Filter: configv1.PluginSet{
    90  					Enabled: []configv1.Plugin{
    91  						{Name: fooPlugin.Name()},
    92  					},
    93  					Disabled: []configv1.Plugin{
    94  						{Name: "*"},
    95  					},
    96  				},
    97  			},
    98  		}},
    99  	})
   100  
   101  	testCtx, teardown := schedulerutils.InitTestSchedulerForFrameworkTest(t, testContext, 0,
   102  		scheduler.WithProfiles(cfg.Profiles...),
   103  		scheduler.WithFrameworkOutOfTreeRegistry(registry),
   104  	)
   105  	defer teardown()
   106  
   107  	node, err := testutils.CreateNode(testCtx.ClientSet, nodeWrapper)
   108  	if err != nil {
   109  		t.Fatalf("Creating node error: %v", err)
   110  	}
   111  
   112  	pod, err := testutils.CreatePausePod(testCtx.ClientSet, podWrapper)
   113  	if err != nil {
   114  		t.Fatalf("Creating pod error: %v", err)
   115  	}
   116  
   117  	if err := testutils.WaitForPodUnschedulable(testCtx.ClientSet, pod); err != nil {
   118  		t.Fatalf("Pod %v got scheduled: %v", pod.Name, err)
   119  	}
   120  	node, err = testCtx.ClientSet.CoreV1().Nodes().Get(testCtx.Ctx, node.Name, metav1.GetOptions{})
   121  	if err != nil {
   122  		t.Fatalf("Error while getting a node: %v", err)
   123  	}
   124  
   125  	// Update node label and node taints
   126  	node.Labels["foo"] = "bar"
   127  	node.Spec.Taints = nil
   128  
   129  	_, err = testCtx.ClientSet.CoreV1().Nodes().Update(testCtx.Ctx, node, metav1.UpdateOptions{})
   130  	if err != nil {
   131  		t.Fatalf("Error updating the node: %v", err)
   132  	}
   133  
   134  	if err := testutils.WaitForPodToSchedule(testCtx.ClientSet, pod); err != nil {
   135  		t.Errorf("Pod %v was not scheduled: %v", pod.Name, err)
   136  	}
   137  }
   138  

View as plain text