Skip to content

Commit 4d175be

Browse files
committed
add validate for NodeResourcesAllocatable and Coscheduling plugin
Signed-off-by: googs1025 <[email protected]>
1 parent 10d0e80 commit 4d175be

File tree

5 files changed

+203
-16
lines changed

5 files changed

+203
-16
lines changed

apis/config/validation/validation_pluginargs.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ limitations under the License.
1717
package validation
1818

1919
import (
20+
"fmt"
21+
2022
"k8s.io/apimachinery/pkg/util/sets"
2123
"k8s.io/apimachinery/pkg/util/validation/field"
24+
schedconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
2225

2326
"sigs.k8s.io/scheduler-plugins/apis/config"
2427
)
@@ -46,3 +49,56 @@ func validateScoringStrategyType(scoringStrategy config.ScoringStrategyType, pat
4649
}
4750
return nil
4851
}
52+
53+
func validateResources(resources []schedconfig.ResourceSpec, p *field.Path) field.ErrorList {
54+
var allErrs field.ErrorList
55+
for i, resource := range resources {
56+
if resource.Weight <= 0 {
57+
msg := fmt.Sprintf("resource weight of %v should be a positive value, got :%v", resource.Name, resource.Weight)
58+
allErrs = append(allErrs, field.Invalid(p.Index(i).Child("weight"), resource.Weight, msg))
59+
}
60+
}
61+
return allErrs
62+
}
63+
64+
var supportNodeResourcesMode = sets.NewString(
65+
string(config.Least),
66+
string(config.Most),
67+
)
68+
69+
func validateNodeResourcesModeType(mode config.ModeType, path *field.Path) *field.Error {
70+
if !supportNodeResourcesMode.Has(string(mode)) {
71+
return field.Invalid(path, mode, "invalid support ModeType")
72+
}
73+
return nil
74+
}
75+
76+
func ValidateNodeResourcesAllocatableArgs(args *config.NodeResourcesAllocatableArgs, path *field.Path) error {
77+
var allErrs field.ErrorList
78+
if args.Resources != nil {
79+
allErrs = append(allErrs, validateResources(args.Resources, path.Child("resources"))...)
80+
}
81+
if err := validateNodeResourcesModeType(args.Mode, path.Child("mode")); err != nil {
82+
allErrs = append(allErrs, err)
83+
}
84+
if len(allErrs) == 0 {
85+
return nil
86+
}
87+
return allErrs.ToAggregate()
88+
}
89+
90+
func ValidateCoschedulingArgs(args *config.CoschedulingArgs, _ *field.Path) error {
91+
var allErrs field.ErrorList
92+
if args.PermitWaitingTimeSeconds < 0 {
93+
allErrs = append(allErrs, field.Invalid(field.NewPath("permitWaitingTimeSeconds"),
94+
args.PermitWaitingTimeSeconds, "must be greater than 0"))
95+
}
96+
if args.PodGroupBackoffSeconds < 0 {
97+
allErrs = append(allErrs, field.Invalid(field.NewPath("podGroupBackoffSeconds"),
98+
args.PodGroupBackoffSeconds, "must be greater than 0"))
99+
}
100+
if len(allErrs) == 0 {
101+
return nil
102+
}
103+
return allErrs.ToAggregate()
104+
}

apis/config/validation/validation_plugingargs_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import (
2121
"strings"
2222
"testing"
2323

24+
gocmp "github.com/google/go-cmp/cmp"
25+
26+
schedconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
27+
2428
"sigs.k8s.io/scheduler-plugins/apis/config"
2529
)
2630

@@ -67,3 +71,125 @@ func TestValidateNodeResourceTopologyMatchArgs(t *testing.T) {
6771
})
6872
}
6973
}
74+
75+
func TestValidateCoschedulingArgs(t *testing.T) {
76+
testCases := []struct {
77+
args *config.CoschedulingArgs
78+
expectedErr error
79+
description string
80+
}{
81+
{
82+
description: "correct config with valid values",
83+
args: &config.CoschedulingArgs{
84+
PermitWaitingTimeSeconds: 30,
85+
PodGroupBackoffSeconds: 60,
86+
},
87+
expectedErr: nil,
88+
},
89+
{
90+
description: "invalid PermitWaitingTimeSeconds (negative value)",
91+
args: &config.CoschedulingArgs{
92+
PermitWaitingTimeSeconds: -10,
93+
PodGroupBackoffSeconds: 60,
94+
},
95+
expectedErr: fmt.Errorf("permitWaitingTimeSeconds: Invalid value: %v: must be greater than 0", -10),
96+
},
97+
{
98+
description: "invalid PodGroupBackoffSeconds (negative value)",
99+
args: &config.CoschedulingArgs{
100+
PermitWaitingTimeSeconds: 30,
101+
PodGroupBackoffSeconds: -20,
102+
},
103+
expectedErr: fmt.Errorf("podGroupBackoffSeconds: Invalid value: %v: must be greater than 0", -20),
104+
},
105+
{
106+
description: "both PermitWaitingTimeSeconds and PodGroupBackoffSeconds are negative",
107+
args: &config.CoschedulingArgs{
108+
PermitWaitingTimeSeconds: -30,
109+
PodGroupBackoffSeconds: -20,
110+
},
111+
expectedErr: fmt.Errorf(
112+
"[permitWaitingTimeSeconds: Invalid value: %v: must be greater than 0, podGroupBackoffSeconds: Invalid value: %v: must be greater than 0]",
113+
-30, -20,
114+
),
115+
},
116+
}
117+
118+
for _, testCase := range testCases {
119+
t.Run(testCase.description, func(t *testing.T) {
120+
err := ValidateCoschedulingArgs(testCase.args, nil)
121+
if testCase.expectedErr != nil {
122+
if err == nil {
123+
t.Fatalf("expected err to equal %v not nil", testCase.expectedErr)
124+
}
125+
if diff := gocmp.Diff(err.Error(), testCase.expectedErr.Error()); diff != "" {
126+
t.Fatalf("expected err to contain %s in error message: %s", testCase.expectedErr.Error(), err.Error())
127+
128+
}
129+
}
130+
if testCase.expectedErr == nil && err != nil {
131+
t.Fatalf("unexpected error: %v", err)
132+
}
133+
})
134+
}
135+
}
136+
137+
func TestValidateNodeResourcesAllocatableArgs(t *testing.T) {
138+
testCases := []struct {
139+
args *config.NodeResourcesAllocatableArgs
140+
expectedErr error
141+
description string
142+
}{
143+
{
144+
description: "correct config with valid resources and mode",
145+
args: &config.NodeResourcesAllocatableArgs{
146+
Resources: []schedconfig.ResourceSpec{
147+
{Name: "cpu", Weight: 1},
148+
{Name: "memory", Weight: 2},
149+
},
150+
Mode: config.Least,
151+
},
152+
expectedErr: nil,
153+
},
154+
{
155+
description: "invalid resource weight (non-positive value)",
156+
args: &config.NodeResourcesAllocatableArgs{
157+
Resources: []schedconfig.ResourceSpec{
158+
{Name: "cpu", Weight: 0},
159+
{Name: "memory", Weight: -1},
160+
},
161+
Mode: config.Least,
162+
},
163+
expectedErr: fmt.Errorf("[resources[0].weight: Invalid value: %v: resource weight of cpu should be a positive value, got :%v, resources[1].weight: Invalid value: %v: resource weight of memory should be a positive value, got :%v]", 0, 0, -1, -1),
164+
},
165+
{
166+
description: "invalid ModeType",
167+
args: &config.NodeResourcesAllocatableArgs{
168+
Resources: []schedconfig.ResourceSpec{
169+
{Name: "cpu", Weight: 1},
170+
{Name: "memory", Weight: 2},
171+
},
172+
Mode: "not existent",
173+
},
174+
expectedErr: fmt.Errorf("mode: Invalid value: \"%s\": invalid support ModeType", "not existent"),
175+
},
176+
}
177+
178+
for _, testCase := range testCases {
179+
t.Run(testCase.description, func(t *testing.T) {
180+
err := ValidateNodeResourcesAllocatableArgs(testCase.args, nil)
181+
if testCase.expectedErr != nil {
182+
if err == nil {
183+
t.Fatalf("expected err to equal %v not nil", testCase.expectedErr)
184+
}
185+
if diff := gocmp.Diff(err.Error(), testCase.expectedErr.Error()); diff != "" {
186+
fmt.Println(diff)
187+
t.Fatalf("expected err to contain %s in error message: %s", testCase.expectedErr.Error(), err.Error())
188+
}
189+
}
190+
if testCase.expectedErr == nil && err != nil {
191+
t.Fatalf("unexpected error: %v", err)
192+
}
193+
})
194+
}
195+
}

pkg/coscheduling/coscheduling.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"sigs.k8s.io/controller-runtime/pkg/client"
3333

3434
"sigs.k8s.io/scheduler-plugins/apis/config"
35+
"sigs.k8s.io/scheduler-plugins/apis/config/validation"
3536
"sigs.k8s.io/scheduler-plugins/apis/scheduling"
3637
"sigs.k8s.io/scheduler-plugins/apis/scheduling/v1alpha1"
3738
"sigs.k8s.io/scheduler-plugins/pkg/coscheduling/core"
@@ -71,6 +72,10 @@ func New(ctx context.Context, obj runtime.Object, handle framework.Handle) (fram
7172
return nil, fmt.Errorf("want args to be of type CoschedulingArgs, got %T", obj)
7273
}
7374

75+
if err := validation.ValidateCoschedulingArgs(args, nil); err != nil {
76+
return nil, err
77+
}
78+
7479
scheme := runtime.NewScheme()
7580
_ = clientscheme.AddToScheme(scheme)
7681
_ = v1.AddToScheme(scheme)

pkg/noderesources/allocatable.go

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@ package noderesources
1919
import (
2020
"context"
2121
"fmt"
22-
"math"
23-
2422
v1 "k8s.io/api/core/v1"
2523
"k8s.io/apimachinery/pkg/runtime"
2624
"k8s.io/klog/v2"
2725
schedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
2826
"k8s.io/kubernetes/pkg/scheduler/framework"
29-
27+
"math"
3028
"sigs.k8s.io/scheduler-plugins/apis/config"
29+
"sigs.k8s.io/scheduler-plugins/apis/config/validation"
3130
)
3231

3332
// Allocatable is a score plugin that favors nodes based on their allocatable
@@ -82,7 +81,7 @@ func (alloc *Allocatable) ScoreExtensions() framework.ScoreExtensions {
8281
func NewAllocatable(ctx context.Context, allocArgs runtime.Object, h framework.Handle) (framework.Plugin, error) {
8382
logger := klog.FromContext(ctx).WithValues("plugin", AllocatableName)
8483
// Start with default values.
85-
mode := config.Least
84+
var mode config.ModeType
8685
resToWeightMap := defaultResourcesToWeightMap
8786

8887
// Update values from args, if specified.
@@ -91,23 +90,19 @@ func NewAllocatable(ctx context.Context, allocArgs runtime.Object, h framework.H
9190
if !ok {
9291
return nil, fmt.Errorf("want args to be of type NodeResourcesAllocatableArgs, got %T", allocArgs)
9392
}
94-
if args.Mode != "" {
95-
mode = args.Mode
96-
if mode != config.Least && mode != config.Most {
97-
return nil, fmt.Errorf("invalid mode, got %s", mode)
98-
}
93+
if args.Mode == "" {
94+
args.Mode = config.Least
95+
}
96+
if err := validation.ValidateNodeResourcesAllocatableArgs(args, nil); err != nil {
97+
return nil, err
9998
}
100-
10199
if len(args.Resources) > 0 {
102-
if err := validateResources(args.Resources); err != nil {
103-
return nil, err
104-
}
105-
106100
resToWeightMap = make(resourceToWeightMap)
107101
for _, resource := range args.Resources {
108102
resToWeightMap[v1.ResourceName(resource.Name)] = resource.Weight
109103
}
110104
}
105+
mode = args.Mode
111106
}
112107

113108
return &Allocatable{

pkg/noderesources/allocatable_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package noderesources
1919
import (
2020
"context"
2121
"reflect"
22+
"sort"
2223
"testing"
2324

2425
v1 "k8s.io/api/core/v1"
@@ -221,15 +222,15 @@ func TestNodeResourcesAllocatable(t *testing.T) {
221222
pod: cpuAndMemory,
222223
nodeInfos: []*framework.NodeInfo{makeNodeInfo("machine", 4000, 10000)},
223224
args: config.NodeResourcesAllocatableArgs{Resources: []schedulerconfig.ResourceSpec{{Name: "memory", Weight: -1}, {Name: "cpu", Weight: 1}}},
224-
wantErr: "resource Weight of memory should be a positive value, got -1",
225+
wantErr: "resources[0].weight: Invalid value: -1: resource weight of memory should be a positive value, got :-1",
225226
name: "resource with negative weight",
226227
},
227228
{
228229
// resource with zero weight is not allowed
229230
pod: cpuAndMemory,
230231
nodeInfos: []*framework.NodeInfo{makeNodeInfo("machine", 4000, 10000)},
231232
args: config.NodeResourcesAllocatableArgs{Resources: []schedulerconfig.ResourceSpec{{Name: "memory", Weight: 1}, {Name: "cpu", Weight: 0}}},
232-
wantErr: "resource Weight of cpu should be a positive value, got 0",
233+
wantErr: "resources[1].weight: Invalid value: 0: resource weight of cpu should be a positive value, got :0",
233234
name: "resource with zero weight",
234235
},
235236
}
@@ -293,9 +294,13 @@ func TestNodeResourcesAllocatable(t *testing.T) {
293294
if !status.IsSuccess() {
294295
t.Errorf("unexpected error: %v", status)
295296
}
297+
sort.Slice(gotList, func(i, j int) bool {
298+
return gotList[i].Name < gotList[j].Name
299+
})
296300

297301
for i := range gotList {
298302
if !reflect.DeepEqual(test.expectedList[i].Score, gotList[i].Score) {
303+
t.Errorf("expected %#v, got %#v", test.expectedList[i].Name, gotList[i].Name)
299304
t.Errorf("expected %#v, got %#v", test.expectedList[i].Score, gotList[i].Score)
300305
}
301306
}

0 commit comments

Comments
 (0)