@@ -17,13 +17,14 @@ import (
1717 corev1listers "k8s.io/client-go/listers/core/v1"
1818 "k8s.io/client-go/tools/cache"
1919 "k8s.io/client-go/util/workqueue"
20+ "k8s.io/utils/ptr"
2021
2122 operatorv1 "github.com/openshift/api/operator/v1"
2223 openshiftconfigclientv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
24+ applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1"
2325 "github.com/openshift/library-go/pkg/apps/deployment"
2426 "github.com/openshift/library-go/pkg/controller/factory"
2527 "github.com/openshift/library-go/pkg/operator/events"
26- "github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
2728 "github.com/openshift/library-go/pkg/operator/status"
2829 "github.com/openshift/library-go/pkg/operator/v1helpers"
2930)
@@ -49,6 +50,7 @@ type Delegate interface {
4950// Callers must provide a sync function for delegation. It should bring the desired workload into operation.
5051// The returned state along with errors will be converted into conditions and persisted in the status field.
5152type Controller struct {
53+ controllerInstanceName string
5254 // conditionsPrefix an optional prefix that will be used as operator's condition type field for example APIServerDeploymentDegraded where APIServer indicates the prefix
5355 conditionsPrefix string
5456 operatorNamespace string
@@ -71,13 +73,13 @@ type Controller struct {
7173
7274// NewController creates a brand new Controller instance.
7375//
74- // the "name " param will be used to set conditions in the status field. It will be suffixed with "WorkloadController",
76+ // the "instanceName " param will be used to set conditions in the status field. It will be suffixed with "WorkloadController",
7577// so it can end up in the condition in the form of "OAuthAPIWorkloadControllerDeploymentAvailable"
7678//
7779// the "operatorNamespace" is used to set "version-mapping" in the correct namespace
7880//
7981// the "targetNamespace" represent the namespace for the managed resource (DaemonSet)
80- func NewController (name , operatorNamespace , targetNamespace , targetOperandVersion , operandNamePrefix , conditionsPrefix string ,
82+ func NewController (instanceName , operatorNamespace , targetNamespace , targetOperandVersion , operandNamePrefix , conditionsPrefix string ,
8183 operatorClient v1helpers.OperatorClient ,
8284 kubeClient kubernetes.Interface ,
8385 podLister corev1listers.PodLister ,
@@ -89,6 +91,7 @@ func NewController(name, operatorNamespace, targetNamespace, targetOperandVersio
8991 versionRecorder status.VersionGetter ,
9092) factory.Controller {
9193 controllerRef := & Controller {
94+ controllerInstanceName : factory .ControllerInstanceName (instanceName , "Workload" ),
9295 operatorNamespace : operatorNamespace ,
9396 targetNamespace : targetNamespace ,
9497 targetOperandVersion : targetOperandVersion ,
@@ -100,7 +103,7 @@ func NewController(name, operatorNamespace, targetNamespace, targetOperandVersio
100103 delegate : delegate ,
101104 openshiftClusterConfigClient : openshiftClusterConfigClient ,
102105 versionRecorder : versionRecorder ,
103- queue : workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), name ),
106+ queue : workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), instanceName ),
104107 }
105108
106109 c := factory .New ()
@@ -111,7 +114,7 @@ func NewController(name, operatorNamespace, targetNamespace, targetOperandVersio
111114 return c .WithSync (controllerRef .sync ).
112115 WithInformers (informers ... ).
113116 ToController (
114- fmt .Sprintf ("%sWorkloadController" , name ), // don't change what is passed here unless you also remove the old FooDegraded condition
117+ fmt .Sprintf ("%sWorkloadController" , controllerRef . controllerInstanceName ),
115118 eventRecorder ,
116119 )
117120}
@@ -161,40 +164,33 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
161164 errs = []error {}
162165 }
163166
164- deploymentAvailableCondition := operatorv1.OperatorCondition {
165- Type : fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeAvailable ),
166- Status : operatorv1 .ConditionTrue ,
167- }
167+ deploymentAvailableCondition := applyoperatorv1 .OperatorCondition ().
168+ WithType (fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeAvailable )).
169+ WithStatus (operatorv1 .ConditionTrue )
168170
169- workloadDegradedCondition := operatorv1.OperatorCondition {
170- Type : fmt .Sprintf ("%sWorkloadDegraded" , c .conditionsPrefix ),
171- Status : operatorv1 .ConditionFalse ,
172- }
171+ workloadDegradedCondition := applyoperatorv1 .OperatorCondition ().
172+ WithType (fmt .Sprintf ("%sWorkloadDegraded" , c .conditionsPrefix )).
173+ WithStatus (operatorv1 .ConditionFalse )
173174
174- deploymentDegradedCondition := operatorv1.OperatorCondition {
175- Type : fmt .Sprintf ("%sDeploymentDegraded" , c .conditionsPrefix ),
176- Status : operatorv1 .ConditionFalse ,
177- }
175+ deploymentDegradedCondition := applyoperatorv1 .OperatorCondition ().
176+ WithType (fmt .Sprintf ("%sDeploymentDegraded" , c .conditionsPrefix )).
177+ WithStatus (operatorv1 .ConditionFalse )
178178
179- deploymentProgressingCondition := operatorv1.OperatorCondition {
180- Type : fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeProgressing ),
181- Status : operatorv1 .ConditionFalse ,
182- }
179+ deploymentProgressingCondition := applyoperatorv1 .OperatorCondition ().
180+ WithType (fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeProgressing )).
181+ WithStatus (operatorv1 .ConditionFalse )
183182
184- // only set updateGenerationFn to update the observed generation if everything is available
185- var updateGenerationFn func (newStatus * operatorv1.OperatorStatus ) error
183+ status := applyoperatorv1 .OperatorStatus ()
186184 defer func () {
187- updates := []v1helpers.UpdateStatusFunc {
188- v1helpers .UpdateConditionFn (deploymentAvailableCondition ),
189- v1helpers .UpdateConditionFn (deploymentDegradedCondition ),
190- v1helpers .UpdateConditionFn (deploymentProgressingCondition ),
191- v1helpers .UpdateConditionFn (workloadDegradedCondition ),
192- }
193- if updateGenerationFn != nil {
194- updates = append (updates , updateGenerationFn )
195- }
196- if _ , _ , updateError := v1helpers .UpdateStatus (ctx , c .operatorClient , updates ... ); updateError != nil {
197- err = updateError
185+ status = status .WithConditions (
186+ deploymentAvailableCondition ,
187+ deploymentDegradedCondition ,
188+ deploymentProgressingCondition ,
189+ workloadDegradedCondition ,
190+ )
191+
192+ if applyError := c .operatorClient .ApplyOperatorStatus (ctx , c .controllerInstanceName , status ); applyError != nil {
193+ err = applyError
198194 }
199195 }()
200196
@@ -209,15 +205,18 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
209205
210206 // we are degraded, not available and we are not progressing
211207
212- deploymentDegradedCondition .Status = operatorv1 .ConditionTrue
213- deploymentDegradedCondition .Reason = "PreconditionNotFulfilled"
214- deploymentDegradedCondition .Message = message
208+ deploymentDegradedCondition = deploymentDegradedCondition .
209+ WithStatus (operatorv1 .ConditionTrue ).
210+ WithReason ("PreconditionNotFulfilled" ).
211+ WithMessage (message )
215212
216- deploymentAvailableCondition .Status = operatorv1 .ConditionFalse
217- deploymentAvailableCondition .Reason = "PreconditionNotFulfilled"
213+ deploymentAvailableCondition = deploymentAvailableCondition .
214+ WithStatus (operatorv1 .ConditionFalse ).
215+ WithReason ("PreconditionNotFulfilled" )
218216
219- deploymentProgressingCondition .Status = operatorv1 .ConditionFalse
220- deploymentProgressingCondition .Reason = "PreconditionNotFulfilled"
217+ deploymentProgressingCondition = deploymentProgressingCondition .
218+ WithStatus (operatorv1 .ConditionFalse ).
219+ WithReason ("PreconditionNotFulfilled" )
221220
222221 return kerrors .NewAggregate (errs )
223222 }
@@ -227,37 +226,44 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
227226 for _ , err := range errs {
228227 message = message + err .Error () + "\n "
229228 }
230- workloadDegradedCondition .Status = operatorv1 .ConditionTrue
231- workloadDegradedCondition .Reason = "SyncError"
232- workloadDegradedCondition .Message = message
229+ workloadDegradedCondition = workloadDegradedCondition .
230+ WithStatus (operatorv1 .ConditionTrue ).
231+ WithReason ("SyncError" ).
232+ WithMessage (message )
233233 } else {
234- workloadDegradedCondition .Status = operatorv1 .ConditionFalse
234+ workloadDegradedCondition = workloadDegradedCondition .
235+ WithStatus (operatorv1 .ConditionFalse )
235236 }
236237
237238 if workload == nil {
238239 message := fmt .Sprintf ("deployment/%s: could not be retrieved" , c .targetNamespace )
239- deploymentAvailableCondition .Status = operatorv1 .ConditionFalse
240- deploymentAvailableCondition .Reason = "NoDeployment"
241- deploymentAvailableCondition .Message = message
240+ deploymentAvailableCondition = deploymentAvailableCondition .
241+ WithStatus (operatorv1 .ConditionFalse ).
242+ WithReason ("NoDeployment" ).
243+ WithMessage (message )
242244
243- deploymentProgressingCondition .Status = operatorv1 .ConditionTrue
244- deploymentProgressingCondition .Reason = "NoDeployment"
245- deploymentProgressingCondition .Message = message
245+ deploymentProgressingCondition = deploymentProgressingCondition .
246+ WithStatus (operatorv1 .ConditionTrue ).
247+ WithReason ("NoDeployment" ).
248+ WithMessage (message )
246249
247- deploymentDegradedCondition .Status = operatorv1 .ConditionTrue
248- deploymentDegradedCondition .Reason = "NoDeployment"
249- deploymentDegradedCondition .Message = message
250+ deploymentDegradedCondition = deploymentDegradedCondition .
251+ WithStatus (operatorv1 .ConditionTrue ).
252+ WithReason ("NoDeployment" ).
253+ WithMessage (message )
250254
251255 return kerrors .NewAggregate (errs )
252256 }
253257
254258 if workload .Status .AvailableReplicas == 0 {
255- deploymentAvailableCondition .Status = operatorv1 .ConditionFalse
256- deploymentAvailableCondition .Reason = "NoPod"
257- deploymentAvailableCondition .Message = fmt .Sprintf ("no %s.%s pods available on any node." , workload .Name , c .targetNamespace )
259+ deploymentAvailableCondition = deploymentAvailableCondition .
260+ WithStatus (operatorv1 .ConditionFalse ).
261+ WithReason ("NoPod" ).
262+ WithMessage (fmt .Sprintf ("no %s.%s pods available on any node." , workload .Name , c .targetNamespace ))
258263 } else {
259- deploymentAvailableCondition .Status = operatorv1 .ConditionTrue
260- deploymentAvailableCondition .Reason = "AsExpected"
264+ deploymentAvailableCondition = deploymentAvailableCondition .
265+ WithStatus (operatorv1 .ConditionTrue ).
266+ WithReason ("AsExpected" )
261267 }
262268
263269 desiredReplicas := int32 (1 )
@@ -268,18 +274,21 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
268274 // If the workload is up to date, then we are no longer progressing
269275 workloadAtHighestGeneration := workload .ObjectMeta .Generation == workload .Status .ObservedGeneration
270276 workloadIsBeingUpdated := workload .Status .UpdatedReplicas < desiredReplicas
271- workloadIsBeingUpdatedTooLong , err := isUpdatingTooLong (previousStatus , deploymentProgressingCondition .Type )
277+ workloadIsBeingUpdatedTooLong , err := isUpdatingTooLong (previousStatus , * deploymentProgressingCondition .Type )
272278 if ! workloadAtHighestGeneration {
273- deploymentProgressingCondition .Status = operatorv1 .ConditionTrue
274- deploymentProgressingCondition .Reason = "NewGeneration"
275- deploymentProgressingCondition .Message = fmt .Sprintf ("deployment/%s.%s: observed generation is %d, desired generation is %d." , workload .Name , c .targetNamespace , workload .Status .ObservedGeneration , workload .ObjectMeta .Generation )
279+ deploymentProgressingCondition = deploymentProgressingCondition .
280+ WithStatus (operatorv1 .ConditionTrue ).
281+ WithReason ("NewGeneration" ).
282+ WithMessage (fmt .Sprintf ("deployment/%s.%s: observed generation is %d, desired generation is %d." , workload .Name , c .targetNamespace , workload .Status .ObservedGeneration , workload .ObjectMeta .Generation ))
276283 } else if workloadIsBeingUpdated {
277- deploymentProgressingCondition .Status = operatorv1 .ConditionTrue
278- deploymentProgressingCondition .Reason = "PodsUpdating"
279- deploymentProgressingCondition .Message = fmt .Sprintf ("deployment/%s.%s: %d/%d pods have been updated to the latest generation" , workload .Name , c .targetNamespace , workload .Status .UpdatedReplicas , desiredReplicas )
284+ deploymentProgressingCondition = deploymentProgressingCondition .
285+ WithStatus (operatorv1 .ConditionTrue ).
286+ WithReason ("PodsUpdating" ).
287+ WithMessage (fmt .Sprintf ("deployment/%s.%s: %d/%d pods have been updated to the latest generation" , workload .Name , c .targetNamespace , workload .Status .UpdatedReplicas , desiredReplicas ))
280288 } else {
281- deploymentProgressingCondition .Status = operatorv1 .ConditionFalse
282- deploymentProgressingCondition .Reason = "AsExpected"
289+ deploymentProgressingCondition = deploymentProgressingCondition .
290+ WithStatus (operatorv1 .ConditionFalse ).
291+ WithReason ("AsExpected" )
283292 }
284293
285294 // During a rollout the default maxSurge (25%) will allow the available
@@ -288,17 +297,19 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
288297 workloadHasAllPodsAvailable := workload .Status .AvailableReplicas >= desiredReplicas
289298 if ! workloadHasAllPodsAvailable && (! workloadIsBeingUpdated || workloadIsBeingUpdatedTooLong ) {
290299 numNonAvailablePods := desiredReplicas - workload .Status .AvailableReplicas
291- deploymentDegradedCondition .Status = operatorv1 .ConditionTrue
292- deploymentDegradedCondition .Reason = "UnavailablePod"
300+ deploymentDegradedCondition = deploymentDegradedCondition .
301+ WithStatus (operatorv1 .ConditionTrue ).
302+ WithReason ("UnavailablePod" )
293303 podContainersStatus , err := deployment .PodContainersStatus (workload , c .podsLister )
294304 if err != nil {
295305 podContainersStatus = []string {fmt .Sprintf ("failed to get pod containers details: %v" , err )}
296306 }
297- deploymentDegradedCondition . Message = fmt . Sprintf ( "%v of %v requested instances are unavailable for %s.%s (%s)" , numNonAvailablePods , desiredReplicas , workload . Name , c . targetNamespace ,
298- strings .Join (podContainersStatus , ", " ))
307+ deploymentDegradedCondition = deploymentDegradedCondition .
308+ WithMessage ( fmt . Sprintf ( "%v of %v requested instances are unavailable for %s.%s (%s)" , numNonAvailablePods , desiredReplicas , workload . Name , c . targetNamespace , strings .Join (podContainersStatus , ", " ) ))
299309 } else {
300- deploymentDegradedCondition .Status = operatorv1 .ConditionFalse
301- deploymentDegradedCondition .Reason = "AsExpected"
310+ deploymentDegradedCondition = deploymentDegradedCondition .
311+ WithStatus (operatorv1 .ConditionFalse ).
312+ WithReason ("AsExpected" )
302313 }
303314
304315 // if the deployment is all available and at the expected generation, then update the version to the latest
@@ -313,11 +324,14 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
313324 c .versionRecorder .SetVersion (operandName , c .targetOperandVersion )
314325 }
315326
316- // set updateGenerationFn so that it is invoked in defer
317- updateGenerationFn = func (newStatus * operatorv1.OperatorStatus ) error {
318- resourcemerge .SetDeploymentGeneration (& newStatus .Generations , workload )
319- return nil
320- }
327+ // set generations
328+ status = status .WithGenerations (& applyoperatorv1.GenerationStatusApplyConfiguration {
329+ Group : ptr .To ("apps" ),
330+ Resource : ptr .To ("deployments" ),
331+ Namespace : ptr .To (workload .Namespace ),
332+ Name : ptr .To (workload .Name ),
333+ LastGeneration : ptr .To (workload .Generation ),
334+ })
321335
322336 if len (errs ) > 0 {
323337 return kerrors .NewAggregate (errs )
0 commit comments