Skip to content

Commit 1187cfd

Browse files
committed
upgrade cloneset from v1alpha1 to v1beta1
Signed-off-by: PersistentJZH <zhihao.kan17@gmail.com> fix e2e test fix ut fix ut fix ut fix ut
1 parent 3e86101 commit 1187cfd

60 files changed

Lines changed: 5115 additions & 538 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apis/apps/defaults/v1beta1.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
v1 "k8s.io/kubernetes/pkg/apis/core/v1"
2424
"k8s.io/utils/ptr"
2525

26+
appspub "github.com/openkruise/kruise/apis/apps/pub"
2627
"github.com/openkruise/kruise/apis/apps/v1beta1"
2728
"github.com/openkruise/kruise/pkg/features"
2829
utilfeature "github.com/openkruise/kruise/pkg/util/feature"
@@ -257,3 +258,50 @@ func SetDefaultsDaemonSetV1beta1(obj *v1beta1.DaemonSet) {
257258
obj.Spec.RevisionHistoryLimit = ptr.To(int32(10))
258259
}
259260
}
261+
262+
// SetDefaultsCloneSetV1beta1 sets default values for v1beta1 CloneSet.
263+
func SetDefaultsCloneSetV1beta1(obj *v1beta1.CloneSet, injectTemplateDefaults bool) {
264+
if obj.Spec.Replicas == nil {
265+
obj.Spec.Replicas = ptr.To(int32(1))
266+
}
267+
if obj.Spec.RevisionHistoryLimit == nil {
268+
obj.Spec.RevisionHistoryLimit = ptr.To(int32(10))
269+
}
270+
271+
// For v1beta1, set DisablePVCReuse default to true (safer default)
272+
// This is only applied during Create operations by the webhook
273+
// Note: v1alpha1 keeps default as false for backward compatibility
274+
275+
if injectTemplateDefaults {
276+
SetDefaultPodSpec(&obj.Spec.Template.Spec)
277+
for i := range obj.Spec.VolumeClaimTemplates {
278+
a := &obj.Spec.VolumeClaimTemplates[i]
279+
v1.SetDefaults_PersistentVolumeClaim(a)
280+
v1.SetDefaults_ResourceList(&a.Spec.Resources.Limits)
281+
v1.SetDefaults_ResourceList(&a.Spec.Resources.Requests)
282+
v1.SetDefaults_ResourceList(&a.Status.Capacity)
283+
}
284+
}
285+
286+
switch obj.Spec.UpdateStrategy.Type {
287+
case "":
288+
obj.Spec.UpdateStrategy.Type = v1beta1.RecreateCloneSetUpdateStrategyType
289+
case v1beta1.InPlaceIfPossibleCloneSetUpdateStrategyType, v1beta1.InPlaceOnlyCloneSetUpdateStrategyType:
290+
if obj.Spec.UpdateStrategy.InPlaceUpdateStrategy == nil {
291+
obj.Spec.UpdateStrategy.InPlaceUpdateStrategy = &appspub.InPlaceUpdateStrategy{}
292+
}
293+
}
294+
295+
if obj.Spec.UpdateStrategy.Partition == nil {
296+
partition := intstr.FromInt(0)
297+
obj.Spec.UpdateStrategy.Partition = &partition
298+
}
299+
if obj.Spec.UpdateStrategy.MaxUnavailable == nil {
300+
maxUnavailable := intstr.FromString(v1beta1.DefaultCloneSetMaxUnavailable)
301+
obj.Spec.UpdateStrategy.MaxUnavailable = &maxUnavailable
302+
}
303+
if obj.Spec.UpdateStrategy.MaxSurge == nil {
304+
maxSurge := intstr.FromInt(0)
305+
obj.Spec.UpdateStrategy.MaxSurge = &maxSurge
306+
}
307+
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*
2+
Copyright 2025 The Kruise 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 v1alpha1
18+
19+
import (
20+
"fmt"
21+
22+
"sigs.k8s.io/controller-runtime/pkg/conversion"
23+
24+
"github.com/openkruise/kruise/apis/apps/v1beta1"
25+
)
26+
27+
func (cs *CloneSet) ConvertTo(dst conversion.Hub) error {
28+
switch t := dst.(type) {
29+
case *v1beta1.CloneSet:
30+
csv1beta1 := dst.(*v1beta1.CloneSet)
31+
csv1beta1.ObjectMeta = cs.ObjectMeta
32+
33+
// spec
34+
csv1beta1.Spec = v1beta1.CloneSetSpec{
35+
Replicas: cs.Spec.Replicas,
36+
Selector: cs.Spec.Selector,
37+
Template: cs.Spec.Template,
38+
VolumeClaimTemplates: cs.Spec.VolumeClaimTemplates,
39+
RevisionHistoryLimit: cs.Spec.RevisionHistoryLimit,
40+
MinReadySeconds: cs.Spec.MinReadySeconds,
41+
Lifecycle: cs.Spec.Lifecycle,
42+
}
43+
44+
// Convert ScaleStrategy
45+
csv1beta1.Spec.ScaleStrategy = v1beta1.CloneSetScaleStrategy{
46+
PodsToDelete: cs.Spec.ScaleStrategy.PodsToDelete,
47+
MaxUnavailable: cs.Spec.ScaleStrategy.MaxUnavailable,
48+
DisablePVCReuse: cs.Spec.ScaleStrategy.DisablePVCReuse,
49+
// Convert spec field to v1beta1
50+
ExcludePreparingDelete: cs.Spec.ScaleStrategy.ExcludePreparingDelete,
51+
}
52+
53+
// Convert label to spec field for v1beta1
54+
// If the label is set to "true", set the spec field to true
55+
if cs.Labels != nil && cs.Labels[CloneSetScalingExcludePreparingDeleteKey] == "true" {
56+
csv1beta1.Spec.ScaleStrategy.ExcludePreparingDelete = true
57+
}
58+
59+
// Convert UpdateStrategy
60+
csv1beta1.Spec.UpdateStrategy = v1beta1.CloneSetUpdateStrategy{
61+
Type: v1beta1.CloneSetUpdateStrategyType(cs.Spec.UpdateStrategy.Type),
62+
Partition: cs.Spec.UpdateStrategy.Partition,
63+
MaxUnavailable: cs.Spec.UpdateStrategy.MaxUnavailable,
64+
MaxSurge: cs.Spec.UpdateStrategy.MaxSurge,
65+
Paused: cs.Spec.UpdateStrategy.Paused,
66+
PriorityStrategy: cs.Spec.UpdateStrategy.PriorityStrategy,
67+
ScatterStrategy: convertUpdateScatterStrategyToV1beta1(cs.Spec.UpdateStrategy.ScatterStrategy),
68+
InPlaceUpdateStrategy: cs.Spec.UpdateStrategy.InPlaceUpdateStrategy,
69+
}
70+
71+
// status
72+
csv1beta1.Status = v1beta1.CloneSetStatus{
73+
ObservedGeneration: cs.Status.ObservedGeneration,
74+
Replicas: cs.Status.Replicas,
75+
ReadyReplicas: cs.Status.ReadyReplicas,
76+
AvailableReplicas: cs.Status.AvailableReplicas,
77+
UpdatedReplicas: cs.Status.UpdatedReplicas,
78+
UpdatedReadyReplicas: cs.Status.UpdatedReadyReplicas,
79+
UpdatedAvailableReplicas: cs.Status.UpdatedAvailableReplicas,
80+
ExpectedUpdatedReplicas: cs.Status.ExpectedUpdatedReplicas,
81+
UpdateRevision: cs.Status.UpdateRevision,
82+
CurrentRevision: cs.Status.CurrentRevision,
83+
CollisionCount: cs.Status.CollisionCount,
84+
Conditions: convertCloneSetConditionsToV1beta1(cs.Status.Conditions),
85+
LabelSelector: cs.Status.LabelSelector,
86+
}
87+
88+
return nil
89+
90+
default:
91+
return fmt.Errorf("unsupported type %v", t)
92+
}
93+
}
94+
95+
func (cs *CloneSet) ConvertFrom(src conversion.Hub) error {
96+
switch t := src.(type) {
97+
case *v1beta1.CloneSet:
98+
csv1beta1 := src.(*v1beta1.CloneSet)
99+
cs.ObjectMeta = csv1beta1.ObjectMeta
100+
101+
// spec
102+
cs.Spec = CloneSetSpec{
103+
Replicas: csv1beta1.Spec.Replicas,
104+
Selector: csv1beta1.Spec.Selector,
105+
Template: csv1beta1.Spec.Template,
106+
VolumeClaimTemplates: csv1beta1.Spec.VolumeClaimTemplates,
107+
RevisionHistoryLimit: csv1beta1.Spec.RevisionHistoryLimit,
108+
MinReadySeconds: csv1beta1.Spec.MinReadySeconds,
109+
Lifecycle: csv1beta1.Spec.Lifecycle,
110+
}
111+
112+
// Convert ScaleStrategy
113+
cs.Spec.ScaleStrategy = CloneSetScaleStrategy{
114+
PodsToDelete: csv1beta1.Spec.ScaleStrategy.PodsToDelete,
115+
MaxUnavailable: csv1beta1.Spec.ScaleStrategy.MaxUnavailable,
116+
DisablePVCReuse: csv1beta1.Spec.ScaleStrategy.DisablePVCReuse,
117+
ExcludePreparingDelete: csv1beta1.Spec.ScaleStrategy.ExcludePreparingDelete,
118+
}
119+
120+
// Convert UpdateStrategy
121+
cs.Spec.UpdateStrategy = CloneSetUpdateStrategy{
122+
Type: CloneSetUpdateStrategyType(csv1beta1.Spec.UpdateStrategy.Type),
123+
Partition: csv1beta1.Spec.UpdateStrategy.Partition,
124+
MaxUnavailable: csv1beta1.Spec.UpdateStrategy.MaxUnavailable,
125+
MaxSurge: csv1beta1.Spec.UpdateStrategy.MaxSurge,
126+
Paused: csv1beta1.Spec.UpdateStrategy.Paused,
127+
PriorityStrategy: csv1beta1.Spec.UpdateStrategy.PriorityStrategy,
128+
ScatterStrategy: convertUpdateScatterStrategyFromV1beta1(csv1beta1.Spec.UpdateStrategy.ScatterStrategy),
129+
InPlaceUpdateStrategy: csv1beta1.Spec.UpdateStrategy.InPlaceUpdateStrategy,
130+
}
131+
132+
// status
133+
cs.Status = CloneSetStatus{
134+
ObservedGeneration: csv1beta1.Status.ObservedGeneration,
135+
Replicas: csv1beta1.Status.Replicas,
136+
ReadyReplicas: csv1beta1.Status.ReadyReplicas,
137+
AvailableReplicas: csv1beta1.Status.AvailableReplicas,
138+
UpdatedReplicas: csv1beta1.Status.UpdatedReplicas,
139+
UpdatedReadyReplicas: csv1beta1.Status.UpdatedReadyReplicas,
140+
UpdatedAvailableReplicas: csv1beta1.Status.UpdatedAvailableReplicas,
141+
ExpectedUpdatedReplicas: csv1beta1.Status.ExpectedUpdatedReplicas,
142+
UpdateRevision: csv1beta1.Status.UpdateRevision,
143+
CurrentRevision: csv1beta1.Status.CurrentRevision,
144+
CollisionCount: csv1beta1.Status.CollisionCount,
145+
Conditions: convertCloneSetConditionsFromV1beta1(csv1beta1.Status.Conditions),
146+
LabelSelector: csv1beta1.Status.LabelSelector,
147+
}
148+
149+
return nil
150+
151+
default:
152+
return fmt.Errorf("unsupported type %v", t)
153+
}
154+
}
155+
156+
func convertUpdateScatterStrategyToV1beta1(src UpdateScatterStrategy) v1beta1.UpdateScatterStrategy {
157+
if src == nil {
158+
return nil
159+
}
160+
dst := make(v1beta1.UpdateScatterStrategy, len(src))
161+
for i, term := range src {
162+
dst[i] = v1beta1.UpdateScatterTerm{
163+
Key: term.Key,
164+
Value: term.Value,
165+
}
166+
}
167+
return dst
168+
}
169+
170+
func convertUpdateScatterStrategyFromV1beta1(src v1beta1.UpdateScatterStrategy) UpdateScatterStrategy {
171+
if src == nil {
172+
return nil
173+
}
174+
dst := make(UpdateScatterStrategy, len(src))
175+
for i, term := range src {
176+
dst[i] = UpdateScatterTerm{
177+
Key: term.Key,
178+
Value: term.Value,
179+
}
180+
}
181+
return dst
182+
}
183+
184+
func convertCloneSetConditionsToV1beta1(src []CloneSetCondition) []v1beta1.CloneSetCondition {
185+
if src == nil {
186+
return nil
187+
}
188+
dst := make([]v1beta1.CloneSetCondition, len(src))
189+
for i, condition := range src {
190+
dst[i] = v1beta1.CloneSetCondition{
191+
Type: v1beta1.CloneSetConditionType(condition.Type),
192+
Status: condition.Status,
193+
LastTransitionTime: condition.LastTransitionTime,
194+
Reason: condition.Reason,
195+
Message: condition.Message,
196+
}
197+
}
198+
return dst
199+
}
200+
201+
func convertCloneSetConditionsFromV1beta1(src []v1beta1.CloneSetCondition) []CloneSetCondition {
202+
if src == nil {
203+
return nil
204+
}
205+
dst := make([]CloneSetCondition, len(src))
206+
for i, condition := range src {
207+
dst[i] = CloneSetCondition{
208+
Type: CloneSetConditionType(condition.Type),
209+
Status: condition.Status,
210+
LastTransitionTime: condition.LastTransitionTime,
211+
Reason: condition.Reason,
212+
Message: condition.Message,
213+
}
214+
}
215+
return dst
216+
}

apis/apps/v1alpha1/cloneset_types.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,16 @@ type CloneSetScaleStrategy struct {
9696
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`
9797

9898
// Indicate if cloneSet will reuse already existed pvc to
99-
// rebuild a new pod
100-
DisablePVCReuse bool `json:"disablePVCReuse,omitempty"`
99+
// rebuild a new pod.
100+
// Default is false for v1alpha1 (backward compatibility).
101+
// Note: omitempty is removed to ensure the field is always serialized,
102+
// preventing v1beta1 CRD default from being applied during conversion.
103+
DisablePVCReuse bool `json:"disablePVCReuse"`
104+
105+
// ExcludePreparingDelete indicates whether the CloneSet should calculate scale number excluding Pods in PreparingDelete state.
106+
// Default is false.
107+
// +optional
108+
ExcludePreparingDelete bool `json:"excludePreparingDelete,omitempty"`
101109
}
102110

103111
// CloneSetUpdateStrategy defines strategies for pods update.

0 commit comments

Comments
 (0)