Change:
There is no reason this should be allowed to happen, especially that we can't configure duplicate plugins differently since plugin configs is a separate list . /sig scheduling
/label help-wanted
The label(s) cannot be applied. These labels are supported: <detailsIn response to : /label help-wanted Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/help-wanted
/help /good-first-issue
/assign
/remove-good-first-issue /remove-help

Discussion:
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library", <ins> "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", </ins> "//staging/src/k8s.io/client-go/util/workqueue:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/sigs.k8s.io/yaml:go_default_library",

import ( "context" "fmt" <ins> "reflect" </ins> "time" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" <ins> "k8s.io/apimachinery/pkg/util/sets" </ins> "k8s.io/client-go/util/workqueue" "k8s.io/klog" "k8s.io/kubernetes/pkg/scheduler/apis/config"

} } <del> if plugins.PreFilter != nil { for _, pf := range plugins.PreFilter.Enabled { if pg, ok := pluginsMap[pf.Name]; ok { p, ok := pg.(PreFilterPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend prefilter plugin", pf.Name) } f.preFilterPlugins = append(f.preFilterPlugins, p) } else { return nil, fmt.Errorf("prefilter plugin %q does not exist", pf.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.preFilterPlugins), plugins.PreFilter, reflect.TypeOf((*PreFilterPlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.Filter != nil { for _, r := range plugins.Filter.Enabled { if pg, ok := pluginsMap[r.Name]; ok { p, ok := pg.(FilterPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend filter plugin", r.Name) } f.filterPlugins = append(f.filterPlugins, p) } else { return nil, fmt.Errorf("filter plugin %q does not exist", r.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.filterPlugins), plugins.Filter, reflect.TypeOf((*FilterPlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.Score != nil { for _, sc := range plugins.Score.Enabled { if pg, ok := pluginsMap[sc.Name]; ok { p, ok := pg.(ScorePlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend score plugin", sc.Name) } if f.pluginNameToWeightMap[p.Name()] == 0 { return nil, fmt.Errorf("score plugin %q is not configured with weight", p.Name()) } f.scorePlugins = append(f.scorePlugins, p) } else { return nil, fmt.Errorf("score plugin %q does not exist", sc.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.reservePlugins), plugins.Reserve, reflect.TypeOf((*ReservePlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.Reserve != nil { for _, r := range plugins.Reserve.Enabled { if pg, ok := pluginsMap[r.Name]; ok { p, ok := pg.(ReservePlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend reserve plugin", r.Name) } f.reservePlugins = append(f.reservePlugins, p) } else { return nil, fmt.Errorf("reserve plugin %q does not exist", r.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.postFilterPlugins), plugins.PostFilter, reflect.TypeOf((*PostFilterPlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.PostFilter != nil { for _, r := range plugins.PostFilter.Enabled { if pg, ok := pluginsMap[r.Name]; ok { p, ok := pg.(PostFilterPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend post-filter plugin", r.Name) } f.postFilterPlugins = append(f.postFilterPlugins, p) } else { return nil, fmt.Errorf("post-filter plugin %q does not exist", r.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.scorePlugins), plugins.Score, reflect.TypeOf((*ScorePlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.PreBind != nil { for _, pb := range plugins.PreBind.Enabled { if pg, ok := pluginsMap[pb.Name]; ok { p, ok := pg.(PreBindPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend prebind plugin", pb.Name) } f.preBindPlugins = append(f.preBindPlugins, p) } else { return nil, fmt.Errorf("prebind plugin %q does not exist", pb.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.preBindPlugins), plugins.PreBind, reflect.TypeOf((*PreBindPlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.Bind != nil { for _, pb := range plugins.Bind.Enabled { if pg, ok := pluginsMap[pb.Name]; ok { p, ok := pg.(BindPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend bind plugin", pb.Name) } f.bindPlugins = append(f.bindPlugins, p) } else { return nil, fmt.Errorf("bind plugin %q does not exist", pb.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.bindPlugins), plugins.Bind, reflect.TypeOf((*BindPlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.PostBind != nil { for _, pb := range plugins.PostBind.Enabled { if pg, ok := pluginsMap[pb.Name]; ok { p, ok := pg.(PostBindPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend postbind plugin", pb.Name) } f.postBindPlugins = append(f.postBindPlugins, p) } else { return nil, fmt.Errorf("postbind plugin %q does not exist", pb.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.postBindPlugins), plugins.PostBind, reflect.TypeOf((*PostBindPlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.Unreserve != nil { for _, ur := range plugins.Unreserve.Enabled { if pg, ok := pluginsMap[ur.Name]; ok { p, ok := pg.(UnreservePlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend unreserve plugin", ur.Name) } f.unreservePlugins = append(f.unreservePlugins, p) } else { return nil, fmt.Errorf("unreserve plugin %q does not exist", ur.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.unreservePlugins), plugins.Unreserve, reflect.TypeOf((*UnreservePlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.Permit != nil { for _, pr := range plugins.Permit.Enabled { if pg, ok := pluginsMap[pr.Name]; ok { p, ok := pg.(PermitPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend permit plugin", pr.Name) } f.permitPlugins = append(f.permitPlugins, p) } else { return nil, fmt.Errorf("permit plugin %q does not exist", pr.Name) } } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.permitPlugins), plugins.Permit, reflect.TypeOf((*PermitPlugin)(nil)), pluginsMap); err != nil { return nil, err </ins> } <del> if plugins.QueueSort != nil { for _, qs := range plugins.QueueSort.Enabled { if pg, ok := pluginsMap[qs.Name]; ok { p, ok := pg.(QueueSortPlugin) if !ok { return nil, fmt.Errorf("plugin %q does not extend queue sort plugin", qs.Name) } f.queueSortPlugins = append(f.queueSortPlugins, p) if len(f.queueSortPlugins) > 1 { return nil, fmt.Errorf("only one queue sort plugin can be enabled") } } else { return nil, fmt.Errorf("queue sort plugin %q does not exist", qs.Name) } </del> <ins> if err := updatePluginList(reflect.ValueOf(&f.queueSortPlugins), plugins.QueueSort, reflect.TypeOf((*QueueSortPlugin)(nil)), pluginsMap); err != nil { return nil, err } for _, scorePlugin := range f.scorePlugins { if f.pluginNameToWeightMap[scorePlugin.Name()] == 0 { return nil, fmt.Errorf("score plugin %q is not configured with weight", scorePlugin.Name()) </ins> } } <ins> if len(f.queueSortPlugins) > 1 { return nil, fmt.Errorf("only one queue sort plugin can be enabled") } </ins> return f, nil } <ins> func updatePluginList(pluginList reflect.Value, pluginSet *config.PluginSet, pluginType reflect.Type, pluginsMap map[string]Plugin) error { if pluginSet == nil { return nil } plugins := pluginList.Elem() pluginType = pluginType.Elem() set := sets.NewString() for _, ep := range pluginSet.Enabled { pg, ok := pluginsMap[ep.Name] if !ok { return fmt.Errorf("%s %q does not exist", pluginType.String(), ep.Name) } if !reflect.TypeOf(pg).Implements(pluginType) { return fmt.Errorf("plugin %q does not extend %s plugin", ep.Name, pluginType.String()) } if set.Has(ep.Name) { return fmt.Errorf("plugin %q already registered as %q", ep.Name, pluginType.String()) } set.Insert(ep.Name) newPlugins := reflect.Append(plugins, reflect.ValueOf(pg)) plugins.Set(newPlugins) } return nil } </ins> // QueueSortFunc returns the function to sort pods in scheduling queue func (f *framework) QueueSortFunc() LessFunc { if len(f.queueSortPlugins) == 0 {

import ( "fmt" "reflect" <ins> "strings" </ins> "testing" v1 "k8s.io/api/core/v1"

pluginNotImplementingScore        = "plugin-not-implementing-score" preFilterPluginName               = "prefilter-plugin" preFilterWithExtensionsPluginName = "prefilter-with-extensions-plugin" <ins> duplicatePluginName               = "duplicate-plugin" </ins> ) // TestScoreWithNormalizePlugin implements ScoreWithNormalizePlugin interface.

return pl } <ins> type TestDuplicatePlugin struct { } func (dp *TestDuplicatePlugin) Name() string { return duplicatePluginName } func (dp *TestDuplicatePlugin) PreFilter(pc *PluginContext, p *v1.Pod) *Status { return nil } func (dp *TestDuplicatePlugin) Extensions() PreFilterExtensions { return nil } var _ PreFilterPlugin = &TestDuplicatePlugin{} func newDuplicatePlugin(_ *runtime.Unknown, _ FrameworkHandle) (Plugin, error) { return &TestDuplicatePlugin{}, nil } </ins> var registry Registry = func() Registry { r := make(Registry) r.Register(scoreWithNormalizePlugin1, newScoreWithNormalizePlugin1) r.Register(scoreWithNormalizePlugin2, newScoreWithNormalizePlugin2) r.Register(scorePlugin1, newScorePlugin1) r.Register(pluginNotImplementingScore, newPluginNotImplementingScore) <ins> r.Register(duplicatePluginName, newDuplicatePlugin) </ins> return r }()

} } <ins> func TestRegisterDuplicatePluginWouldFail(t *testing.T) { plugin := config.Plugin{Name: duplicatePluginName, Weight: 1} pluginSet := config.PluginSet{ Enabled: []config.Plugin{ plugin, plugin, }, } plugins := config.Plugins{} plugins.PreFilter = &pluginSet _, err := NewFramework(registry, &plugins, emptyArgs) if err == nil { t.Fatal("Framework initialization should fail") } if err != nil && !strings.Contains(err.Error(), "already registered") { t.Fatalf("Unexpected error, got %s, expect: plugin already registered", err.Error()) } } </ins> func TestRunScorePlugins(t *testing.T) { tests := []struct { name          string