Repository navigation
✨ Enrich ObservedPhase with Status, CompletedAt, Message, and PhaseStatus #3044
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -557,10 +557,11 @@ type ClusterObjectSetStatus struct { | |
| // | ||
| // +kubebuilder:validation:XValidation:rule="self == oldSelf || oldSelf == null",message="completedAt is immutable" | ||
| // +optional | ||
| CompletedAt metav1.Time `json:"completedAt,omitempty,omitzero"` | ||
| CompletedAt metav1.Time `json:"completedAt,omitzero"` | ||
| } | ||
|
|
||
| // ObservedPhase records the observed content digest of a resolved phase. | ||
| // +kubebuilder:validation:XValidation:rule="!has(oldSelf.completedAt) || has(self.completedAt)",message="completedAt cannot be removed once set" | ||
| type ObservedPhase struct { | ||
| // name is the phase name matching a phase in spec.phases. | ||
| // | ||
|
|
@@ -570,6 +571,28 @@ type ObservedPhase struct { | |
| // +kubebuilder:validation:XValidation:rule=`!format.dns1123Label().validate(self).hasValue()`,message="the value must consist of only lowercase alphanumeric characters and hyphens, and must start and end with an alphanumeric character." | ||
| Name string `json:"name"` | ||
|
|
||
| // status is the current state of this phase in the rollout. Must be one of | ||
| // InvalidSpecification, PreconditionsNotMet, Pending, Reconciling, | ||
| // Stabilizing, Ready, Unknown, Superseded, Archiving, or Archived. | ||
| // +required | ||
| Status PhaseStatus `json:"status"` | ||
|
|
||
| // completedAt is the timestamp when this phase first became Ready. | ||
| // Set once and never cleared. Nil means the phase has never been | ||
| // Ready. | ||
| // +optional | ||
| // +kubebuilder:validation:XValidation:rule="self == oldSelf || oldSelf == null",message="completedAt is immutable" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think oldSelf is ever null - maybe "self == oldSelf" is enough? Does the object-scoped rule already cover this? |
||
| CompletedAt metav1.Time `json:"completedAt,omitzero"` | ||
|
|
||
| // message is a phase-level message providing context about the | ||
| // current status (e.g. a validation error for Invalid phases, or | ||
| // a summary for Pending phases). At most 1024 characters; longer | ||
| // messages are truncated by the controller. | ||
| // +kubebuilder:validation:MinLength=1 | ||
| // +kubebuilder:validation:MaxLength=1024 | ||
| // +optional | ||
| Message string `json:"message,omitempty"` | ||
|
dtfranz marked this conversation as resolved.
|
||
|
|
||
| // digest is the digest of the phase's resolved object content | ||
| // at first successful resolution, in the format "<algorithm>:<hex>". | ||
| // | ||
|
|
@@ -581,10 +604,14 @@ type ObservedPhase struct { | |
| Digest string `json:"digest"` | ||
|
|
||
| // objectCounts reports the number of objects in this phase by state. | ||
| // It is omitted until counts have been computed; when present, all count | ||
| // fields are reported (including zeros). | ||
| // +optional | ||
| ObjectCounts ObjectCounts `json:"objectCounts,omitzero"` | ||
|
|
||
| // lastTransitionTime is the last time the phase transitioned from one status to another. | ||
| // +required | ||
| // +kubebuilder:validation:Type=string | ||
| // +kubebuilder:validation:Format=date-time | ||
| LastTransitionTime metav1.Time `json:"lastTransitionTime,omitzero"` | ||
| } | ||
|
|
||
| // ObjectCounts reports the number of objects in a ClusterObjectSet or phase by state. | ||
|
|
@@ -596,16 +623,16 @@ type ObjectCounts struct { | |
| Total int64 `json:"total"` | ||
|
|
||
| // present is the number of objects in this phase that exist on the | ||
| // cluster. During reconcile, this counts objects that the controller | ||
| // has found or created. During teardown, this decrements toward zero | ||
| // as objects are deleted. | ||
| // cluster and are owned by this object set, or another in the same group. | ||
| // During reconcile, this counts objects that the controller has found or | ||
| // created. During teardown, this decrements toward zero as objects are deleted. | ||
| // +required | ||
| // +kubebuilder:validation:Minimum:=0 | ||
| // +kubebuilder:validation:Maximum:=1000 | ||
| Present int64 `json:"present"` | ||
|
|
||
| // synced is the number of objects in this phase whose cluster state | ||
| // matches the desired state. | ||
| // matches the desired state. Set to zero during teardown. | ||
| // +required | ||
| // +kubebuilder:validation:Minimum:=0 | ||
| // +kubebuilder:validation:Maximum:=1000 | ||
|
|
@@ -619,6 +646,54 @@ type ObjectCounts struct { | |
| Ready int64 `json:"ready"` | ||
| } | ||
|
|
||
| // PhaseStatus describes the current state of a phase in the rollout. | ||
| // | ||
| // +kubebuilder:validation:Enum=InvalidSpecification;Pending;Reconciling;Stabilizing;Ready;Unknown;Superseded;Archiving;Archived | ||
| type PhaseStatus string | ||
|
|
||
| const ( | ||
| // PhaseStatusInvalidSpecification indicates the phase failed preflight validation | ||
| // in a permanent way (e.g. cross-phase duplication). | ||
| PhaseStatusInvalidSpecification PhaseStatus = "InvalidSpecification" | ||
|
|
||
| // PhaseStatusPending indicates the phase is not being actively | ||
| // reconciled, but the controller has checked and some objects do not | ||
| // match the desired state. The objectDetails field lists what would | ||
| // need to change. | ||
| PhaseStatusPending PhaseStatus = "Pending" | ||
|
|
||
| // PhaseStatusReconciling indicates the controller is actively applying | ||
| // objects in this phase and not all objects are synced yet. | ||
| PhaseStatusReconciling PhaseStatus = "Reconciling" | ||
|
|
||
| // PhaseStatusStabilizing indicates all objects in this phase are | ||
| // synced but some assertions are not yet passing. The controller is | ||
| // not actively writing; it is waiting for other controllers or | ||
| // external actions to bring the objects into the expected state. | ||
| PhaseStatusStabilizing PhaseStatus = "Stabilizing" | ||
|
|
||
| // PhaseStatusReady indicates all objects in this phase are synced | ||
| // and pass their assertions. | ||
| PhaseStatusReady PhaseStatus = "Ready" | ||
|
|
||
| // PhaseStatusUnknown indicates this phase was not evaluated during | ||
| // the most recent reconcile. | ||
| PhaseStatusUnknown PhaseStatus = "Unknown" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we're currently not setting this status in the code |
||
|
|
||
| // PhaseStatusSuperseded indicates all objects in this phase have been | ||
| // adopted by a newer revision. | ||
| PhaseStatusSuperseded PhaseStatus = "Superseded" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you're saying that in a given phase we may have both objects that have been superseded by the subsequent revision and some that have been archived instead? If we aren't avoiding the use of
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point @dtfranz. The assumption here is that there is no use to differentiate between "Superseded" and "Archived", as once the objects are either taken over or deleted it changes nothing for the Phase: seems clear that the assumption holds to me, making it explicit to double check.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean, for example, rev-1.phase-1 has objects {a, b, c, d} and rev-2.phase-1 has objects {a, b, c} rev-1.phase-1 will never has a HasTransitioned() == true because object d isn't present in rev-2. So, I'm wondering whether a phase is superseded once any of its objects is now owned by a subsequent revision.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can stick to the current semantic - but this is something we'll probably want to revisit |
||
|
|
||
| // PhaseStatusArchiving indicates the controller is actively deleting | ||
| // objects in this phase. Objects still awaiting deletion are listed | ||
| // in objectDetails. | ||
| PhaseStatusArchiving PhaseStatus = "Archiving" | ||
|
|
||
| // PhaseStatusArchived indicates all objects in this phase have | ||
| // been deleted from the cluster. | ||
| PhaseStatusArchived PhaseStatus = "Archived" | ||
| ) | ||
|
|
||
| // TODO(COD): Update the archival description below when archival decisions move | ||
| // to ClusterObjectDeployment reconciliation. | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.