feat: implement "post-filter" extension point for scheduling framework

This commit is contained in:
draveness
2019-07-31 11:21:26 +08:00
parent c981c65c90
commit feb64858aa
8 changed files with 285 additions and 32 deletions

View File

@@ -21,7 +21,7 @@ import (
"testing"
"time"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@@ -58,6 +58,11 @@ type ReservePlugin struct {
failReserve bool
}
type PostFilterPlugin struct {
numPostFilterCalled int
failPostFilter bool
}
type PrebindPlugin struct {
numPrebindCalled int
failPrebind bool
@@ -100,6 +105,7 @@ const (
scorePluginName = "score-plugin"
scoreWithNormalizePluginName = "score-with-normalize-plugin"
filterPluginName = "filter-plugin"
postFilterPluginName = "postfilter-plugin"
reservePluginName = "reserve-plugin"
prebindPluginName = "prebind-plugin"
unreservePluginName = "unreserve-plugin"
@@ -113,6 +119,7 @@ var _ = framework.FilterPlugin(&FilterPlugin{})
var _ = framework.ScorePlugin(&ScorePlugin{})
var _ = framework.ScoreWithNormalizePlugin(&ScoreWithNormalizePlugin{})
var _ = framework.ReservePlugin(&ReservePlugin{})
var _ = framework.PostFilterPlugin(&PostFilterPlugin{})
var _ = framework.PrebindPlugin(&PrebindPlugin{})
var _ = framework.BindPlugin(&BindPlugin{})
var _ = framework.PostbindPlugin(&PostbindPlugin{})
@@ -241,6 +248,34 @@ func NewReservePlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framewor
return resPlugin, nil
}
// Name returns name of the plugin.
func (*PostFilterPlugin) Name() string {
return postFilterPluginName
}
var postFilterPlugin = &PostFilterPlugin{}
// PostFilter is a test function.
func (pfp *PostFilterPlugin) PostFilter(_ *framework.PluginContext, pod *v1.Pod, _ []*v1.Node, _ framework.NodeToStatusMap) *framework.Status {
pfp.numPostFilterCalled++
if pfp.failPostFilter {
return framework.NewStatus(framework.Error, fmt.Sprintf("injecting failure for pod %v", pod.Name))
}
return nil
}
// reset used to reset postfilter plugin.
func (pfp *PostFilterPlugin) reset() {
pfp.numPostFilterCalled = 0
pfp.failPostFilter = false
}
// NewPostFilterPlugin is the factory for post-filter plugin.
func NewPostFilterPlugin(_ *runtime.Unknown, _ framework.FrameworkHandle) (framework.Plugin, error) {
return postFilterPlugin, nil
}
var pbdPlugin = &PrebindPlugin{}
// Name returns name of the plugin.
@@ -1447,6 +1482,65 @@ func TestFilterPlugin(t *testing.T) {
}
}
// TestPostFilterPlugin tests invocation of post-filter plugins.
func TestPostFilterPlugin(t *testing.T) {
// Create a plugin registry for testing. Register only a post-filter plugin.
registry := framework.Registry{postFilterPluginName: NewPostFilterPlugin}
// Setup initial post-filter plugin for testing.
pluginsConfig := &schedulerconfig.Plugins{
PostFilter: &schedulerconfig.PluginSet{
Enabled: []schedulerconfig.Plugin{
{
Name: postFilterPluginName,
},
},
},
}
// Set empty plugin config for testing
emptyPluginConfig := []schedulerconfig.PluginConfig{}
// Create the master and the scheduler with the test plugin set.
context := initTestSchedulerWithOptions(t,
initTestMaster(t, "post-filter-plugin", nil),
false, nil, registry, pluginsConfig, emptyPluginConfig, false, time.Second)
defer cleanupTest(t, context)
cs := context.clientSet
// Add a few nodes.
_, err := createNodes(cs, "test-node", nil, 2)
if err != nil {
t.Fatalf("Cannot create nodes: %v", err)
}
for _, fail := range []bool{false, true} {
postFilterPlugin.failPostFilter = fail
// Create a best effort pod.
pod, err := createPausePod(cs,
initPausePod(cs, &pausePodConfig{Name: "test-pod", Namespace: context.ns.Name}))
if err != nil {
t.Errorf("Error while creating a test pod: %v", err)
}
if fail {
if err = waitForPodUnschedulable(cs, pod); err != nil {
t.Errorf("Didn't expect the pod to be scheduled. error: %v", err)
}
} else {
if err = waitForPodToSchedule(cs, pod); err != nil {
t.Errorf("Expected the pod to be scheduled. error: %v", err)
}
}
if postFilterPlugin.numPostFilterCalled == 0 {
t.Errorf("Expected the post-filter plugin to be called.")
}
postFilterPlugin.reset()
cleanupPods(cs, t, []*v1.Pod{pod})
}
}
// TestPreemptWithPermitPlugin tests preempt with permit plugins.
func TestPreemptWithPermitPlugin(t *testing.T) {
// Create a plugin registry for testing. Register only a permit plugin.