From 60f802c3a82020f1d40b7f8cb8359592e412761c Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 17 Mar 2026 09:23:51 -0700 Subject: [PATCH] install: Annotate HyperShift bootstrap manifests with include.release.openshift.io/bootstrap-cluster-version-operator HyperShift currently massages release-image manifests [1] and then applies the ones it expects the cluster-version operator to need [2] in order to get that Deployment running. That can cause problems like installing the v1alpha1 clusterversionoperators.operator.openshift.io [3] when HyperShift is using filename-based logic and assuming the remaining manifests are all necessary to bootstrap the CVO [2]: oc apply -f /var/payload/manifests With this commit, I'm adding the include.release.openshift.io/bootstrap-cluster-version-operator annotation to the manifests we actually need for HyperShift bootstrapping, to allow the HyperShift operator to move to something like: oc create -f $(grep -rl 'include.release.openshift.io/bootstrap-cluster-version-operator: .*hypershift' /var/payload/manifests) For the two manifests we maintain locally, I've added the grep target as an annotation. We need the ClusterVersion CustomResourceDefinition in place too, see 7480a5f7dd (Get cluster version object earlier in startup, 2022-03-11, cache.WaitForCacheSync in CVO.Run, or we stick on: I0318 21:30:46.499731 1 reflector.go:404] "Listing and watching" type="*v1.ClusterOperator" reflector="github.com/openshift/client-go/config/informers/externalversions/factory.go:125" E0318 21:30:46.500825 1 reflector.go:205] "Failed to watch" err="failed to list *v1.ClusterOperator: the server could not find the requested resource (get clusteroperators.config.openshift.io)" logger="UnhandledError" reflector="github.com/openshift/client-go/config/informers/externalversions/factory.go:125" type="*v1.ClusterOperator" But we are unlikely to need any fancy feature-gated knobs in the CRDs just to get the CVO going. So with this commit I'm appending a YAML comment with the grep target to the Default CRD, and the expectation is that: 1. The bootstrapping creates the Default ClusterVersion CRD. 2. The HyperShift control-plane operator populates it with enough to get the initial CVO running (e.g. spec.capabilities to exclude some capabilities, because once installed, capabilities cannot be uninstalled [4]). 3. CVO comes up, reads in the initial CluserVersion and FeatureGate and whatever else it needs, and if necessary, updates the ClusterVersion CRD. 4. HyperShift populates any feature-gated ClusterVersion knobs, now that those slots exist. 5. Post-install cluster lifecycle continues to have the CVO managing its own resources in the cluster, no more need for HyperShift bootstrapping. It would be elegant to have the new grep target as an annotation in the CVO, but for a flag of such limited utility, finding a way to reliably inject it from the Dockerfile seems like more trouble than it would be worth, which is why I'm using the YAML comment approach. [1]: https://github.com/openshift/hypershift/blob/a85cd0a7ed067748f74a7869955ebd05a01912b8/control-plane-operator/controllers/hostedcontrolplane/v2/cvo/deployment.go#L205-L241 [2]: https://github.com/openshift/hypershift/blob/a85cd0a7ed067748f74a7869955ebd05a01912b8/control-plane-operator/controllers/hostedcontrolplane/v2/assets/cluster-version-operator/deployment.yaml#L89-L104 [3]: https://github.com/openshift/cluster-version-operator/pull/1282#issuecomment-4059395971 [4]: https://github.com/openshift/enhancements/blob/2b38513b8661632f08e64f4acc3b856e842f8669/enhancements/installer/component-selection.md#capabilities-cannot-be-uninstalled --- Dockerfile.rhel | 2 ++ install/0000_00_cluster-version-operator_00_namespace.yaml | 1 + install/0000_00_cluster-version-operator_02_roles.yaml | 1 + 3 files changed, 4 insertions(+) diff --git a/Dockerfile.rhel b/Dockerfile.rhel index df40d2734a..84aa2b4d33 100644 --- a/Dockerfile.rhel +++ b/Dockerfile.rhel @@ -10,5 +10,7 @@ COPY --from=builder /tmp/build/cluster-version-operator /tmp/build/cluster-versi COPY install /manifests COPY vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_00_cluster-version-operator_* /manifests/ COPY vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.crd-manifests/0000_00_cluster-version-operator_* /manifests/ +RUN echo '# include.release.openshift.io/bootstrap-cluster-version-operator: hypershift' >>/manifests/0000_00_cluster-version-operator_01_clusterversions-Default.crd.yaml && \ + echo '# include.release.openshift.io/bootstrap-cluster-version-operator: hypershift' >>/manifests/0000_00_cluster-version-operator_01_clusteroperators.crd.yaml COPY bootstrap /bootstrap ENTRYPOINT ["/usr/bin/cluster-version-operator"] diff --git a/install/0000_00_cluster-version-operator_00_namespace.yaml b/install/0000_00_cluster-version-operator_00_namespace.yaml index 00346c476f..7ac80f1405 100644 --- a/install/0000_00_cluster-version-operator_00_namespace.yaml +++ b/install/0000_00_cluster-version-operator_00_namespace.yaml @@ -5,6 +5,7 @@ metadata: annotations: kubernetes.io/description: The cluster-version operator manages OpenShift updates and reconciles core resources and cluster operators. include.release.openshift.io/self-managed-high-availability: "true" + include.release.openshift.io/bootstrap-cluster-version-operator: hypershift openshift.io/node-selector: "" workload.openshift.io/allowed: "management" labels: diff --git a/install/0000_00_cluster-version-operator_02_roles.yaml b/install/0000_00_cluster-version-operator_02_roles.yaml index 9396aa6149..33a6787f35 100644 --- a/install/0000_00_cluster-version-operator_02_roles.yaml +++ b/install/0000_00_cluster-version-operator_02_roles.yaml @@ -5,6 +5,7 @@ metadata: annotations: kubernetes.io/description: Grant the cluster-version operator permission to perform cluster-admin actions while managing the OpenShift core. include.release.openshift.io/self-managed-high-availability: "true" + include.release.openshift.io/bootstrap-cluster-version-operator: hypershift roleRef: kind: ClusterRole name: cluster-admin