From 1f5738df84811149fbf95099efcfd761175816e7 Mon Sep 17 00:00:00 2001 From: caohe Date: Wed, 29 Nov 2023 14:07:27 +0800 Subject: [PATCH] fix(scheduler): fix incorrect loop logic in MultiPoint to avoid a plugin being loaded multiple times Signed-off-by: caohe --- pkg/scheduler/framework/runtime/framework.go | 3 +- .../framework/runtime/framework_test.go | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/pkg/scheduler/framework/runtime/framework.go b/pkg/scheduler/framework/runtime/framework.go index 8caa8ec1cb4..3a2ba6a005e 100644 --- a/pkg/scheduler/framework/runtime/framework.go +++ b/pkg/scheduler/framework/runtime/framework.go @@ -37,6 +37,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework/parallelize" "k8s.io/kubernetes/pkg/scheduler/metrics" + "k8s.io/kubernetes/pkg/util/slice" ) const ( @@ -526,7 +527,7 @@ func (f *frameworkImpl) expandMultiPointPlugins(logger klog.Logger, profile *con // - part 3: other plugins (excluded by part 1 & 2) in regular extension point. newPlugins := reflect.New(reflect.TypeOf(e.slicePtr).Elem()).Elem() // part 1 - for _, name := range enabledSet.list { + for _, name := range slice.CopyStrings(enabledSet.list) { if overridePlugins.has(name) { newPlugins = reflect.Append(newPlugins, reflect.ValueOf(pluginsMap[name])) enabledSet.delete(name) diff --git a/pkg/scheduler/framework/runtime/framework_test.go b/pkg/scheduler/framework/runtime/framework_test.go index 9acf3b43c70..a7ad623b122 100644 --- a/pkg/scheduler/framework/runtime/framework_test.go +++ b/pkg/scheduler/framework/runtime/framework_test.go @@ -46,6 +46,7 @@ const ( scoreWithNormalizePlugin1 = "score-with-normalize-plugin-1" scoreWithNormalizePlugin2 = "score-with-normalize-plugin-2" scorePlugin1 = "score-plugin-1" + scorePlugin2 = "score-plugin-2" pluginNotImplementingScore = "plugin-not-implementing-score" preFilterPluginName = "prefilter-plugin" preFilterWithExtensionsPluginName = "prefilter-with-extensions-plugin" @@ -100,6 +101,14 @@ func newScorePlugin1(_ context.Context, injArgs runtime.Object, f framework.Hand return &TestScorePlugin{scorePlugin1, inj}, nil } +func newScorePlugin2(_ context.Context, injArgs runtime.Object, f framework.Handle) (framework.Plugin, error) { + var inj injectedResult + if err := DecodeInto(injArgs, &inj); err != nil { + return nil, err + } + return &TestScorePlugin{scorePlugin2, inj}, nil +} + func newPluginNotImplementingScore(_ context.Context, _ runtime.Object, _ framework.Handle) (framework.Plugin, error) { return &PluginNotImplementingScore{}, nil } @@ -358,11 +367,13 @@ func (t TestBindPlugin) Bind(ctx context.Context, state *framework.CycleState, p return nil } +// nolint:errcheck // Ignore the error returned by Register as before var registry = func() Registry { r := make(Registry) r.Register(scoreWithNormalizePlugin1, newScoreWithNormalizePlugin1) r.Register(scoreWithNormalizePlugin2, newScoreWithNormalizePlugin2) r.Register(scorePlugin1, newScorePlugin1) + r.Register(scorePlugin2, newScorePlugin2) r.Register(pluginNotImplementingScore, newPluginNotImplementingScore) r.Register(duplicatePluginName, newDuplicatePlugin) r.Register(testPlugin, newTestPlugin) @@ -826,6 +837,44 @@ func TestNewFrameworkMultiPointExpansion(t *testing.T) { }, wantErr: "already registered", }, + { + name: "Override MultiPoint plugins weights and avoid a plugin being loaded multiple times", + plugins: &config.Plugins{ + MultiPoint: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: testPlugin}, + {Name: scorePlugin1}, + }, + }, + Score: config.PluginSet{ + Enabled: []config.Plugin{ + {Name: scorePlugin1, Weight: 5}, + {Name: scorePlugin2, Weight: 5}, + {Name: testPlugin, Weight: 3}, + }, + }, + }, + wantPlugins: &config.Plugins{ + QueueSort: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + PreFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + Filter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + PostFilter: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + PreScore: config.PluginSet{Enabled: []config.Plugin{ + {Name: testPlugin}, + {Name: scorePlugin1}, + }}, + Score: config.PluginSet{Enabled: []config.Plugin{ + {Name: scorePlugin1, Weight: 5}, + {Name: testPlugin, Weight: 3}, + {Name: scorePlugin2, Weight: 5}, + }}, + Reserve: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + Permit: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + PreBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + Bind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + PostBind: config.PluginSet{Enabled: []config.Plugin{{Name: testPlugin}}}, + }, + }, } for _, tc := range tests {