Skip to content

Commit 5af7d1d

Browse files
committed
pkg/operator: Split OCM/RCM status conditions
OCM and RCM are now associated with separate sets of status conditions. Available, Progressing and WorkloadDegraded are associated with OCM only. The same conditions having RouteControllerManager prefix are associated with RCM.
1 parent 0a0b2ce commit 5af7d1d

File tree

2 files changed

+409
-474
lines changed

2 files changed

+409
-474
lines changed

pkg/operator/sync_openshiftcontrollermanager_v311_00.go

Lines changed: 106 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
4244
var 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

296309
func manageOpenShiftControllerManagerClientCA_v311_00_to_latest(client coreclientv1.ConfigMapsGetter, recorder events.Recorder) (*corev1.ConfigMap, bool, error) {

0 commit comments

Comments
 (0)