Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Total priority overflow check #45122

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions plugin/pkg/scheduler/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ import (
"k8s.io/kubernetes/pkg/api/v1"
)

const (
MaxUint = ^uint(0)
MaxInt = int(MaxUint >> 1)
MaxTotalPriority = MaxInt
MaxPriority = 10
MaxWeight = MaxInt / MaxPriority
)

type Policy struct {
metav1.TypeMeta
// Holds the information to configure the fit predicate functions
Expand Down
4 changes: 2 additions & 2 deletions plugin/pkg/scheduler/api/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func ValidatePolicy(policy schedulerapi.Policy) error {
var validationErrors []error

for _, priority := range policy.Priorities {
if priority.Weight <= 0 {
validationErrors = append(validationErrors, fmt.Errorf("Priority %s should have a positive weight applied to it", priority.Name))
if priority.Weight <= 0 || priority.Weight >= schedulerapi.MaxWeight {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer to priority.Weight > schedulerapi.MaxWeight, it'll align with checking against MaxTotalPriority.

validationErrors = append(validationErrors, fmt.Errorf("Priority %s should have a positive weight applied to it or it has overflown", priority.Name))
}
}

Expand Down
7 changes: 7 additions & 0 deletions plugin/pkg/scheduler/api/validation/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ func TestValidatePriorityWithNegativeWeight(t *testing.T) {
}
}

func TestValidatePriorityWithOverFlowWeight(t *testing.T) {
policy := api.Policy{Priorities: []api.PriorityPolicy{{Name: "WeightPriority", Weight: api.MaxWeight}}}
if ValidatePolicy(policy) == nil {
t.Errorf("Expected error about priority weight not being overflown.")
}
}

func TestValidateExtenderWithNonNegativeWeight(t *testing.T) {
extenderPolicy := api.Policy{ExtenderConfigs: []api.ExtenderConfig{{URLPrefix: "http://127.0.0.1:8081/extender", FilterVerb: "filter", Weight: 2}}}
errs := ValidatePolicy(extenderPolicy)
Expand Down
19 changes: 17 additions & 2 deletions plugin/pkg/scheduler/factory/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ import (
"strings"
"sync"

"github.com/golang/glog"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates"
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities"
schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"

"github.com/golang/glog"
)

// PluginFactoryArgs are passed to all plugin factory functions.
Expand Down Expand Up @@ -356,9 +355,25 @@ func getPriorityFunctionConfigs(names sets.String, args PluginFactoryArgs) ([]al
})
}
}
if err := validateSelectedConfigs(configs); err != nil {
return nil, err
}
return configs, nil
}

// validateSelectedConfigs validates the config weights to avoid the overflow.
func validateSelectedConfigs(configs []algorithm.PriorityConfig) error {
var totalPriority int
for _, config := range configs {
// Checks totalPriority against MaxTotalPriority to avoid overflow
if config.Weight*schedulerapi.MaxPriority > schedulerapi.MaxTotalPriority-totalPriority {
return fmt.Errorf("Total priority of priority functions has overflown")
}
totalPriority += config.Weight * schedulerapi.MaxPriority
}
return nil
}

var validName = regexp.MustCompile("^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])$")

func validateAlgorithmNameOrDie(name string) {
Expand Down
42 changes: 41 additions & 1 deletion plugin/pkg/scheduler/factory/plugins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ limitations under the License.

package factory

import "testing"
import (
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
"k8s.io/kubernetes/plugin/pkg/scheduler/api"
"testing"
)

func TestAlgorithmNameValidation(t *testing.T) {
algorithmNamesShouldValidate := []string{
Expand All @@ -39,3 +43,39 @@ func TestAlgorithmNameValidation(t *testing.T) {
}
}
}

func TestValidatePriorityConfigOverFlow(t *testing.T) {
tests := []struct {
description string
configs []algorithm.PriorityConfig
expected bool
}{
{
description: "one of the weights is MaxInt",
configs: []algorithm.PriorityConfig{{Weight: api.MaxInt}, {Weight: 5}},
expected: true,
},
{
description: "after multiplication with MaxPriority the weight is larger than MaxWeight",
configs: []algorithm.PriorityConfig{{Weight: api.MaxInt/api.MaxPriority + api.MaxPriority}, {Weight: 5}},
expected: true,
},
{
description: "normal weights",
configs: []algorithm.PriorityConfig{{Weight: 10000}, {Weight: 5}},
expected: false,
},
}
for _, test := range tests {
err := validateSelectedConfigs(test.configs)
if test.expected {
if err == nil {
t.Errorf("Expected Overflow for %s", test.description)
}
} else {
if err != nil {
t.Errorf("Did not expect an overflow for %s", test.description)
}
}
}
}