Skip to content

Commit 31eeb0d

Browse files
committed
NE-2097: Add logic to pick up next InstallPlan if desired version jumps upgrade graph
1 parent d41a9be commit 31eeb0d

File tree

4 files changed

+441
-2
lines changed

4 files changed

+441
-2
lines changed

manifests/00-cluster-role.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ rules:
180180
resources:
181181
- subscriptions
182182
- installplans
183+
- clusterserviceversions
183184
verbs:
184185
- '*'
185186

manifests/02-deployment.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ spec:
8181
value: openshift/origin-cluster-ingress-operator:latest
8282
- name: GATEWAY_API_OPERATOR_CHANNEL
8383
value: stable
84+
# NOTE:
85+
# Use an operator version that exists in the catalog.
86+
# If the specified version is not found, the latest available
87+
# OSSM operator version will be installed as of the upgrade date.
88+
# Downgrades are not supported; the new version must be
89+
# semantically greater than the previous one.
8490
- name: GATEWAY_API_OPERATOR_VERSION
8591
value: servicemeshoperator3.v3.0.1
8692
resources:

pkg/operator/controller/gatewayclass/subscription.go

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@ func (r *reconciler) ensureServiceMeshOperatorInstallPlan(ctx context.Context) (
176176
}
177177

178178
// currentInstallPlan returns the InstallPlan that describes installing the expected version of the GatewayAPI
179-
// implementation, if one exists.
179+
// implementation. If no InstallPlan exists for the expected version, return the InstallPlan which replaces the currently installed one.
180+
// This InstallPlan is expected to advance the OSSM operator toward the next CSV in the upgrade graph,
181+
// assuming that the configured version is available further up the graph.
180182
func (r *reconciler) currentInstallPlan(ctx context.Context) (bool, *operatorsv1alpha1.InstallPlan, error) {
181183
_, subscription, err := r.currentSubscription(ctx, operatorcontroller.ServiceMeshOperatorSubscriptionName())
182184
if err != nil {
@@ -189,7 +191,7 @@ func (r *reconciler) currentInstallPlan(ctx context.Context) (bool, *operatorsv1
189191
if installPlans == nil || len(installPlans.Items) == 0 {
190192
return false, nil, nil
191193
}
192-
var currentInstallPlan *operatorsv1alpha1.InstallPlan
194+
var currentInstallPlan, nextInstallPlan *operatorsv1alpha1.InstallPlan
193195
multipleInstallPlans := false
194196
for _, installPlan := range installPlans.Items {
195197
if len(installPlan.OwnerReferences) == 0 || len(installPlan.Spec.ClusterServiceVersionNames) == 0 {
@@ -209,6 +211,7 @@ func (r *reconciler) currentInstallPlan(ctx context.Context) (bool, *operatorsv1
209211
if installPlan.Status.Phase != operatorsv1alpha1.InstallPlanPhaseRequiresApproval {
210212
continue
211213
}
214+
// Check whether InstallPlan implements the expected operator version.
212215
for _, csvName := range installPlan.Spec.ClusterServiceVersionNames {
213216
if csvName == r.config.GatewayAPIOperatorVersion {
214217
// Keep the newest InstallPlan to return at the end of the loop.
@@ -223,10 +226,56 @@ func (r *reconciler) currentInstallPlan(ctx context.Context) (bool, *operatorsv1
223226
}
224227
}
225228
}
229+
// Check whether InstallPlan implements the next operator version in the upgrade graph.
230+
for _, csvName := range installPlan.Spec.ClusterServiceVersionNames {
231+
// The definitions of InstalledCSV and CurrentCSV are non-trivial:
232+
//
233+
// - InstalledCSV represents the currently running CSV.
234+
// - CurrentCSV represents the version that "subscription is progressing to"
235+
// which practically means "the next CSV in the upgrade graph."
236+
//
237+
// - If InstalledCSV < CurrentCSV:
238+
// No CSV replacement is ongoing. InstalledCSV is the current version,
239+
// and CurrentCSV is the next one in the upgrade graph.
240+
// - If InstalledCSV == CurrentCSV:
241+
// One of the following scenarios is possible:
242+
// 1. CSV replacement is in progress "InstalledCSV-1" is being replaced with CurrentCSV.
243+
// 2. Installation of the first CSV is in progress.
244+
// 3. There is no "next CSV" in the upgrade graph, so CurrentCSV
245+
// cannot point to a future version.
246+
// CurrentCSV only becomes the next version once the replacement finishes,
247+
// and the next InstallPlan appears around the same time.
248+
//
249+
// The first condition (below) prevents setting the next InstallPlan while a replacement
250+
// or installation is ongoing, or when the end of the upgrade graph is reached.
251+
if subscription.Status.InstalledCSV != subscription.Status.CurrentCSV && csvName == subscription.Status.CurrentCSV {
252+
if nextInstallPlan == nil {
253+
nextInstallPlan = &installPlan
254+
break
255+
}
256+
}
257+
}
226258
}
227259
if multipleInstallPlans {
228260
log.Info(fmt.Sprintf("found multiple valid InstallPlans. using %s because it's the newest", currentInstallPlan.Name))
229261
}
262+
// No InstallPlan with the expected operator version was found,
263+
// but the next one in the upgrade graph exists.
264+
// Return the next InstallPlan to continue the upgrade.
265+
if currentInstallPlan == nil && nextInstallPlan != nil {
266+
log.Info("next install plan time")
267+
// The condition below prevents approving an InstallPlan
268+
// that targets a version beyond the expected operator version.
269+
// This can happen when:
270+
// - InstallPlan with the expected version is complete (no approval needed).
271+
// - Newer versions exist in the upgrade graph.
272+
// The check ensures that the currently running CSV is different
273+
// from the expected version. Once they match, no further action is needed.
274+
if subscription.Status.InstalledCSV != r.config.GatewayAPIOperatorVersion {
275+
log.Info("installplan with expected operator version was not found; proceedng with an intermedite installplan", "name", nextInstallPlan.Name, "csv", subscription.Status.CurrentCSV)
276+
currentInstallPlan = nextInstallPlan
277+
}
278+
}
230279
return (currentInstallPlan != nil), currentInstallPlan, nil
231280
}
232281

0 commit comments

Comments
 (0)