Distinguish unschedulable with unresolvable in scheduler

Before, in RunPostFilterPlugins, we didn't distinguish between unschedulable and unresolvable
because we only have one postFilterPlugin by default, now, we have at least two, we should
make sure that once a postFilterPlugin returns unresolvable, we'll return directly

Signed-off-by: Kante Yin <kerthcet@gmail.com>
This commit is contained in:
Kante Yin
2023-01-05 16:59:19 +08:00
parent 41b442534d
commit 2c205e291d
5 changed files with 120 additions and 104 deletions

View File

@@ -96,10 +96,12 @@ type FilterPlugin struct {
}
type PostFilterPlugin struct {
name string
fh framework.Handle
numPostFilterCalled int
failPostFilter bool
rejectPostFilter bool
breakPostFilter bool
}
type ReservePlugin struct {
@@ -463,7 +465,7 @@ func (pp *PreFilterPlugin) reset() {
// Name returns name of the plugin.
func (pp *PostFilterPlugin) Name() string {
return postfilterPluginName
return pp.name
}
func (pp *PostFilterPlugin) PostFilter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, _ framework.NodeToStatusMap) (*framework.PostFilterResult, *framework.Status) {
@@ -486,8 +488,12 @@ func (pp *PostFilterPlugin) PostFilter(ctx context.Context, state *framework.Cyc
return nil, framework.NewStatus(framework.Error, fmt.Sprintf("injecting failure for pod %v", pod.Name))
}
if pp.rejectPostFilter {
return nil, framework.NewStatus(framework.Unschedulable, fmt.Sprintf("reject pod %v", pod.Name))
return nil, framework.NewStatus(framework.Unschedulable, fmt.Sprintf("injecting unschedulable for pod %v", pod.Name))
}
if pp.breakPostFilter {
return nil, framework.NewStatus(framework.UnschedulableAndUnresolvable, fmt.Sprintf("injecting unresolvable for pod %v", pod.Name))
}
return nil, framework.NewStatus(framework.Success, fmt.Sprintf("make room for pod %v to be schedulable", pod.Name))
}
@@ -628,7 +634,7 @@ func TestPreFilterPlugin(t *testing.T) {
}
}
// TestPostFilterPlugin tests invocation of postfilter plugins.
// TestPostFilterPlugin tests invocation of postFilter plugins.
func TestPostFilterPlugin(t *testing.T) {
var numNodes int32 = 1
tests := []struct {
@@ -637,6 +643,9 @@ func TestPostFilterPlugin(t *testing.T) {
rejectFilter bool
failScore bool
rejectPostFilter bool
rejectPostFilter2 bool
breakPostFilter bool
breakPostFilter2 bool
expectFilterNumCalled int32
expectScoreNumCalled int32
expectPostFilterNumCalled int
@@ -669,7 +678,7 @@ func TestPostFilterPlugin(t *testing.T) {
rejectPostFilter: true,
expectFilterNumCalled: numNodes * 2,
expectScoreNumCalled: 1,
expectPostFilterNumCalled: 1,
expectPostFilterNumCalled: 2,
},
{
name: "Score failed and PostFilter failed",
@@ -679,25 +688,53 @@ func TestPostFilterPlugin(t *testing.T) {
rejectPostFilter: true,
expectFilterNumCalled: numNodes * 2,
expectScoreNumCalled: 1,
expectPostFilterNumCalled: 2,
},
{
name: "Filter failed and first PostFilter broken",
numNodes: numNodes,
rejectFilter: true,
breakPostFilter: true,
expectFilterNumCalled: numNodes * 2,
expectScoreNumCalled: 0,
expectPostFilterNumCalled: 1,
},
{
name: "Filter failed and second PostFilter broken",
numNodes: numNodes,
rejectFilter: true,
rejectPostFilter: true,
rejectPostFilter2: true,
breakPostFilter2: true,
expectFilterNumCalled: numNodes * 2,
expectScoreNumCalled: 0,
expectPostFilterNumCalled: 2,
},
}
var postFilterPluginName2 = postfilterPluginName + "2"
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create a plugin registry for testing. Register a combination of filter and postFilter plugin.
var (
filterPlugin = &FilterPlugin{}
scorePlugin = &ScorePlugin{}
postFilterPlugin = &PostFilterPlugin{}
filterPlugin = &FilterPlugin{}
scorePlugin = &ScorePlugin{}
postFilterPlugin = &PostFilterPlugin{name: postfilterPluginName}
postFilterPlugin2 = &PostFilterPlugin{name: postFilterPluginName2}
)
filterPlugin.rejectFilter = tt.rejectFilter
scorePlugin.failScore = tt.failScore
postFilterPlugin.rejectPostFilter = tt.rejectPostFilter
postFilterPlugin2.rejectPostFilter = tt.rejectPostFilter2
postFilterPlugin.breakPostFilter = tt.breakPostFilter
postFilterPlugin2.breakPostFilter = tt.breakPostFilter2
registry := frameworkruntime.Registry{
filterPluginName: newPlugin(filterPlugin),
scorePluginName: newPlugin(scorePlugin),
postfilterPluginName: newPlugin(postFilterPlugin),
filterPluginName: newPlugin(filterPlugin),
scorePluginName: newPlugin(scorePlugin),
postfilterPluginName: newPlugin(postFilterPlugin),
postFilterPluginName2: newPlugin(postFilterPlugin2),
}
// Setup plugins for testing.
@@ -723,9 +760,10 @@ func TestPostFilterPlugin(t *testing.T) {
PostFilter: configv1.PluginSet{
Enabled: []configv1.Plugin{
{Name: postfilterPluginName},
{Name: postFilterPluginName2},
},
// Need to disable default in-tree PostFilter plugins, as they will
// call RunFilterPlugins and hence impact the "numFilterCalled".
// call RunPostFilterPlugins and hence impact the "numPostFilterCalled".
Disabled: []configv1.Plugin{
{Name: "*"},
},
@@ -760,9 +798,6 @@ func TestPostFilterPlugin(t *testing.T) {
if numScoreCalled := atomic.LoadInt32(&scorePlugin.numScoreCalled); numScoreCalled < tt.expectScoreNumCalled {
t.Errorf("Expected the score plugin to be called at least %v times, but got %v.", tt.expectScoreNumCalled, numScoreCalled)
}
if postFilterPlugin.numPostFilterCalled < tt.expectPostFilterNumCalled {
t.Errorf("Expected the postfilter plugin to be called at least %v times, but got %v.", tt.expectPostFilterNumCalled, postFilterPlugin.numPostFilterCalled)
}
} else {
if err = testutils.WaitForPodToSchedule(testCtx.ClientSet, pod); err != nil {
t.Errorf("Expected the pod to be scheduled. error: %v", err)
@@ -773,9 +808,11 @@ func TestPostFilterPlugin(t *testing.T) {
if numScoreCalled := atomic.LoadInt32(&scorePlugin.numScoreCalled); numScoreCalled != tt.expectScoreNumCalled {
t.Errorf("Expected the score plugin to be called %v times, but got %v.", tt.expectScoreNumCalled, numScoreCalled)
}
if postFilterPlugin.numPostFilterCalled != tt.expectPostFilterNumCalled {
t.Errorf("Expected the postfilter plugin to be called %v times, but got %v.", tt.expectPostFilterNumCalled, postFilterPlugin.numPostFilterCalled)
}
}
numPostFilterCalled := postFilterPlugin.numPostFilterCalled + postFilterPlugin2.numPostFilterCalled
if numPostFilterCalled != tt.expectPostFilterNumCalled {
t.Errorf("Expected the postfilter plugin to be called %v times, but got %v.", tt.expectPostFilterNumCalled, numPostFilterCalled)
}
})
}