@@ -17,6 +17,9 @@ limitations under the License.
1717package v1alpha1
1818
1919import (
20+ "strconv"
21+ "time"
22+
2023 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2124 "k8s.io/apimachinery/pkg/util/intstr"
2225)
@@ -119,6 +122,10 @@ type StormServiceStatus struct {
119122
120123 // The label selector information of the pods belonging to the StormService object.
121124 ScalingTargetSelector string `json:"scalingTargetSelector,omitempty"`
125+
126+ // CanaryStatus tracks the progress of canary deployments.
127+ // +optional
128+ CanaryStatus * CanaryStatus `json:"canaryStatus,omitempty"`
122129}
123130
124131// These are valid conditions of a stormService.
@@ -146,6 +153,10 @@ type StormServiceUpdateStrategy struct {
146153
147154 // +optional
148155 MaxSurge * intstr.IntOrString `json:"maxSurge,omitempty" protobuf:"bytes,2,opt,name=maxSurge"`
156+
157+ // Canary defines the canary deployment strategy for gradual rollouts.
158+ // +optional
159+ Canary * CanaryUpdateStrategy `json:"canary,omitempty"`
149160}
150161
151162// +enum
@@ -181,6 +192,137 @@ type StormServiceList struct {
181192 Items []StormService `json:"items"`
182193}
183194
195+ // CanaryUpdateStrategy defines the canary deployment configuration
196+ type CanaryUpdateStrategy struct {
197+ // Steps defines the sequence of canary deployment steps
198+ Steps []CanaryStep `json:"steps,omitempty"`
199+ }
200+
201+ // CanaryStep defines a single step in the canary deployment process
202+ type CanaryStep struct {
203+ // SetWeight defines the percentage of traffic/replicas to route to the new version
204+ // +kubebuilder:validation:Minimum=0
205+ // +kubebuilder:validation:Maximum=100
206+ // +optional
207+ SetWeight * int32 `json:"setWeight,omitempty"`
208+
209+ // Pause defines a pause in the canary deployment
210+ // +optional
211+ Pause * PauseStep `json:"pause,omitempty"`
212+ }
213+
214+ // PauseStep defines pause behavior in canary deployments
215+ type PauseStep struct {
216+ // Duration specifies how long to pause
217+ // - String: "30s", "5m", etc. (parsed as time.Duration)
218+ // - Int: seconds as integer
219+ // - nil: manual pause requiring user intervention
220+ // Resume manual pause by setting duration to "0" or 0
221+ // +optional
222+ Duration * intstr.IntOrString `json:"duration,omitempty"`
223+ }
224+
225+ // DurationSeconds converts the pause duration to seconds
226+ // Returns:
227+ // - >= 0: pause duration in seconds
228+ // - 0: manual pause (nil duration) or resume (duration "0"/0)
229+ // - -1: invalid duration string
230+ func (p * PauseStep ) DurationSeconds () int32 {
231+ if p .Duration == nil {
232+ return 0 // Manual pause
233+ }
234+
235+ if p .Duration .Type == intstr .String {
236+ // Try parsing as integer first
237+ if s , err := strconv .ParseInt (p .Duration .StrVal , 10 , 32 ); err == nil {
238+ return int32 (s )
239+ }
240+ // Try parsing as duration string
241+ if d , err := time .ParseDuration (p .Duration .StrVal ); err == nil {
242+ return int32 (d .Seconds ())
243+ }
244+ return - 1 // Invalid string
245+ }
246+
247+ return p .Duration .IntVal
248+ }
249+
250+ // IsManualPause returns true if this is a manual pause (nil duration)
251+ func (p * PauseStep ) IsManualPause () bool {
252+ return p .Duration == nil
253+ }
254+
255+ // IsResume returns true if this represents a resume action (duration 0 or "0")
256+ func (p * PauseStep ) IsResume () bool {
257+ if p .Duration == nil {
258+ return false
259+ }
260+ return p .DurationSeconds () == 0
261+ }
262+
263+ // CanaryStatus tracks the progress of a canary deployment
264+ type CanaryStatus struct {
265+ // CurrentStep is the index of the current step in the canary deployment
266+ // +optional
267+ CurrentStep int32 `json:"currentStep,omitempty"`
268+
269+ // CurrentWeight is the current percentage of traffic/replicas on the new version
270+ // +optional
271+ CurrentWeight int32 `json:"currentWeight,omitempty"`
272+
273+ // PausedAt indicates when the canary deployment was paused
274+ // +optional
275+ PausedAt * metav1.Time `json:"pausedAt,omitempty"`
276+
277+ // PauseConditions indicates the reasons why the canary deployment is paused
278+ // +optional
279+ PauseConditions []PauseCondition `json:"pauseConditions,omitempty"`
280+
281+ // StableRevision is the revision of the stable/old version
282+ // +optional
283+ StableRevision string `json:"stableRevision,omitempty"`
284+
285+ // CanaryRevision is the revision of the canary/new version
286+ // +optional
287+ CanaryRevision string `json:"canaryRevision,omitempty"`
288+
289+ // Phase indicates the current phase of the canary deployment
290+ // +optional
291+ Phase CanaryPhase `json:"phase,omitempty"`
292+ }
293+
294+ // CanaryPhase represents the phase of a canary deployment
295+ // +enum
296+ type CanaryPhase string
297+
298+ const (
299+ // CanaryPhaseInitializing indicates the canary deployment is starting
300+ CanaryPhaseInitializing CanaryPhase = "Initializing"
301+ // CanaryPhaseProgressing indicates the canary deployment is progressing through steps
302+ CanaryPhaseProgressing CanaryPhase = "Progressing"
303+ // CanaryPhasePaused indicates the canary deployment is paused
304+ CanaryPhasePaused CanaryPhase = "Paused"
305+ // CanaryPhaseCompleted indicates the canary deployment has completed successfully
306+ CanaryPhaseCompleted CanaryPhase = "Completed"
307+ )
308+
309+ // PauseReason represents the reason for a pause condition
310+ // +enum
311+ type PauseReason string
312+
313+ const (
314+ // PauseReasonCanaryPauseStep indicates a pause at a canary step
315+ PauseReasonCanaryPauseStep PauseReason = "CanaryPauseStep"
316+ )
317+
318+ // PauseCondition represents a pause condition in the canary deployment
319+ type PauseCondition struct {
320+ // Reason indicates why the canary deployment was paused
321+ Reason PauseReason `json:"reason"`
322+ // StartTime is when the pause condition was added
323+ StartTime metav1.Time `json:"startTime"`
324+ }
325+
184326func init () {
185327 SchemeBuilder .Register (& StormService {}, & StormServiceList {})
186328}
0 commit comments