From 149ba05783b9bfaf4fd66c8db871f624f8665634 Mon Sep 17 00:00:00 2001
From: Ahmed Abdalla
Date: Mon, 9 Mar 2026 14:38:30 +0100
Subject: [PATCH 1/5] feat(api): add ControlPlaneVersionStatus to track control
plane component versions
Add ControlPlaneVersionStatus and ControlPlaneUpdateHistory types to
HostedClusterStatus and HostedControlPlaneStatus. These track
management-side control plane component versions independently from CVO,
enabling service providers to detect completed control plane upgrades
and compute NodePool version skew without waiting for data-plane rollout.
Ref: CNTRLPLANE-2914
Co-Authored-By: Claude Opus 4.6 (1M context)
Signed-off-by: Ahmed Abdalla
---
.../v1beta1/controlplaneversion_types.go | 70 +++++++++++++++++++
api/hypershift/v1beta1/hosted_controlplane.go | 6 ++
api/hypershift/v1beta1/hostedcluster_types.go | 9 +++
3 files changed, 85 insertions(+)
create mode 100644 api/hypershift/v1beta1/controlplaneversion_types.go
diff --git a/api/hypershift/v1beta1/controlplaneversion_types.go b/api/hypershift/v1beta1/controlplaneversion_types.go
new file mode 100644
index 000000000000..c2770e1b38eb
--- /dev/null
+++ b/api/hypershift/v1beta1/controlplaneversion_types.go
@@ -0,0 +1,70 @@
+package v1beta1
+
+import (
+ configv1 "github.com/openshift/api/config/v1"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// ControlPlaneVersionStatus tracks the rollout state of management-side control plane components.
+// It records the desired release, a pruned history of version transitions (newest first), and
+// the last observed generation of the HostedControlPlane spec.
+// +k8s:deepcopy-gen=true
+type ControlPlaneVersionStatus struct {
+ // desired is the release version that the control plane is reconciling towards.
+ // It is derived from the HostedControlPlane release image fields.
+ // +required
+ Desired configv1.Release `json:"desired,omitempty,omitzero"`
+
+ // history contains a list of versions applied to management-side control plane components. The newest entry is
+ // first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ // version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ // +optional
+ // +listType=atomic
+ // +kubebuilder:validation:MinItems=1
+ // +kubebuilder:validation:MaxItems=100
+ History []ControlPlaneUpdateHistory `json:"history,omitempty"`
+
+ // observedGeneration reports which generation of the HostedControlPlane spec is being synced.
+ // +optional
+ // +kubebuilder:validation:Minimum=1
+ // +kubebuilder:validation:Maximum=9007199254740992
+ ObservedGeneration int64 `json:"observedGeneration,omitempty,omitzero"`
+}
+
+// ControlPlaneUpdateHistory is a record of a single version transition for management-side
+// control plane components. Each entry captures the target version, its release image, when
+// the rollout started, and when (or whether) it completed.
+// +k8s:deepcopy-gen=true
+type ControlPlaneUpdateHistory struct {
+ // state reflects whether the update was fully applied. The Partial state
+ // indicates the update is not fully applied, while the Completed state
+ // indicates the update was successfully rolled out.
+ // +required
+ // +kubebuilder:validation:Enum=Completed;Partial
+ State configv1.UpdateState `json:"state,omitempty"`
+
+ // startedTime is the time at which the update was started.
+ // +required
+ StartedTime metav1.Time `json:"startedTime,omitempty,omitzero"`
+
+ // completionTime is the time at which the update completed. It is set
+ // when all management-side components have reached the target version.
+ // It is not set while the update is in progress.
+ // +optional
+ CompletionTime metav1.Time `json:"completionTime,omitempty,omitzero"`
+
+ // version is a semantic version string identifying the update version
+ // (e.g. "4.20.1").
+ // +required
+ // +kubebuilder:validation:XValidation:rule=`self.matches('^\\d+\\.\\d+\\.\\d+.*')`,message="version must start with semantic version prefix x.y.z"
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=64
+ Version string `json:"version,omitempty"`
+
+ // image is the release image pullspec used for this update.
+ // +required
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=447
+ Image string `json:"image,omitempty"`
+}
diff --git a/api/hypershift/v1beta1/hosted_controlplane.go b/api/hypershift/v1beta1/hosted_controlplane.go
index d7f368ee51d0..69f9bd7b1c55 100644
--- a/api/hypershift/v1beta1/hosted_controlplane.go
+++ b/api/hypershift/v1beta1/hosted_controlplane.go
@@ -349,6 +349,12 @@ type HostedControlPlaneStatus struct {
// +kubebuilder:validation:MaxLength=255
OAuthCallbackURLTemplate string `json:"oauthCallbackURLTemplate,omitempty"`
+ // controlPlaneVersion tracks the rollout status of the control plane
+ // components running on the management cluster, independently from
+ // the data-plane version reported in the version field.
+ // +optional
+ ControlPlaneVersion ControlPlaneVersionStatus `json:"controlPlaneVersion,omitzero"`
+
// versionStatus is the status of the release version applied by the
// hosted control plane operator.
// +optional
diff --git a/api/hypershift/v1beta1/hostedcluster_types.go b/api/hypershift/v1beta1/hostedcluster_types.go
index 58989453f97e..953738e492e9 100644
--- a/api/hypershift/v1beta1/hostedcluster_types.go
+++ b/api/hypershift/v1beta1/hostedcluster_types.go
@@ -1787,6 +1787,12 @@ type HostedClusterStatus struct {
// +kubebuilder:validation:MaxItems=100
Conditions []metav1.Condition `json:"conditions,omitempty"`
+ // controlPlaneVersion tracks the rollout status of the control plane
+ // components running on the management cluster, independently from
+ // the data-plane version reported in the version field.
+ // +optional
+ ControlPlaneVersion ControlPlaneVersionStatus `json:"controlPlaneVersion,omitzero"`
+
// version is the status of the release version applied to the
// HostedCluster.
// +optional
@@ -2018,11 +2024,14 @@ type OperatorConfiguration struct {
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version.history[?(@.state==\"Completed\")].version",description="Version"
+// +kubebuilder:printcolumn:name="CP Version",type="string",JSONPath=".status.controlPlaneVersion.history[?(@.state==\"Completed\")].version",description="Control Plane Version"
// +kubebuilder:printcolumn:name="KubeConfig",type="string",JSONPath=".status.kubeconfig.name",description="KubeConfig Secret"
// +kubebuilder:printcolumn:name="Progress",type="string",JSONPath=".status.version.history[?(@.state!=\"\")].state",description="Progress"
// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.conditions[?(@.type==\"Available\")].status",description="Available"
// +kubebuilder:printcolumn:name="Progressing",type="string",JSONPath=".status.conditions[?(@.type==\"Progressing\")].status",description="Progressing"
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[?(@.type==\"Available\")].message",description="Message"
+// +kubebuilder:printcolumn:name="CP Progress",type="string",JSONPath=".status.controlPlaneVersion.history[0].state",description="Control Plane Progress",priority=1
+// +kubebuilder:printcolumn:name="DP Progress",type="string",JSONPath=".status.version.history[0].state",description="Data Plane Progress",priority=1
type HostedCluster struct {
metav1.TypeMeta `json:",inline"`
// metadata is the metadata for the HostedCluster.
From 2fb5bd9efa6bf88c7b8a99890c0d39055c5b6c7d Mon Sep 17 00:00:00 2001
From: Ahmed Abdalla
Date: Tue, 7 Apr 2026 15:57:53 +0200
Subject: [PATCH 2/5] chore: run make update to regenerate CRDs, deepcopy,
clients, vendor, and docs
Co-Authored-By: Claude Opus 4.6 (1M context)
---
.../v1beta1/zz_generated.deepcopy.go | 42 ++++
..._generated.featuregated-crd-manifests.yaml | 14 ++
.../AAA_ungated.yaml | 125 ++++++++++++
.../AutoNodeKarpenter.yaml | 125 ++++++++++++
.../ClusterVersionOperatorConfiguration.yaml | 125 ++++++++++++
.../ExternalOIDC.yaml | 125 ++++++++++++
...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 125 ++++++++++++
.../GCPPlatform.yaml | 125 ++++++++++++
...perShiftOnlyDynamicResourceAllocation.yaml | 125 ++++++++++++
.../ImageStreamImportMode.yaml | 136 +++++++++++++
.../KMSEncryptionProvider.yaml | 125 ++++++++++++
.../NetworkDiagnosticsConfig.yaml | 125 ++++++++++++
.../OpenStack.yaml | 125 ++++++++++++
.../AAA_ungated.yaml | 111 +++++++++++
.../AutoNodeKarpenter.yaml | 111 +++++++++++
.../ClusterVersionOperatorConfiguration.yaml | 111 +++++++++++
.../ExternalOIDC.yaml | 111 +++++++++++
...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 111 +++++++++++
.../GCPPlatform.yaml | 111 +++++++++++
...perShiftOnlyDynamicResourceAllocation.yaml | 111 +++++++++++
.../ImageStreamImportMode.yaml | 122 ++++++++++++
.../KMSEncryptionProvider.yaml | 111 +++++++++++
.../NetworkDiagnosticsConfig.yaml | 111 +++++++++++
.../OpenStack.yaml | 111 +++++++++++
.../v1beta1/controlplaneupdatehistory.go | 79 ++++++++
.../v1beta1/controlplaneversionstatus.go | 65 +++++++
.../hypershift/v1beta1/hostedclusterstatus.go | 31 +--
.../v1beta1/hostedcontrolplanestatus.go | 41 ++--
client/applyconfiguration/utils.go | 4 +
...usters-Hypershift-CustomNoUpgrade.crd.yaml | 136 +++++++++++++
...hostedclusters-Hypershift-Default.crd.yaml | 125 ++++++++++++
...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 125 ++++++++++++
...planes-Hypershift-CustomNoUpgrade.crd.yaml | 122 ++++++++++++
...dcontrolplanes-Hypershift-Default.crd.yaml | 111 +++++++++++
...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 111 +++++++++++
docs/content/reference/api.md | 182 ++++++++++++++++++
.../v1beta1/controlplaneversion_types.go | 70 +++++++
.../hypershift/v1beta1/hosted_controlplane.go | 6 +
.../hypershift/v1beta1/hostedcluster_types.go | 9 +
.../v1beta1/zz_generated.deepcopy.go | 42 ++++
..._generated.featuregated-crd-manifests.yaml | 14 ++
41 files changed, 3920 insertions(+), 27 deletions(-)
create mode 100644 client/applyconfiguration/hypershift/v1beta1/controlplaneupdatehistory.go
create mode 100644 client/applyconfiguration/hypershift/v1beta1/controlplaneversionstatus.go
create mode 100644 vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/controlplaneversion_types.go
diff --git a/api/hypershift/v1beta1/zz_generated.deepcopy.go b/api/hypershift/v1beta1/zz_generated.deepcopy.go
index 033c005b7996..1bd44ee230f5 100644
--- a/api/hypershift/v1beta1/zz_generated.deepcopy.go
+++ b/api/hypershift/v1beta1/zz_generated.deepcopy.go
@@ -1313,6 +1313,46 @@ func (in *ControlPlaneManagedIdentities) DeepCopy() *ControlPlaneManagedIdentiti
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ControlPlaneUpdateHistory) DeepCopyInto(out *ControlPlaneUpdateHistory) {
+ *out = *in
+ in.StartedTime.DeepCopyInto(&out.StartedTime)
+ in.CompletionTime.DeepCopyInto(&out.CompletionTime)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneUpdateHistory.
+func (in *ControlPlaneUpdateHistory) DeepCopy() *ControlPlaneUpdateHistory {
+ if in == nil {
+ return nil
+ }
+ out := new(ControlPlaneUpdateHistory)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ControlPlaneVersionStatus) DeepCopyInto(out *ControlPlaneVersionStatus) {
+ *out = *in
+ in.Desired.DeepCopyInto(&out.Desired)
+ if in.History != nil {
+ in, out := &in.History, &out.History
+ *out = make([]ControlPlaneUpdateHistory, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneVersionStatus.
+func (in *ControlPlaneVersionStatus) DeepCopy() *ControlPlaneVersionStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(ControlPlaneVersionStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DNSSpec) DeepCopyInto(out *DNSSpec) {
*out = *in
@@ -1854,6 +1894,7 @@ func (in *HostedClusterStatus) DeepCopyInto(out *HostedClusterStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
+ in.ControlPlaneVersion.DeepCopyInto(&out.ControlPlaneVersion)
if in.Version != nil {
in, out := &in.Version, &out.Version
*out = new(ClusterVersionStatus)
@@ -2084,6 +2125,7 @@ func (in *HostedControlPlaneStatus) DeepCopyInto(out *HostedControlPlaneStatus)
**out = **in
}
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
+ in.ControlPlaneVersion.DeepCopyInto(&out.ControlPlaneVersion)
if in.VersionStatus != nil {
in, out := &in.VersionStatus, &out.VersionStatus
*out = new(ClusterVersionStatus)
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml
index ed85cead0a34..11a35a29a601 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml
@@ -155,6 +155,10 @@ hostedclusters.hypershift.openshift.io:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -175,6 +179,16 @@ hostedclusters.hypershift.openshift.io:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
Scope: Namespaced
ShortNames:
- hc
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml
index 64889f1e4643..4bcbce791b91 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6146,6 +6160,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml
index 78b57c4f29c7..0949de097737 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6176,6 +6190,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml
index fc2eebcd3d0d..117ba502c06b 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6149,6 +6163,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml
index 449110612b01..13260ff364bb 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6657,6 +6671,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
index d80f4eda886e..414d2ec6d75c 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6811,6 +6825,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml
index 0fe8dbf2a026..92906a2a0513 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6428,6 +6442,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml
index 5c093d885efb..fd3cb4d51f26 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6151,6 +6165,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml
index 1e6d3ee733ce..1880960b7110 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6147,6 +6161,128 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ architecture:
+ description: |-
+ architecture is an optional field that indicates the
+ value of the cluster architecture. In this context cluster
+ architecture means either a single architecture or a multi
+ architecture.
+ Valid values are 'Multi' and empty.
+ enum:
+ - Multi
+ - ""
+ type: string
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml
index 8ffdae5905db..54047ddc6f86 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6205,6 +6219,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml
index a442f548d58b..f00669dbb960 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6281,6 +6295,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml
index e3042379b229..6538d577005f 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml
@@ -21,6 +21,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -41,6 +45,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -6680,6 +6694,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml
index b3f2af593574..a1d1cc0753a4 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml
@@ -5971,6 +5971,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml
index 5f530d52a9d0..137b21d82da2 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml
@@ -6001,6 +6001,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml
index 9fe3f7cdda1e..2c6083c1a74a 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml
@@ -5974,6 +5974,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml
index bbc0a377f1cf..cf81667197f1 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml
@@ -6482,6 +6482,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
index 8cd1b1a5fadc..6345815fb6c2 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml
@@ -6636,6 +6636,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
index 8841aba982ec..dcdb0e1d3a44 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml
@@ -6253,6 +6253,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml
index b6fbd0537dfa..f761b5f81530 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml
@@ -5976,6 +5976,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml
index 1ca8beb484a9..029dc3c4cc5e 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml
@@ -5972,6 +5972,128 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ architecture:
+ description: |-
+ architecture is an optional field that indicates the
+ value of the cluster architecture. In this context cluster
+ architecture means either a single architecture or a multi
+ architecture.
+ Valid values are 'Multi' and empty.
+ enum:
+ - Multi
+ - ""
+ type: string
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml
index d6aa6a4163cd..6fcd9a3c67dd 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml
@@ -6030,6 +6030,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml
index 99810c89aef7..945fa982420e 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml
@@ -6106,6 +6106,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml
index 9e019144a409..197efdec437c 100644
--- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml
+++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml
@@ -6505,6 +6505,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/client/applyconfiguration/hypershift/v1beta1/controlplaneupdatehistory.go b/client/applyconfiguration/hypershift/v1beta1/controlplaneupdatehistory.go
new file mode 100644
index 000000000000..4c8e80285169
--- /dev/null
+++ b/client/applyconfiguration/hypershift/v1beta1/controlplaneupdatehistory.go
@@ -0,0 +1,79 @@
+/*
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+// Code generated by applyconfiguration-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+ v1 "github.com/openshift/api/config/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// ControlPlaneUpdateHistoryApplyConfiguration represents a declarative configuration of the ControlPlaneUpdateHistory type for use
+// with apply.
+type ControlPlaneUpdateHistoryApplyConfiguration struct {
+ State *v1.UpdateState `json:"state,omitempty"`
+ StartedTime *metav1.Time `json:"startedTime,omitempty"`
+ CompletionTime *metav1.Time `json:"completionTime,omitempty"`
+ Version *string `json:"version,omitempty"`
+ Image *string `json:"image,omitempty"`
+}
+
+// ControlPlaneUpdateHistoryApplyConfiguration constructs a declarative configuration of the ControlPlaneUpdateHistory type for use with
+// apply.
+func ControlPlaneUpdateHistory() *ControlPlaneUpdateHistoryApplyConfiguration {
+ return &ControlPlaneUpdateHistoryApplyConfiguration{}
+}
+
+// WithState sets the State field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the State field is set to the value of the last call.
+func (b *ControlPlaneUpdateHistoryApplyConfiguration) WithState(value v1.UpdateState) *ControlPlaneUpdateHistoryApplyConfiguration {
+ b.State = &value
+ return b
+}
+
+// WithStartedTime sets the StartedTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the StartedTime field is set to the value of the last call.
+func (b *ControlPlaneUpdateHistoryApplyConfiguration) WithStartedTime(value metav1.Time) *ControlPlaneUpdateHistoryApplyConfiguration {
+ b.StartedTime = &value
+ return b
+}
+
+// WithCompletionTime sets the CompletionTime field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the CompletionTime field is set to the value of the last call.
+func (b *ControlPlaneUpdateHistoryApplyConfiguration) WithCompletionTime(value metav1.Time) *ControlPlaneUpdateHistoryApplyConfiguration {
+ b.CompletionTime = &value
+ return b
+}
+
+// WithVersion sets the Version field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the Version field is set to the value of the last call.
+func (b *ControlPlaneUpdateHistoryApplyConfiguration) WithVersion(value string) *ControlPlaneUpdateHistoryApplyConfiguration {
+ b.Version = &value
+ return b
+}
+
+// WithImage sets the Image field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the Image field is set to the value of the last call.
+func (b *ControlPlaneUpdateHistoryApplyConfiguration) WithImage(value string) *ControlPlaneUpdateHistoryApplyConfiguration {
+ b.Image = &value
+ return b
+}
diff --git a/client/applyconfiguration/hypershift/v1beta1/controlplaneversionstatus.go b/client/applyconfiguration/hypershift/v1beta1/controlplaneversionstatus.go
new file mode 100644
index 000000000000..c0d66c9cba12
--- /dev/null
+++ b/client/applyconfiguration/hypershift/v1beta1/controlplaneversionstatus.go
@@ -0,0 +1,65 @@
+/*
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+// Code generated by applyconfiguration-gen. DO NOT EDIT.
+
+package v1beta1
+
+import (
+ v1 "github.com/openshift/api/config/v1"
+)
+
+// ControlPlaneVersionStatusApplyConfiguration represents a declarative configuration of the ControlPlaneVersionStatus type for use
+// with apply.
+type ControlPlaneVersionStatusApplyConfiguration struct {
+ Desired *v1.Release `json:"desired,omitempty"`
+ History []ControlPlaneUpdateHistoryApplyConfiguration `json:"history,omitempty"`
+ ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
+}
+
+// ControlPlaneVersionStatusApplyConfiguration constructs a declarative configuration of the ControlPlaneVersionStatus type for use with
+// apply.
+func ControlPlaneVersionStatus() *ControlPlaneVersionStatusApplyConfiguration {
+ return &ControlPlaneVersionStatusApplyConfiguration{}
+}
+
+// WithDesired sets the Desired field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the Desired field is set to the value of the last call.
+func (b *ControlPlaneVersionStatusApplyConfiguration) WithDesired(value v1.Release) *ControlPlaneVersionStatusApplyConfiguration {
+ b.Desired = &value
+ return b
+}
+
+// WithHistory adds the given value to the History field in the declarative configuration
+// and returns the receiver, so that objects can be build by chaining "With" function invocations.
+// If called multiple times, values provided by each call will be appended to the History field.
+func (b *ControlPlaneVersionStatusApplyConfiguration) WithHistory(values ...*ControlPlaneUpdateHistoryApplyConfiguration) *ControlPlaneVersionStatusApplyConfiguration {
+ for i := range values {
+ if values[i] == nil {
+ panic("nil value passed to WithHistory")
+ }
+ b.History = append(b.History, *values[i])
+ }
+ return b
+}
+
+// WithObservedGeneration sets the ObservedGeneration field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ObservedGeneration field is set to the value of the last call.
+func (b *ControlPlaneVersionStatusApplyConfiguration) WithObservedGeneration(value int64) *ControlPlaneVersionStatusApplyConfiguration {
+ b.ObservedGeneration = &value
+ return b
+}
diff --git a/client/applyconfiguration/hypershift/v1beta1/hostedclusterstatus.go b/client/applyconfiguration/hypershift/v1beta1/hostedclusterstatus.go
index 237d38391ab0..3a3350161eea 100644
--- a/client/applyconfiguration/hypershift/v1beta1/hostedclusterstatus.go
+++ b/client/applyconfiguration/hypershift/v1beta1/hostedclusterstatus.go
@@ -26,17 +26,18 @@ import (
// HostedClusterStatusApplyConfiguration represents a declarative configuration of the HostedClusterStatus type for use
// with apply.
type HostedClusterStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- Version *ClusterVersionStatusApplyConfiguration `json:"version,omitempty"`
- KubeConfig *corev1.LocalObjectReference `json:"kubeconfig,omitempty"`
- CustomKubeconfig *corev1.LocalObjectReference `json:"customKubeconfig,omitempty"`
- KubeadminPassword *corev1.LocalObjectReference `json:"kubeadminPassword,omitempty"`
- IgnitionEndpoint *string `json:"ignitionEndpoint,omitempty"`
- ControlPlaneEndpoint *APIEndpointApplyConfiguration `json:"controlPlaneEndpoint,omitempty"`
- OAuthCallbackURLTemplate *string `json:"oauthCallbackURLTemplate,omitempty"`
- PayloadArch *hypershiftv1beta1.PayloadArchType `json:"payloadArch,omitempty"`
- Platform *PlatformStatusApplyConfiguration `json:"platform,omitempty"`
- Configuration *ConfigurationStatusApplyConfiguration `json:"configuration,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ ControlPlaneVersion *ControlPlaneVersionStatusApplyConfiguration `json:"controlPlaneVersion,omitempty"`
+ Version *ClusterVersionStatusApplyConfiguration `json:"version,omitempty"`
+ KubeConfig *corev1.LocalObjectReference `json:"kubeconfig,omitempty"`
+ CustomKubeconfig *corev1.LocalObjectReference `json:"customKubeconfig,omitempty"`
+ KubeadminPassword *corev1.LocalObjectReference `json:"kubeadminPassword,omitempty"`
+ IgnitionEndpoint *string `json:"ignitionEndpoint,omitempty"`
+ ControlPlaneEndpoint *APIEndpointApplyConfiguration `json:"controlPlaneEndpoint,omitempty"`
+ OAuthCallbackURLTemplate *string `json:"oauthCallbackURLTemplate,omitempty"`
+ PayloadArch *hypershiftv1beta1.PayloadArchType `json:"payloadArch,omitempty"`
+ Platform *PlatformStatusApplyConfiguration `json:"platform,omitempty"`
+ Configuration *ConfigurationStatusApplyConfiguration `json:"configuration,omitempty"`
}
// HostedClusterStatusApplyConfiguration constructs a declarative configuration of the HostedClusterStatus type for use with
@@ -58,6 +59,14 @@ func (b *HostedClusterStatusApplyConfiguration) WithConditions(values ...*v1.Con
return b
}
+// WithControlPlaneVersion sets the ControlPlaneVersion field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ControlPlaneVersion field is set to the value of the last call.
+func (b *HostedClusterStatusApplyConfiguration) WithControlPlaneVersion(value *ControlPlaneVersionStatusApplyConfiguration) *HostedClusterStatusApplyConfiguration {
+ b.ControlPlaneVersion = value
+ return b
+}
+
// WithVersion sets the Version field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Version field is set to the value of the last call.
diff --git a/client/applyconfiguration/hypershift/v1beta1/hostedcontrolplanestatus.go b/client/applyconfiguration/hypershift/v1beta1/hostedcontrolplanestatus.go
index becd0ad500af..e4cef5dcb2bf 100644
--- a/client/applyconfiguration/hypershift/v1beta1/hostedcontrolplanestatus.go
+++ b/client/applyconfiguration/hypershift/v1beta1/hostedcontrolplanestatus.go
@@ -26,22 +26,23 @@ import (
// HostedControlPlaneStatusApplyConfiguration represents a declarative configuration of the HostedControlPlaneStatus type for use
// with apply.
type HostedControlPlaneStatusApplyConfiguration struct {
- Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
- Ready *bool `json:"ready,omitempty"`
- Initialized *bool `json:"initialized,omitempty"`
- ExternalManagedControlPlane *bool `json:"externalManagedControlPlane,omitempty"`
- ControlPlaneEndpoint *APIEndpointApplyConfiguration `json:"controlPlaneEndpoint,omitempty"`
- OAuthCallbackURLTemplate *string `json:"oauthCallbackURLTemplate,omitempty"`
- VersionStatus *ClusterVersionStatusApplyConfiguration `json:"versionStatus,omitempty"`
- Version *string `json:"version,omitempty"`
- ReleaseImage *string `json:"releaseImage,omitempty"`
- LastReleaseImageTransitionTime *metav1.Time `json:"lastReleaseImageTransitionTime,omitempty"`
- KubeConfig *KubeconfigSecretRefApplyConfiguration `json:"kubeConfig,omitempty"`
- CustomKubeconfig *KubeconfigSecretRefApplyConfiguration `json:"customKubeconfig,omitempty"`
- KubeadminPassword *corev1.LocalObjectReference `json:"kubeadminPassword,omitempty"`
- Platform *PlatformStatusApplyConfiguration `json:"platform,omitempty"`
- NodeCount *int `json:"nodeCount,omitempty"`
- Configuration *ConfigurationStatusApplyConfiguration `json:"configuration,omitempty"`
+ Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+ Ready *bool `json:"ready,omitempty"`
+ Initialized *bool `json:"initialized,omitempty"`
+ ExternalManagedControlPlane *bool `json:"externalManagedControlPlane,omitempty"`
+ ControlPlaneEndpoint *APIEndpointApplyConfiguration `json:"controlPlaneEndpoint,omitempty"`
+ OAuthCallbackURLTemplate *string `json:"oauthCallbackURLTemplate,omitempty"`
+ ControlPlaneVersion *ControlPlaneVersionStatusApplyConfiguration `json:"controlPlaneVersion,omitempty"`
+ VersionStatus *ClusterVersionStatusApplyConfiguration `json:"versionStatus,omitempty"`
+ Version *string `json:"version,omitempty"`
+ ReleaseImage *string `json:"releaseImage,omitempty"`
+ LastReleaseImageTransitionTime *metav1.Time `json:"lastReleaseImageTransitionTime,omitempty"`
+ KubeConfig *KubeconfigSecretRefApplyConfiguration `json:"kubeConfig,omitempty"`
+ CustomKubeconfig *KubeconfigSecretRefApplyConfiguration `json:"customKubeconfig,omitempty"`
+ KubeadminPassword *corev1.LocalObjectReference `json:"kubeadminPassword,omitempty"`
+ Platform *PlatformStatusApplyConfiguration `json:"platform,omitempty"`
+ NodeCount *int `json:"nodeCount,omitempty"`
+ Configuration *ConfigurationStatusApplyConfiguration `json:"configuration,omitempty"`
}
// HostedControlPlaneStatusApplyConfiguration constructs a declarative configuration of the HostedControlPlaneStatus type for use with
@@ -103,6 +104,14 @@ func (b *HostedControlPlaneStatusApplyConfiguration) WithOAuthCallbackURLTemplat
return b
}
+// WithControlPlaneVersion sets the ControlPlaneVersion field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the ControlPlaneVersion field is set to the value of the last call.
+func (b *HostedControlPlaneStatusApplyConfiguration) WithControlPlaneVersion(value *ControlPlaneVersionStatusApplyConfiguration) *HostedControlPlaneStatusApplyConfiguration {
+ b.ControlPlaneVersion = value
+ return b
+}
+
// WithVersionStatus sets the VersionStatus field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the VersionStatus field is set to the value of the last call.
diff --git a/client/applyconfiguration/utils.go b/client/applyconfiguration/utils.go
index 00fde501d38c..a683bf4913f6 100644
--- a/client/applyconfiguration/utils.go
+++ b/client/applyconfiguration/utils.go
@@ -149,6 +149,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return &hypershiftv1beta1.ConfigurationStatusApplyConfiguration{}
case v1beta1.SchemeGroupVersion.WithKind("ControlPlaneManagedIdentities"):
return &hypershiftv1beta1.ControlPlaneManagedIdentitiesApplyConfiguration{}
+ case v1beta1.SchemeGroupVersion.WithKind("ControlPlaneUpdateHistory"):
+ return &hypershiftv1beta1.ControlPlaneUpdateHistoryApplyConfiguration{}
+ case v1beta1.SchemeGroupVersion.WithKind("ControlPlaneVersionStatus"):
+ return &hypershiftv1beta1.ControlPlaneVersionStatusApplyConfiguration{}
case v1beta1.SchemeGroupVersion.WithKind("DataPlaneManagedIdentities"):
return &hypershiftv1beta1.DataPlaneManagedIdentitiesApplyConfiguration{}
case v1beta1.SchemeGroupVersion.WithKind("Diagnostics"):
diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml
index 1fbff107469b..2c8a39e88fba 100644
--- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml
@@ -23,6 +23,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -43,6 +47,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -7988,6 +8002,128 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ architecture:
+ description: |-
+ architecture is an optional field that indicates the
+ value of the cluster architecture. In this context cluster
+ architecture means either a single architecture or a multi
+ architecture.
+ Valid values are 'Multi' and empty.
+ enum:
+ - Multi
+ - ""
+ type: string
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml
index 154a4061f570..34f7d181b330 100644
--- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml
+++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml
@@ -23,6 +23,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -43,6 +47,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -7000,6 +7014,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml
index 957dee17b625..75f19de5318f 100644
--- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -23,6 +23,10 @@ spec:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -43,6 +47,16 @@ spec:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
name: v1beta1
schema:
openAPIV3Schema:
@@ -7899,6 +7913,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig is a local secret reference to the external custom kubeconfig.
diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml
index 79c28ac986aa..c927555910c0 100644
--- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml
+++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml
@@ -7813,6 +7813,128 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ architecture:
+ description: |-
+ architecture is an optional field that indicates the
+ value of the cluster architecture. In this context cluster
+ architecture means either a single architecture or a multi
+ architecture.
+ Valid values are 'Multi' and empty.
+ enum:
+ - Multi
+ - ""
+ type: string
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml
index c2d3f779771d..f84d16e639d2 100644
--- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml
+++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml
@@ -6825,6 +6825,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml
index 5062a7530618..92619d44c33f 100644
--- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml
+++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml
@@ -7724,6 +7724,117 @@ spec:
- host
- port
type: object
+ controlPlaneVersion:
+ description: |-
+ controlPlaneVersion tracks the rollout status of the control plane
+ components running on the management cluster, independently from
+ the data-plane version reported in the version field.
+ properties:
+ desired:
+ description: |-
+ desired is the release version that the control plane is reconciling towards.
+ It is derived from the HostedControlPlane release image fields.
+ properties:
+ channels:
+ description: |-
+ channels is the set of Cincinnati channels to which the release
+ currently belongs.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: set
+ image:
+ description: |-
+ image is a container image location that contains the update. When this
+ field is part of spec, image is optional if version is specified and the
+ availableUpdates field contains a matching version.
+ type: string
+ url:
+ description: |-
+ url contains information about this release. This URL is set by
+ the 'url' metadata property on a release or the metadata returned by
+ the update API and should be displayed as a link in user
+ interfaces. The URL field may not be set for test or nightly
+ releases.
+ type: string
+ version:
+ description: |-
+ version is a semantic version identifying the update version. When this
+ field is part of spec, version is optional if image is specified.
+ type: string
+ required:
+ - image
+ - version
+ type: object
+ history:
+ description: |-
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+ first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ items:
+ description: |-
+ ControlPlaneUpdateHistory is a record of a single version transition for management-side
+ control plane components. Each entry captures the target version, its release image, when
+ the rollout started, and when (or whether) it completed.
+ properties:
+ completionTime:
+ description: |-
+ completionTime is the time at which the update completed. It is set
+ when all management-side components have reached the target version.
+ It is not set while the update is in progress.
+ format: date-time
+ type: string
+ image:
+ description: image is the release image pullspec used for
+ this update.
+ maxLength: 447
+ minLength: 1
+ type: string
+ startedTime:
+ description: startedTime is the time at which the update
+ was started.
+ format: date-time
+ type: string
+ state:
+ description: |-
+ state reflects whether the update was fully applied. The Partial state
+ indicates the update is not fully applied, while the Completed state
+ indicates the update was successfully rolled out.
+ enum:
+ - Completed
+ - Partial
+ type: string
+ version:
+ description: |-
+ version is a semantic version string identifying the update version
+ (e.g. "4.20.1").
+ maxLength: 64
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: version must start with semantic version prefix
+ x.y.z
+ rule: self.matches('^\\d+\\.\\d+\\.\\d+.*')
+ required:
+ - image
+ - startedTime
+ - state
+ - version
+ type: object
+ maxItems: 100
+ minItems: 1
+ type: array
+ x-kubernetes-list-type: atomic
+ observedGeneration:
+ description: observedGeneration reports which generation of the
+ HostedControlPlane spec is being synced.
+ format: int64
+ maximum: 9007199254740992
+ minimum: 1
+ type: integer
+ required:
+ - desired
+ type: object
customKubeconfig:
description: |-
customKubeconfig references an external custom kubeconfig secret.
diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md
index 2ff670d6e6db..97ed4bf0eecd 100644
--- a/docs/content/reference/api.md
+++ b/docs/content/reference/api.md
@@ -5459,6 +5459,156 @@ ManagedIdentity
+###ControlPlaneUpdateHistory { #hypershift.openshift.io/v1beta1.ControlPlaneUpdateHistory }
+
+(Appears on:
+ControlPlaneVersionStatus)
+
+
+
ControlPlaneUpdateHistory is a record of a single version transition for management-side
+control plane components. Each entry captures the target version, its release image, when
+the rollout started, and when (or whether) it completed.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+state
+
+
+github.com/openshift/api/config/v1.UpdateState
+
+
+ |
+
+ state reflects whether the update was fully applied. The Partial state
+indicates the update is not fully applied, while the Completed state
+indicates the update was successfully rolled out.
+ |
+
+
+
+startedTime,omitempty,omitzero
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+ startedTime is the time at which the update was started.
+ |
+
+
+
+completionTime,omitempty,omitzero
+
+
+Kubernetes meta/v1.Time
+
+
+ |
+
+(Optional)
+ completionTime is the time at which the update completed. It is set
+when all management-side components have reached the target version.
+It is not set while the update is in progress.
+ |
+
+
+
+version
+
+string
+
+ |
+
+ version is a semantic version string identifying the update version
+(e.g. “4.20.1”).
+ |
+
+
+
+image
+
+string
+
+ |
+
+ image is the release image pullspec used for this update.
+ |
+
+
+
+###ControlPlaneVersionStatus { #hypershift.openshift.io/v1beta1.ControlPlaneVersionStatus }
+
+(Appears on:
+HostedClusterStatus,
+HostedControlPlaneStatus)
+
+
+
ControlPlaneVersionStatus tracks the rollout state of management-side control plane components.
+It records the desired release, a pruned history of version transitions (newest first), and
+the last observed generation of the HostedControlPlane spec.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+desired,omitempty,omitzero
+
+
+github.com/openshift/api/config/v1.Release
+
+
+ |
+
+ desired is the release version that the control plane is reconciling towards.
+It is derived from the HostedControlPlane release image fields.
+ |
+
+
+
+history
+
+
+[]ControlPlaneUpdateHistory
+
+
+ |
+
+(Optional)
+ history contains a list of versions applied to management-side control plane components. The newest entry is
+first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ |
+
+
+
+observedGeneration,omitempty,omitzero
+
+int64
+
+ |
+
+(Optional)
+ observedGeneration reports which generation of the HostedControlPlane spec is being synced.
+ |
+
+
+
###DNSSpec { #hypershift.openshift.io/v1beta1.DNSSpec }
(Appears on:
@@ -7093,6 +7243,22 @@ plane’s current state.
+controlPlaneVersion,omitzero
+
+
+ControlPlaneVersionStatus
+
+
+ |
+
+(Optional)
+ controlPlaneVersion tracks the rollout status of the control plane
+components running on the management cluster, independently from
+the data-plane version reported in the version field.
+ |
+
+
+
version
@@ -7848,6 +8014,22 @@ This is populated after the infrastructure is ready.
|
+controlPlaneVersion,omitzero
+
+
+ControlPlaneVersionStatus
+
+
+ |
+
+(Optional)
+ controlPlaneVersion tracks the rollout status of the control plane
+components running on the management cluster, independently from
+the data-plane version reported in the version field.
+ |
+
+
+
versionStatus
diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/controlplaneversion_types.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/controlplaneversion_types.go
new file mode 100644
index 000000000000..c2770e1b38eb
--- /dev/null
+++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/controlplaneversion_types.go
@@ -0,0 +1,70 @@
+package v1beta1
+
+import (
+ configv1 "github.com/openshift/api/config/v1"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// ControlPlaneVersionStatus tracks the rollout state of management-side control plane components.
+// It records the desired release, a pruned history of version transitions (newest first), and
+// the last observed generation of the HostedControlPlane spec.
+// +k8s:deepcopy-gen=true
+type ControlPlaneVersionStatus struct {
+ // desired is the release version that the control plane is reconciling towards.
+ // It is derived from the HostedControlPlane release image fields.
+ // +required
+ Desired configv1.Release `json:"desired,omitempty,omitzero"`
+
+ // history contains a list of versions applied to management-side control plane components. The newest entry is
+ // first in the list. Entries have state Completed when all ControlPlaneComponent resources report the target
+ // version with RolloutComplete=True. Entries have state Partial when the rollout is in progress or has failed.
+ // +optional
+ // +listType=atomic
+ // +kubebuilder:validation:MinItems=1
+ // +kubebuilder:validation:MaxItems=100
+ History []ControlPlaneUpdateHistory `json:"history,omitempty"`
+
+ // observedGeneration reports which generation of the HostedControlPlane spec is being synced.
+ // +optional
+ // +kubebuilder:validation:Minimum=1
+ // +kubebuilder:validation:Maximum=9007199254740992
+ ObservedGeneration int64 `json:"observedGeneration,omitempty,omitzero"`
+}
+
+// ControlPlaneUpdateHistory is a record of a single version transition for management-side
+// control plane components. Each entry captures the target version, its release image, when
+// the rollout started, and when (or whether) it completed.
+// +k8s:deepcopy-gen=true
+type ControlPlaneUpdateHistory struct {
+ // state reflects whether the update was fully applied. The Partial state
+ // indicates the update is not fully applied, while the Completed state
+ // indicates the update was successfully rolled out.
+ // +required
+ // +kubebuilder:validation:Enum=Completed;Partial
+ State configv1.UpdateState `json:"state,omitempty"`
+
+ // startedTime is the time at which the update was started.
+ // +required
+ StartedTime metav1.Time `json:"startedTime,omitempty,omitzero"`
+
+ // completionTime is the time at which the update completed. It is set
+ // when all management-side components have reached the target version.
+ // It is not set while the update is in progress.
+ // +optional
+ CompletionTime metav1.Time `json:"completionTime,omitempty,omitzero"`
+
+ // version is a semantic version string identifying the update version
+ // (e.g. "4.20.1").
+ // +required
+ // +kubebuilder:validation:XValidation:rule=`self.matches('^\\d+\\.\\d+\\.\\d+.*')`,message="version must start with semantic version prefix x.y.z"
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=64
+ Version string `json:"version,omitempty"`
+
+ // image is the release image pullspec used for this update.
+ // +required
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=447
+ Image string `json:"image,omitempty"`
+}
diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hosted_controlplane.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hosted_controlplane.go
index d7f368ee51d0..69f9bd7b1c55 100644
--- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hosted_controlplane.go
+++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hosted_controlplane.go
@@ -349,6 +349,12 @@ type HostedControlPlaneStatus struct {
// +kubebuilder:validation:MaxLength=255
OAuthCallbackURLTemplate string `json:"oauthCallbackURLTemplate,omitempty"`
+ // controlPlaneVersion tracks the rollout status of the control plane
+ // components running on the management cluster, independently from
+ // the data-plane version reported in the version field.
+ // +optional
+ ControlPlaneVersion ControlPlaneVersionStatus `json:"controlPlaneVersion,omitzero"`
+
// versionStatus is the status of the release version applied by the
// hosted control plane operator.
// +optional
diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.go
index 58989453f97e..953738e492e9 100644
--- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.go
+++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/hostedcluster_types.go
@@ -1787,6 +1787,12 @@ type HostedClusterStatus struct {
// +kubebuilder:validation:MaxItems=100
Conditions []metav1.Condition `json:"conditions,omitempty"`
+ // controlPlaneVersion tracks the rollout status of the control plane
+ // components running on the management cluster, independently from
+ // the data-plane version reported in the version field.
+ // +optional
+ ControlPlaneVersion ControlPlaneVersionStatus `json:"controlPlaneVersion,omitzero"`
+
// version is the status of the release version applied to the
// HostedCluster.
// +optional
@@ -2018,11 +2024,14 @@ type OperatorConfiguration struct {
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version.history[?(@.state==\"Completed\")].version",description="Version"
+// +kubebuilder:printcolumn:name="CP Version",type="string",JSONPath=".status.controlPlaneVersion.history[?(@.state==\"Completed\")].version",description="Control Plane Version"
// +kubebuilder:printcolumn:name="KubeConfig",type="string",JSONPath=".status.kubeconfig.name",description="KubeConfig Secret"
// +kubebuilder:printcolumn:name="Progress",type="string",JSONPath=".status.version.history[?(@.state!=\"\")].state",description="Progress"
// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.conditions[?(@.type==\"Available\")].status",description="Available"
// +kubebuilder:printcolumn:name="Progressing",type="string",JSONPath=".status.conditions[?(@.type==\"Progressing\")].status",description="Progressing"
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[?(@.type==\"Available\")].message",description="Message"
+// +kubebuilder:printcolumn:name="CP Progress",type="string",JSONPath=".status.controlPlaneVersion.history[0].state",description="Control Plane Progress",priority=1
+// +kubebuilder:printcolumn:name="DP Progress",type="string",JSONPath=".status.version.history[0].state",description="Data Plane Progress",priority=1
type HostedCluster struct {
metav1.TypeMeta `json:",inline"`
// metadata is the metadata for the HostedCluster.
diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go
index 033c005b7996..1bd44ee230f5 100644
--- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go
+++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go
@@ -1313,6 +1313,46 @@ func (in *ControlPlaneManagedIdentities) DeepCopy() *ControlPlaneManagedIdentiti
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ControlPlaneUpdateHistory) DeepCopyInto(out *ControlPlaneUpdateHistory) {
+ *out = *in
+ in.StartedTime.DeepCopyInto(&out.StartedTime)
+ in.CompletionTime.DeepCopyInto(&out.CompletionTime)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneUpdateHistory.
+func (in *ControlPlaneUpdateHistory) DeepCopy() *ControlPlaneUpdateHistory {
+ if in == nil {
+ return nil
+ }
+ out := new(ControlPlaneUpdateHistory)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ControlPlaneVersionStatus) DeepCopyInto(out *ControlPlaneVersionStatus) {
+ *out = *in
+ in.Desired.DeepCopyInto(&out.Desired)
+ if in.History != nil {
+ in, out := &in.History, &out.History
+ *out = make([]ControlPlaneUpdateHistory, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneVersionStatus.
+func (in *ControlPlaneVersionStatus) DeepCopy() *ControlPlaneVersionStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(ControlPlaneVersionStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DNSSpec) DeepCopyInto(out *DNSSpec) {
*out = *in
@@ -1854,6 +1894,7 @@ func (in *HostedClusterStatus) DeepCopyInto(out *HostedClusterStatus) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
+ in.ControlPlaneVersion.DeepCopyInto(&out.ControlPlaneVersion)
if in.Version != nil {
in, out := &in.Version, &out.Version
*out = new(ClusterVersionStatus)
@@ -2084,6 +2125,7 @@ func (in *HostedControlPlaneStatus) DeepCopyInto(out *HostedControlPlaneStatus)
**out = **in
}
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
+ in.ControlPlaneVersion.DeepCopyInto(&out.ControlPlaneVersion)
if in.VersionStatus != nil {
in, out := &in.VersionStatus, &out.VersionStatus
*out = new(ClusterVersionStatus)
diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml
index ed85cead0a34..11a35a29a601 100644
--- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml
+++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests.yaml
@@ -155,6 +155,10 @@ hostedclusters.hypershift.openshift.io:
jsonPath: .status.version.history[?(@.state=="Completed")].version
name: Version
type: string
+ - description: Control Plane Version
+ jsonPath: .status.controlPlaneVersion.history[?(@.state=="Completed")].version
+ name: CP Version
+ type: string
- description: KubeConfig Secret
jsonPath: .status.kubeconfig.name
name: KubeConfig
@@ -175,6 +179,16 @@ hostedclusters.hypershift.openshift.io:
jsonPath: .status.conditions[?(@.type=="Available")].message
name: Message
type: string
+ - description: Control Plane Progress
+ jsonPath: .status.controlPlaneVersion.history[0].state
+ name: CP Progress
+ priority: 1
+ type: string
+ - description: Data Plane Progress
+ jsonPath: .status.version.history[0].state
+ name: DP Progress
+ priority: 1
+ type: string
Scope: Namespaced
ShortNames:
- hc
From 05025042e0a4ac3576b32aeaf558d479bed827f5 Mon Sep 17 00:00:00 2001
From: Ahmed Abdalla
Date: Tue, 17 Mar 2026 11:29:33 +0100
Subject: [PATCH 3/5] feat(cpo): reconcile controlPlaneVersion from
ControlPlaneComponent status
Implement reconcileControlPlaneVersion() that aggregates
ControlPlaneComponent status into hcp.Status.ControlPlaneVersion with
version transition logic, image-only change detection, and
observedGeneration tracking.
Include pruneHistory() ported from CVO's weighted ranking algorithm
with exact constants to cap history at 100 entries.
Ref: CNTRLPLANE-2914
Co-Authored-By: Claude Opus 4.6 (1M context)
Signed-off-by: Ahmed Abdalla
---
.../hostedcontrolplane/controlplaneversion.go | 362 +++++++++++++
.../controlplaneversion_pruning_test.go | 349 ++++++++++++
.../controlplaneversion_test.go | 502 ++++++++++++++++++
.../hostedcontrolplane_controller.go | 39 ++
.../hostedcontrolplane_controller_test.go | 2 +
5 files changed, 1254 insertions(+)
create mode 100644 control-plane-operator/controllers/hostedcontrolplane/controlplaneversion.go
create mode 100644 control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_pruning_test.go
create mode 100644 control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_test.go
diff --git a/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion.go b/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion.go
new file mode 100644
index 000000000000..13df9165bce2
--- /dev/null
+++ b/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion.go
@@ -0,0 +1,362 @@
+package hostedcontrolplane
+
+import (
+ "math"
+ "strings"
+
+ hyperv1 "github.com/openshift/hypershift/api/hypershift/v1beta1"
+
+ configv1 "github.com/openshift/api/config/v1"
+
+ "k8s.io/apimachinery/pkg/api/meta"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/utils/clock"
+)
+
+// Pruning constants ported from CVO (pkg/cvo/status_history.go).
+const (
+ maxHistory = 100
+ maxFinalEntryIndex = 4
+ mostImportantWeight = 1000.0
+ interestingWeight = 30.0
+ partialMinorWeight = 20.0
+ partialZStreamWeight = -20.0
+ sliceIndexWeight = -1.01
+)
+
+// ensureControlPlaneVersionPartial ensures a Partial history entry exists for the
+// desired version without updating observedGeneration. This is called on list
+// failure so consumers know an upgrade was attempted, consistent with
+// CVO's syncFailingStatus pattern.
+func ensureControlPlaneVersionPartial(
+ hcp *hyperv1.HostedControlPlane,
+ clk clock.Clock,
+ releaseVersion string,
+ desiredImage string,
+) hyperv1.ControlPlaneVersionStatus {
+ now := metav1.NewTime(clk.Now())
+
+ existing := hcp.Status.ControlPlaneVersion
+ desired := configv1.Release{Version: releaseVersion, Image: desiredImage}
+ if existing.Desired.Image == "" {
+ return hyperv1.ControlPlaneVersionStatus{
+ Desired: desired,
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.PartialUpdate,
+ StartedTime: now,
+ Version: releaseVersion,
+ Image: desiredImage,
+ },
+ },
+ // Do not set observedGeneration — preserve nil to signal
+ // the generation was not successfully processed.
+ }
+ }
+
+ result := existing.DeepCopy()
+ result.Desired = desired
+ // Preserve existing observedGeneration — do not update it.
+
+ // There is no history yet, or the latest entry is for a different release
+ // than what we're now targeting
+ if len(result.History) == 0 || !mergeEqualVersions(&result.History[0], result.Desired) {
+ if len(result.History) > 0 && result.History[0].CompletionTime.IsZero() {
+ result.History[0].CompletionTime = now
+ }
+ entry := hyperv1.ControlPlaneUpdateHistory{
+ State: configv1.PartialUpdate,
+ StartedTime: now,
+ Version: releaseVersion,
+ Image: desiredImage,
+ }
+ result.History = append([]hyperv1.ControlPlaneUpdateHistory{entry}, result.History...)
+ result.History = pruneHistory(result.History)
+ }
+ return *result
+}
+
+// reconcileControlPlaneVersion aggregates ControlPlaneComponent status into
+// hcp.Status.ControlPlaneVersion, implementing CVO mergeEqualVersions
+// semantics for change detection, dual version+rollout completion checks,
+// first-population behavior, and observedGeneration updates.
+func reconcileControlPlaneVersion(
+ hcp *hyperv1.HostedControlPlane,
+ components []hyperv1.ControlPlaneComponent,
+ clk clock.Clock,
+ releaseVersion string,
+ desiredImage string,
+) hyperv1.ControlPlaneVersionStatus {
+ now := metav1.NewTime(clk.Now())
+
+ existing := hcp.Status.ControlPlaneVersion
+ desired := configv1.Release{Version: releaseVersion, Image: desiredImage}
+ if existing.Desired.Image == "" {
+ // First population: create initial Partial entry.
+ return hyperv1.ControlPlaneVersionStatus{
+ Desired: desired,
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.PartialUpdate,
+ StartedTime: now,
+ Version: releaseVersion,
+ Image: desiredImage,
+ },
+ },
+ ObservedGeneration: hcp.Generation,
+ }
+ }
+
+ result := existing.DeepCopy()
+ result.Desired = desired
+ result.ObservedGeneration = hcp.Generation
+
+ // Detect desired release change using CVO mergeEqualVersions semantics.
+ // If the current history entry does NOT merge with the new desired release,
+ // a new version transition has occurred.
+ if len(result.History) > 0 && !mergeEqualVersions(&result.History[0], desired) {
+ // Close out the previous entry by setting CompletionTime.
+ entry := &result.History[0]
+ if entry.CompletionTime.IsZero() {
+ entry.CompletionTime = now
+ }
+ // Prepend new Partial entry for the new desired release.
+ newEntry := hyperv1.ControlPlaneUpdateHistory{
+ State: configv1.PartialUpdate,
+ StartedTime: now,
+ Version: releaseVersion,
+ Image: desiredImage,
+ }
+ result.History = append([]hyperv1.ControlPlaneUpdateHistory{newEntry}, result.History...)
+ result.History = pruneHistory(result.History)
+ return *result
+ }
+
+ // No desired change — check completion.
+ // All components must report Status.Version == desired version AND RolloutComplete=True.
+ if len(result.History) > 0 && result.History[0].State == configv1.PartialUpdate {
+ if allComponentsAtVersion(components, releaseVersion) {
+ result.History[0].State = configv1.CompletedUpdate
+ result.History[0].CompletionTime = now
+ }
+ }
+
+ result.History = pruneHistory(result.History)
+ return *result
+}
+
+// mergeEqualVersions implements CVO's mergeEqualVersions semantics (pkg/cvo/status.go).
+// It returns true if the current history entry and desired release refer to the same
+// version, meaning no new history entry should be created. It also updates the current
+// entry's version/image when the other side is empty, matching CVO behavior.
+func mergeEqualVersions(current *hyperv1.ControlPlaneUpdateHistory, desired configv1.Release) bool {
+ if len(desired.Image) > 0 && desired.Image == current.Image {
+ if len(desired.Version) == 0 {
+ return true
+ }
+ if len(current.Version) == 0 || desired.Version == current.Version {
+ current.Version = desired.Version
+ return true
+ }
+ }
+ if len(desired.Version) > 0 && desired.Version == current.Version {
+ if len(current.Image) == 0 || desired.Image == current.Image {
+ current.Image = desired.Image
+ return true
+ }
+ }
+ return false
+}
+
+// allComponentsAtVersion returns true when every component reports
+// Status.Version == desiredVersion AND has the RolloutComplete condition
+// set to True. Returns false when there are no components.
+// Components with no Status.Version or a mismatching version are treated
+// as not matching the desired version and keep the state Partial.
+func allComponentsAtVersion(components []hyperv1.ControlPlaneComponent, desiredVersion string) bool {
+ if len(components) == 0 {
+ return false
+ }
+ for i := range components {
+ if components[i].Status.Version != desiredVersion {
+ return false
+ }
+ cond := meta.FindStatusCondition(components[i].Status.Conditions, string(hyperv1.ControlPlaneComponentRolloutComplete))
+ if cond == nil || cond.Status != metav1.ConditionTrue {
+ return false
+ }
+ }
+ return true
+}
+
+// pruneHistory caps the history at maxHistory entries by repeatedly removing
+// the lowest-ranked entry, faithfully porting the CVO algorithm from
+// pkg/cvo/status_history.go.
+func pruneHistory(history []hyperv1.ControlPlaneUpdateHistory) []hyperv1.ControlPlaneUpdateHistory {
+ for len(history) > maxHistory {
+ history = pruneHistoryWithMax(history, maxHistory)
+ }
+ return history
+}
+
+// pruneHistoryWithMax is the core pruning implementation. maxSize is configurable
+// to ease unit testing with smaller history slices.
+func pruneHistoryWithMax(history []hyperv1.ControlPlaneUpdateHistory, maxSize int) []hyperv1.ControlPlaneUpdateHistory {
+ if len(history) <= maxSize {
+ return history
+ }
+ mostRecentCompletedIdx := -1
+ for i := range history {
+ if history[i].State == configv1.CompletedUpdate {
+ mostRecentCompletedIdx = i
+ break
+ }
+ }
+
+ lowestRank := math.MaxFloat64
+ var lowestRankIdx int
+
+ for i := range history {
+ rank := 0.0
+ if isTheInitialEntry(i, maxSize) || isAFinalEntry(i) || isTheMostRecentCompletedEntry(i, mostRecentCompletedIdx) {
+ rank = mostImportantWeight
+ } else if isTheFirstOrLastCompletedInAMinor(i, history, maxSize) {
+ rank += interestingWeight
+ } else if isPartialPortionOfMinorTransition(i, history, maxSize) {
+ rank += partialMinorWeight
+ } else if isPartialWithinAZStream(i, history, maxSize) {
+ rank += partialZStreamWeight
+ }
+ rank += sliceIndexWeight * float64(i)
+
+ if rank < lowestRank {
+ lowestRank = rank
+ lowestRankIdx = i
+ }
+ }
+
+ if lowestRankIdx == maxSize {
+ return history[:maxSize]
+ }
+ return append(history[:lowestRankIdx], history[lowestRankIdx+1:]...)
+}
+
+// isTheInitialEntry returns true if the entry is the oldest entry (at the max history boundary).
+func isTheInitialEntry(entryIndex, maxHistorySize int) bool {
+ return entryIndex == maxHistorySize
+}
+
+// isAFinalEntry returns true if the entry is among the most recent entries.
+func isAFinalEntry(entryIndex int) bool {
+ return entryIndex <= maxFinalEntryIndex
+}
+
+// isTheMostRecentCompletedEntry returns true if the entry is the most recent completed entry.
+func isTheMostRecentCompletedEntry(entryIndex, mostRecentCompletedEntryIndex int) bool {
+ return entryIndex == mostRecentCompletedEntryIndex
+}
+
+// isTheFirstOrLastCompletedInAMinor returns true if the entry at idx is the first or last
+// completed update for a given minor version.
+func isTheFirstOrLastCompletedInAMinor(idx int, h []hyperv1.ControlPlaneUpdateHistory, maxSize int) bool {
+ if h[idx].State == configv1.PartialUpdate {
+ return false
+ }
+ if idx == 0 || idx == maxSize {
+ return true
+ }
+ nextOlder := findNextOlderCompleted(idx, h)
+ if nextOlder == idx || !sameMinorVersion(h[idx], h[nextOlder]) {
+ return true
+ }
+ nextNewer := findNextNewerCompleted(idx, h)
+ if nextNewer == idx || !sameMinorVersion(h[idx], h[nextNewer]) {
+ return true
+ }
+ return false
+}
+
+// isPartialPortionOfMinorTransition returns true if the entry at idx is a partial update
+// between completed updates that transition from one minor version to another.
+func isPartialPortionOfMinorTransition(idx int, h []hyperv1.ControlPlaneUpdateHistory, maxSize int) bool {
+ if h[idx].State == configv1.CompletedUpdate || idx == 0 || idx == maxSize {
+ return false
+ }
+ prevIdx := findNextOlderCompleted(idx, h)
+ if prevIdx == idx {
+ return false
+ }
+ nextIdx := findNextNewerCompleted(idx, h)
+ if nextIdx == idx || sameMinorVersion(h[prevIdx], h[nextIdx]) {
+ return false
+ }
+ return true
+}
+
+// isPartialWithinAZStream returns true if the entry at idx is a partial update between
+// completed updates that transition from one z-stream version to another within the same minor.
+func isPartialWithinAZStream(idx int, h []hyperv1.ControlPlaneUpdateHistory, maxSize int) bool {
+ if h[idx].State == configv1.CompletedUpdate || idx == 0 || idx == maxSize {
+ return false
+ }
+ prevIdx := findNextOlderCompleted(idx, h)
+ if prevIdx == idx {
+ return false
+ }
+ nextIdx := findNextNewerCompleted(idx, h)
+ if nextIdx == idx || sameZStreamVersion(h[prevIdx], h[nextIdx]) {
+ return false
+ }
+ return true
+}
+
+// findNextOlderCompleted returns the index of the next older (higher index) completed entry.
+// Returns idx if none found.
+func findNextOlderCompleted(idx int, h []hyperv1.ControlPlaneUpdateHistory) int {
+ for i := idx + 1; i < len(h); i++ {
+ if h[i].State == configv1.CompletedUpdate {
+ return i
+ }
+ }
+ return idx
+}
+
+// findNextNewerCompleted returns the index of the next newer (lower index) completed entry.
+// Returns idx if none found.
+func findNextNewerCompleted(idx int, h []hyperv1.ControlPlaneUpdateHistory) int {
+ for i := idx - 1; i >= 0; i-- {
+ if h[i].State == configv1.CompletedUpdate {
+ return i
+ }
+ }
+ return idx
+}
+
+// sameMinorVersion returns true if both entries have the same minor version.
+func sameMinorVersion(a, b hyperv1.ControlPlaneUpdateHistory) bool {
+ return getEffectiveMinor(a.Version) == getEffectiveMinor(b.Version)
+}
+
+// sameZStreamVersion returns true if both entries have the same minor and micro version.
+func sameZStreamVersion(a, b hyperv1.ControlPlaneUpdateHistory) bool {
+ return getEffectiveMinor(a.Version) == getEffectiveMinor(b.Version) &&
+ getEffectiveMicro(a.Version) == getEffectiveMicro(b.Version)
+}
+
+// getEffectiveMinor returns the minor component (y) from a version string x.y[.z].
+func getEffectiveMinor(version string) string {
+ splits := strings.Split(version, ".")
+ if len(splits) < 2 {
+ return ""
+ }
+ return splits[1]
+}
+
+// getEffectiveMicro returns the micro/z-stream component (z) from a version string x.y.z.
+func getEffectiveMicro(version string) string {
+ splits := strings.Split(version, ".")
+ if len(splits) < 3 {
+ return ""
+ }
+ return splits[2]
+}
diff --git a/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_pruning_test.go b/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_pruning_test.go
new file mode 100644
index 000000000000..19629d62ff41
--- /dev/null
+++ b/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_pruning_test.go
@@ -0,0 +1,349 @@
+package hostedcontrolplane
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+
+ hyperv1 "github.com/openshift/hypershift/api/hypershift/v1beta1"
+
+ configv1 "github.com/openshift/api/config/v1"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+// makeHistory creates a slice of ControlPlaneUpdateHistory entries for pruning tests.
+// Entries are ordered newest-first (index 0 = most recent). Callers provide version
+// strings in the form "4.17.2" and states (Completed or Partial).
+func makeHistory(entries []struct {
+ version string
+ state configv1.UpdateState
+}) []hyperv1.ControlPlaneUpdateHistory {
+ result := make([]hyperv1.ControlPlaneUpdateHistory, len(entries))
+ for i, e := range entries {
+ h := hyperv1.ControlPlaneUpdateHistory{
+ State: e.state,
+ StartedTime: metav1.Now(),
+ Version: e.version,
+ Image: fmt.Sprintf("quay.io/ocp/release:%s", e.version),
+ }
+ if e.state == configv1.CompletedUpdate {
+ now := metav1.Now()
+ h.CompletionTime = now
+ }
+ result[i] = h
+ }
+ return result
+}
+
+// makeSimpleHistory creates a slice of ControlPlaneUpdateHistory with just state and version,
+// matching the CVO test style where only State and Version matter for pruning logic.
+func makeSimpleHistory(entries []struct {
+ state configv1.UpdateState
+ version string
+}) []hyperv1.ControlPlaneUpdateHistory {
+ result := make([]hyperv1.ControlPlaneUpdateHistory, len(entries))
+ for i, e := range entries {
+ result[i] = hyperv1.ControlPlaneUpdateHistory{
+ State: e.state,
+ Version: e.version,
+ }
+ }
+ return result
+}
+
+// historyVersions extracts state+version pairs for comparison, ignoring time fields.
+func historyVersions(h []hyperv1.ControlPlaneUpdateHistory) []struct {
+ state configv1.UpdateState
+ version string
+} {
+ result := make([]struct {
+ state configv1.UpdateState
+ version string
+ }, len(h))
+ for i, e := range h {
+ result[i] = struct {
+ state configv1.UpdateState
+ version string
+ }{state: e.State, version: e.Version}
+ }
+ return result
+}
+
+// testMaxHistory is the max history size used in the CVO-ported prune test cases.
+// CVO tests use 10 (with 11-entry inputs) to keep test data small.
+const testMaxHistory = 10
+
+// TestPruneHistory ports CVO's Test_prune test cases.
+func TestPruneHistory(t *testing.T) {
+ type entry = struct {
+ state configv1.UpdateState
+ version string
+ }
+ tests := []struct {
+ name string
+ history []entry
+ want []entry
+ }{
+ {
+ name: "When a partial update exists within a minor transition, it should prune the z-stream partial",
+ history: []entry{
+ {configv1.CompletedUpdate, "4.6.3"},
+ {configv1.CompletedUpdate, "4.5.3"},
+ {configv1.CompletedUpdate, "4.4.3"},
+ {configv1.CompletedUpdate, "4.3.3"},
+ {configv1.CompletedUpdate, "4.3.2"},
+ {configv1.CompletedUpdate, "4.3.1"},
+ {configv1.CompletedUpdate, "4.2.1"},
+ {configv1.PartialUpdate, "4.1.4"},
+ {configv1.PartialUpdate, "4.1.3"},
+ {configv1.PartialUpdate, "4.1.2"},
+ {configv1.CompletedUpdate, "4.1.1"},
+ },
+ want: []entry{
+ {configv1.CompletedUpdate, "4.6.3"},
+ {configv1.CompletedUpdate, "4.5.3"},
+ {configv1.CompletedUpdate, "4.4.3"},
+ {configv1.CompletedUpdate, "4.3.3"},
+ {configv1.CompletedUpdate, "4.3.2"},
+ {configv1.CompletedUpdate, "4.3.1"},
+ {configv1.CompletedUpdate, "4.2.1"},
+ {configv1.PartialUpdate, "4.1.4"},
+ {configv1.PartialUpdate, "4.1.3"},
+ {configv1.CompletedUpdate, "4.1.1"},
+ },
+ },
+ {
+ name: "When a partial update exists within a z-stream transition, it should prune the z-stream partial",
+ history: []entry{
+ {configv1.CompletedUpdate, "4.5.3"},
+ {configv1.CompletedUpdate, "4.4.3"},
+ {configv1.CompletedUpdate, "4.4.3"},
+ {configv1.CompletedUpdate, "4.4.2"},
+ {configv1.CompletedUpdate, "4.1.10"},
+ {configv1.CompletedUpdate, "4.1.9"},
+ {configv1.CompletedUpdate, "4.1.4"},
+ {configv1.PartialUpdate, "4.1.3"},
+ {configv1.CompletedUpdate, "4.1.2"},
+ {configv1.PartialUpdate, "4.0.1"},
+ {configv1.CompletedUpdate, "4.0.1"},
+ },
+ want: []entry{
+ {configv1.CompletedUpdate, "4.5.3"},
+ {configv1.CompletedUpdate, "4.4.3"},
+ {configv1.CompletedUpdate, "4.4.3"},
+ {configv1.CompletedUpdate, "4.4.2"},
+ {configv1.CompletedUpdate, "4.1.10"},
+ {configv1.CompletedUpdate, "4.1.9"},
+ {configv1.CompletedUpdate, "4.1.4"},
+ {configv1.CompletedUpdate, "4.1.2"},
+ {configv1.PartialUpdate, "4.0.1"},
+ {configv1.CompletedUpdate, "4.0.1"},
+ },
+ },
+ {
+ name: "When all entries are completed across different minors, it should prune the oldest not in mostImportantWeight set",
+ history: []entry{
+ {configv1.CompletedUpdate, "4.11.0"},
+ {configv1.CompletedUpdate, "4.10.0"},
+ {configv1.CompletedUpdate, "4.9.0"},
+ {configv1.CompletedUpdate, "4.8.0"},
+ {configv1.CompletedUpdate, "4.7.0"},
+ {configv1.CompletedUpdate, "4.6.0"},
+ {configv1.CompletedUpdate, "4.5.0"},
+ {configv1.CompletedUpdate, "4.4.0"},
+ {configv1.CompletedUpdate, "4.3.0"},
+ {configv1.CompletedUpdate, "4.2.0"},
+ {configv1.CompletedUpdate, "4.1.0"},
+ },
+ want: []entry{
+ {configv1.CompletedUpdate, "4.11.0"},
+ {configv1.CompletedUpdate, "4.10.0"},
+ {configv1.CompletedUpdate, "4.9.0"},
+ {configv1.CompletedUpdate, "4.8.0"},
+ {configv1.CompletedUpdate, "4.7.0"},
+ {configv1.CompletedUpdate, "4.6.0"},
+ {configv1.CompletedUpdate, "4.5.0"},
+ {configv1.CompletedUpdate, "4.4.0"},
+ {configv1.CompletedUpdate, "4.3.0"},
+ {configv1.CompletedUpdate, "4.1.0"},
+ },
+ },
+ {
+ name: "When a partial exists not in mostImportantWeight set, it should prune only the partial",
+ history: []entry{
+ {configv1.CompletedUpdate, "4.11.0"},
+ {configv1.PartialUpdate, "4.10.0"},
+ {configv1.CompletedUpdate, "4.9.0"},
+ {configv1.CompletedUpdate, "4.8.0"},
+ {configv1.CompletedUpdate, "4.7.0"},
+ {configv1.PartialUpdate, "4.6.0"},
+ {configv1.CompletedUpdate, "4.5.0"},
+ {configv1.CompletedUpdate, "4.4.0"},
+ {configv1.CompletedUpdate, "4.3.0"},
+ {configv1.CompletedUpdate, "4.2.0"},
+ {configv1.CompletedUpdate, "4.1.0"},
+ },
+ want: []entry{
+ {configv1.CompletedUpdate, "4.11.0"},
+ {configv1.PartialUpdate, "4.10.0"},
+ {configv1.CompletedUpdate, "4.9.0"},
+ {configv1.CompletedUpdate, "4.8.0"},
+ {configv1.CompletedUpdate, "4.7.0"},
+ {configv1.CompletedUpdate, "4.5.0"},
+ {configv1.CompletedUpdate, "4.4.0"},
+ {configv1.CompletedUpdate, "4.3.0"},
+ {configv1.CompletedUpdate, "4.2.0"},
+ {configv1.CompletedUpdate, "4.1.0"},
+ },
+ },
+ {
+ name: "When both z-stream and minor partials exist, it should prune the z-stream partial over the minor partial",
+ history: []entry{
+ {configv1.CompletedUpdate, "4.11.0"},
+ {configv1.CompletedUpdate, "4.10.0"},
+ {configv1.CompletedUpdate, "4.9.0"},
+ {configv1.CompletedUpdate, "4.8.0"},
+ {configv1.CompletedUpdate, "4.6.1"},
+ {configv1.PartialUpdate, "4.6.1"},
+ {configv1.CompletedUpdate, "4.6.0"},
+ {configv1.CompletedUpdate, "4.4.0"},
+ {configv1.PartialUpdate, "4.3.0"},
+ {configv1.CompletedUpdate, "4.2.0"},
+ {configv1.CompletedUpdate, "4.1.0"},
+ },
+ want: []entry{
+ {configv1.CompletedUpdate, "4.11.0"},
+ {configv1.CompletedUpdate, "4.10.0"},
+ {configv1.CompletedUpdate, "4.9.0"},
+ {configv1.CompletedUpdate, "4.8.0"},
+ {configv1.CompletedUpdate, "4.6.1"},
+ {configv1.CompletedUpdate, "4.6.0"},
+ {configv1.CompletedUpdate, "4.4.0"},
+ {configv1.PartialUpdate, "4.3.0"},
+ {configv1.CompletedUpdate, "4.2.0"},
+ {configv1.CompletedUpdate, "4.1.0"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ input := makeSimpleHistory(tt.history)
+ got := pruneHistoryWithMax(input, testMaxHistory)
+ gotVersions := historyVersions(got)
+ if !reflect.DeepEqual(tt.want, gotVersions) {
+ t.Fatalf("unexpected result:\n%s", cmp.Diff(tt.want, gotVersions))
+ }
+ })
+ }
+}
+
+// TestPruneHistory_UnderMaxHistoryUnchanged verifies that when history has fewer
+// than maxHistory entries, pruning is a no-op.
+func TestPruneHistory_UnderMaxHistoryUnchanged(t *testing.T) {
+ entries := make([]struct {
+ version string
+ state configv1.UpdateState
+ }, 50)
+ for i := 0; i < 50; i++ {
+ entries[i] = struct {
+ version string
+ state configv1.UpdateState
+ }{
+ version: fmt.Sprintf("4.17.%d", 49-i),
+ state: configv1.CompletedUpdate,
+ }
+ }
+ history := makeHistory(entries)
+
+ pruned := pruneHistory(history)
+
+ if len(pruned) != 50 {
+ t.Errorf("When fewer than %d entries exist, it should not prune, got %d entries", maxHistory, len(pruned))
+ }
+}
+
+// TestPruneHistory_ExactlyMaxHistoryUnchanged verifies that when history has exactly
+// maxHistory entries, pruning is a no-op.
+func TestPruneHistory_ExactlyMaxHistoryUnchanged(t *testing.T) {
+ entries := make([]struct {
+ version string
+ state configv1.UpdateState
+ }, maxHistory)
+ for i := 0; i < maxHistory; i++ {
+ entries[i] = struct {
+ version string
+ state configv1.UpdateState
+ }{
+ version: fmt.Sprintf("4.17.%d", 99-i),
+ state: configv1.CompletedUpdate,
+ }
+ }
+ history := makeHistory(entries)
+
+ pruned := pruneHistory(history)
+
+ if len(pruned) != maxHistory {
+ t.Errorf("When exactly %d entries exist, it should not prune, got %d entries", maxHistory, len(pruned))
+ }
+}
+
+// TestPruneHistory_CapAtMaxHistory verifies that when more than maxHistory entries
+// exist, pruning reduces the list to exactly maxHistory.
+func TestPruneHistory_CapAtMaxHistory(t *testing.T) {
+ entries := make([]struct {
+ version string
+ state configv1.UpdateState
+ }, 105)
+ for i := 0; i < 105; i++ {
+ entries[i] = struct {
+ version string
+ state configv1.UpdateState
+ }{
+ version: fmt.Sprintf("4.17.%d", 104-i),
+ state: configv1.CompletedUpdate,
+ }
+ }
+ history := makeHistory(entries)
+
+ pruned := pruneHistory(history)
+
+ if len(pruned) != maxHistory {
+ t.Errorf("When more than maxHistory entries exist, it should prune to %d, got %d", maxHistory, len(pruned))
+ }
+}
+
+// TestPruneHistory_DeterministicResults verifies that the pruning algorithm
+// produces deterministic results when called multiple times with the same input.
+func TestPruneHistory_DeterministicResults(t *testing.T) {
+ entries := make([]struct {
+ version string
+ state configv1.UpdateState
+ }, 105)
+ for i := 0; i < 105; i++ {
+ entries[i] = struct {
+ version string
+ state configv1.UpdateState
+ }{
+ version: fmt.Sprintf("4.17.%d", 104-i),
+ state: configv1.CompletedUpdate,
+ }
+ }
+ history := makeHistory(entries)
+
+ pruned1 := pruneHistory(history)
+ pruned2 := pruneHistory(makeHistory(entries))
+
+ if len(pruned1) != len(pruned2) {
+ t.Fatalf("When pruning the same input twice, it should produce same length, got %d vs %d",
+ len(pruned1), len(pruned2))
+ }
+ for i := range pruned1 {
+ if pruned1[i].Version != pruned2[i].Version {
+ t.Errorf("When pruning the same input twice, it should produce deterministic results at index %d: %s vs %s",
+ i, pruned1[i].Version, pruned2[i].Version)
+ }
+ }
+}
diff --git a/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_test.go b/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_test.go
new file mode 100644
index 000000000000..3a2c8c28a5fe
--- /dev/null
+++ b/control-plane-operator/controllers/hostedcontrolplane/controlplaneversion_test.go
@@ -0,0 +1,502 @@
+package hostedcontrolplane
+
+import (
+ "testing"
+ "time"
+
+ hyperv1 "github.com/openshift/hypershift/api/hypershift/v1beta1"
+
+ configv1 "github.com/openshift/api/config/v1"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/utils/clock"
+ testingclock "k8s.io/utils/clock/testing"
+)
+
+// newHCP creates a minimal HostedControlPlane for testing.
+func newHCP(releaseImage string, controlPlaneReleaseImage *string, generation int64) *hyperv1.HostedControlPlane {
+ hcp := &hyperv1.HostedControlPlane{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "test-hcp",
+ Namespace: "test-ns",
+ Generation: generation,
+ },
+ Spec: hyperv1.HostedControlPlaneSpec{
+ ReleaseImage: releaseImage,
+ },
+ }
+ if controlPlaneReleaseImage != nil {
+ hcp.Spec.ControlPlaneReleaseImage = controlPlaneReleaseImage
+ }
+ return hcp
+}
+
+// newComponent creates a ControlPlaneComponent with the given version and rollout status.
+func newComponent(name, version string, rolloutComplete bool) hyperv1.ControlPlaneComponent {
+ conditions := []metav1.Condition{
+ {
+ Type: string(hyperv1.ControlPlaneComponentAvailable),
+ Status: metav1.ConditionTrue,
+ LastTransitionTime: metav1.Now(),
+ },
+ }
+ if rolloutComplete {
+ conditions = append(conditions, metav1.Condition{
+ Type: string(hyperv1.ControlPlaneComponentRolloutComplete),
+ Status: metav1.ConditionTrue,
+ LastTransitionTime: metav1.Now(),
+ })
+ } else {
+ conditions = append(conditions, metav1.Condition{
+ Type: string(hyperv1.ControlPlaneComponentRolloutComplete),
+ Status: metav1.ConditionFalse,
+ LastTransitionTime: metav1.Now(),
+ })
+ }
+ return hyperv1.ControlPlaneComponent{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: name,
+ Namespace: "test-ns",
+ },
+ Status: hyperv1.ControlPlaneComponentStatus{
+ Version: version,
+ Conditions: conditions,
+ },
+ }
+}
+
+func strPtr(s string) *string { return &s }
+
+// TestReconcileControlPlaneVersion_AllComponentsComplete verifies that
+// When all ControlPlaneComponent resources report the target version with
+// RolloutComplete=True, controlPlaneVersion.history[0].State transitions
+// to Completed and completionTime is set.
+func TestReconcileControlPlaneVersion_AllComponentsComplete(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:aaa", nil, 1)
+ hcp.Status.ControlPlaneVersion = hyperv1.ControlPlaneVersionStatus{
+ Desired: configv1.Release{
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.PartialUpdate,
+ StartedTime: metav1.NewTime(fakeClock.Now().Add(-10 * time.Minute)),
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ },
+ ObservedGeneration: 1,
+ }
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "4.17.0", true),
+ newComponent("openshift-apiserver", "4.17.0", true),
+ }
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if result.History[0].State != configv1.CompletedUpdate {
+ t.Errorf("When all components are complete, it should transition to Completed, got %s", result.History[0].State)
+ }
+ if result.History[0].CompletionTime.IsZero() {
+ t.Error("When all components are complete, it should set completionTime")
+ }
+ if result.History[0].Version != "4.17.0" {
+ t.Errorf("When all components are complete, version should be 4.17.0, got %s", result.History[0].Version)
+ }
+ if result.History[0].Image != hcp.Spec.ReleaseImage {
+ t.Errorf("When all components are complete, image should be %s, got %s", hcp.Spec.ReleaseImage, result.History[0].Image)
+ }
+}
+
+// TestReconcileControlPlaneVersion_NewDesiredRelease verifies that
+// When the desired release changes (version bump), a new Partial history entry is prepended.
+func TestReconcileControlPlaneVersion_NewDesiredRelease(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:bbb", nil, 2)
+ hcp.Status.ControlPlaneVersion = hyperv1.ControlPlaneVersionStatus{
+ Desired: configv1.Release{
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.CompletedUpdate,
+ StartedTime: metav1.NewTime(fakeClock.Now().Add(-1 * time.Hour)),
+ CompletionTime: metav1.NewTime(fakeClock.Now().Add(-30 * time.Minute)),
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ },
+ ObservedGeneration: 1,
+ }
+
+ // Components still report old version — they haven't rolled yet
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ }
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if len(result.History) < 2 {
+ t.Fatalf("When desired release changes, it should prepend new entry, got %d entries", len(result.History))
+ }
+ if result.History[0].State != configv1.PartialUpdate {
+ t.Errorf("When desired release changes, it should prepend Partial entry, got %s", result.History[0].State)
+ }
+ if result.History[0].Image != "quay.io/ocp/release@sha256:bbb" {
+ t.Errorf("When desired release changes, it should use new image, got %s", result.History[0].Image)
+ }
+ // Version comes from aggregateComponentVersion which reports what components currently run
+ if result.History[0].Version != "4.17.0" {
+ t.Errorf("When desired release changes but components haven't rolled, it should record current version, got %s", result.History[0].Version)
+ }
+}
+
+// TestReconcileControlPlaneVersion_ImageOnlyChange verifies that
+// When the image digest changes but the semver is the same, a new Partial
+// entry is prepended (CVE patch scenario).
+func TestReconcileControlPlaneVersion_ImageOnlyChange(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:bbb", nil, 2)
+ hcp.Status.ControlPlaneVersion = hyperv1.ControlPlaneVersionStatus{
+ Desired: configv1.Release{
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.CompletedUpdate,
+ StartedTime: metav1.NewTime(fakeClock.Now().Add(-1 * time.Hour)),
+ CompletionTime: metav1.NewTime(fakeClock.Now().Add(-30 * time.Minute)),
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ },
+ ObservedGeneration: 1,
+ }
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ }
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if len(result.History) < 2 {
+ t.Fatalf("When image changes (same version), it should prepend new entry, got %d entries", len(result.History))
+ }
+ if result.History[0].State != configv1.PartialUpdate {
+ t.Errorf("When image changes (same version), it should prepend Partial entry, got %s", result.History[0].State)
+ }
+ if result.History[0].Image != "quay.io/ocp/release@sha256:bbb" {
+ t.Errorf("When image changes (same version), it should use new image, got %s", result.History[0].Image)
+ }
+ if result.History[0].Version != "4.17.0" {
+ t.Errorf("When image changes (same version), version should remain 4.17.0, got %s", result.History[0].Version)
+ }
+}
+
+// TestReconcileControlPlaneVersion_NewComponentMidUpgrade verifies that
+// When a new ControlPlaneComponent is created mid-upgrade that hasn't reached
+// the desired version, controlPlaneVersion remains Partial.
+func TestReconcileControlPlaneVersion_NewComponentMidUpgrade(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:aaa", nil, 1)
+ hcp.Status.ControlPlaneVersion = hyperv1.ControlPlaneVersionStatus{
+ Desired: configv1.Release{
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.PartialUpdate,
+ StartedTime: metav1.NewTime(fakeClock.Now().Add(-5 * time.Minute)),
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ },
+ ObservedGeneration: 1,
+ }
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "4.17.0", true),
+ newComponent("new-component", "4.16.0", false), // mid-upgrade, not at desired version
+ }
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if result.History[0].State != configv1.PartialUpdate {
+ t.Errorf("When a component mid-upgrade hasn't reached desired version, it should remain Partial, got %s", result.History[0].State)
+ }
+ if !result.History[0].CompletionTime.IsZero() {
+ t.Error("When a component mid-upgrade hasn't reached desired version, it should not set completionTime")
+ }
+ if result.History[0].Version != "4.17.0" {
+ t.Errorf("When a component mid-upgrade hasn't reached desired version, history version should remain 4.17.0, got %s", result.History[0].Version)
+ }
+}
+
+// TestReconcileControlPlaneVersion_FirstPopulation verifies that
+// When controlPlaneVersion is first populated on an existing cluster with all
+// components at the desired version, history initializes with Partial on the
+// first reconciliation, then transitions to Completed on the second.
+func TestReconcileControlPlaneVersion_FirstPopulation(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:aaa", nil, 1)
+ // No existing ControlPlaneVersion status (first population)
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "4.17.0", true),
+ }
+
+ // First reconciliation: should create Partial entry
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if len(result.History) != 1 {
+ t.Fatalf("When first populated, it should create 1 history entry, got %d", len(result.History))
+ }
+ if result.History[0].State != configv1.PartialUpdate {
+ t.Errorf("When first populated, it should initialize with Partial, got %s", result.History[0].State)
+ }
+ if result.History[0].Version != "4.17.0" {
+ t.Errorf("When first populated, version should be 4.17.0, got %s", result.History[0].Version)
+ }
+ if result.History[0].Image != hcp.Spec.ReleaseImage {
+ t.Errorf("When first populated, image should be %s, got %s", hcp.Spec.ReleaseImage, result.History[0].Image)
+ }
+
+ // Second reconciliation: should transition to Completed
+ hcp.Status.ControlPlaneVersion = result
+ fakeClock.Step(1 * time.Minute)
+ result2 := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if result2.History[0].State != configv1.CompletedUpdate {
+ t.Errorf("When first populated and all components ready, second reconcile should transition to Completed, got %s", result2.History[0].State)
+ }
+ if result2.History[0].CompletionTime.IsZero() {
+ t.Error("When first populated and all components ready, second reconcile should set completionTime")
+ }
+}
+
+// TestReconcileControlPlaneVersion_ControlPlaneReleaseImage verifies that
+// When HCP.Spec.ControlPlaneReleaseImage is set, controlPlaneVersion.desired
+// reflects ControlPlaneReleaseImage, not Spec.ReleaseImage.
+func TestReconcileControlPlaneVersion_ControlPlaneReleaseImage(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ cpReleaseImage := "quay.io/ocp/release@sha256:cponly"
+ hcp := newHCP("quay.io/ocp/release@sha256:dataplane", strPtr(cpReleaseImage), 1)
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ }
+
+ // The caller resolves the image — when ControlPlaneReleaseImage is set,
+ // the caller passes its resolved digest as desiredImage.
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", cpReleaseImage)
+
+ if result.Desired.Image != cpReleaseImage {
+ t.Errorf("When ControlPlaneReleaseImage is set, it should use it as desired, got %s", result.Desired.Image)
+ }
+}
+
+// TestReconcileControlPlaneVersion_ObservedGeneration verifies that
+// When the CPO reconciles successfully, observedGeneration reflects the
+// generation that was actually processed.
+func TestReconcileControlPlaneVersion_ObservedGeneration(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:aaa", nil, 7)
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ }
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if result.ObservedGeneration != 7 {
+ t.Errorf("When reconciliation succeeds, it should set observedGeneration to current generation (7), got %d", result.ObservedGeneration)
+ }
+}
+
+// TestReconcileControlPlaneVersion_ComponentFailure verifies that
+// when a component is at the desired version but its rollout has not completed
+// (e.g. deployment updated but pods crashing), controlPlaneVersion stays Partial.
+func TestReconcileControlPlaneVersion_ComponentFailure(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:aaa", nil, 1)
+ hcp.Status.ControlPlaneVersion = hyperv1.ControlPlaneVersionStatus{
+ Desired: configv1.Release{
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.PartialUpdate,
+ StartedTime: metav1.NewTime(fakeClock.Now().Add(-5 * time.Minute)),
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ },
+ ObservedGeneration: 1,
+ }
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "4.17.0", false), // at desired version but rollout not complete
+ }
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if result.History[0].State != configv1.PartialUpdate {
+ t.Errorf("When a component fails, it should maintain Partial state, got %s", result.History[0].State)
+ }
+ if !result.History[0].CompletionTime.IsZero() {
+ t.Error("When a component fails, it should not set completionTime")
+ }
+ if result.History[0].Version != "4.17.0" {
+ t.Errorf("When a component fails, history version should remain 4.17.0, got %s", result.History[0].Version)
+ }
+}
+
+// TestReconcileControlPlaneVersion_SupersededPartial verifies that
+// When controlPlaneVersion is Partial for version X and a new desired release
+// Y is detected, the Partial entry for X receives a CompletionTime stamp
+// before Y's entry is prepended.
+func TestReconcileControlPlaneVersion_SupersededPartial(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:bbb", nil, 2)
+ startTime := metav1.NewTime(fakeClock.Now().Add(-10 * time.Minute))
+ hcp.Status.ControlPlaneVersion = hyperv1.ControlPlaneVersionStatus{
+ Desired: configv1.Release{
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ History: []hyperv1.ControlPlaneUpdateHistory{
+ {
+ State: configv1.PartialUpdate,
+ StartedTime: startTime,
+ Version: "4.17.0",
+ Image: "quay.io/ocp/release@sha256:aaa",
+ },
+ },
+ ObservedGeneration: 1,
+ }
+
+ components := []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", false),
+ }
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if len(result.History) < 2 {
+ t.Fatalf("When superseding a Partial entry, it should prepend new entry, got %d entries", len(result.History))
+ }
+ // New entry at [0]
+ if result.History[0].State != configv1.PartialUpdate {
+ t.Errorf("When superseding, it should prepend new Partial entry, got %s", result.History[0].State)
+ }
+ if result.History[0].Image != "quay.io/ocp/release@sha256:bbb" {
+ t.Errorf("When superseding, it should use new image for prepended entry, got %s", result.History[0].Image)
+ }
+ // Superseded entry at [1] should have CompletionTime stamped
+ if result.History[1].CompletionTime.IsZero() {
+ t.Error("When superseding a Partial entry, it should stamp CompletionTime on the old entry")
+ }
+ if result.History[1].State != configv1.PartialUpdate {
+ t.Errorf("When superseding, the old entry should remain Partial (not switch to Completed), got %s", result.History[1].State)
+ }
+}
+
+// TestReconcileControlPlaneVersion_NoComponents verifies behavior when no
+// ControlPlaneComponent resources exist yet — should create initial Partial entry.
+func TestReconcileControlPlaneVersion_NoComponents(t *testing.T) {
+ fakeClock := testingclock.NewFakeClock(time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC))
+ hcp := newHCP("quay.io/ocp/release@sha256:aaa", nil, 1)
+
+ var components []hyperv1.ControlPlaneComponent
+
+ result := reconcileControlPlaneVersion(hcp, components, fakeClock, "4.17.0", hcp.Spec.ReleaseImage)
+
+ if result.Desired.Image == "" {
+ t.Fatal("When no components exist, it should still return a status with desired set")
+ }
+ if len(result.History) != 1 {
+ t.Fatalf("When no components exist, it should create initial Partial entry, got %d entries", len(result.History))
+ }
+ if result.History[0].State != configv1.PartialUpdate {
+ t.Errorf("When no components exist, it should create Partial entry, got %s", result.History[0].State)
+ }
+ if result.History[0].Version != "4.17.0" {
+ t.Errorf("When no components exist, version should be 4.17.0, got %s", result.History[0].Version)
+ }
+ if result.History[0].Image != hcp.Spec.ReleaseImage {
+ t.Errorf("When no components exist, image should be %s, got %s", hcp.Spec.ReleaseImage, result.History[0].Image)
+ }
+}
+
+func TestAllComponentsAtVersion(t *testing.T) {
+ tests := []struct {
+ name string
+ components []hyperv1.ControlPlaneComponent
+ desiredVersion string
+ want bool
+ }{
+ {
+ name: "When no components exist, it should return false",
+ components: nil,
+ desiredVersion: "4.17.0",
+ want: false,
+ },
+ {
+ name: "When all components match version and have RolloutComplete, it should return true",
+ components: []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "4.17.0", true),
+ },
+ desiredVersion: "4.17.0",
+ want: true,
+ },
+ {
+ name: "When a component has a version mismatch, it should return false",
+ components: []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "4.16.0", true),
+ },
+ desiredVersion: "4.17.0",
+ want: false,
+ },
+ {
+ name: "When a component has RolloutComplete=False but version matches, it should return false",
+ components: []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "4.17.0", false),
+ },
+ desiredVersion: "4.17.0",
+ want: false,
+ },
+ {
+ name: "When a component has empty version, it should return false",
+ components: []hyperv1.ControlPlaneComponent{
+ newComponent("kube-apiserver", "4.17.0", true),
+ newComponent("kube-controller-manager", "", true),
+ },
+ desiredVersion: "4.17.0",
+ want: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := allComponentsAtVersion(tt.components, tt.desiredVersion)
+ if got != tt.want {
+ t.Errorf("allComponentsAtVersion() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+// Ensure the clock.Clock interface is used for testability.
+var _ clock.Clock = &testingclock.FakeClock{}
diff --git a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
index bd31e8e1bc33..34b6c30da12f 100644
--- a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
+++ b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
@@ -113,6 +113,7 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/workqueue"
+ "k8s.io/utils/clock"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
@@ -181,9 +182,13 @@ type HostedControlPlaneReconciler struct {
ImageMetadataProvider util.ImageMetadataProvider
cpoAzureCredentialsLoaded sync.Map
kmsAzureCredentialsLoaded sync.Map
+ clock clock.Clock
}
func (r *HostedControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager, createOrUpdate upsert.CreateOrUpdateFN, hcp *hyperv1.HostedControlPlane) error {
+ if r.clock == nil {
+ r.clock = clock.RealClock{}
+ }
r.setup(createOrUpdate)
b := ctrl.NewControllerManagedBy(mgr).
For(&hyperv1.HostedControlPlane{}).
@@ -793,6 +798,40 @@ func (r *HostedControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
return reconcile.Result{}, fmt.Errorf("failed to look up release image metadata: %w", err)
}
+ // Reconcile controlPlaneVersion status.
+ // This runs after LookupReleaseImage so we can use the version and resolved
+ // digest from the release image metadata.
+ {
+ clk := r.clock
+ if clk == nil {
+ clk = clock.RealClock{}
+ }
+ // Resolve the release image to its digest so controlPlaneVersion records
+ // the immutable image reference, consistent with how CVO records images.
+ pullSecret := common.PullSecret(hostedControlPlane.Namespace)
+ if err := r.Client.Get(ctx, client.ObjectKeyFromObject(pullSecret), pullSecret); err != nil {
+ return reconcile.Result{}, fmt.Errorf("failed to get pull secret for version reconciliation: %w", err)
+ }
+ _, resolvedRef, err := r.ImageMetadataProvider.GetDigest(ctx, util.HCPControlPlaneReleaseImage(hostedControlPlane), pullSecret.Data[corev1.DockerConfigJsonKey])
+ if err != nil {
+ return reconcile.Result{}, fmt.Errorf("failed to resolve control plane release image digest: %w", err)
+ }
+ resolvedImage := resolvedRef.String()
+
+ componentsList := &hyperv1.ControlPlaneComponentList{}
+ if listErr := r.Client.List(ctx, componentsList, client.InNamespace(hostedControlPlane.Namespace)); listErr != nil {
+ // On list failure, ensure a Partial entry exists so consumers
+ // know an upgrade was attempted. Preserve observedGeneration.
+ hostedControlPlane.Status.ControlPlaneVersion = ensureControlPlaneVersionPartial(hostedControlPlane, clk, releaseImage.Version(), resolvedImage)
+ // Persist the Partial entry before returning the error.
+ if patchErr := r.Client.Status().Patch(ctx, hostedControlPlane, client.MergeFromWithOptions(originalHostedControlPlane, client.MergeFromWithOptimisticLock{})); patchErr != nil {
+ return reconcile.Result{}, fmt.Errorf("failed to patch status after component list failure: %w (list error: %v)", patchErr, listErr)
+ }
+ return reconcile.Result{}, fmt.Errorf("failed to list control plane components for version reconciliation: %w", listErr)
+ }
+ hostedControlPlane.Status.ControlPlaneVersion = reconcileControlPlaneVersion(hostedControlPlane, componentsList.Items, clk, releaseImage.Version(), resolvedImage)
+ }
+
hostedControlPlane.Status.Initialized = true
meta.SetStatusCondition(&hostedControlPlane.Status.Conditions, util.GenerateReconciliationActiveCondition(hostedControlPlane.Spec.PausedUntil, hostedControlPlane.Generation))
diff --git a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
index 4b528a32bca6..8bb156faf4a9 100644
--- a/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
+++ b/control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
@@ -722,6 +722,7 @@ func TestEventHandling(t *testing.T) {
ManagementClusterCapabilities: &fakecapabilities.FakeSupportAllCapabilities{},
ReleaseProvider: mockedProviderWithOpenshiftImageRegistryOverrides,
UserReleaseProvider: &fakereleaseprovider.FakeReleaseProvider{},
+ ImageMetadataProvider: &fakeimagemetadataprovider.FakeRegistryClientImageMetadataProviderHCCO{},
reconcileInfrastructureStatus: func(context.Context, *hyperv1.HostedControlPlane) (infra.InfrastructureStatus, error) {
return readyInfraStatus, nil
},
@@ -803,6 +804,7 @@ func TestNonReadyInfraTriggersRequeueAfter(t *testing.T) {
ManagementClusterCapabilities: &fakecapabilities.FakeSupportAllCapabilities{},
ReleaseProvider: mockedProviderWithOpenshiftImageRegistryOverrides,
UserReleaseProvider: &fakereleaseprovider.FakeReleaseProvider{},
+ ImageMetadataProvider: &fakeimagemetadataprovider.FakeRegistryClientImageMetadataProviderHCCO{},
reconcileInfrastructureStatus: func(context.Context, *hyperv1.HostedControlPlane) (infra.InfrastructureStatus, error) {
return infra.InfrastructureStatus{}, nil
},
From 60675d443a1d408c532cb7b6806d40da65b4fdc3 Mon Sep 17 00:00:00 2001
From: Ahmed Abdalla
Date: Mon, 9 Mar 2026 14:39:04 +0100
Subject: [PATCH 4/5] feat(hc): propagate controlPlaneVersion from HCP to HC
status
Deep-copy controlPlaneVersion from HostedControlPlane status to
HostedCluster status, following the existing Platform field propagation
pattern. Handles nil gracefully for version skew safety during rolling
upgrades.
Ref: CNTRLPLANE-2914
Co-Authored-By: Claude Opus 4.6 (1M context)
Signed-off-by: Ahmed Abdalla
---
.../hostedcluster/hostedcluster_controller.go | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go
index 187b3eefdbe2..43a6c96d5717 100644
--- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go
+++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go
@@ -856,6 +856,9 @@ func (r *HostedClusterReconciler) reconcile(ctx context.Context, req ctrl.Reques
hcluster.Status.Platform = hcp.Status.Platform
}
+ // Copy the control plane version status from the hostedcontrolplane
+ propagateControlPlaneVersion(hcluster, hcp)
+
// Copy the AWSDefaultSecurityGroupCreated condition from the hostedcontrolplane
if hcluster.Spec.Platform.Type == hyperv1.AWSPlatform {
if hcp != nil {
@@ -4981,3 +4984,13 @@ func (r *HostedClusterReconciler) reconcileAdditionalTrustBundle(ctx context.Con
return nil
}
+
+// propagateControlPlaneVersion copies the ControlPlaneVersion status from the
+// HostedControlPlane to the HostedCluster using DeepCopy for value safety.
+// When HCP is nil (not yet created) the existing HC value is preserved.
+func propagateControlPlaneVersion(hcluster *hyperv1.HostedCluster, hcp *hyperv1.HostedControlPlane) {
+ if hcp == nil {
+ return
+ }
+ hcluster.Status.ControlPlaneVersion = *hcp.Status.ControlPlaneVersion.DeepCopy()
+}
From 74d1d3a4cb20deeb44c9b6be1915f427e915a53d Mon Sep 17 00:00:00 2001
From: Ahmed Abdalla
Date: Wed, 18 Mar 2026 12:18:24 +0100
Subject: [PATCH 5/5] chore(make): extract api-lint and api-lint-fix targets
Extract the api/ module lint commands into standalone api-lint and
api-lint-fix targets, reused by lint and lint-fix as dependencies.
Co-Authored-By: Claude Opus 4.6 (1M context)
Signed-off-by: Ahmed Abdalla
---
Makefile | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index 70c4d8a655e8..6ee44baf32c5 100644
--- a/Makefile
+++ b/Makefile
@@ -74,15 +74,25 @@ KUBEAPILINTER_PLUGIN := $(abspath $(TOOLS_BIN_DIR)/kube-api-linter.so)
$(KUBEAPILINTER_PLUGIN): $(TOOLS_DIR)/go.mod # Build kube-api-linter as Go plugin
cd $(TOOLS_DIR); CGO_ENABLED=1 $(GO) build -buildmode=plugin -o $(KUBEAPILINTER_PLUGIN) sigs.k8s.io/kube-api-linter/pkg/plugin
+# When not otherwise set, diff/lint against the local main branch.
+# This is always set in OpenShift CI.
+PULL_BASE_SHA ?= main
+
+.PHONY: api-lint
+api-lint: $(GOLANGCI_LINT) $(KUBEAPILINTER_PLUGIN)
+ cd api && $(GOLANGCI_LINT) run --config ./.golangci.yml --modules-download-mode=readonly -v --new-from-rev=${PULL_BASE_SHA}
+
+.PHONY: api-lint-fix
+api-lint-fix: $(GOLANGCI_LINT) $(KUBEAPILINTER_PLUGIN)
+ cd api && $(GOLANGCI_LINT) run --config ./.golangci.yml --fix -v --new-from-rev=${PULL_BASE_SHA}
+
.PHONY: lint
-lint: generate $(GOLANGCI_LINT) $(KUBEAPILINTER_PLUGIN)
+lint: generate api-lint
$(GOLANGCI_LINT) run --config ./.golangci.yml --modules-download-mode=readonly -v
- cd api && $(GOLANGCI_LINT) run --config ./.golangci.yml --modules-download-mode=readonly -v
.PHONY: lint-fix
-lint-fix: generate $(GOLANGCI_LINT) $(KUBEAPILINTER_PLUGIN)
+lint-fix: generate api-lint-fix
$(GOLANGCI_LINT) run --config ./.golangci.yml --fix -v
- cd api && $(GOLANGCI_LINT) run --config ./.golangci.yml --fix -v
.PHONY: verify
verify: generate update staticcheck fmt vet verify-codespell lint cpo-container-sync run-gitlint
|