Skip to content

Commit ad675f3

Browse files
committed
[fix] Don't ignore --max-binpacking-time flag
1 parent 7fe519c commit ad675f3

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

cluster-autoscaler/processors/binpacking/time_limiter.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,27 @@ import (
2929
type TimeLimiter struct {
3030
startTime time.Time
3131
maxBinpackingDuration time.Duration
32+
now func() time.Time
3233
}
3334

3435
// NewTimeLimiter returns an instance of a new TimeLimiter.
3536
func NewTimeLimiter(maxBinpackingDuration time.Duration) *TimeLimiter {
3637
return &TimeLimiter{
3738
maxBinpackingDuration: maxBinpackingDuration,
39+
now: time.Now,
40+
}
41+
}
42+
43+
func newTimeLimiterWithClock(maxBinpackingDuration time.Duration, now func() time.Time) *TimeLimiter {
44+
return &TimeLimiter{
45+
maxBinpackingDuration: maxBinpackingDuration,
46+
now: now,
3847
}
3948
}
4049

4150
// InitBinpacking initialises the TimeLimiter.
4251
func (b *TimeLimiter) InitBinpacking(autoscalingCtx *ca_context.AutoscalingContext, nodeGroups []cloudprovider.NodeGroup) {
43-
b.startTime = time.Now()
52+
b.startTime = b.now()
4453
}
4554

4655
// MarkProcessed marks the nodegroup as processed.
@@ -49,9 +58,10 @@ func (b *TimeLimiter) MarkProcessed(autoscalingCtx *ca_context.AutoscalingContex
4958

5059
// StopBinpacking returns true if the binpacking time exceeds maxBinpackingDuration.
5160
func (b *TimeLimiter) StopBinpacking(autoscalingCtx *ca_context.AutoscalingContext, evaluatedOptions []expander.Option) bool {
52-
now := time.Now()
61+
now := b.now()
5362
if now.After(b.startTime.Add(b.maxBinpackingDuration)) {
5463
klog.Infof("Binpacking is cut short after %v seconds due to exceeding maxBinpackingDuration", now.Sub(b.startTime).Seconds())
64+
return true
5565
}
5666
return false
5767
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
Copyright 2025 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 binpacking
18+
19+
import (
20+
"testing"
21+
"time"
22+
23+
"github.com/stretchr/testify/assert"
24+
testingclock "k8s.io/utils/clock/testing"
25+
)
26+
27+
func TestTimeLimiter(t *testing.T) {
28+
testCases := []struct {
29+
name string
30+
maxBinpackingDuration time.Duration
31+
timeAdvanced time.Duration
32+
expectStop bool
33+
}{
34+
{
35+
name: "Time limit not exceeded",
36+
maxBinpackingDuration: 10 * time.Second,
37+
timeAdvanced: 5 * time.Second,
38+
expectStop: false,
39+
},
40+
{
41+
name: "Time limit exceeded",
42+
maxBinpackingDuration: 10 * time.Second,
43+
timeAdvanced: 15 * time.Second,
44+
expectStop: true,
45+
},
46+
{
47+
name: "Time limit met exactly",
48+
maxBinpackingDuration: 10 * time.Second,
49+
timeAdvanced: 10 * time.Second,
50+
expectStop: false,
51+
},
52+
{
53+
name: "Zero duration",
54+
maxBinpackingDuration: 0,
55+
timeAdvanced: 1 * time.Millisecond,
56+
expectStop: true,
57+
},
58+
}
59+
60+
for _, tc := range testCases {
61+
t.Run(tc.name, func(t *testing.T) {
62+
fakeClock := testingclock.NewFakeClock(time.Now())
63+
limiter := newTimeLimiterWithClock(tc.maxBinpackingDuration, fakeClock.Now)
64+
65+
limiter.InitBinpacking(nil, nil)
66+
fakeClock.Step(tc.timeAdvanced)
67+
68+
assert.Equal(t, tc.expectStop, limiter.StopBinpacking(nil, nil))
69+
})
70+
}
71+
}

0 commit comments

Comments
 (0)