@@ -23,15 +23,18 @@ import (
23
23
24
24
"github.com/google/go-cmp/cmp"
25
25
"github.com/google/go-cmp/cmp/cmpopts"
26
+ "github.com/stretchr/testify/assert"
26
27
apiv1 "k8s.io/api/core/v1"
27
28
"k8s.io/apimachinery/pkg/api/resource"
28
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
30
30
31
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
31
32
testprovider "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/test"
32
33
"k8s.io/autoscaler/cluster-autoscaler/config"
33
- "k8s.io/autoscaler/cluster-autoscaler/context"
34
34
"k8s.io/autoscaler/cluster-autoscaler/core/scaledown/deletiontracker"
35
+ "k8s.io/autoscaler/cluster-autoscaler/core/test"
36
+ "k8s.io/autoscaler/cluster-autoscaler/simulator/clustersnapshot"
37
+ "k8s.io/client-go/kubernetes/fake"
35
38
)
36
39
37
40
func TestCropNodesToBudgets (t * testing.T ) {
@@ -49,6 +52,7 @@ func TestCropNodesToBudgets(t *testing.T) {
49
52
drain []* NodeGroupView
50
53
wantEmpty []* NodeGroupView
51
54
wantDrain []* NodeGroupView
55
+ otherNodes []* NodeGroupView
52
56
}{
53
57
"no nodes" : {
54
58
empty : []* NodeGroupView {},
@@ -201,8 +205,8 @@ func TestCropNodesToBudgets(t *testing.T) {
201
205
// Empty and drain nodes together.
202
206
"empty&drain nodes within max limits, no deletions in progress" : {
203
207
empty : generateNodeGroupViewList (testNg , 0 , 5 ),
204
- drain : generateNodeGroupViewList (testNg , 0 , 5 ),
205
- wantDrain : generateNodeGroupViewList (testNg , 0 , 5 ),
208
+ drain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
209
+ wantDrain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
206
210
wantEmpty : generateNodeGroupViewList (testNg , 0 , 5 ),
207
211
},
208
212
"empty&drain atomic nodes within max limits, no deletions in progress" : {
@@ -213,8 +217,8 @@ func TestCropNodesToBudgets(t *testing.T) {
213
217
},
214
218
"empty&drain nodes exceeding overall limit, no deletions in progress" : {
215
219
empty : generateNodeGroupViewList (testNg , 0 , 8 ),
216
- drain : generateNodeGroupViewList (testNg , 0 , 8 ),
217
- wantDrain : generateNodeGroupViewList (testNg , 0 , 2 ),
220
+ drain : generateNodeGroupViewList (testNg2 , 0 , 8 ),
221
+ wantDrain : generateNodeGroupViewList (testNg2 , 0 , 2 ),
218
222
wantEmpty : generateNodeGroupViewList (testNg , 0 , 8 ),
219
223
},
220
224
"empty&drain atomic nodes exceeding overall limit, no deletions in progress" : {
@@ -241,11 +245,18 @@ func TestCropNodesToBudgets(t *testing.T) {
241
245
wantEmpty : generateNodeGroupViewList (atomic8 , 0 , 2 ),
242
246
wantDrain : generateNodeGroupViewList (atomic8 , 2 , 8 ),
243
247
},
244
- "empty&drain atomic nodes in same group not matching node group size, no deletions in progress" : {
248
+ "empty&drain atomic nodes in same group not matching registered node group size, no deletions in progress" : {
249
+ empty : generateNodeGroupViewList (atomic8 , 0 , 2 ),
250
+ drain : generateNodeGroupViewList (atomic8 , 2 , 4 ),
251
+ wantEmpty : []* NodeGroupView {},
252
+ wantDrain : []* NodeGroupView {},
253
+ otherNodes : generateNodeGroupViewList (atomic8 , 4 , 8 ),
254
+ },
255
+ "empty&drain atomic nodes in same group matching registered node group size, no deletions in progress" : {
245
256
empty : generateNodeGroupViewList (atomic8 , 0 , 2 ),
246
257
drain : generateNodeGroupViewList (atomic8 , 2 , 4 ),
247
- wantEmpty : [] * NodeGroupView {} ,
248
- wantDrain : [] * NodeGroupView {} ,
258
+ wantEmpty : generateNodeGroupViewList ( atomic8 , 0 , 2 ) ,
259
+ wantDrain : generateNodeGroupViewList ( atomic8 , 2 , 4 ) ,
249
260
},
250
261
"empty&drain atomic nodes exceeding drain limit, no deletions in progress" : {
251
262
empty : generateNodeGroupViewList (atomic4 , 0 , 4 ),
@@ -285,14 +296,14 @@ func TestCropNodesToBudgets(t *testing.T) {
285
296
},
286
297
"empty&drain nodes exceeding drain limit, no deletions in progress" : {
287
298
empty : generateNodeGroupViewList (testNg , 0 , 2 ),
288
- drain : generateNodeGroupViewList (testNg , 0 , 8 ),
289
- wantDrain : generateNodeGroupViewList (testNg , 0 , 5 ),
299
+ drain : generateNodeGroupViewList (testNg2 , 0 , 8 ),
300
+ wantDrain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
290
301
wantEmpty : generateNodeGroupViewList (testNg , 0 , 2 ),
291
302
},
292
303
"empty&drain nodes with deletions in progress, 0 overall budget left" : {
293
304
emptyDeletionsInProgress : 10 ,
294
305
empty : generateNodeGroupViewList (testNg , 0 , 5 ),
295
- drain : generateNodeGroupViewList (testNg , 0 , 5 ),
306
+ drain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
296
307
wantEmpty : []* NodeGroupView {},
297
308
wantDrain : []* NodeGroupView {},
298
309
},
@@ -313,14 +324,14 @@ func TestCropNodesToBudgets(t *testing.T) {
313
324
"empty&drain nodes with deletions in progress, overall budget exceeded (shouldn't happen, just a sanity check)" : {
314
325
emptyDeletionsInProgress : 50 ,
315
326
empty : generateNodeGroupViewList (testNg , 0 , 5 ),
316
- drain : generateNodeGroupViewList (testNg , 0 , 5 ),
327
+ drain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
317
328
wantEmpty : []* NodeGroupView {},
318
329
wantDrain : []* NodeGroupView {},
319
330
},
320
331
"empty&drain nodes with deletions in progress, 0 drain budget left" : {
321
332
drainDeletionsInProgress : 5 ,
322
333
empty : generateNodeGroupViewList (testNg , 0 , 5 ),
323
- drain : generateNodeGroupViewList (testNg , 0 , 5 ),
334
+ drain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
324
335
wantEmpty : generateNodeGroupViewList (testNg , 0 , 5 ),
325
336
wantDrain : []* NodeGroupView {},
326
337
},
@@ -334,33 +345,33 @@ func TestCropNodesToBudgets(t *testing.T) {
334
345
"empty&drain nodes with deletions in progress, drain budget exceeded (shouldn't happen, just a sanity check)" : {
335
346
drainDeletionsInProgress : 9 ,
336
347
empty : generateNodeGroupViewList (testNg , 0 , 5 ),
337
- drain : generateNodeGroupViewList (testNg , 0 , 5 ),
348
+ drain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
338
349
wantEmpty : generateNodeGroupViewList (testNg , 0 , 1 ),
339
350
wantDrain : []* NodeGroupView {},
340
351
},
341
352
"empty&drain nodes with deletions in progress, overall budget exceeded, only empty nodes fit" : {
342
353
emptyDeletionsInProgress : 5 ,
343
354
drainDeletionsInProgress : 3 ,
344
355
empty : generateNodeGroupViewList (testNg , 0 , 5 ),
345
- drain : generateNodeGroupViewList (testNg , 0 , 2 ),
356
+ drain : generateNodeGroupViewList (testNg2 , 0 , 2 ),
346
357
wantEmpty : generateNodeGroupViewList (testNg , 0 , 2 ),
347
358
wantDrain : []* NodeGroupView {},
348
359
},
349
360
"empty&drain nodes with deletions in progress, overall budget exceeded, both empty&drain nodes fit" : {
350
361
emptyDeletionsInProgress : 5 ,
351
362
drainDeletionsInProgress : 3 ,
352
363
empty : generateNodeGroupViewList (testNg , 0 , 1 ),
353
- drain : generateNodeGroupViewList (testNg , 0 , 2 ),
364
+ drain : generateNodeGroupViewList (testNg2 , 0 , 2 ),
354
365
wantEmpty : generateNodeGroupViewList (testNg , 0 , 1 ),
355
- wantDrain : generateNodeGroupViewList (testNg , 0 , 1 ),
366
+ wantDrain : generateNodeGroupViewList (testNg2 , 0 , 1 ),
356
367
},
357
368
"empty&drain nodes with deletions in progress, drain budget exceeded" : {
358
369
emptyDeletionsInProgress : 1 ,
359
370
drainDeletionsInProgress : 3 ,
360
371
empty : generateNodeGroupViewList (testNg , 0 , 4 ),
361
- drain : generateNodeGroupViewList (testNg , 0 , 5 ),
372
+ drain : generateNodeGroupViewList (testNg2 , 0 , 5 ),
362
373
wantEmpty : generateNodeGroupViewList (testNg , 0 , 4 ),
363
- wantDrain : generateNodeGroupViewList (testNg , 0 , 2 ),
374
+ wantDrain : generateNodeGroupViewList (testNg2 , 0 , 2 ),
364
375
},
365
376
"empty&drain atomic nodes with deletions in progress, overall budget exceeded, only empty nodes fit" : {
366
377
emptyDeletionsInProgress : 5 ,
@@ -423,23 +434,25 @@ func TestCropNodesToBudgets(t *testing.T) {
423
434
provider := testprovider .NewTestCloudProviderBuilder ().WithOnScaleDown (func (nodeGroup string , node string ) error {
424
435
return nil
425
436
}).Build ()
426
- for _ , bucket := range append (tc .empty , tc .drain ... ) {
437
+ allNodes := []* apiv1.Node {}
438
+ for _ , bucket := range append (append (tc .empty , tc .drain ... ), tc .otherNodes ... ) {
427
439
bucket .Group .(* testprovider.TestNodeGroup ).SetCloudProvider (provider )
428
440
provider .InsertNodeGroup (bucket .Group )
429
441
for _ , node := range bucket .Nodes {
430
442
provider .AddNode (bucket .Group .Id (), node )
431
443
}
444
+ allNodes = append (allNodes , bucket .Nodes ... )
432
445
}
433
446
434
- ctx := & context.AutoscalingContext {
435
- AutoscalingOptions : config.AutoscalingOptions {
436
- MaxScaleDownParallelism : 10 ,
437
- MaxDrainParallelism : 5 ,
438
- NodeDeletionBatcherInterval : 0 * time .Second ,
439
- NodeDeleteDelayAfterTaint : 1 * time .Second ,
440
- },
441
- CloudProvider : provider ,
447
+ options := config.AutoscalingOptions {
448
+ MaxScaleDownParallelism : 10 ,
449
+ MaxDrainParallelism : 5 ,
450
+ NodeDeletionBatcherInterval : 0 * time .Second ,
451
+ NodeDeleteDelayAfterTaint : 1 * time .Second ,
442
452
}
453
+
454
+ ctx , err := test .NewScaleTestAutoscalingContext (options , & fake.Clientset {}, nil , provider , nil , nil )
455
+ assert .NoError (t , err )
443
456
ndt := deletiontracker .NewNodeDeletionTracker (1 * time .Hour )
444
457
for i := 0 ; i < tc .emptyDeletionsInProgress ; i ++ {
445
458
ndt .StartDeletion ("ng1" , fmt .Sprintf ("empty-node-%d" , i ))
@@ -455,7 +468,8 @@ func TestCropNodesToBudgets(t *testing.T) {
455
468
drainList = append (drainList , bucket .Nodes ... )
456
469
}
457
470
458
- budgeter := NewScaleDownBudgetProcessor (ctx )
471
+ clustersnapshot .InitializeClusterSnapshotOrDie (t , ctx .ClusterSnapshot , allNodes , nil )
472
+ budgeter := NewScaleDownBudgetProcessor (& ctx )
459
473
gotEmpty , gotDrain := budgeter .CropNodes (ndt , emptyList , drainList )
460
474
if diff := cmp .Diff (tc .wantEmpty , gotEmpty , cmpopts .EquateEmpty (), transformNodeGroupView ); diff != "" {
461
475
t .Errorf ("cropNodesToBudgets empty nodes diff (-want +got):\n %s" , diff )
@@ -510,6 +524,9 @@ func generateNodeGroupViewList(ng cloudprovider.NodeGroup, from, to int) []*Node
510
524
func generateNode (name string ) * apiv1.Node {
511
525
return & apiv1.Node {
512
526
ObjectMeta : metav1.ObjectMeta {Name : name },
527
+ Spec : apiv1.NodeSpec {
528
+ ProviderID : name ,
529
+ },
513
530
Status : apiv1.NodeStatus {
514
531
Allocatable : apiv1.ResourceList {
515
532
apiv1 .ResourceCPU : resource .MustParse ("8" ),
0 commit comments