Commit 301be4ee authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #29272 from mksalawa/pending

Automatic merge from submit-queue Modify predicate() interface to return all failed predicates As stated in the comments below, this is the first step of showing the user all predicates that failed for a given node when scheduling of a given pod failed on every node. ref #20064 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.kubernetes.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.kubernetes.io/reviews/kubernetes/kubernetes/29272) <!-- Reviewable:end -->
parents da53a247 2749ec75
...@@ -693,7 +693,7 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *api.Node, ds *exte ...@@ -693,7 +693,7 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *api.Node, ds *exte
if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed { if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed {
continue continue
} }
// ignore pods that belong to the daemonset when taking into account wheter // ignore pods that belong to the daemonset when taking into account whether
// a daemonset should bind to a node. // a daemonset should bind to a node.
if pds := dsc.getPodDaemonSet(pod); pds != nil && ds.Name == pds.Name { if pds := dsc.getPodDaemonSet(pod); pds != nil && ds.Name == pds.Name {
continue continue
...@@ -703,18 +703,12 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *api.Node, ds *exte ...@@ -703,18 +703,12 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *api.Node, ds *exte
nodeInfo := schedulercache.NewNodeInfo(pods...) nodeInfo := schedulercache.NewNodeInfo(pods...)
nodeInfo.SetNode(node) nodeInfo.SetNode(node)
fit, err := predicates.GeneralPredicates(newPod, nil, nodeInfo) fit, reasons, err := predicates.GeneralPredicates(newPod, nil, nodeInfo)
if err != nil { if err != nil {
if re, ok := err.(*predicates.PredicateFailureError); ok { glog.Warningf("GeneralPredicates failed on pod %s due to unexpected error: %v", newPod.Name, err)
message := re.Error() }
glog.V(2).Infof("Predicate failed on Pod: %s, for reason: %v", newPod.Name, message) for _, r := range reasons {
} glog.V(2).Infof("GeneralPredicates failed on pod %s for reason: %v", newPod.Name, r.GetReason())
if re, ok := err.(*predicates.InsufficientResourceError); ok {
message := re.Error()
glog.V(2).Infof("Predicate failed on Pod: %s, for reason: %v", newPod.Name, message)
}
message := fmt.Sprintf("GeneralPredicates failed due to %v.", err)
glog.Warningf("Predicate failed on Pod %s - %s", newPod.Name, message)
} }
return fit return fit
} }
......
...@@ -2059,23 +2059,40 @@ func (kl *Kubelet) canAdmitPod(pods []*api.Pod, pod *api.Pod) (bool, string, str ...@@ -2059,23 +2059,40 @@ func (kl *Kubelet) canAdmitPod(pods []*api.Pod, pod *api.Pod) (bool, string, str
} }
nodeInfo := schedulercache.NewNodeInfo(pods...) nodeInfo := schedulercache.NewNodeInfo(pods...)
nodeInfo.SetNode(node) nodeInfo.SetNode(node)
fit, err := predicates.GeneralPredicates(pod, nil, nodeInfo) fit, reasons, err := predicates.GeneralPredicates(pod, nil, nodeInfo)
if err != nil {
message := fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", err)
glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message)
return fit, "UnexpectedError", message
}
if !fit { if !fit {
if re, ok := err.(*predicates.PredicateFailureError); ok { var reason string
reason := re.PredicateName var message string
message := re.Error() if len(reasons) == 0 {
message = fmt.Sprint("GeneralPredicates failed due to unknown reason, which is unexpected.")
glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message)
return fit, "UnknownReason", message
}
// If there are failed predicates, we only return the first one as a reason.
r := reasons[0]
switch re := r.(type) {
case *predicates.PredicateFailureError:
reason = re.PredicateName
message = re.Error()
glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message)
return fit, reason, message case *predicates.InsufficientResourceError:
} reason = fmt.Sprintf("OutOf%s", re.ResourceName)
if re, ok := err.(*predicates.InsufficientResourceError); ok {
reason := fmt.Sprintf("OutOf%s", re.ResourceName)
message := re.Error() message := re.Error()
glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message) glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message)
return fit, reason, message case *predicates.FailureReason:
reason = re.GetReason()
message = fmt.Sprintf("Failure: %s", re.GetReason())
glog.V(2).Infof("Predicate failed on Pod: %v, for reason: %v", format.Pod(pod), message)
default:
reason = "UnexpectedPredicateFailureType"
message := fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", r)
glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message)
} }
reason := "UnexpectedPredicateFailureType"
message := fmt.Sprintf("GeneralPredicates failed due to %v, which is unexpected.", err)
glog.Warningf("Failed to admit pod %v - %s", format.Pod(pod), message)
return fit, reason, message return fit, reason, message
} }
// TODO: When disk space scheduling is implemented (#11976), remove the out-of-disk check here and // TODO: When disk space scheduling is implemented (#11976), remove the out-of-disk check here and
......
...@@ -16,13 +16,9 @@ limitations under the License. ...@@ -16,13 +16,9 @@ limitations under the License.
package predicates package predicates
import "fmt" import (
"fmt"
const ( "k8s.io/kubernetes/pkg/api"
podCountResourceName string = "PodCount"
cpuResourceName string = "CPU"
memoryResourceName string = "Memory"
nvidiaGpuResourceName string = "NvidiaGpu"
) )
var ( var (
...@@ -49,13 +45,13 @@ var ( ...@@ -49,13 +45,13 @@ var (
// hit and caused the unfitting failure. // hit and caused the unfitting failure.
type InsufficientResourceError struct { type InsufficientResourceError struct {
// resourceName is the name of the resource that is insufficient // resourceName is the name of the resource that is insufficient
ResourceName string ResourceName api.ResourceName
requested int64 requested int64
used int64 used int64
capacity int64 capacity int64
} }
func newInsufficientResourceError(resourceName string, requested, used, capacity int64) *InsufficientResourceError { func NewInsufficientResourceError(resourceName api.ResourceName, requested, used, capacity int64) *InsufficientResourceError {
return &InsufficientResourceError{ return &InsufficientResourceError{
ResourceName: resourceName, ResourceName: resourceName,
requested: requested, requested: requested,
...@@ -69,14 +65,34 @@ func (e *InsufficientResourceError) Error() string { ...@@ -69,14 +65,34 @@ func (e *InsufficientResourceError) Error() string {
e.ResourceName, e.requested, e.used, e.capacity) e.ResourceName, e.requested, e.used, e.capacity)
} }
func (e *InsufficientResourceError) GetReason() string {
return fmt.Sprintf("Insufficient %v", e.ResourceName)
}
type PredicateFailureError struct { type PredicateFailureError struct {
PredicateName string PredicateName string
} }
func newPredicateFailureError(predicateName string) *PredicateFailureError { func newPredicateFailureError(predicateName string) *PredicateFailureError {
return &PredicateFailureError{predicateName} return &PredicateFailureError{PredicateName: predicateName}
} }
func (e *PredicateFailureError) Error() string { func (e *PredicateFailureError) Error() string {
return fmt.Sprintf("Predicate %s failed", e.PredicateName) return fmt.Sprintf("Predicate %s failed", e.PredicateName)
} }
func (e *PredicateFailureError) GetReason() string {
return e.PredicateName
}
type FailureReason struct {
reason string
}
func NewFailureReason(msg string) *FailureReason {
return &FailureReason{reason: msg}
}
func (e *FailureReason) GetReason() string {
return e.reason
}
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
// FitPredicate is a function that indicates if a pod fits into an existing node. // FitPredicate is a function that indicates if a pod fits into an existing node.
// The failure information is given by the error. // The failure information is given by the error.
type FitPredicate func(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) type FitPredicate func(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []PredicateFailureReason, error)
type PriorityFunction func(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*api.Node) (schedulerapi.HostPriorityList, error) type PriorityFunction func(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*api.Node) (schedulerapi.HostPriorityList, error)
...@@ -32,3 +32,7 @@ type PriorityConfig struct { ...@@ -32,3 +32,7 @@ type PriorityConfig struct {
Function PriorityFunction Function PriorityFunction
Weight int Weight int
} }
type PredicateFailureReason interface {
GetReason() string
}
...@@ -32,6 +32,7 @@ import ( ...@@ -32,6 +32,7 @@ import (
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/types"
utiltesting "k8s.io/kubernetes/pkg/util/testing" utiltesting "k8s.io/kubernetes/pkg/util/testing"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api" schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
latestschedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest" latestschedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest"
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache" "k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
...@@ -115,12 +116,12 @@ func TestCreateFromEmptyConfig(t *testing.T) { ...@@ -115,12 +116,12 @@ func TestCreateFromEmptyConfig(t *testing.T) {
factory.CreateFromConfig(policy) factory.CreateFromConfig(policy)
} }
func PredicateOne(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) { func PredicateOne(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
return true, nil return true, nil, nil
} }
func PredicateTwo(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) { func PredicateTwo(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
return true, nil return true, nil, nil
} }
func PriorityOne(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*api.Node) (schedulerapi.HostPriorityList, error) { func PriorityOne(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*api.Node) (schedulerapi.HostPriorityList, error) {
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"sort" "sort"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
...@@ -35,7 +36,7 @@ import ( ...@@ -35,7 +36,7 @@ import (
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache" "k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
) )
type FailedPredicateMap map[string]string type FailedPredicateMap map[string][]algorithm.PredicateFailureReason
type FitError struct { type FitError struct {
Pod *api.Pod Pod *api.Pod
...@@ -48,9 +49,13 @@ var ErrNoNodesAvailable = fmt.Errorf("no nodes available to schedule pods") ...@@ -48,9 +49,13 @@ var ErrNoNodesAvailable = fmt.Errorf("no nodes available to schedule pods")
func (f *FitError) Error() string { func (f *FitError) Error() string {
var buf bytes.Buffer var buf bytes.Buffer
buf.WriteString(fmt.Sprintf("pod (%s) failed to fit in any node\n", f.Pod.Name)) buf.WriteString(fmt.Sprintf("pod (%s) failed to fit in any node\n", f.Pod.Name))
for node, predicate := range f.FailedPredicates { for node, predicates := range f.FailedPredicates {
reason := fmt.Sprintf("fit failure on node (%s): %s\n", node, predicate) reasons := make([]string, 0)
buf.WriteString(reason) for _, pred := range predicates {
reasons = append(reasons, pred.GetReason())
}
reasonMsg := fmt.Sprintf("fit failure on node (%s): %s\n", node, strings.Join(reasons, ", "))
buf.WriteString(reasonMsg)
} }
return buf.String() return buf.String()
} }
...@@ -159,7 +164,7 @@ func findNodesThatFit( ...@@ -159,7 +164,7 @@ func findNodesThatFit(
var filteredLen int32 var filteredLen int32
checkNode := func(i int) { checkNode := func(i int) {
nodeName := nodes[i].Name nodeName := nodes[i].Name
fits, failedPredicate, err := podFitsOnNode(pod, meta, nodeNameToInfo[nodeName], predicateFuncs) fits, failedPredicates, err := podFitsOnNode(pod, meta, nodeNameToInfo[nodeName], predicateFuncs)
if err != nil { if err != nil {
predicateResultLock.Lock() predicateResultLock.Lock()
errs = append(errs, err) errs = append(errs, err)
...@@ -170,7 +175,7 @@ func findNodesThatFit( ...@@ -170,7 +175,7 @@ func findNodesThatFit(
filtered[atomic.AddInt32(&filteredLen, 1)-1] = nodes[i] filtered[atomic.AddInt32(&filteredLen, 1)-1] = nodes[i]
} else { } else {
predicateResultLock.Lock() predicateResultLock.Lock()
failedPredicateMap[nodeName] = failedPredicate failedPredicateMap[nodeName] = failedPredicates
predicateResultLock.Unlock() predicateResultLock.Unlock()
} }
} }
...@@ -189,7 +194,10 @@ func findNodesThatFit( ...@@ -189,7 +194,10 @@ func findNodesThatFit(
} }
for failedNodeName, failedMsg := range failedMap { for failedNodeName, failedMsg := range failedMap {
failedPredicateMap[failedNodeName] = failedMsg if _, found := failedPredicateMap[failedNodeName]; !found {
failedPredicateMap[failedNodeName] = []algorithm.PredicateFailureReason{}
}
failedPredicateMap[failedNodeName] = append(failedPredicateMap[failedNodeName], predicates.NewFailureReason(failedMsg))
} }
filtered = filteredList filtered = filteredList
if len(filtered) == 0 { if len(filtered) == 0 {
...@@ -201,38 +209,19 @@ func findNodesThatFit( ...@@ -201,38 +209,19 @@ func findNodesThatFit(
} }
// Checks whether node with a given name and NodeInfo satisfies all predicateFuncs. // Checks whether node with a given name and NodeInfo satisfies all predicateFuncs.
func podFitsOnNode(pod *api.Pod, meta interface{}, info *schedulercache.NodeInfo, predicateFuncs map[string]algorithm.FitPredicate) (bool, string, error) { func podFitsOnNode(pod *api.Pod, meta interface{}, info *schedulercache.NodeInfo, predicateFuncs map[string]algorithm.FitPredicate) (bool, []algorithm.PredicateFailureReason, error) {
var failedPredicates []algorithm.PredicateFailureReason
for _, predicate := range predicateFuncs { for _, predicate := range predicateFuncs {
fit, err := predicate(pod, meta, info) fit, reasons, err := predicate(pod, meta, info)
if err != nil { if err != nil {
switch e := err.(type) { err := fmt.Errorf("SchedulerPredicates failed due to %v, which is unexpected.", err)
case *predicates.InsufficientResourceError: return false, []algorithm.PredicateFailureReason{}, err
if fit {
err := fmt.Errorf("got InsufficientResourceError: %v, but also fit='true' which is unexpected", e)
return false, "", err
}
case *predicates.PredicateFailureError:
if fit {
err := fmt.Errorf("got PredicateFailureError: %v, but also fit='true' which is unexpected", e)
return false, "", err
}
default:
return false, "", err
}
} }
if !fit { if !fit {
if re, ok := err.(*predicates.InsufficientResourceError); ok { failedPredicates = append(failedPredicates, reasons...)
return false, fmt.Sprintf("Insufficient %s", re.ResourceName), nil
}
if re, ok := err.(*predicates.PredicateFailureError); ok {
return false, re.PredicateName, nil
} else {
err := fmt.Errorf("SchedulerPredicates failed due to %v, which is unexpected.", err)
return false, "", err
}
} }
} }
return true, "", nil return len(failedPredicates) == 0, failedPredicates, nil
} }
// Prioritizes the nodes by running the individual priority functions in parallel. // Prioritizes the nodes by running the individual priority functions in parallel.
......
...@@ -33,30 +33,30 @@ import ( ...@@ -33,30 +33,30 @@ import (
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache" "k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
) )
func falsePredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) { func falsePredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
return false, algorithmpredicates.ErrFakePredicate return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil
} }
func truePredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) { func truePredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
return true, nil return true, nil, nil
} }
func matchesPredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) { func matchesPredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
node := nodeInfo.Node() node := nodeInfo.Node()
if node == nil { if node == nil {
return false, fmt.Errorf("node not found") return false, nil, fmt.Errorf("node not found")
} }
if pod.Name == node.Name { if pod.Name == node.Name {
return true, nil return true, nil, nil
} }
return false, algorithmpredicates.ErrFakePredicate return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil
} }
func hasNoPodsPredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, error) { func hasNoPodsPredicate(pod *api.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
if len(nodeInfo.Pods()) == 0 { if len(nodeInfo.Pods()) == 0 {
return true, nil return true, nil, nil
} }
return false, algorithmpredicates.ErrFakePredicate return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil
} }
func numericPriority(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*api.Node) (schedulerapi.HostPriorityList, error) { func numericPriority(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodes []*api.Node) (schedulerapi.HostPriorityList, error) {
...@@ -193,8 +193,8 @@ func TestGenericScheduler(t *testing.T) { ...@@ -193,8 +193,8 @@ func TestGenericScheduler(t *testing.T) {
wErr: &FitError{ wErr: &FitError{
Pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, Pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}},
FailedPredicates: FailedPredicateMap{ FailedPredicates: FailedPredicateMap{
"machine1": algorithmpredicates.ErrFakePredicate.PredicateName, "machine1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate},
"machine2": algorithmpredicates.ErrFakePredicate.PredicateName, "machine2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate},
}}, }},
}, },
{ {
...@@ -251,9 +251,9 @@ func TestGenericScheduler(t *testing.T) { ...@@ -251,9 +251,9 @@ func TestGenericScheduler(t *testing.T) {
wErr: &FitError{ wErr: &FitError{
Pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, Pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}},
FailedPredicates: FailedPredicateMap{ FailedPredicates: FailedPredicateMap{
"3": algorithmpredicates.ErrFakePredicate.PredicateName, "3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate},
"2": algorithmpredicates.ErrFakePredicate.PredicateName, "2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate},
"1": algorithmpredicates.ErrFakePredicate.PredicateName, "1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate},
}, },
}, },
}, },
...@@ -282,8 +282,8 @@ func TestGenericScheduler(t *testing.T) { ...@@ -282,8 +282,8 @@ func TestGenericScheduler(t *testing.T) {
wErr: &FitError{ wErr: &FitError{
Pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, Pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}},
FailedPredicates: FailedPredicateMap{ FailedPredicates: FailedPredicateMap{
"1": algorithmpredicates.ErrFakePredicate.PredicateName, "1": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate},
"2": algorithmpredicates.ErrFakePredicate.PredicateName, "2": []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate},
}, },
}, },
}, },
...@@ -327,12 +327,12 @@ func TestFindFitAllError(t *testing.T) { ...@@ -327,12 +327,12 @@ func TestFindFitAllError(t *testing.T) {
} }
for _, node := range nodes { for _, node := range nodes {
failure, found := predicateMap[node] failures, found := predicateMap[node]
if !found { if !found {
t.Errorf("failed to find node: %s in %v", node, predicateMap) t.Errorf("failed to find node: %s in %v", node, predicateMap)
} }
if failure != "FakePredicateError" { if len(failures) != 1 || failures[0] != algorithmpredicates.ErrFakePredicate {
t.Errorf("unexpected failures: %v", failure) t.Errorf("unexpected failures: %v", failures)
} }
} }
} }
...@@ -351,7 +351,7 @@ func TestFindFitSomeError(t *testing.T) { ...@@ -351,7 +351,7 @@ func TestFindFitSomeError(t *testing.T) {
} }
_, predicateMap, err := findNodesThatFit(pod, nodeNameToInfo, makeNodeList(nodes), predicates, nil) _, predicateMap, err := findNodesThatFit(pod, nodeNameToInfo, makeNodeList(nodes), predicates, nil)
if err != nil && !reflect.DeepEqual(err, algorithmpredicates.ErrFakePredicate) { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
...@@ -363,12 +363,12 @@ func TestFindFitSomeError(t *testing.T) { ...@@ -363,12 +363,12 @@ func TestFindFitSomeError(t *testing.T) {
if node == pod.Name { if node == pod.Name {
continue continue
} }
failure, found := predicateMap[node] failures, found := predicateMap[node]
if !found { if !found {
t.Errorf("failed to find node: %s in %v", node, predicateMap) t.Errorf("failed to find node: %s in %v", node, predicateMap)
} }
if failure != "FakePredicateError" { if len(failures) != 1 || failures[0] != algorithmpredicates.ErrFakePredicate {
t.Errorf("unexpected failures: %v", failure) t.Errorf("unexpected failures: %v", failures)
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment