...

Source file src/k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources/least_allocated_test.go

Documentation: k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package noderesources
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/google/go-cmp/cmp"
    24  	v1 "k8s.io/api/core/v1"
    25  	"k8s.io/apimachinery/pkg/util/validation/field"
    26  	"k8s.io/klog/v2/ktesting"
    27  	"k8s.io/kubernetes/pkg/scheduler/apis/config"
    28  	"k8s.io/kubernetes/pkg/scheduler/framework"
    29  	plfeature "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
    30  	"k8s.io/kubernetes/pkg/scheduler/framework/runtime"
    31  	"k8s.io/kubernetes/pkg/scheduler/internal/cache"
    32  	st "k8s.io/kubernetes/pkg/scheduler/testing"
    33  	tf "k8s.io/kubernetes/pkg/scheduler/testing/framework"
    34  )
    35  
    36  func TestLeastAllocatedScoringStrategy(t *testing.T) {
    37  	tests := []struct {
    38  		name           string
    39  		requestedPod   *v1.Pod
    40  		nodes          []*v1.Node
    41  		existingPods   []*v1.Pod
    42  		expectedScores framework.NodeScoreList
    43  		resources      []config.ResourceSpec
    44  		wantErrs       field.ErrorList
    45  		wantStatusCode framework.Code
    46  	}{
    47  		{
    48  			// Node1 scores (remaining resources) on 0-MaxNodeScore scale
    49  			// CPU Score: ((4000 - 0) * MaxNodeScore) / 4000 = MaxNodeScore
    50  			// Memory Score: ((10000 - 0) * MaxNodeScore) / 10000 = MaxNodeScore
    51  			// Node1 Score: (100 + 100) / 2 = 100
    52  			// Node2 scores (remaining resources) on 0-MaxNodeScore scale
    53  			// CPU Score: ((4000 - 0) * MaxNodeScore) / 4000 = MaxNodeScore
    54  			// Memory Score: ((10000 - 0) * MaxNodeScore) / 10000 = MaxNodeScore
    55  			// Node2 Score: (MaxNodeScore + MaxNodeScore) / 2 = MaxNodeScore
    56  			name:         "nothing scheduled, nothing requested",
    57  			requestedPod: st.MakePod().Obj(),
    58  			nodes: []*v1.Node{
    59  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
    60  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
    61  			},
    62  			existingPods:   nil,
    63  			expectedScores: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
    64  			resources:      defaultResources,
    65  		},
    66  		{
    67  			// Node1 scores on 0-MaxNodeScore scale
    68  			// CPU Score: ((4000 - 3000) * MaxNodeScore) / 4000 = 25
    69  			// Memory Score: ((10000 - 5000) * MaxNodeScore) / 10000 = 50
    70  			// Node1 Score: (25 + 50) / 2 = 37
    71  			// Node2 scores on 0-MaxNodeScore scale
    72  			// CPU Score: ((6000 - 3000) * MaxNodeScore) / 6000 = 50
    73  			// Memory Score: ((10000 - 5000) * MaxNodeScore) / 10000 = 50
    74  			// Node2 Score: (50 + 50) / 2 = 50
    75  			name: "nothing scheduled, resources requested, differently sized nodes",
    76  			requestedPod: st.MakePod().
    77  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
    78  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
    79  				Obj(),
    80  			nodes: []*v1.Node{
    81  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
    82  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000"}).Obj(),
    83  			},
    84  			existingPods:   nil,
    85  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 37}, {Name: "node2", Score: 50}},
    86  			resources:      defaultResources,
    87  		},
    88  		{
    89  			name: "Resources not set, pods scheduled with error",
    90  			requestedPod: st.MakePod().
    91  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
    92  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
    93  				Obj(),
    94  			nodes: []*v1.Node{
    95  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
    96  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000"}).Obj(),
    97  			},
    98  			existingPods:   nil,
    99  			expectedScores: []framework.NodeScore{{Name: "node1", Score: framework.MinNodeScore}, {Name: "node2", Score: framework.MinNodeScore}},
   100  			resources:      nil,
   101  			wantStatusCode: framework.Error,
   102  		},
   103  		{
   104  			// Node1 scores on 0-MaxNodeScore scale
   105  			// CPU Score: ((4000 - 0) * MaxNodeScore) / 4000 = MaxNodeScore
   106  			// Memory Score: ((10000 - 0) * MaxNodeScore) / 10000 = MaxNodeScore
   107  			// Node1 Score: (MaxNodeScore + MaxNodeScore) / 2 = MaxNodeScore
   108  			// Node2 scores on 0-MaxNodeScore scale
   109  			// CPU Score: ((4000 - 0) * MaxNodeScore) / 4000 = MaxNodeScore
   110  			// Memory Score: ((10000 - 0) * MaxNodeScore) / 10000 = MaxNodeScore
   111  			// Node2 Score: (MaxNodeScore + MaxNodeScore) / 2 = MaxNodeScore
   112  			name:         "no resources requested, pods scheduled",
   113  			requestedPod: st.MakePod().Obj(),
   114  			nodes: []*v1.Node{
   115  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   116  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   117  			},
   118  			existingPods: []*v1.Pod{
   119  				st.MakePod().Node("node1").Obj(),
   120  				st.MakePod().Node("node1").Obj(),
   121  				st.MakePod().Node("node2").Obj(),
   122  				st.MakePod().Node("node2").Obj(),
   123  			},
   124  			expectedScores: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
   125  			resources:      defaultResources,
   126  		},
   127  		{
   128  			// Node1 scores on 0-MaxNodeScore scale
   129  			// CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40
   130  			// Memory Score: ((20000 - 0) * MaxNodeScore) / 20000 = MaxNodeScore
   131  			// Node1 Score: (40 + 100) / 2 = 70
   132  			// Node2 scores on 0-MaxNodeScore scale
   133  			// CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40
   134  			// Memory Score: ((20000 - 5000) * MaxNodeScore) / 20000 = 75
   135  			// Node2 Score: (40 + 75) / 2 = 57
   136  			name:         "no resources requested, pods scheduled with resources",
   137  			requestedPod: st.MakePod().Obj(),
   138  			nodes: []*v1.Node{
   139  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "10000", "memory": "20000"}).Obj(),
   140  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "10000", "memory": "20000"}).Obj(),
   141  			},
   142  			existingPods: []*v1.Pod{
   143  				st.MakePod().Node("node1").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   144  				st.MakePod().Node("node1").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   145  				st.MakePod().Node("node2").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   146  				st.MakePod().Node("node2").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "5000"}).Obj(),
   147  			},
   148  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 70}, {Name: "node2", Score: 57}},
   149  			resources:      defaultResources,
   150  		},
   151  		{
   152  			// Node1 scores on 0-MaxNodeScore scale
   153  			// CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40
   154  			// Memory Score: ((20000 - 5000) * MaxNodeScore) / 20000 = 75
   155  			// Node1 Score: (40 + 75) / 2 = 57
   156  			// Node2 scores on 0-MaxNodeScore scale
   157  			// CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40
   158  			// Memory Score: ((20000 - 10000) * MaxNodeScore) / 20000 = 50
   159  			// Node2 Score: (40 + 50) / 2 = 45
   160  			name: "resources requested, pods scheduled with resources",
   161  			requestedPod: st.MakePod().
   162  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
   163  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
   164  				Obj(),
   165  			nodes: []*v1.Node{
   166  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "10000", "memory": "20000"}).Obj(),
   167  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "10000", "memory": "20000"}).Obj(),
   168  			},
   169  			existingPods: []*v1.Pod{
   170  				st.MakePod().Node("node1").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   171  				st.MakePod().Node("node2").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "5000"}).Obj(),
   172  			},
   173  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 57}, {Name: "node2", Score: 45}},
   174  			resources:      defaultResources,
   175  		},
   176  		{
   177  			// Node1 scores on 0-MaxNodeScore scale
   178  			// CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40
   179  			// Memory Score: ((20000 - 5000) * MaxNodeScore) / 20000 = 75
   180  			// Node1 Score: (40 + 75) / 2 = 57
   181  			// Node2 scores on 0-MaxNodeScore scale
   182  			// CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40
   183  			// Memory Score: ((50000 - 10000) * MaxNodeScore) / 50000 = 80
   184  			// Node2 Score: (40 + 80) / 2 = 60
   185  			name: "resources requested, pods scheduled with resources, differently sized nodes",
   186  			requestedPod: st.MakePod().
   187  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
   188  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
   189  				Obj(),
   190  			nodes: []*v1.Node{
   191  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "10000", "memory": "20000"}).Obj(),
   192  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "10000", "memory": "50000"}).Obj(),
   193  			},
   194  			existingPods: []*v1.Pod{
   195  				st.MakePod().Node("node1").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   196  				st.MakePod().Node("node2").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "5000"}).Obj(),
   197  			},
   198  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 57}, {Name: "node2", Score: 60}},
   199  			resources:      defaultResources,
   200  		},
   201  		{
   202  			// Node1 scores on 0-MaxNodeScore scale
   203  			// CPU Score: ((4000 - 6000) * MaxNodeScore) / 4000 = 0
   204  			// Memory Score: ((10000 - 0) * MaxNodeScore) / 10000 = MaxNodeScore
   205  			// Node1 Score: (0 + MaxNodeScore) / 2 = 50
   206  			// Node2 scores on 0-MaxNodeScore scale
   207  			// CPU Score: ((4000 - 6000) * MaxNodeScore) / 4000 = 0
   208  			// Memory Score: ((10000 - 5000) * MaxNodeScore) / 10000 = 50
   209  			// Node2 Score: (0 + 50) / 2 = 25
   210  			name:         "requested resources exceed node capacity",
   211  			requestedPod: st.MakePod().Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   212  			nodes: []*v1.Node{
   213  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   214  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   215  			},
   216  			existingPods: []*v1.Pod{
   217  				st.MakePod().Node("node1").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   218  				st.MakePod().Node("node2").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "5000"}).Obj(),
   219  			},
   220  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 50}, {Name: "node2", Score: 25}},
   221  			resources:      defaultResources,
   222  		},
   223  		{
   224  			name:         "zero node resources, pods scheduled with resources",
   225  			requestedPod: st.MakePod().Obj(),
   226  			nodes: []*v1.Node{
   227  				st.MakeNode().Name("node1").Obj(),
   228  				st.MakeNode().Name("node2").Obj(),
   229  			},
   230  			existingPods: []*v1.Pod{
   231  				st.MakePod().Node("node1").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "0"}).Obj(),
   232  				st.MakePod().Node("node2").Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "5000"}).Obj(),
   233  			},
   234  			expectedScores: []framework.NodeScore{{Name: "node1", Score: framework.MinNodeScore}, {Name: "node2", Score: framework.MinNodeScore}},
   235  			resources:      defaultResources,
   236  		},
   237  		{
   238  			// CPU Score: ((4000 - 3000) *100) / 4000 = 25
   239  			// Memory Score: ((10000 - 5000) *100) / 10000 = 50
   240  			// Node1 Score: (25 * 1 + 50 * 2) / (1 + 2) = 41
   241  			// CPU Score: ((6000 - 3000) *100) / 6000 = 50
   242  			// Memory Score: ((10000 - 5000) *100) / 10000 = 50
   243  			// Node2 Score: (50 * 1 + 50 * 2) / (1 + 2) = 50
   244  			name: "nothing scheduled, resources requested with different weight on CPU and memory, differently sized nodes",
   245  			requestedPod: st.MakePod().Node("node1").
   246  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
   247  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
   248  				Obj(),
   249  			nodes: []*v1.Node{
   250  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   251  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000"}).Obj(),
   252  			},
   253  			existingPods:   nil,
   254  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 41}, {Name: "node2", Score: 50}},
   255  			resources: []config.ResourceSpec{
   256  				{Name: "memory", Weight: 2},
   257  				{Name: "cpu", Weight: 1},
   258  			},
   259  		},
   260  		{
   261  			// resource with negative weight is not allowed
   262  			name: "resource with negative weight",
   263  			requestedPod: st.MakePod().Node("node1").
   264  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
   265  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
   266  				Obj(),
   267  			nodes: []*v1.Node{
   268  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   269  			},
   270  			resources: []config.ResourceSpec{
   271  				{Name: "memory", Weight: -1},
   272  				{Name: "cpu", Weight: 1},
   273  			},
   274  			wantErrs: field.ErrorList{
   275  				&field.Error{
   276  					Type:  field.ErrorTypeInvalid,
   277  					Field: "scoringStrategy.resources[0].weight",
   278  				},
   279  			},
   280  		},
   281  		{
   282  			// resource with zero weight is not allowed
   283  			name: "resource with zero weight",
   284  			requestedPod: st.MakePod().Node("node1").
   285  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
   286  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
   287  				Obj(),
   288  			nodes: []*v1.Node{
   289  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   290  			},
   291  			existingPods:   nil,
   292  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 41}, {Name: "node2", Score: 50}},
   293  			resources: []config.ResourceSpec{
   294  				{Name: "memory", Weight: 1},
   295  				{Name: "cpu", Weight: 0},
   296  			},
   297  			wantErrs: field.ErrorList{
   298  				&field.Error{
   299  					Type:  field.ErrorTypeInvalid,
   300  					Field: "scoringStrategy.resources[1].weight",
   301  				},
   302  			},
   303  		},
   304  		{
   305  			// resource weight should be less than MaxNodeScore
   306  			name: "resource weight larger than MaxNodeScore",
   307  			requestedPod: st.MakePod().Node("node1").
   308  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
   309  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
   310  				Obj(),
   311  			nodes: []*v1.Node{
   312  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "4000", "memory": "10000"}).Obj(),
   313  			},
   314  			resources: []config.ResourceSpec{
   315  				{Name: "memory", Weight: 1},
   316  				{Name: "cpu", Weight: 101},
   317  			},
   318  			wantErrs: field.ErrorList{
   319  				&field.Error{
   320  					Type:  field.ErrorTypeInvalid,
   321  					Field: "scoringStrategy.resources[1].weight",
   322  				},
   323  			},
   324  		},
   325  		{
   326  			// Bypass extended resource if the pod does not request.
   327  			// For both nodes: cpuScore and memScore are 50
   328  			// Given that extended resource score are intentionally bypassed,
   329  			// the final scores are:
   330  			// - node1: (50 + 50) / 2 = 50
   331  			// - node2: (50 + 50) / 2 = 50
   332  			name: "bypass extended resource if the pod does not request",
   333  			requestedPod: st.MakePod().Node("node1").
   334  				Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
   335  				Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
   336  				Obj(),
   337  			nodes: []*v1.Node{
   338  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000"}).Obj(),
   339  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000", v1.ResourceName(extendedRes): "4"}).Obj(),
   340  			},
   341  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 50}, {Name: "node2", Score: 50}},
   342  			resources:      extendedResourceSet,
   343  		},
   344  		{
   345  			// Honor extended resource if the pod requests.
   346  			// For both nodes: cpuScore and memScore are 50.
   347  			// In terms of extended resource score:
   348  			// - node1 get: 2 / 4 * 100 = 50
   349  			// - node2 get: (10 - 2) / 10 * 100 = 80
   350  			// So the final scores are:
   351  			// - node1: (50 + 50 + 50) / 3 = 50
   352  			// - node2: (50 + 50 + 80) / 3 = 60
   353  			name: "honor extended resource if the pod requests",
   354  			requestedPod: st.MakePod().Node("node1").
   355  				Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "5000", v1.ResourceName(extendedRes): "2"}).
   356  				Obj(),
   357  			nodes: []*v1.Node{
   358  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000", v1.ResourceName(extendedRes): "4"}).Obj(),
   359  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000", v1.ResourceName(extendedRes): "10"}).Obj(),
   360  			},
   361  			existingPods:   nil,
   362  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 50}, {Name: "node2", Score: 60}},
   363  			resources:      extendedResourceSet,
   364  		},
   365  		{
   366  			// If the node doesn't have a resource
   367  			// CPU Score: ((6000 - 3000) * 100) / 6000 = 50
   368  			// Memory Score: ((10000 - 4000) * 100) / 10000 = 60
   369  			// Node1 Score: (50 * 1 + 60 * 1) / (1 + 1) = 55
   370  			// Node2 Score: (50 * 1 + 60 * 1) / (1 + 1) = 55
   371  			name: "if the node doesn't have a resource",
   372  			requestedPod: st.MakePod().Node("node1").
   373  				Req(map[v1.ResourceName]string{"cpu": "3000", "memory": "4000"}).
   374  				Obj(),
   375  			nodes: []*v1.Node{
   376  				st.MakeNode().Name("node1").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000"}).Obj(),
   377  				st.MakeNode().Name("node2").Capacity(map[v1.ResourceName]string{"cpu": "6000", "memory": "10000", v1.ResourceName(extendedRes): "4"}).Obj(),
   378  			},
   379  			expectedScores: []framework.NodeScore{{Name: "node1", Score: 55}, {Name: "node2", Score: 55}},
   380  			resources: []config.ResourceSpec{
   381  				{Name: extendedRes, Weight: 2},
   382  				{Name: string(v1.ResourceCPU), Weight: 1},
   383  				{Name: string(v1.ResourceMemory), Weight: 1},
   384  			},
   385  		},
   386  	}
   387  
   388  	for _, test := range tests {
   389  		t.Run(test.name, func(t *testing.T) {
   390  			_, ctx := ktesting.NewTestContext(t)
   391  			ctx, cancel := context.WithCancel(ctx)
   392  			defer cancel()
   393  
   394  			state := framework.NewCycleState()
   395  			snapshot := cache.NewSnapshot(test.existingPods, test.nodes)
   396  			fh, _ := runtime.NewFramework(ctx, nil, nil, runtime.WithSnapshotSharedLister(snapshot))
   397  
   398  			p, err := NewFit(
   399  				ctx,
   400  				&config.NodeResourcesFitArgs{
   401  					ScoringStrategy: &config.ScoringStrategy{
   402  						Type:      config.LeastAllocated,
   403  						Resources: test.resources,
   404  					},
   405  				}, fh, plfeature.Features{})
   406  
   407  			if diff := cmp.Diff(test.wantErrs.ToAggregate(), err, ignoreBadValueDetail); diff != "" {
   408  				t.Fatalf("got err (-want,+got):\n%s", diff)
   409  			}
   410  			if err != nil {
   411  				return
   412  			}
   413  
   414  			status := p.(framework.PreScorePlugin).PreScore(ctx, state, test.requestedPod, tf.BuildNodeInfos(test.nodes))
   415  			if !status.IsSuccess() {
   416  				t.Errorf("PreScore is expected to return success, but didn't. Got status: %v", status)
   417  			}
   418  
   419  			var gotScores framework.NodeScoreList
   420  			for _, n := range test.nodes {
   421  				score, status := p.(framework.ScorePlugin).Score(ctx, state, test.requestedPod, n.Name)
   422  				if status.Code() != test.wantStatusCode {
   423  					t.Errorf("unexpected status code, want: %v, got: %v", test.wantStatusCode, status.Code())
   424  				}
   425  				gotScores = append(gotScores, framework.NodeScore{Name: n.Name, Score: score})
   426  			}
   427  
   428  			if diff := cmp.Diff(test.expectedScores, gotScores); diff != "" {
   429  				t.Errorf("Unexpected scores (-want,+got):\n%s", diff)
   430  			}
   431  		})
   432  	}
   433  }
   434  

View as plain text