Skip to content

Commit ffc7479

Browse files
authored
interface: start/stop API for updateRun (#314)
1 parent 9caeb4e commit ffc7479

6 files changed

+468
-19
lines changed

apis/placement/v1beta1/stageupdate_types.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ type UpdateRunObjList interface {
9292
// +kubebuilder:printcolumn:JSONPath=`.spec.resourceSnapshotIndex`,name="Resource-Snapshot-Index",type=string
9393
// +kubebuilder:printcolumn:JSONPath=`.status.policySnapshotIndexUsed`,name="Policy-Snapshot-Index",type=string
9494
// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Initialized")].status`,name="Initialized",type=string
95+
// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Progressing")].status`,name="Progressing",type=string
9596
// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Succeeded")].status`,name="Succeeded",type=string
9697
// +kubebuilder:printcolumn:JSONPath=`.metadata.creationTimestamp`,name="Age",type=date
9798
// +kubebuilder:printcolumn:JSONPath=`.spec.stagedRolloutStrategyName`,name="Strategy",priority=1,type=string
@@ -107,9 +108,8 @@ type ClusterStagedUpdateRun struct {
107108
metav1.TypeMeta `json:",inline"`
108109
metav1.ObjectMeta `json:"metadata,omitempty"`
109110

110-
// The desired state of ClusterStagedUpdateRun. The spec is immutable.
111+
// The desired state of ClusterStagedUpdateRun.
111112
// +kubebuilder:validation:Required
112-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="The spec field is immutable"
113113
Spec UpdateRunSpec `json:"spec"`
114114

115115
// The observed status of ClusterStagedUpdateRun.
@@ -147,27 +147,66 @@ func (c *ClusterStagedUpdateRun) SetUpdateRunStatus(status UpdateRunStatus) {
147147
c.Status = status
148148
}
149149

150+
// State represents the desired state of an update run.
151+
// +enum
152+
type State string
153+
154+
const (
155+
// StateNotStarted describes user intent to initialize but not execute the update run.
156+
// This is the default state when an update run is created.
157+
StateNotStarted State = "NotStarted"
158+
159+
// StateStarted describes user intent to execute (or resume execution if paused).
160+
// Users can subsequently set the state to Stopped or Abandoned.
161+
StateStarted State = "Started"
162+
163+
// StateStopped describes user intent to pause the update run.
164+
// Users can subsequently set the state to Started or Abandoned.
165+
StateStopped State = "Stopped"
166+
167+
// StateAbandoned describes user intent to abandon the update run.
168+
// This is a terminal state; once set, it cannot be changed.
169+
StateAbandoned State = "Abandoned"
170+
)
171+
150172
// UpdateRunSpec defines the desired rollout strategy and the snapshot indices of the resources to be updated.
151173
// It specifies a stage-by-stage update process across selected clusters for the given ResourcePlacement object.
174+
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.state) || oldSelf.state != 'NotStarted' || self.state != 'Stopped'",message="invalid state transition: cannot transition from NotStarted to Stopped"
175+
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.state) || oldSelf.state != 'Started' || self.state != 'NotStarted'",message="invalid state transition: cannot transition from Started to NotStarted"
176+
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.state) || oldSelf.state != 'Stopped' || self.state != 'NotStarted'",message="invalid state transition: cannot transition from Stopped to NotStarted"
177+
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.state) || oldSelf.state != 'Abandoned' || self.state == 'Abandoned'",message="invalid state transition: Abandoned is a terminal state and cannot transition to any other state"
152178
type UpdateRunSpec struct {
153179
// PlacementName is the name of placement that this update run is applied to.
154180
// There can be multiple active update runs for each placement, but
155181
// it's up to the DevOps team to ensure they don't conflict with each other.
156182
// +kubebuilder:validation:Required
157183
// +kubebuilder:validation:MaxLength=255
184+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="placementName is immutable"
158185
PlacementName string `json:"placementName"`
159186

160187
// The resource snapshot index of the selected resources to be updated across clusters.
161188
// The index represents a group of resource snapshots that includes all the resources a ResourcePlacement selected.
162189
// +kubebuilder:validation:Required
190+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="resourceSnapshotIndex is immutable"
163191
ResourceSnapshotIndex string `json:"resourceSnapshotIndex"`
164192

165193
// The name of the update strategy that specifies the stages and the sequence
166194
// in which the selected resources will be updated on the member clusters. The stages
167195
// are computed according to the referenced strategy when the update run starts
168196
// and recorded in the status field.
169197
// +kubebuilder:validation:Required
198+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="stagedRolloutStrategyName is immutable"
170199
StagedUpdateStrategyName string `json:"stagedRolloutStrategyName"`
200+
201+
// State indicates the desired state of the update run.
202+
// NotStarted: The update run is initialized but execution has not started (default).
203+
// Started: The update run should execute or resume execution.
204+
// Stopped: The update run should pause execution.
205+
// Abandoned: The update run should be abandoned and terminated.
206+
// +kubebuilder:validation:Optional
207+
// +kubebuilder:default=NotStarted
208+
// +kubebuilder:validation:Enum=NotStarted;Started;Stopped;Abandoned
209+
State State `json:"state,omitempty"`
171210
}
172211

173212
// UpdateStrategySpecGetterSetter offers the functionality to work with UpdateStrategySpec.
@@ -387,7 +426,7 @@ const (
387426
// StagedUpdateRunConditionProgressing indicates whether the staged update run is making progress.
388427
// Its condition status can be one of the following:
389428
// - "True": The staged update run is making progress.
390-
// - "False": The staged update run is waiting/paused.
429+
// - "False": The staged update run is waiting/paused/abandoned.
391430
// - "Unknown" means it is unknown.
392431
StagedUpdateRunConditionProgressing StagedUpdateRunConditionType = "Progressing"
393432

@@ -746,6 +785,7 @@ func (c *ClusterApprovalRequestList) GetApprovalRequestObjs() []ApprovalRequestO
746785
// +kubebuilder:printcolumn:JSONPath=`.spec.resourceSnapshotIndex`,name="Resource-Snapshot-Index",type=string
747786
// +kubebuilder:printcolumn:JSONPath=`.status.policySnapshotIndexUsed`,name="Policy-Snapshot-Index",type=string
748787
// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Initialized")].status`,name="Initialized",type=string
788+
// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Progressing")].status`,name="Progressing",type=string
749789
// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Succeeded")].status`,name="Succeeded",type=string
750790
// +kubebuilder:printcolumn:JSONPath=`.metadata.creationTimestamp`,name="Age",type=date
751791
// +kubebuilder:printcolumn:JSONPath=`.spec.stagedRolloutStrategyName`,name="Strategy",priority=1,type=string
@@ -761,9 +801,8 @@ type StagedUpdateRun struct {
761801
metav1.TypeMeta `json:",inline"`
762802
metav1.ObjectMeta `json:"metadata,omitempty"`
763803

764-
// The desired state of StagedUpdateRun. The spec is immutable.
804+
// The desired state of StagedUpdateRun.
765805
// +kubebuilder:validation:Required
766-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="The spec field is immutable"
767806
Spec UpdateRunSpec `json:"spec"`
768807

769808
// The observed status of StagedUpdateRun.

config/crd/bases/placement.kubernetes-fleet.io_clusterstagedupdateruns.yaml

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,9 @@ spec:
11121112
- jsonPath: .status.conditions[?(@.type=="Initialized")].status
11131113
name: Initialized
11141114
type: string
1115+
- jsonPath: .status.conditions[?(@.type=="Progressing")].status
1116+
name: Progressing
1117+
type: string
11151118
- jsonPath: .status.conditions[?(@.type=="Succeeded")].status
11161119
name: Succeeded
11171120
type: string
@@ -1151,8 +1154,7 @@ spec:
11511154
metadata:
11521155
type: object
11531156
spec:
1154-
description: The desired state of ClusterStagedUpdateRun. The spec is
1155-
immutable.
1157+
description: The desired state of ClusterStagedUpdateRun.
11561158
properties:
11571159
placementName:
11581160
description: |-
@@ -1161,26 +1163,63 @@ spec:
11611163
it's up to the DevOps team to ensure they don't conflict with each other.
11621164
maxLength: 255
11631165
type: string
1166+
x-kubernetes-validations:
1167+
- message: placementName is immutable
1168+
rule: self == oldSelf
11641169
resourceSnapshotIndex:
11651170
description: |-
11661171
The resource snapshot index of the selected resources to be updated across clusters.
11671172
The index represents a group of resource snapshots that includes all the resources a ResourcePlacement selected.
11681173
type: string
1174+
x-kubernetes-validations:
1175+
- message: resourceSnapshotIndex is immutable
1176+
rule: self == oldSelf
11691177
stagedRolloutStrategyName:
11701178
description: |-
11711179
The name of the update strategy that specifies the stages and the sequence
11721180
in which the selected resources will be updated on the member clusters. The stages
11731181
are computed according to the referenced strategy when the update run starts
11741182
and recorded in the status field.
11751183
type: string
1184+
x-kubernetes-validations:
1185+
- message: stagedRolloutStrategyName is immutable
1186+
rule: self == oldSelf
1187+
state:
1188+
default: NotStarted
1189+
description: |-
1190+
State indicates the desired state of the update run.
1191+
NotStarted: The update run is initialized but execution has not started (default).
1192+
Started: The update run should execute or resume execution.
1193+
Stopped: The update run should pause execution.
1194+
Abandoned: The update run should be abandoned and terminated.
1195+
enum:
1196+
- NotStarted
1197+
- Started
1198+
- Stopped
1199+
- Abandoned
1200+
type: string
11761201
required:
11771202
- placementName
11781203
- resourceSnapshotIndex
11791204
- stagedRolloutStrategyName
11801205
type: object
11811206
x-kubernetes-validations:
1182-
- message: The spec field is immutable
1183-
rule: self == oldSelf
1207+
- message: 'invalid state transition: cannot transition from NotStarted
1208+
to Stopped'
1209+
rule: '!has(oldSelf.state) || oldSelf.state != ''NotStarted'' || self.state
1210+
!= ''Stopped'''
1211+
- message: 'invalid state transition: cannot transition from Started to
1212+
NotStarted'
1213+
rule: '!has(oldSelf.state) || oldSelf.state != ''Started'' || self.state
1214+
!= ''NotStarted'''
1215+
- message: 'invalid state transition: cannot transition from Stopped to
1216+
NotStarted'
1217+
rule: '!has(oldSelf.state) || oldSelf.state != ''Stopped'' || self.state
1218+
!= ''NotStarted'''
1219+
- message: 'invalid state transition: Abandoned is a terminal state and
1220+
cannot transition to any other state'
1221+
rule: '!has(oldSelf.state) || oldSelf.state != ''Abandoned'' || self.state
1222+
== ''Abandoned'''
11841223
status:
11851224
description: The observed status of ClusterStagedUpdateRun.
11861225
properties:
@@ -1998,7 +2037,7 @@ spec:
19982037
description: |-
19992038
MaxConcurrency specifies the maximum number of clusters that can be updated concurrently within this stage.
20002039
Value can be an absolute number (ex: 5) or a percentage of the total clusters in the stage (ex: 50%).
2001-
Absolute number is calculated from percentage by rounding up.
2040+
Fractional results are rounded down. A minimum of 1 update is enforced.
20022041
If not specified, all clusters in the stage are updated sequentially (effectively maxConcurrency = 1).
20032042
Defaults to 1.
20042043
pattern: ^((100|[0-9]{1,2})%|[0-9]+)$

config/crd/bases/placement.kubernetes-fleet.io_clusterstagedupdatestrategies.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ spec:
312312
description: |-
313313
MaxConcurrency specifies the maximum number of clusters that can be updated concurrently within this stage.
314314
Value can be an absolute number (ex: 5) or a percentage of the total clusters in the stage (ex: 50%).
315-
Absolute number is calculated from percentage by rounding up.
315+
Fractional results are rounded down. A minimum of 1 update is enforced.
316316
If not specified, all clusters in the stage are updated sequentially (effectively maxConcurrency = 1).
317317
Defaults to 1.
318318
pattern: ^((100|[0-9]{1,2})%|[0-9]+)$

config/crd/bases/placement.kubernetes-fleet.io_stagedupdateruns.yaml

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ spec:
3232
- jsonPath: .status.conditions[?(@.type=="Initialized")].status
3333
name: Initialized
3434
type: string
35+
- jsonPath: .status.conditions[?(@.type=="Progressing")].status
36+
name: Progressing
37+
type: string
3538
- jsonPath: .status.conditions[?(@.type=="Succeeded")].status
3639
name: Succeeded
3740
type: string
@@ -71,7 +74,7 @@ spec:
7174
metadata:
7275
type: object
7376
spec:
74-
description: The desired state of StagedUpdateRun. The spec is immutable.
77+
description: The desired state of StagedUpdateRun.
7578
properties:
7679
placementName:
7780
description: |-
@@ -80,26 +83,63 @@ spec:
8083
it's up to the DevOps team to ensure they don't conflict with each other.
8184
maxLength: 255
8285
type: string
86+
x-kubernetes-validations:
87+
- message: placementName is immutable
88+
rule: self == oldSelf
8389
resourceSnapshotIndex:
8490
description: |-
8591
The resource snapshot index of the selected resources to be updated across clusters.
8692
The index represents a group of resource snapshots that includes all the resources a ResourcePlacement selected.
8793
type: string
94+
x-kubernetes-validations:
95+
- message: resourceSnapshotIndex is immutable
96+
rule: self == oldSelf
8897
stagedRolloutStrategyName:
8998
description: |-
9099
The name of the update strategy that specifies the stages and the sequence
91100
in which the selected resources will be updated on the member clusters. The stages
92101
are computed according to the referenced strategy when the update run starts
93102
and recorded in the status field.
94103
type: string
104+
x-kubernetes-validations:
105+
- message: stagedRolloutStrategyName is immutable
106+
rule: self == oldSelf
107+
state:
108+
default: NotStarted
109+
description: |-
110+
State indicates the desired state of the update run.
111+
NotStarted: The update run is initialized but execution has not started (default).
112+
Started: The update run should execute or resume execution.
113+
Stopped: The update run should pause execution.
114+
Abandoned: The update run should be abandoned and terminated.
115+
enum:
116+
- NotStarted
117+
- Started
118+
- Stopped
119+
- Abandoned
120+
type: string
95121
required:
96122
- placementName
97123
- resourceSnapshotIndex
98124
- stagedRolloutStrategyName
99125
type: object
100126
x-kubernetes-validations:
101-
- message: The spec field is immutable
102-
rule: self == oldSelf
127+
- message: 'invalid state transition: cannot transition from NotStarted
128+
to Stopped'
129+
rule: '!has(oldSelf.state) || oldSelf.state != ''NotStarted'' || self.state
130+
!= ''Stopped'''
131+
- message: 'invalid state transition: cannot transition from Started to
132+
NotStarted'
133+
rule: '!has(oldSelf.state) || oldSelf.state != ''Started'' || self.state
134+
!= ''NotStarted'''
135+
- message: 'invalid state transition: cannot transition from Stopped to
136+
NotStarted'
137+
rule: '!has(oldSelf.state) || oldSelf.state != ''Stopped'' || self.state
138+
!= ''NotStarted'''
139+
- message: 'invalid state transition: Abandoned is a terminal state and
140+
cannot transition to any other state'
141+
rule: '!has(oldSelf.state) || oldSelf.state != ''Abandoned'' || self.state
142+
== ''Abandoned'''
103143
status:
104144
description: The observed status of StagedUpdateRun.
105145
properties:
@@ -917,7 +957,7 @@ spec:
917957
description: |-
918958
MaxConcurrency specifies the maximum number of clusters that can be updated concurrently within this stage.
919959
Value can be an absolute number (ex: 5) or a percentage of the total clusters in the stage (ex: 50%).
920-
Absolute number is calculated from percentage by rounding up.
960+
Fractional results are rounded down. A minimum of 1 update is enforced.
921961
If not specified, all clusters in the stage are updated sequentially (effectively maxConcurrency = 1).
922962
Defaults to 1.
923963
pattern: ^((100|[0-9]{1,2})%|[0-9]+)$

config/crd/bases/placement.kubernetes-fleet.io_stagedupdatestrategies.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ spec:
174174
description: |-
175175
MaxConcurrency specifies the maximum number of clusters that can be updated concurrently within this stage.
176176
Value can be an absolute number (ex: 5) or a percentage of the total clusters in the stage (ex: 50%).
177-
Absolute number is calculated from percentage by rounding up.
177+
Fractional results are rounded down. A minimum of 1 update is enforced.
178178
If not specified, all clusters in the stage are updated sequentially (effectively maxConcurrency = 1).
179179
Defaults to 1.
180180
pattern: ^((100|[0-9]{1,2})%|[0-9]+)$

0 commit comments

Comments
 (0)