Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 83
⚠️ ClusterExtensionRevision API Updates#2491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -42,14 +42,18 @@ const ( | ||
| type ClusterExtensionRevisionSpec struct { | ||
| // lifecycleState specifies the lifecycle state of the ClusterExtensionRevision. | ||
| // | ||
| // When set to "Active" (the default), the revision is actively managed and reconciled. | ||
| // When set to "Active", the revision is actively managed and reconciled. | ||
| // When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted. | ||
| // The revision is removed from the owner list of all objects previously under management. | ||
| // All objects that did not transition to a succeeding revision are deleted. | ||
| // | ||
| // Once a revision is set to "Archived", it cannot be un-archived. | ||
| // | ||
| // +kubebuilder:default="Active" | ||
| // It is possible for more than one revision to be "Active" simultaneously. This will occur when | ||
| // moving from one revision to another. The old revision will not be set to "Archived" until the | ||
| // new revision has been completely rolled out. | ||
| // | ||
| // +required | ||
| // +kubebuilder:validation:Enum=Active;Archived | ||
| // +kubebuilder:validation:XValidation:rule="oldSelf == 'Active' || oldSelf == 'Archived' && oldSelf == self", message="cannot un-archive" | ||
| LifecycleState ClusterExtensionRevisionLifecycleState `json:"lifecycleState,omitempty"` | ||
| @@ -82,7 +86,10 @@ type ClusterExtensionRevisionSpec struct { | ||
| // | ||
| // Once set, even if empty, the phases field is immutable. | ||
| // | ||
| // Each phase in the list must have a unique name. The maximum number of phases is 20. | ||
| // | ||
| // +kubebuilder:validation:XValidation:rule="self == oldSelf || oldSelf.size() == 0", message="phases is immutable" | ||
| // +kubebuilder:validation:MaxItems=20 | ||
| // +listType=map | ||
| // +listMapKey=name | ||
| // +optional | ||
| @@ -125,13 +132,17 @@ type ClusterExtensionRevisionPhase struct { | ||
| // | ||
| // [RFC 1123]: https://tools.ietf.org/html/rfc1123 | ||
| // | ||
| // +required | ||
| // +kubebuilder:validation:MinLength=1 | ||
| // +kubebuilder:validation:MaxLength=63 | ||
| // +kubebuilder:validation:Pattern=`^[a-z]([-a-z0-9]*[a-z0-9])?$` | ||
| // +kubebuilder:validation:XValidation:rule=`!format.dns1123Label().validate(self).hasValue()`,message="the value must consist of only lowercase alphanumeric characters and hyphens, and must start with an alphabetic character and end with an alphanumeric character." | ||
| Name string `json:"name"` | ||
dtfranz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| // objects is a required list of all Kubernetes objects that belong to this phase. | ||
| // | ||
| // All objects in this list are applied to the cluster in no particular order. | ||
| // All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50. | ||
| // +required | ||
| // +kubebuilder:validation:MaxItems=50 | ||
pedjak marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Objects []ClusterExtensionRevisionObject `json:"objects"` | ||
| } | ||
| @@ -149,7 +160,9 @@ type ClusterExtensionRevisionObject struct { | ||
| // collisionProtection controls whether the operator can adopt and modify objects | ||
| // that already exist on the cluster. | ||
| // | ||
| // When set to "Prevent" (the default), the operator only manages objects it created itself. | ||
| // Allowed values are: "Prevent", "IfNoController", and "None". | ||
| // | ||
| // When set to "Prevent", the operator only manages objects it created itself. | ||
| // This prevents ownership collisions. | ||
| // | ||
| // When set to "IfNoController", the operator can adopt and modify pre-existing objects | ||
| @@ -161,9 +174,8 @@ type ClusterExtensionRevisionObject struct { | ||
| // Use this setting with extreme caution as it may cause multiple controllers to fight over | ||
| // the same resource, resulting in increased load on the API server and etcd. | ||
| // | ||
| // +kubebuilder:default="Prevent" | ||
| // +required | ||
| // +kubebuilder:validation:Enum=Prevent;IfNoController;None | ||
| // +optional | ||
| CollisionProtection CollisionProtection `json:"collisionProtection,omitempty"` | ||
pedjak marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. dtfranz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
dtfranz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -21,16 +21,18 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) { | ||
| }{ | ||
| "revision is immutable": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| Revision: 1, | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| }, | ||
| updateFunc: func(cer *ClusterExtensionRevision) { | ||
| cer.Spec.Revision = 2 | ||
| }, | ||
| }, | ||
| "phases may be initially empty": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| Revision: 1, | ||
| Phases: []ClusterExtensionRevisionPhase{}, | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| Phases: []ClusterExtensionRevisionPhase{}, | ||
| }, | ||
| updateFunc: func(cer *ClusterExtensionRevision) { | ||
| cer.Spec.Phases = []ClusterExtensionRevisionPhase{ | ||
| @@ -44,7 +46,8 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) { | ||
| }, | ||
| "phases may be initially unset": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| Revision: 1, | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| }, | ||
| updateFunc: func(cer *ClusterExtensionRevision) { | ||
| cer.Spec.Phases = []ClusterExtensionRevisionPhase{ | ||
| @@ -58,7 +61,8 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) { | ||
| }, | ||
| "phases are immutable if not empty": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| Revision: 1, | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| Phases: []ClusterExtensionRevisionPhase{ | ||
| { | ||
| Name: "foo", | ||
| @@ -107,20 +111,87 @@ func TestClusterExtensionRevisionValidity(t *testing.T) { | ||
| }{ | ||
| "revision cannot be negative": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| Revision: -1, | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: -1, | ||
| }, | ||
| valid: false, | ||
| }, | ||
| "revision cannot be zero": { | ||
| spec: ClusterExtensionRevisionSpec{}, | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| }, | ||
| valid: false, | ||
| }, | ||
| "revision must be positive": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| Revision: 1, | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| }, | ||
| valid: true, | ||
| }, | ||
| "lifecycleState must be set": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| Revision: 1, | ||
| }, | ||
| valid: false, | ||
| }, | ||
| "phases must have no more than 20 phases": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| Phases: make([]ClusterExtensionRevisionPhase, 21), | ||
| }, | ||
| valid: false, | ||
| }, | ||
Comment on lines
+138
to
+145
CopilotAI | ||
| "phases entries must have no more than 50 objects": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| Phases: []ClusterExtensionRevisionPhase{ | ||
| { | ||
| Name: "too-many-objects", | ||
| Objects: make([]ClusterExtensionRevisionObject, 51), | ||
| }, | ||
| }, | ||
| }, | ||
| valid: false, | ||
| }, | ||
Comment on lines
+146
to
+158
CopilotAI | ||
| "phases entry names cannot be empty": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| Phases: []ClusterExtensionRevisionPhase{ | ||
| { | ||
| Name: "", | ||
| }, | ||
| }, | ||
| }, | ||
| valid: false, | ||
| }, | ||
| "phases entry names cannot start with symbols": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| Phases: []ClusterExtensionRevisionPhase{ | ||
| { | ||
| Name: "-invalid", | ||
| }, | ||
| }, | ||
| }, | ||
| valid: false, | ||
| }, | ||
| "phases entry names cannot start with numeric characters": { | ||
| spec: ClusterExtensionRevisionSpec{ | ||
| LifecycleState: ClusterExtensionRevisionLifecycleStateActive, | ||
| Revision: 1, | ||
| Phases: []ClusterExtensionRevisionPhase{ | ||
| { | ||
| Name: "1-invalid", | ||
| }, | ||
| }, | ||
| }, | ||
| valid: false, | ||
| }, | ||
| } { | ||
| t.Run(name, func(t *testing.T) { | ||
| cer := &ClusterExtensionRevision{ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -57,16 +57,19 @@ spec: | ||
| description: spec defines the desired state of the ClusterExtensionRevision. | ||
| properties: | ||
| lifecycleState: | ||
| default: Active | ||
| description: |- | ||
| lifecycleState specifies the lifecycle state of the ClusterExtensionRevision. | ||
| When set to "Active" (the default), the revision is actively managed and reconciled. | ||
| When set to "Active", the revision is actively managed and reconciled. | ||
| When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted. | ||
| The revision is removed from the owner list of all objects previously under management. | ||
| All objects that did not transition to a succeeding revision are deleted. | ||
| Once a revision is set to "Archived", it cannot be un-archived. | ||
| It is possible for more than one revision to be "Active" simultaneously. This will occur when | ||
| moving from one revision to another. The old revision will not be set to "Archived" until the | ||
| new revision has been completely rolled out. | ||
| enum: | ||
| - Active | ||
| - Archived | ||
| @@ -92,6 +95,8 @@ spec: | ||
| The revision progresses to the next phase only after all objects in the current phase pass their readiness probes. | ||
| Once set, even if empty, the phases field is immutable. | ||
| Each phase in the list must have a unique name. The maximum number of phases is 20. | ||
| items: | ||
| description: |- | ||
| ClusterExtensionRevisionPhase represents a group of objects that are applied together. The phase is considered | ||
| @@ -109,25 +114,31 @@ spec: | ||
| [RFC 1123]: https://tools.ietf.org/html/rfc1123 | ||
| maxLength: 63 | ||
| pattern: ^[a-z]([-a-z0-9]*[a-z0-9])?$ | ||
| minLength: 1 | ||
| type: string | ||
| x-kubernetes-validations: | ||
| - message: the value must consist of only lowercase alphanumeric | ||
| characters and hyphens, and must start with an alphabetic | ||
| character and end with an alphanumeric character. | ||
dtfranz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| rule: '!format.dns1123Label().validate(self).hasValue()' | ||
| objects: | ||
| description: |- | ||
| objects is a required list of all Kubernetes objects that belong to this phase. | ||
| All objects in this list are applied to the cluster in no particular order. | ||
| All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50. | ||
| items: | ||
| description: |- | ||
| ClusterExtensionRevisionObject represents a Kubernetes object to be applied as part | ||
| of a phase, along with its collision protection settings. | ||
| properties: | ||
| collisionProtection: | ||
| default: Prevent | ||
| description: |- | ||
| collisionProtection controls whether the operator can adopt and modify objects | ||
| that already exist on the cluster. | ||
| When set to "Prevent" (the default), the operator only manages objects it created itself. | ||
| Allowed values are: "Prevent", "IfNoController", and "None". | ||
| When set to "Prevent", the operator only manages objects it created itself. | ||
| This prevents ownership collisions. | ||
| When set to "IfNoController", the operator can adopt and modify pre-existing objects | ||
| @@ -152,13 +163,16 @@ spec: | ||
| x-kubernetes-embedded-resource: true | ||
| x-kubernetes-preserve-unknown-fields: true | ||
| required: | ||
| - collisionProtection | ||
| - object | ||
| type: object | ||
| maxItems: 50 | ||
| type: array | ||
| required: | ||
| - name | ||
| - objects | ||
| type: object | ||
| maxItems: 20 | ||
| type: array | ||
| x-kubernetes-list-map-keys: | ||
| - name | ||
| @@ -191,6 +205,7 @@ spec: | ||
| - message: revision is immutable | ||
| rule: self == oldSelf | ||
| required: | ||
| - lifecycleState | ||
| - revision | ||
| type: object | ||
| status: | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.