Skip to content

Commit 7aa2a5c

Browse files
engedaamjmdealnjtran
authored
chore: Backport NillableDuration updates for v0.36.x (#1556)
Co-authored-by: Jason Deal <[email protected]> Co-authored-by: Nick Tran <[email protected]>
1 parent 45344ab commit 7aa2a5c

18 files changed

+201
-81
lines changed

pkg/apis/v1/duration.go

+28-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ package v1
1818

1919
import (
2020
"encoding/json"
21+
"fmt"
22+
"slices"
2123
"time"
24+
25+
"github.com/samber/lo"
2226
)
2327

2428
const Never = "Never"
@@ -28,6 +32,17 @@ const Never = "Never"
2832
// that the duration is disabled and sets the inner duration as nil
2933
type NillableDuration struct {
3034
*time.Duration
35+
36+
// Raw is used to ensure we remarshal the NillableDuration in the same format it was specified.
37+
// This ensures tools like Flux and ArgoCD don't mistakenly detect drift due to our conversion webhooks.
38+
Raw []byte `hash:"ignore"`
39+
}
40+
41+
func MustParseNillableDuration(val string) NillableDuration {
42+
nd := NillableDuration{}
43+
// Use %q instead of %s to ensure that we unmarshal the value as a string and not an int
44+
lo.Must0(json.Unmarshal([]byte(fmt.Sprintf("%q", val)), &nd))
45+
return nd
3146
}
3247

3348
// UnmarshalJSON implements the json.Unmarshaller interface.
@@ -44,22 +59,29 @@ func (d *NillableDuration) UnmarshalJSON(b []byte) error {
4459
if err != nil {
4560
return err
4661
}
62+
d.Raw = slices.Clone(b)
4763
d.Duration = &pd
4864
return nil
4965
}
5066

5167
// MarshalJSON implements the json.Marshaler interface.
5268
func (d NillableDuration) MarshalJSON() ([]byte, error) {
53-
if d.Duration == nil {
54-
return json.Marshal(Never)
69+
if d.Raw != nil {
70+
return d.Raw, nil
71+
}
72+
if d.Duration != nil {
73+
return json.Marshal(d.Duration.String())
5574
}
56-
return json.Marshal(d.Duration.String())
75+
return json.Marshal(Never)
5776
}
5877

5978
// ToUnstructured implements the value.UnstructuredConverter interface.
6079
func (d NillableDuration) ToUnstructured() interface{} {
61-
if d.Duration == nil {
62-
return Never
80+
if d.Raw != nil {
81+
return d.Raw
82+
}
83+
if d.Duration != nil {
84+
return d.Duration.String()
6385
}
64-
return d.Duration.String()
86+
return Never
6587
}

pkg/apis/v1/nodeclaim_conversion_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ var _ = Describe("Convert V1beta1 to V1 NodeClaim API", func() {
288288
},
289289
},
290290
}
291-
v1nodePool.Spec.Template.Spec.ExpireAfter = NillableDuration{Duration: lo.ToPtr(30 * time.Minute)}
291+
v1nodePool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("30m")
292292
v1nodeclaim = &NodeClaim{
293293
ObjectMeta: metav1.ObjectMeta{
294294
Labels: map[string]string{
@@ -326,13 +326,13 @@ var _ = Describe("Convert V1beta1 to V1 NodeClaim API", func() {
326326
Context("ExpireAfter", func() {
327327
It("should default the v1beta1 expireAfter to v1 when the nodepool doesn't exist", func() {
328328
Expect(env.Client.Delete(ctx, v1nodePool)).To(Succeed())
329-
v1nodePool.Spec.Template.Spec.ExpireAfter = NillableDuration{Duration: lo.ToPtr(30 * time.Minute)}
329+
v1nodePool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("30m")
330330
Expect(v1nodeclaim.ConvertFrom(ctx, v1beta1nodeclaim)).To(Succeed())
331331
Expect(v1nodeclaim.Spec.ExpireAfter.Duration).To(BeNil())
332332
})
333333
It("should default the v1beta1 expireAfter to v1 when the nodepool label doesn't exist", func() {
334334
delete(v1beta1nodeclaim.Labels, v1beta1.NodePoolLabelKey)
335-
v1nodePool.Spec.Template.Spec.ExpireAfter = NillableDuration{Duration: lo.ToPtr(30 * time.Minute)}
335+
v1nodePool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("30m")
336336
Expect(env.Client.Update(ctx, v1nodePool)).To(Succeed())
337337
Expect(v1nodeclaim.ConvertFrom(ctx, v1beta1nodeclaim)).To(Succeed())
338338
Expect(v1nodeclaim.Spec.ExpireAfter.Duration).To(BeNil())

pkg/apis/v1/nodepool_conversion_test.go

+71-3
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,13 @@ var _ = Describe("Convert V1 to V1beta1 NodePool API", func() {
213213
Context("Disruption", func() {
214214
It("should convert v1 nodepool consolidateAfter to nil with WhenEmptyOrUnderutilized", func() {
215215
v1nodepool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmptyOrUnderutilized
216-
v1nodepool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: lo.ToPtr(time.Second * 2121)}
216+
v1nodepool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("2121s")
217217
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
218218
Expect(v1beta1nodepool.Spec.Disruption.ConsolidateAfter).To(BeNil())
219219
})
220220
It("should convert v1 nodepool consolidateAfter with WhenEmpty", func() {
221221
v1nodepool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmpty
222-
v1nodepool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: lo.ToPtr(time.Second * 2121)}
222+
v1nodepool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("2121s")
223223
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
224224
Expect(lo.FromPtr(v1beta1nodepool.Spec.Disruption.ConsolidateAfter.Duration)).To(Equal(lo.FromPtr(v1nodepool.Spec.Disruption.ConsolidateAfter.Duration)))
225225
})
@@ -229,7 +229,7 @@ var _ = Describe("Convert V1 to V1beta1 NodePool API", func() {
229229
Expect(string(v1beta1nodepool.Spec.Disruption.ConsolidationPolicy)).To(Equal(string(v1nodepool.Spec.Disruption.ConsolidationPolicy)))
230230
})
231231
It("should convert v1 nodepool ExpireAfter", func() {
232-
v1nodepool.Spec.Template.Spec.ExpireAfter = NillableDuration{Duration: lo.ToPtr(time.Second * 2121)}
232+
v1nodepool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("2121s")
233233
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
234234
Expect(v1beta1nodepool.Spec.Disruption.ExpireAfter.Duration).To(Equal(v1nodepool.Spec.Template.Spec.ExpireAfter.Duration))
235235
})
@@ -274,6 +274,40 @@ var _ = Describe("Convert V1 to V1beta1 NodePool API", func() {
274274
Expect(v1beta1nodepool.Status.Resources[resource]).To(Equal(v1nodepool.Status.Resources[resource]))
275275
}
276276
})
277+
Context("Round Trip", func() {
278+
It("spec.template.spec.expireAfter", func() {
279+
v1nodepool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("10h")
280+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
281+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
282+
result, err := json.Marshal(v1nodepool.Spec.Template.Spec.ExpireAfter)
283+
Expect(err).To(BeNil())
284+
Expect(string(result)).To(Equal(`"10h"`))
285+
})
286+
It("spec.template.spec.expireAfter (Never)", func() {
287+
v1nodepool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("Never")
288+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
289+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
290+
result, err := json.Marshal(v1nodepool.Spec.Template.Spec.ExpireAfter)
291+
Expect(err).To(BeNil())
292+
Expect(string(result)).To(Equal(`"Never"`))
293+
})
294+
It("spec.disruption.consolidateAfter", func() {
295+
v1nodepool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("10h")
296+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
297+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
298+
result, err := json.Marshal(v1nodepool.Spec.Disruption.ConsolidateAfter)
299+
Expect(err).To(BeNil())
300+
Expect(string(result)).To(Equal(`"10h"`))
301+
})
302+
It("spec.disruption.consolidateAfter (Never)", func() {
303+
v1nodepool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("Never")
304+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
305+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
306+
result, err := json.Marshal(v1nodepool.Spec.Disruption.ConsolidateAfter)
307+
Expect(err).To(BeNil())
308+
Expect(string(result)).To(Equal(`"Never"`))
309+
})
310+
})
277311
})
278312

279313
var _ = Describe("Convert V1beta1 to V1 NodePool API", func() {
@@ -547,4 +581,38 @@ var _ = Describe("Convert V1beta1 to V1 NodePool API", func() {
547581
Expect(v1beta1nodepool.Status.Resources[resource]).To(Equal(v1nodepool.Status.Resources[resource]))
548582
}
549583
})
584+
Context("Round Trip", func() {
585+
It("spec.disruption.expireAfter", func() {
586+
v1beta1nodepool.Spec.Disruption.ExpireAfter = v1beta1.MustParseNillableDuration("10h")
587+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
588+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
589+
result, err := json.Marshal(v1beta1nodepool.Spec.Disruption.ExpireAfter)
590+
Expect(err).To(BeNil())
591+
Expect(string(result)).To(Equal(`"10h"`))
592+
})
593+
It("spec.disruption.expireAfter (Never)", func() {
594+
v1beta1nodepool.Spec.Disruption.ExpireAfter = v1beta1.MustParseNillableDuration("Never")
595+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
596+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
597+
result, err := json.Marshal(v1beta1nodepool.Spec.Disruption.ExpireAfter)
598+
Expect(err).To(BeNil())
599+
Expect(string(result)).To(Equal(`"Never"`))
600+
})
601+
It("spec.disruption.consolidateAfter", func() {
602+
v1beta1nodepool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(v1beta1.MustParseNillableDuration("10h"))
603+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
604+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
605+
result, err := json.Marshal(lo.FromPtr(v1beta1nodepool.Spec.Disruption.ConsolidateAfter))
606+
Expect(err).To(BeNil())
607+
Expect(string(result)).To(Equal(`"10h"`))
608+
})
609+
It("spec.disruption.consolidateAfter (Never)", func() {
610+
v1beta1nodepool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(v1beta1.MustParseNillableDuration("Never"))
611+
Expect(v1nodepool.ConvertFrom(ctx, v1beta1nodepool)).To(Succeed())
612+
Expect(v1nodepool.ConvertTo(ctx, v1beta1nodepool)).To(Succeed())
613+
result, err := json.Marshal(lo.FromPtr(v1beta1nodepool.Spec.Disruption.ConsolidateAfter))
614+
Expect(err).To(BeNil())
615+
Expect(string(result)).To(Equal(`"Never"`))
616+
})
617+
})
550618
})

pkg/apis/v1/nodepool_validation_cel_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -64,47 +64,47 @@ var _ = Describe("CEL/Validation", func() {
6464
})
6565
Context("Disruption", func() {
6666
It("should fail on negative expireAfter", func() {
67-
nodePool.Spec.Template.Spec.ExpireAfter.Duration = lo.ToPtr(lo.Must(time.ParseDuration("-1s")))
67+
nodePool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("-1s")
6868
Expect(env.Client.Create(ctx, nodePool)).ToNot(Succeed())
6969
})
7070
It("should succeed on a disabled expireAfter", func() {
71-
nodePool.Spec.Template.Spec.ExpireAfter.Duration = nil
71+
nodePool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("Never")
7272
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
7373
})
7474
It("should succeed on a valid expireAfter", func() {
75-
nodePool.Spec.Template.Spec.ExpireAfter.Duration = lo.ToPtr(lo.Must(time.ParseDuration("30s")))
75+
nodePool.Spec.Template.Spec.ExpireAfter = MustParseNillableDuration("30s")
7676
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
7777
})
7878
It("should fail on negative consolidateAfter", func() {
79-
nodePool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("-1s")))}
79+
nodePool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("-1s")
8080
Expect(env.Client.Create(ctx, nodePool)).ToNot(Succeed())
8181
})
8282
It("should succeed on a disabled consolidateAfter", func() {
83-
nodePool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: nil}
83+
nodePool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("Never")
8484
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
8585
})
8686
It("should succeed on a valid consolidateAfter", func() {
87-
nodePool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("30s")))}
87+
nodePool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("30s")
8888
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmpty
8989
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
9090
})
9191
It("should succeed when setting consolidateAfter with consolidationPolicy=WhenEmpty", func() {
92-
nodePool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("30s")))}
92+
nodePool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("30s")
9393
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmpty
9494
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
9595
})
9696
It("should succeed when setting consolidateAfter with consolidationPolicy=WhenEmptyOrUnderutilized", func() {
97-
nodePool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("30s")))}
97+
nodePool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("30s")
9898
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmptyOrUnderutilized
9999
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
100100
})
101101
It("should succeed when setting consolidateAfter to 'Never' with consolidationPolicy=WhenEmptyOrUnderutilized", func() {
102-
nodePool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: nil}
102+
nodePool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("Never")
103103
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmptyOrUnderutilized
104104
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
105105
})
106106
It("should succeed when setting consolidateAfter to 'Never' with consolidationPolicy=WhenEmpty", func() {
107-
nodePool.Spec.Disruption.ConsolidateAfter = NillableDuration{Duration: nil}
107+
nodePool.Spec.Disruption.ConsolidateAfter = MustParseNillableDuration("Never")
108108
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmpty
109109
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
110110
})

pkg/apis/v1/zz_generated.deepcopy.go

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/v1beta1/duration.go

+28-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ package v1beta1
1818

1919
import (
2020
"encoding/json"
21+
"fmt"
22+
"slices"
2123
"time"
24+
25+
"github.com/samber/lo"
2226
)
2327

2428
const Never = "Never"
@@ -28,6 +32,17 @@ const Never = "Never"
2832
// that the duration is disabled and sets the inner duration as nil
2933
type NillableDuration struct {
3034
*time.Duration
35+
36+
// Raw is used to ensure we remarshal the NillableDuration in the same format it was specified.
37+
// This ensures tools like Flux and ArgoCD don't mistakenly detect drift due to our conversion webhooks.
38+
Raw []byte `hash:"ignore"`
39+
}
40+
41+
func MustParseNillableDuration(val string) NillableDuration {
42+
nd := NillableDuration{}
43+
// Use %q instead of %s to ensure that we unmarshal the value as a string and not an int
44+
lo.Must0(json.Unmarshal([]byte(fmt.Sprintf("%q", val)), &nd))
45+
return nd
3146
}
3247

3348
// UnmarshalJSON implements the json.Unmarshaller interface.
@@ -44,22 +59,29 @@ func (d *NillableDuration) UnmarshalJSON(b []byte) error {
4459
if err != nil {
4560
return err
4661
}
62+
d.Raw = slices.Clone(b)
4763
d.Duration = &pd
4864
return nil
4965
}
5066

5167
// MarshalJSON implements the json.Marshaler interface.
5268
func (d NillableDuration) MarshalJSON() ([]byte, error) {
53-
if d.Duration == nil {
54-
return json.Marshal(Never)
69+
if d.Raw != nil {
70+
return d.Raw, nil
71+
}
72+
if d.Duration != nil {
73+
return json.Marshal(d.Duration.String())
5574
}
56-
return json.Marshal(d.Duration.String())
75+
return json.Marshal(Never)
5776
}
5877

5978
// ToUnstructured implements the value.UnstructuredConverter interface.
6079
func (d NillableDuration) ToUnstructured() interface{} {
61-
if d.Duration == nil {
62-
return Never
80+
if d.Raw != nil {
81+
return d.Raw
82+
}
83+
if d.Duration != nil {
84+
return d.Duration.String()
6385
}
64-
return d.Duration.String()
86+
return Never
6587
}

pkg/apis/v1beta1/nodepool_validation_cel_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -70,38 +70,38 @@ var _ = Describe("CEL/Validation", func() {
7070
Expect(env.Client.Create(ctx, nodePool)).ToNot(Succeed())
7171
})
7272
It("should succeed on a disabled expireAfter", func() {
73-
nodePool.Spec.Disruption.ExpireAfter.Duration = nil
73+
nodePool.Spec.Disruption.ExpireAfter = MustParseNillableDuration("Never")
7474
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
7575
})
7676
It("should succeed on a valid expireAfter", func() {
77-
nodePool.Spec.Disruption.ExpireAfter.Duration = lo.ToPtr(lo.Must(time.ParseDuration("30s")))
77+
nodePool.Spec.Disruption.ExpireAfter = MustParseNillableDuration("30s")
7878
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
7979
})
8080
It("should fail on negative consolidateAfter", func() {
81-
nodePool.Spec.Disruption.ConsolidateAfter = &NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("-1s")))}
81+
nodePool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(MustParseNillableDuration("-1s"))
8282
Expect(env.Client.Create(ctx, nodePool)).ToNot(Succeed())
8383
})
8484
It("should succeed on a disabled consolidateAfter", func() {
85-
nodePool.Spec.Disruption.ConsolidateAfter = &NillableDuration{Duration: nil}
85+
nodePool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(MustParseNillableDuration("Never"))
8686
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
8787
})
8888
It("should succeed on a valid consolidateAfter", func() {
89-
nodePool.Spec.Disruption.ConsolidateAfter = &NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("30s")))}
89+
nodePool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(MustParseNillableDuration("30s"))
9090
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmpty
9191
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
9292
})
9393
It("should succeed when setting consolidateAfter with consolidationPolicy=WhenEmpty", func() {
94-
nodePool.Spec.Disruption.ConsolidateAfter = &NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("30s")))}
94+
nodePool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(MustParseNillableDuration("30s"))
9595
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenEmpty
9696
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
9797
})
9898
It("should fail when setting consolidateAfter with consolidationPolicy=WhenUnderutilized", func() {
99-
nodePool.Spec.Disruption.ConsolidateAfter = &NillableDuration{Duration: lo.ToPtr(lo.Must(time.ParseDuration("30s")))}
99+
nodePool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(MustParseNillableDuration("30s"))
100100
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenUnderutilized
101101
Expect(env.Client.Create(ctx, nodePool)).ToNot(Succeed())
102102
})
103103
It("should succeed when not setting consolidateAfter to 'Never' with consolidationPolicy=WhenUnderutilized", func() {
104-
nodePool.Spec.Disruption.ConsolidateAfter = &NillableDuration{Duration: nil}
104+
nodePool.Spec.Disruption.ConsolidateAfter = lo.ToPtr(MustParseNillableDuration("Never"))
105105
nodePool.Spec.Disruption.ConsolidationPolicy = ConsolidationPolicyWhenUnderutilized
106106
Expect(env.Client.Create(ctx, nodePool)).To(Succeed())
107107
})

0 commit comments

Comments
 (0)