@@ -100,6 +100,9 @@ func New(mgr manager.Manager, config Config) (controller.Controller, error) {
100100 isIngressClusterOperator := func (o client.Object ) bool {
101101 return o .GetName () == operatorcontroller .IngressClusterOperatorName ().Name
102102 }
103+ isOpenshiftOperatorNamespace := func (o client.Object ) bool {
104+ return o .GetNamespace () == operatorcontroller .OpenshiftOperatorNamespace
105+ }
103106 toDefaultIngressController := func (ctx context.Context , _ client.Object ) []reconcile.Request {
104107 return []reconcile.Request {{
105108 NamespacedName : types.NamespacedName {
@@ -129,13 +132,13 @@ func New(mgr manager.Manager, config Config) (controller.Controller, error) {
129132 return e .Object .GetNamespace () == operatorcontroller .OpenshiftOperatorNamespace
130133 },
131134 UpdateFunc : func (e event.UpdateEvent ) bool {
132- return false
135+ return e . ObjectNew . GetNamespace () == operatorcontroller . OpenshiftOperatorNamespace
133136 },
134137 DeleteFunc : func (e event.DeleteEvent ) bool {
135138 return e .Object .GetNamespace () == operatorcontroller .OpenshiftOperatorNamespace
136139 },
137140 GenericFunc : func (e event.GenericEvent ) bool {
138- return false
141+ return e . Object . GetNamespace () == operatorcontroller . OpenshiftOperatorNamespace
139142 },
140143 })); err != nil {
141144 return nil , err
@@ -156,6 +159,9 @@ func New(mgr manager.Manager, config Config) (controller.Controller, error) {
156159 })); err != nil {
157160 return nil , err
158161 }
162+ if err := c .Watch (source .Kind [client.Object ](operatorCache , & operatorsv1alpha1.ClusterServiceVersion {}, handler .EnqueueRequestsFromMapFunc (toDefaultIngressController ), predicate .NewPredicateFuncs (isOpenshiftOperatorNamespace ))); err != nil {
163+ return nil , err
164+ }
159165 }
160166
161167 return c , nil
@@ -295,13 +301,11 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
295301 co .Status .Conditions = mergeConditions (co .Status .Conditions ,
296302 computeOperatorAvailableCondition (state .IngressControllers ),
297303 computeOperatorProgressingCondition (
298- state .IngressControllers ,
304+ state ,
305+ r .config ,
299306 allIngressesAvailable ,
300307 oldStatus .Versions ,
301308 co .Status .Versions ,
302- r .config .OperatorReleaseVersion ,
303- r .config .IngressControllerImage ,
304- r .config .CanaryImage ,
305309 ),
306310 computeOperatorDegradedCondition (state ),
307311 computeOperatorUpgradeableCondition (state .IngressControllers ),
@@ -366,6 +370,18 @@ type operatorState struct {
366370 // haveGatewayclassesResource means that the
367371 // "gatewayclasses.gateway.networking.k8s.io" CRD exists.
368372 haveGatewayclassesResource bool
373+ // desiredOSSMVersion contains the desired OSSM operator
374+ // as recorded in the subscription.
375+ desiredOSSMVersion string
376+ // installedOSSMVersion contains the currently installed
377+ // version of the OSSM operator.
378+ installedOSSMVersion string
379+ // currentOSSMVersion contains the OSSM operator version
380+ // which is currently being installed or the next in the upgrade graph.
381+ currentOSSMVersion string
382+ // installedOSSMVersionSucceeded means that the installed OSSM operator
383+ // version succeeded.
384+ installedOSSMVersionSucceeded bool
369385}
370386
371387// getOperatorState gets and returns the resources necessary to compute the
@@ -417,6 +433,27 @@ func (r *reconciler) getOperatorState(ctx context.Context, ingressNamespace, can
417433 } else {
418434 state .haveOSSMSubscription = true
419435
436+ // To compute the OSSM operator's progressing status,
437+ // we need to inspect the CSV level to determine whether
438+ // the installedCSV of the subscription succeeded.
439+ var installedCSV operatorsv1alpha1.ClusterServiceVersion
440+ installedCSVName := types.NamespacedName {
441+ Name : subscription .Status .InstalledCSV ,
442+ Namespace : operatorcontroller .OpenshiftOperatorNamespace ,
443+ }
444+ if err := r .cache .Get (ctx , installedCSVName , & installedCSV ); err != nil {
445+ if ! errors .IsNotFound (err ) {
446+ return state , fmt .Errorf ("failed to get installed CSV %q: %v" , installedCSVName .Name , err )
447+ }
448+ } else {
449+ state .installedOSSMVersionSucceeded = (installedCSV .Status .Phase == operatorsv1alpha1 .CSVPhaseSucceeded )
450+ }
451+ // StartingCSV is set by the gatewayclass controller to record
452+ // the desired operator version, even if this field is noop for OLM
453+ // after the operator was installed.
454+ state .desiredOSSMVersion = subscription .Spec .StartingCSV
455+ state .installedOSSMVersion = subscription .Status .InstalledCSV
456+ state .currentOSSMVersion = subscription .Status .CurrentCSV
420457 }
421458
422459 var (
@@ -648,7 +685,19 @@ func computeOperatorEvaluationConditionsDetectedCondition(ingresses []operatorv1
648685}
649686
650687// computeOperatorProgressingCondition computes the operator's current Progressing status state.
651- func computeOperatorProgressingCondition (ingresscontrollers []operatorv1.IngressController , allIngressesAvailable bool , oldVersions , curVersions []configv1.OperandVersion , operatorReleaseVersion , ingressControllerImage string , canaryImage string ) configv1.ClusterOperatorStatusCondition {
688+ func computeOperatorProgressingCondition (state operatorState , config Config , allIngressesAvailable bool , oldVersions , curVersions []configv1.OperandVersion ) configv1.ClusterOperatorStatusCondition {
689+ progressingCondition := configv1.ClusterOperatorStatusCondition {
690+ Type : configv1 .OperatorProgressing ,
691+ }
692+
693+ icCondition := computeIngressControllersProgressingCondition (state .IngressControllers , allIngressesAvailable , oldVersions , curVersions , config .OperatorReleaseVersion , config .IngressControllerImage , config .CanaryImage )
694+ ossmCondition := computeOSSMOperatorProgressingCondition (state )
695+
696+ return joinConditions (joinConditions (progressingCondition , icCondition ), ossmCondition )
697+ }
698+
699+ // computeIngressControllersProgressingCondition computes the IngressControllers' current Progressing status state.
700+ func computeIngressControllersProgressingCondition (ingresscontrollers []operatorv1.IngressController , allIngressesAvailable bool , oldVersions , curVersions []configv1.OperandVersion , operatorReleaseVersion , ingressControllerImage string , canaryImage string ) configv1.ClusterOperatorStatusCondition {
652701 progressingCondition := configv1.ClusterOperatorStatusCondition {
653702 Type : configv1 .OperatorProgressing ,
654703 }
@@ -715,6 +764,51 @@ func computeOperatorProgressingCondition(ingresscontrollers []operatorv1.Ingress
715764 return progressingCondition
716765}
717766
767+ // computeOSSMOperatorProgressingCondition computes the OSSM operator's current Progressing status state.
768+ func computeOSSMOperatorProgressingCondition (state operatorState ) configv1.ClusterOperatorStatusCondition {
769+ progressingCondition := configv1.ClusterOperatorStatusCondition {}
770+
771+ // Skip updating the progressing status if OSSM operator subscription doesn't exist.
772+ if ! state .haveOSSMSubscription {
773+ return progressingCondition
774+ }
775+
776+ progressing := false
777+
778+ // Set the progressing to true if the desired version is different
779+ // from the currently installed.
780+ if state .desiredOSSMVersion != state .installedOSSMVersion {
781+ // Note that the progressing state remains "true" if the desired version is
782+ // beyond the latest available in the upgrade graph.
783+ // There is no reliable way of knowing that the end of the upgrade graph
784+ // is reached and no next version is available. None of OLM resources
785+ // can provide such information.
786+ progressing = true
787+ } else {
788+ // The desired version was reached. However the CSV may still be
789+ // in "Replacing" or "Installing" state, stop setting progressing
790+ // when the installed CSV succeeded.
791+ if ! state .installedOSSMVersionSucceeded {
792+ progressing = true
793+ }
794+ }
795+
796+ if progressing {
797+ progressingCondition .Status = configv1 .ConditionTrue
798+ progressingCondition .Reason = "OSSMOperatorUpgrading"
799+ progressingCondition .Message = fmt .Sprintf ("OSSM operator is upgrading to version %q" , state .desiredOSSMVersion )
800+ if len (state .installedOSSMVersion ) > 0 && len (state .currentOSSMVersion ) > 0 {
801+ progressingCondition .Message += fmt .Sprintf (" (installed(-ing):%q,next:%q)" , state .installedOSSMVersion , state .currentOSSMVersion )
802+ }
803+ } else {
804+ progressingCondition .Status = configv1 .ConditionFalse
805+ progressingCondition .Reason = "OSSMOperatorUpToDate"
806+ progressingCondition .Message = fmt .Sprintf ("OSSM operator is running the expected version %q" , state .desiredOSSMVersion )
807+ }
808+
809+ return progressingCondition
810+ }
811+
718812// computeOperatorAvailableCondition computes the operator's current Available status state.
719813func computeOperatorAvailableCondition (ingresses []operatorv1.IngressController ) configv1.ClusterOperatorStatusCondition {
720814 availableCondition := configv1.ClusterOperatorStatusCondition {
@@ -825,7 +919,7 @@ func operatorStatusesEqual(a, b configv1.ClusterOperatorStatus) bool {
825919
826920// joinConditions merges two cluster operator conditions into one.
827921// If both conditions have the same status:
828- // - Reason becomes: "MultipleComponents[Not]" + condType .
922+ // - Reasons are concatenated using "And" as a delimiter .
829923// - Messages are concatenated.
830924// If the new condition has a higher-priority status, it overrides the current one.
831925// Status priority (highest to lowest): True, Unknown, False, empty.
0 commit comments