k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/integration/scheduler/util.go (about) 1 /* 2 Copyright 2017 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 scheduler 18 19 import ( 20 "context" 21 "testing" 22 "time" 23 24 v1 "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apimachinery/pkg/util/wait" 28 configv1 "k8s.io/kube-scheduler/config/v1" 29 "k8s.io/kubernetes/pkg/scheduler" 30 schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config" 31 configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing" 32 "k8s.io/kubernetes/pkg/scheduler/framework" 33 "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder" 34 frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime" 35 st "k8s.io/kubernetes/pkg/scheduler/testing" 36 testutils "k8s.io/kubernetes/test/integration/util" 37 "k8s.io/utils/pointer" 38 ) 39 40 // The returned shutdown func will delete created resources and scheduler, resources should be those 41 // that will affect the scheduling result, like nodes, pods, etc.. Namespaces should not be 42 // deleted here because it's created together with the apiserver, they should be deleted 43 // simultaneously or we'll have no namespace. 44 // This should only be called when you want to kill the scheduler alone, away from apiserver. 45 // For example, in scheduler integration tests, recreating apiserver is performance consuming, 46 // then shutdown the scheduler and recreate it between each test case is a better approach. 47 func InitTestSchedulerForFrameworkTest(t *testing.T, testCtx *testutils.TestContext, nodeCount int, opts ...scheduler.Option) (*testutils.TestContext, testutils.ShutdownFunc) { 48 testCtx = testutils.InitTestSchedulerWithOptions(t, testCtx, 0, opts...) 49 testutils.SyncSchedulerInformerFactory(testCtx) 50 go testCtx.Scheduler.Run(testCtx.SchedulerCtx) 51 52 if nodeCount > 0 { 53 if _, err := testutils.CreateAndWaitForNodesInCache(testCtx, "test-node", st.MakeNode(), nodeCount); err != nil { 54 // Make sure to cleanup the resources when initializing error. 55 testutils.CleanupTest(t, testCtx) 56 t.Fatal(err) 57 } 58 } 59 60 teardown := func() { 61 err := testCtx.ClientSet.CoreV1().Nodes().DeleteCollection(testCtx.SchedulerCtx, *metav1.NewDeleteOptions(0), metav1.ListOptions{}) 62 if err != nil { 63 t.Errorf("error while deleting all nodes: %v", err) 64 } 65 err = testCtx.ClientSet.CoreV1().Pods(testCtx.NS.Name).DeleteCollection(testCtx.SchedulerCtx, *metav1.NewDeleteOptions(0), metav1.ListOptions{}) 66 if err != nil { 67 t.Errorf("error while deleting pod: %v", err) 68 } 69 // Wait for all pods to be deleted, or will failed to create same name pods 70 // required in other test cases. 71 err = wait.PollUntilContextTimeout(testCtx.SchedulerCtx, time.Millisecond, wait.ForeverTestTimeout, true, 72 testutils.PodsCleanedUp(testCtx.SchedulerCtx, testCtx.ClientSet, testCtx.NS.Name)) 73 if err != nil { 74 t.Errorf("error while waiting for all pods to be deleted: %v", err) 75 } 76 // Kill the scheduler. 77 testCtx.SchedulerCloseFn() 78 } 79 80 return testCtx, teardown 81 } 82 83 // NewPlugin returns a plugin factory with specified Plugin. 84 func NewPlugin(plugin framework.Plugin) frameworkruntime.PluginFactory { 85 return func(_ context.Context, _ runtime.Object, fh framework.Handle) (framework.Plugin, error) { 86 return plugin, nil 87 } 88 } 89 90 // InitRegistryAndConfig returns registry and plugins config based on give plugins. 91 func InitRegistryAndConfig(t *testing.T, factory func(plugin framework.Plugin) frameworkruntime.PluginFactory, plugins ...framework.Plugin) (frameworkruntime.Registry, schedulerconfig.KubeSchedulerProfile) { 92 if len(plugins) == 0 { 93 return frameworkruntime.Registry{}, schedulerconfig.KubeSchedulerProfile{} 94 } 95 96 if factory == nil { 97 factory = NewPlugin 98 } 99 100 registry := frameworkruntime.Registry{} 101 pls := &configv1.Plugins{} 102 103 for _, p := range plugins { 104 registry.Register(p.Name(), factory(p)) 105 plugin := configv1.Plugin{Name: p.Name()} 106 107 switch p.(type) { 108 case framework.PreEnqueuePlugin: 109 pls.PreEnqueue.Enabled = append(pls.PreEnqueue.Enabled, plugin) 110 case framework.PreFilterPlugin: 111 pls.PreFilter.Enabled = append(pls.PreFilter.Enabled, plugin) 112 case framework.FilterPlugin: 113 pls.Filter.Enabled = append(pls.Filter.Enabled, plugin) 114 case framework.PreScorePlugin: 115 pls.PreScore.Enabled = append(pls.PreScore.Enabled, plugin) 116 case framework.ScorePlugin: 117 pls.Score.Enabled = append(pls.Score.Enabled, plugin) 118 case framework.ReservePlugin: 119 pls.Reserve.Enabled = append(pls.Reserve.Enabled, plugin) 120 case framework.PreBindPlugin: 121 pls.PreBind.Enabled = append(pls.PreBind.Enabled, plugin) 122 case framework.BindPlugin: 123 pls.Bind.Enabled = append(pls.Bind.Enabled, plugin) 124 // It's intentional to disable the DefaultBind plugin. Otherwise, DefaultBinder's failure would fail 125 // a pod's scheduling, as well as the test BindPlugin's execution. 126 pls.Bind.Disabled = []configv1.Plugin{{Name: defaultbinder.Name}} 127 case framework.PostBindPlugin: 128 pls.PostBind.Enabled = append(pls.PostBind.Enabled, plugin) 129 case framework.PermitPlugin: 130 pls.Permit.Enabled = append(pls.Permit.Enabled, plugin) 131 } 132 } 133 134 versionedCfg := configv1.KubeSchedulerConfiguration{ 135 Profiles: []configv1.KubeSchedulerProfile{{ 136 SchedulerName: pointer.String(v1.DefaultSchedulerName), 137 Plugins: pls, 138 }}, 139 } 140 cfg := configtesting.V1ToInternalWithDefaults(t, versionedCfg) 141 return registry, cfg.Profiles[0] 142 }