@@ -37,6 +37,8 @@ import (
3737 "github.com/openshift/cluster-openshift-controller-manager-operator/pkg/util"
3838)
3939
40+ const rcmConditionTypePrefix = "RouteControllerManager"
41+
4042// ControllerCapabilities maps controllers to capabilities, so we can enable/disable controllers
4143// based on capabilities.
4244var controllerCapabilities = map [controlplanev1.OpenShiftControllerName ]configv1.ClusterVersionCapability {
@@ -60,8 +62,10 @@ func syncOpenShiftControllerManager_v311_00_to_latest(
6062 countNodes nodeCountFunc ,
6163 ensureAtMostOnePodPerNodeFn ensureAtMostOnePodPerNodeFunc ,
6264) (bool , error ) {
63- errors := []error {}
64- var err error
65+ var (
66+ ocmErrors , rcmErrors []error
67+ err error
68+ )
6569 operatorConfig := originalOperatorConfig .DeepCopy ()
6670
6771 operandName := "openshift-controller-manager"
@@ -78,14 +82,14 @@ func syncOpenShiftControllerManager_v311_00_to_latest(
7882 // OpenShift Controller Manager
7983 configMap , _ , err := manageOpenShiftControllerManagerConfigMap_v311_00_to_latest (c .clusterVersionLister , c .kubeClient , c .configMapsGetter , c .recorder , operatorConfig )
8084 if err != nil {
81- errors = append (errors , fmt .Errorf ("%q %q: %v " , operandName , "config" , err ))
85+ ocmErrors = append (ocmErrors , fmt .Errorf ("%q %q: %w " , operandName , "config" , err ))
8286 } else {
8387 specAnnotations ["configmaps/config" ] = configMap .ObjectMeta .ResourceVersion
8488 }
8589 // the kube-apiserver is the source of truth for client CA bundles
8690 clientCAConfigMap , _ , err := manageOpenShiftControllerManagerClientCA_v311_00_to_latest (c .kubeClient .CoreV1 (), c .recorder )
8791 if err != nil {
88- errors = append (errors , fmt .Errorf ("%q %q: %v" , operandName , "client-ca" , err ))
92+ ocmErrors = append (ocmErrors , fmt .Errorf ("%q %q: %v" , operandName , "client-ca" , err ))
8993 } else {
9094 resourceVersion := "0"
9195 if clientCAConfigMap != nil { // SyncConfigMap can return nil
@@ -96,30 +100,30 @@ func syncOpenShiftControllerManager_v311_00_to_latest(
96100
97101 serviceCAConfigMap , _ , err := manageOpenShiftServiceCAConfigMap_v311_00_to_latest (c .kubeClient , c .configMapsGetter , c .recorder )
98102 if err != nil {
99- errors = append (errors , fmt .Errorf ("%q %q: %v" , operandName , "openshift-service-ca" , err ))
103+ ocmErrors = append (ocmErrors , fmt .Errorf ("%q %q: %v" , operandName , "openshift-service-ca" , err ))
100104 } else {
101105 specAnnotations ["configmaps/openshift-service-ca" ] = serviceCAConfigMap .ObjectMeta .ResourceVersion
102106 }
103107
104108 globalCAConfigMap , _ , err := manageOpenShiftGlobalCAConfigMap_v311_00_to_latest (c .kubeClient , c .configMapsGetter , c .recorder )
105109 if err != nil {
106- errors = append (errors , fmt .Errorf ("%q %q: %v" , operandName , "openshift-global-ca" , err ))
110+ ocmErrors = append (ocmErrors , fmt .Errorf ("%q %q: %v" , operandName , "openshift-global-ca" , err ))
107111 } else {
108112 specAnnotations ["configmaps/openshift-global-ca" ] = globalCAConfigMap .ObjectMeta .ResourceVersion
109113 }
110114
111115 // Route Controller Manager
112116 rcConfigMap , _ , err := manageRouteControllerManagerConfigMap_v311_00_to_latest (c .kubeClient , c .configMapsGetter , c .recorder , operatorConfig )
113117 if err != nil {
114- errors = append (errors , fmt .Errorf ("%q %q: %v" , rcOperandName , "configmap" , err ))
118+ rcmErrors = append (rcmErrors , fmt .Errorf ("%q %q: %v" , rcOperandName , "configmap" , err ))
115119 } else {
116120 rcSpecAnnotations ["configmaps/config" ] = rcConfigMap .ObjectMeta .ResourceVersion
117121 }
118122
119123 // the kube-apiserver is the source of truth for client CA bundles
120124 rcClientCAConfigMap , _ , err := manageRouteControllerManagerClientCA_v311_00_to_latest (c .kubeClient .CoreV1 (), c .recorder )
121125 if err != nil {
122- errors = append (errors , fmt .Errorf ("%q %q: %v" , rcOperandName , "client-ca" , err ))
126+ rcmErrors = append (rcmErrors , fmt .Errorf ("%q %q: %v" , rcOperandName , "client-ca" , err ))
123127 } else {
124128 resourceVersion := "0"
125129 if rcClientCAConfigMap != nil { // SyncConfigMap can return nil
@@ -129,7 +133,6 @@ func syncOpenShiftControllerManager_v311_00_to_latest(
129133 }
130134
131135 // our configmaps and secrets are in order, now it is time to create the Deployment
132- var progressingMessages []string
133136 actualDeployment , _ , openshiftControllerManagerError := manageOpenShiftControllerManagerDeployment_v311_00_to_latest (
134137 bindata .MustAsset ,
135138 c .kubeClient .AppsV1 (),
@@ -143,9 +146,7 @@ func syncOpenShiftControllerManager_v311_00_to_latest(
143146 specAnnotations ,
144147 )
145148 if openshiftControllerManagerError != nil {
146- msg := fmt .Sprintf ("%q %q: %v" , operandName , "deployment" , openshiftControllerManagerError )
147- progressingMessages = append (progressingMessages , msg )
148- errors = append (errors , fmt .Errorf (msg ))
149+ ocmErrors = append (ocmErrors , fmt .Errorf ("%q %q: %v" , operandName , "deployment" , openshiftControllerManagerError ))
149150 }
150151
151152 actualRCDeployment , _ , routerControllerManagerError := manageRouteControllerManagerDeployment_v311_00_to_latest (
@@ -159,138 +160,150 @@ func syncOpenShiftControllerManager_v311_00_to_latest(
159160 rcSpecAnnotations ,
160161 )
161162 if routerControllerManagerError != nil {
162- msg := fmt .Sprintf ("%q %q: %v" , rcOperandName , "deployment" , routerControllerManagerError )
163- progressingMessages = append (progressingMessages , msg )
164- errors = append (errors , fmt .Errorf (msg ))
163+ rcmErrors = append (rcmErrors , fmt .Errorf ("%q %q: %v" , rcOperandName , "deployment" , routerControllerManagerError ))
165164 }
166165
167166 // library-go func called by manageOpenShiftControllerManagerDeployment_v311_00_to_latest can return nil with errors
168167 if openshiftControllerManagerError != nil || routerControllerManagerError != nil {
169- return syncReturn (c , errors , originalOperatorConfig , operatorConfig )
168+ return syncReturn (c , ocmErrors , rcmErrors , originalOperatorConfig , operatorConfig )
170169 }
171170
172- // at this point we know that the actualDeployment and actualRCDeployment are both non-nil and non-empty
173- available := actualDeployment .Status .AvailableReplicas > 0
174- rcAvailable := actualRCDeployment .Status .AvailableReplicas > 0
175-
176171 // manage status
177- if available && rcAvailable {
172+ // first we need to update operator config status version based on the OCM deployment
173+ if d := actualDeployment ; d .Status .AvailableReplicas > 0 && d .Status .UpdatedReplicas == d .Status .Replicas && len (d .Annotations [util .VersionAnnotation ]) > 0 {
174+ operatorConfig .Status .Version = d .Annotations [util .VersionAnnotation ]
175+ }
176+
177+ setControllerManagerStatusConditions (operatorConfig , actualDeployment , "openshift controller manager" , "" )
178+ setControllerManagerStatusConditions (operatorConfig , actualRCDeployment , "route controller manager" , rcmConditionTypePrefix )
179+
180+ v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
181+ Type : operatorapiv1 .OperatorStatusTypeUpgradeable ,
182+ Status : operatorapiv1 .ConditionTrue ,
183+ })
184+
185+ operatorConfig .Status .ObservedGeneration = operatorConfig .ObjectMeta .Generation
186+ resourcemerge .SetDeploymentGeneration (& operatorConfig .Status .Generations , actualDeployment )
187+ resourcemerge .SetDeploymentGeneration (& operatorConfig .Status .Generations , actualRCDeployment )
188+
189+ return syncReturn (c , ocmErrors , rcmErrors , originalOperatorConfig , operatorConfig )
190+ }
191+
192+ // setControllerManagerStatusConditions sets operator status conditions for an operand.
193+ // Available and Progressing are being handled here, Degraded is handled in syncReturn.
194+ //
195+ // Make sure operatorConfig.Status.Version is set properly before calling this helper function.
196+ func setControllerManagerStatusConditions (
197+ operatorConfig * operatorapiv1.OpenShiftControllerManager ,
198+ d * appsv1.Deployment ,
199+ operandReadableName string ,
200+ conditionTypePrefix string ,
201+ ) {
202+ available := d .Status .AvailableReplicas > 0
203+
204+ // Available
205+ if available {
178206 v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
179- Type : operatorapiv1 .OperatorStatusTypeAvailable ,
207+ Type : conditionTypePrefix + operatorapiv1 .OperatorStatusTypeAvailable ,
180208 Status : operatorapiv1 .ConditionTrue ,
181209 })
182210 } else {
183- msg := "no pods available on any node."
184- if ! available && rcAvailable {
185- msg = fmt .Sprintf ("no openshift controller manager daemon pods available on any node." )
186- }
187- if available && ! rcAvailable {
188- msg = fmt .Sprintf ("no route controller manager deployment pods available on any node." )
189- }
190-
191211 v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
192- Type : operatorapiv1 .OperatorStatusTypeAvailable ,
212+ Type : conditionTypePrefix + operatorapiv1 .OperatorStatusTypeAvailable ,
193213 Status : operatorapiv1 .ConditionFalse ,
194214 Reason : "NoPodsAvailable" ,
195- Message : msg ,
215+ Message : fmt . Sprintf ( "no %s deployment pods available on any node" , operandReadableName ) ,
196216 })
197217 }
198218
199- if available && actualDeployment .Status .UpdatedReplicas == actualDeployment .Status .Replicas {
200- if len (actualDeployment .Annotations [util .VersionAnnotation ]) > 0 {
201- operatorConfig .Status .Version = actualDeployment .Annotations [util .VersionAnnotation ]
202- } else {
203- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/controller-manager: version annotation %s missing." , util .VersionAnnotation ))
204- }
205- }
206-
207- if rcAvailable && actualRCDeployment .Status .UpdatedReplicas == actualRCDeployment .Status .Replicas {
208- if len (actualRCDeployment .Annotations [util .VersionAnnotation ]) > 0 {
209- // version should be the same as the controller-manager, just do a check the route-controller-manager has the same
210- if len (operatorConfig .Status .Version ) != 0 && operatorConfig .Status .Version != actualRCDeployment .Annotations [util .VersionAnnotation ] {
211- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/route-controller-manager: has invalid version annotation %s, desired version %s." , util .VersionAnnotation , operatorConfig .Status .Version ))
219+ // Progressing
220+ var progressingMessages []string
221+ if available && d .Status .UpdatedReplicas == d .Status .Replicas {
222+ if len (d .Annotations [util .VersionAnnotation ]) > 0 {
223+ if len (operatorConfig .Status .Version ) != 0 && operatorConfig .Status .Version != d .Annotations [util .VersionAnnotation ] {
224+ progressingMessages = append (progressingMessages , fmt .Sprintf (
225+ "deployment/%s: has invalid version annotation %s, desired version %s" ,
226+ d .Name , util .VersionAnnotation , operatorConfig .Status .Version ))
212227 }
213228 } else {
214- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/route-controller-manager: version annotation %s missing." , util .VersionAnnotation ))
229+ progressingMessages = append (progressingMessages , fmt .Sprintf (
230+ "deployment/%s: version annotation %s missing" , d .Name , util .VersionAnnotation ))
215231 }
216232 }
217-
218- if actualDeployment != nil && actualDeployment .ObjectMeta .Generation != actualDeployment .Status .ObservedGeneration {
219- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/controller-manager: observed generation is %d, desired generation is %d." , actualDeployment .Status .ObservedGeneration , actualDeployment .ObjectMeta .Generation ))
233+ if d .ObjectMeta .Generation != d .Status .ObservedGeneration {
234+ progressingMessages = append (progressingMessages , fmt .Sprintf (
235+ "deployment/%s: observed generation is %d, desired generation is %d" ,
236+ d .Name , d .Status .ObservedGeneration , d .ObjectMeta .Generation ))
220237 }
221- if actualDeployment .Status .AvailableReplicas == 0 {
222- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/controller-manager: available replicas is %d, desired available replicas > %d " , actualDeployment . Status . AvailableReplicas , 1 ))
238+ if d .Status .AvailableReplicas == 0 {
239+ progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/%s: no available replica found " , d . Name ))
223240 }
224- if actualDeployment .Status .UpdatedReplicas != * actualDeployment .Spec .Replicas {
225- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/controller-manager: updated replicas is %d, desired replicas is %d" , actualDeployment .Status .UpdatedReplicas , * actualDeployment .Spec .Replicas ))
226- }
227- if actualRCDeployment != nil && actualRCDeployment .ObjectMeta .Generation != actualRCDeployment .Status .ObservedGeneration {
228- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/route-controller-manager: observed generation is %d, desired generation is %d." , actualRCDeployment .Status .ObservedGeneration , actualRCDeployment .ObjectMeta .Generation ))
229- }
230- if actualRCDeployment .Status .AvailableReplicas == 0 {
231- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/route-controller-manager: available replicas is %d, desired available replicas > %d" , actualRCDeployment .Status .AvailableReplicas , 1 ))
232- }
233- if actualRCDeployment .Status .UpdatedReplicas != * actualRCDeployment .Spec .Replicas {
234- progressingMessages = append (progressingMessages , fmt .Sprintf ("deployment/route-controller-manager: updated replicas is %d, desired replicas is %d" , actualRCDeployment .Status .UpdatedReplicas , * actualRCDeployment .Spec .Replicas ))
241+ if d .Status .UpdatedReplicas != * d .Spec .Replicas {
242+ progressingMessages = append (progressingMessages , fmt .Sprintf (
243+ "deployment/%s: updated replicas is %d, desired replicas is %d" ,
244+ d .Name , d .Status .UpdatedReplicas , * d .Spec .Replicas ))
235245 }
246+
247+ // This is actually not depending on the deployment object,
248+ // but generation mismatch sets all operands to Progressing.
236249 if operatorConfig .ObjectMeta .Generation != operatorConfig .Status .ObservedGeneration {
237- progressingMessages = append (progressingMessages , fmt .Sprintf ("openshiftcontrollermanagers.operator.openshift.io/cluster: observed generation is %d, desired generation is %d." , operatorConfig .Status .ObservedGeneration , operatorConfig .ObjectMeta .Generation ))
250+ progressingMessages = append (progressingMessages , fmt .Sprintf (
251+ "openshiftcontrollermanagers.operator.openshift.io/cluster: observed generation is %d, desired generation is %d" ,
252+ operatorConfig .Status .ObservedGeneration , operatorConfig .ObjectMeta .Generation ))
238253 }
254+
239255 if len (progressingMessages ) == 0 {
240256 v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
241- Type : operatorapiv1 .OperatorStatusTypeProgressing ,
257+ Type : conditionTypePrefix + operatorapiv1 .OperatorStatusTypeProgressing ,
242258 Status : operatorapiv1 .ConditionFalse ,
243259 })
244260 } else {
245261 v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
246- Type : operatorapiv1 .OperatorStatusTypeProgressing ,
262+ Type : conditionTypePrefix + operatorapiv1 .OperatorStatusTypeProgressing ,
247263 Status : operatorapiv1 .ConditionTrue ,
248264 Reason : "DesiredStateNotYetAchieved" ,
249265 Message : strings .Join (progressingMessages , "\n " ),
250266 })
251267 }
252-
253- v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
254- Type : operatorapiv1 .OperatorStatusTypeUpgradeable ,
255- Status : operatorapiv1 .ConditionTrue ,
256- })
257-
258- operatorConfig .Status .ObservedGeneration = operatorConfig .ObjectMeta .Generation
259- resourcemerge .SetDeploymentGeneration (& operatorConfig .Status .Generations , actualDeployment )
260- resourcemerge .SetDeploymentGeneration (& operatorConfig .Status .Generations , actualRCDeployment )
261-
262- return syncReturn (c , errors , originalOperatorConfig , operatorConfig )
263268}
264269
265- func syncReturn (c OpenShiftControllerManagerOperator , errors []error , originalOperatorConfig , operatorConfig * operatorapiv1.OpenShiftControllerManager ) (bool , error ) {
266- if len (errors ) > 0 {
267- message := ""
268- for _ , err := range errors {
269- message = message + err .Error () + "\n "
270+ // syncReturn checks the error slices and sets Degraded conditions in the operator config before returning.
271+ func syncReturn (
272+ c OpenShiftControllerManagerOperator ,
273+ ocmErrors , rcmErrors []error ,
274+ originalOperatorConfig , operatorConfig * operatorapiv1.OpenShiftControllerManager ,
275+ ) (bool , error ) {
276+ setDegraded := func (errs []error , conditionType string ) {
277+ if len (errs ) == 0 {
278+ v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
279+ Type : conditionType ,
280+ Status : operatorapiv1 .ConditionFalse ,
281+ })
282+ return
283+ }
284+
285+ var msg strings.Builder
286+ for _ , err := range errs {
287+ msg .WriteString (err .Error ())
288+ msg .WriteString ("\n " )
270289 }
271290 v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
272- Type : workloadDegradedCondition ,
291+ Type : conditionType ,
273292 Status : operatorapiv1 .ConditionTrue ,
274- Message : message ,
293+ Message : msg . String () ,
275294 Reason : "SyncError" ,
276295 })
277- } else {
278- v1helpers .SetOperatorCondition (& operatorConfig .Status .Conditions , operatorapiv1.OperatorCondition {
279- Type : workloadDegradedCondition ,
280- Status : operatorapiv1 .ConditionFalse ,
281- })
282296 }
283297
298+ setDegraded (ocmErrors , workloadDegradedCondition )
299+ setDegraded (rcmErrors , rcmConditionTypePrefix + "Degraded" )
300+
284301 if ! equality .Semantic .DeepEqual (operatorConfig .Status , originalOperatorConfig .Status ) {
285302 if _ , err := c .operatorConfigClient .OpenShiftControllerManagers ().UpdateStatus (context .TODO (), operatorConfig , metav1.UpdateOptions {}); err != nil {
286303 return false , err
287304 }
288305 }
289-
290- if len (errors ) > 0 {
291- return true , nil
292- }
293- return false , nil
306+ return len (ocmErrors ) > 0 || len (rcmErrors ) > 0 , nil
294307}
295308
296309func manageOpenShiftControllerManagerClientCA_v311_00_to_latest (client coreclientv1.ConfigMapsGetter , recorder events.Recorder ) (* corev1.ConfigMap , bool , error ) {
0 commit comments