Change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --Recent commit: import an issue when multiple custom plugin configured in scheduler config file, and those plugins are default plugins too. It was manipulating slice with index, but the slice is updated while index is not, which will cause the index out of range, see the exceptions listed below, config file should be handled properly without such exception override multiple default plugin in scheduler's config file. Kubernetes version (use ): latest (1.22) Cloud provider or hardware configuration: OS (e.g: ): all Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others: /assign
/sig scheduling /triage accepted

Discussion:
} cfg.Profiles = completedProfiles <del> if len(fileName) > 0 { // Since the default component config lists all the default plugins as enabled // without disabling them, we must explicitly disable all the plugins for each // extension point using the "*" expression to ensure that the generated config // file is usable disabledPlugins := []config.Plugin{{Name: "*"}} for i := range cfg.Profiles { if cfg.Profiles[i].Plugins == nil { continue } cfg.Profiles[i].Plugins.QueueSort.Disabled = disabledPlugins cfg.Profiles[i].Plugins.PreFilter.Disabled = disabledPlugins cfg.Profiles[i].Plugins.Filter.Disabled = disabledPlugins cfg.Profiles[i].Plugins.PostFilter.Disabled = disabledPlugins cfg.Profiles[i].Plugins.PreScore.Disabled = disabledPlugins cfg.Profiles[i].Plugins.Score.Disabled = disabledPlugins cfg.Profiles[i].Plugins.Reserve.Disabled = disabledPlugins cfg.Profiles[i].Plugins.Permit.Disabled = disabledPlugins cfg.Profiles[i].Plugins.PreBind.Disabled = disabledPlugins cfg.Profiles[i].Plugins.Bind.Disabled = disabledPlugins cfg.Profiles[i].Plugins.PostBind.Disabled = disabledPlugins } } </del> buf, err := encodeConfig(cfg) if err != nil { return err

func mergePluginSet(defaultPluginSet, customPluginSet v1beta2.PluginSet) v1beta2.PluginSet { disabledPlugins := sets.NewString() enabledCustomPlugins := make(map[string]pluginIndex) <ins> // replacedPluginIndex is a set of index of plugins, which have replaced the default plugins. replacedPluginIndex := sets.NewInt() </ins> for _, disabledPlugin := range customPluginSet.Disabled { disabledPlugins.Insert(disabledPlugin.Name) }

} // The default plugin is explicitly re-configured, update the default plugin accordingly. if customPlugin, ok := enabledCustomPlugins[defaultEnabledPlugin.Name]; ok { <del> klog.InfoS("Defaut plugin is explicitly re-configured and is overriding.", "plugin", defaultEnabledPlugin.Name) // update the default plugin in place to preserve order </del> <ins> klog.InfoS("Default plugin is explicitly re-configured; overriding", "plugin", defaultEnabledPlugin.Name) // Update the default plugin in place to preserve order. </ins> defaultEnabledPlugin = customPlugin.plugin <del> // kick the plugin from the enabled list of custom plugins customPluginSet.Enabled = append(customPluginSet.Enabled[:customPlugin.index], customPluginSet.Enabled[customPlugin.index+1:]...) </del> <ins> replacedPluginIndex.Insert(customPlugin.index) </ins> } enabledPlugins = append(enabledPlugins, defaultEnabledPlugin) } } <del> enabledPlugins = append(enabledPlugins, customPluginSet.Enabled...) </del> <ins> // Append all the custom plugins which haven't replaced any default plugins. // Note: duplicated custom plugins will still be appended here. // If so, the instantiation of scheduler framework will detect it and abort. for index, plugin := range customPluginSet.Enabled { if !replacedPluginIndex.Has(index) { enabledPlugins = append(enabledPlugins, plugin) } } </ins> return v1beta2.PluginSet{Enabled: enabledPlugins} }

Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ {Name: "Plugin1", Weight: pointer.Int32Ptr(2)}, <ins> {Name: "Plugin3", Weight: pointer.Int32Ptr(3)}, </ins> }, }, },

Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ {Name: "Plugin1"}, <ins> {Name: "Plugin2"}, {Name: "Plugin3"}, </ins> }, }, },

Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ {Name: "Plugin1", Weight: pointer.Int32Ptr(2)}, <ins> {Name: "Plugin2"}, {Name: "Plugin3", Weight: pointer.Int32Ptr(3)}, </ins> }, }, },

Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, <ins> {Name: "Plugin1", Weight: pointer.Int32Ptr(1)}, </ins> }, }, },

expectedPlugins: &v1beta2.Plugins{ Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ <ins> {Name: "Plugin1", Weight: pointer.Int32Ptr(1)}, {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, {Name: "Plugin3"}, }, }, }, }, { name: "RepeatedCustomPlugin", customPlugins: &v1beta2.Plugins{ Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ </ins> {Name: "Plugin1"}, {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, {Name: "Plugin3"}, <ins> {Name: "Plugin2", Weight: pointer.Int32Ptr(4)}, }, }, }, defaultPlugins: &v1beta2.Plugins{ Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ {Name: "Plugin1"}, {Name: "Plugin2"}, {Name: "Plugin3"}, }, }, }, expectedPlugins: &v1beta2.Plugins{ Filter: v1beta2.PluginSet{ Enabled: []v1beta2.Plugin{ {Name: "Plugin1"}, {Name: "Plugin2", Weight: pointer.Int32Ptr(4)}, {Name: "Plugin3"}, {Name: "Plugin2", Weight: pointer.Int32Ptr(2)}, </ins> }, }, },