Skip to content

Commit 0c04d51

Browse files
committed
hypershift-operator/controllers/hostedcluster: isUpgradeable minor-bump scoping
Godocs for Upgradeable [1]: Upgradeable indicates whether the component (operator and all configured operands) is safe to upgrade based on the current cluster state. When Upgradeable is False, the cluster-version operator will prevent the cluster from performing impacted updates unless forced. When set on ClusterVersion, the message will explain which updates (minor or patch) are impacted. When set on ClusterOperator, False will block minor OpenShift updates. The message field should contain a human readable description of what the administrator should do to allow the cluster or component to successfully update. The cluster-version operator will allow updates when this condition is not False, including when it is missing, True, or Unknown. So we specifically doc it as only about 4.y -> 4.(y+1) minor updates when seen on ClusterOperator. But we leave it unclear on ClusterVersion because when you set some ClusterVersion overrides, it can break patch updates, so QE asked us to also block patch updates in that case [2,3]. With this patch, I'm using availableUpdates and conditionalUpdates to look up a version associated with the proposed target release pullspec. That's a bit less reliable than the current cluster-version operator behavior, which is extracting the proposed target version from the proposed release image itself (e.g. see [4]). But it's probably sufficient for now, with the odds that the OpenShift Update Service serves bad data low. And we can refine further in the future if we want. [1]: https://github.com/openshift/api/blob/cce310ad2932f6de24491052d506926e484c082c/config/v1/types_cluster_operator.go#L179-L190 : [2]: openshift/cluster-version-operator#364 [3]: https://bugzilla.redhat.com/show_bug.cgi?id=1822844 [4]: openshift/cluster-version-operator#431
1 parent a0377ae commit 0c04d51

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4214,10 +4214,40 @@ func (r *HostedClusterReconciler) reconcileAWSSubnets(ctx context.Context, creat
42144214
return nil
42154215
}
42164216

4217+
func releaseImageToVersion(hcluster *hyperv1.HostedCluster, image string) (semver.Version, error) {
4218+
for _, update := range hcluster.Status.Version.AvailableUpdates {
4219+
if update.Image == image { // TODO: all we care about is matching digests
4220+
return semver.Parse(update.Version)
4221+
}
4222+
}
4223+
for _, update := range hcluster.Status.Version.ConditionalUpdates {
4224+
if update.Release.Image == image { // TODO: all we care about is matching digests
4225+
return semver.Parse(update.Release.Version)
4226+
}
4227+
}
4228+
var version semver.Version
4229+
return version, fmt.Errorf("unable to determine a version string for %s", image)
4230+
}
4231+
42174232
func isUpgradeable(hcluster *hyperv1.HostedCluster) (bool, string, error) {
42184233
if hcluster.Status.Version != nil && hcluster.Status.Version.Desired.Image != hcluster.Spec.Release.Image {
42194234
upgradeable := meta.FindStatusCondition(hcluster.Status.Conditions, string(hyperv1.ClusterVersionUpgradeable))
42204235
if upgradeable != nil && upgradeable.Status == metav1.ConditionFalse {
4236+
currentTargetVersion, err := semver.Parse(hcluster.Status.Version.Desired.Version)
4237+
if err != nil {
4238+
return true, "", fmt.Errorf("cluster is %s=%s (%s: %s), and failed to parse the current target %s as a Semantic Version: %w", upgradeable.Type, upgradeable.Status, upgradeable.Reason, upgradeable.Message, hcluster.Status.Version.Desired.Version, err)
4239+
}
4240+
4241+
requestedVersion, err := releaseImageToVersion(hcluster, hcluster.Spec.Release.Image)
4242+
if err != nil {
4243+
return true, "", fmt.Errorf("cluster is %s=%s (%s: %s), and failed determine a version for %s to see if it is a minor update from %s: %w", upgradeable.Type, upgradeable.Status, upgradeable.Reason, upgradeable.Message, hcluster.Spec.Release.Image, hcluster.Status.Version.Desired.Version, err)
4244+
}
4245+
4246+
if requestedVersion.Major == currentTargetVersion.Major && requestedVersion.Minor == currentTargetVersion.Minor {
4247+
// ClusterVersion's Upgradeable condition is mostly about minor bumps from x.y to x.(y+1) and larger. It is not intended to block patch updates from x.y.z to x.y.z' except under very limited circumstances which we can ignore for now.
4248+
return true, "", nil
4249+
}
4250+
42214251
releaseImage, exists := hcluster.Annotations[hyperv1.ForceUpgradeToAnnotation]
42224252
if !exists {
42234253
return true, "", fmt.Errorf("cluster version is not upgradeable")

0 commit comments

Comments
 (0)