@@ -20,10 +20,10 @@ import (
2020
2121 operatorv1 "github.com/openshift/api/operator/v1"
2222 openshiftconfigclientv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
23+ applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1"
2324 "github.com/openshift/library-go/pkg/apps/deployment"
2425 "github.com/openshift/library-go/pkg/controller/factory"
2526 "github.com/openshift/library-go/pkg/operator/events"
26- "github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
2727 "github.com/openshift/library-go/pkg/operator/status"
2828 "github.com/openshift/library-go/pkg/operator/v1helpers"
2929)
@@ -49,6 +49,7 @@ type Delegate interface {
4949// Callers must provide a sync function for delegation. It should bring the desired workload into operation.
5050// The returned state along with errors will be converted into conditions and persisted in the status field.
5151type Controller struct {
52+ controllerInstanceName string
5253 // conditionsPrefix an optional prefix that will be used as operator's condition type field for example APIServerDeploymentDegraded where APIServer indicates the prefix
5354 conditionsPrefix string
5455 operatorNamespace string
@@ -71,13 +72,13 @@ type Controller struct {
7172
7273// NewController creates a brand new Controller instance.
7374//
74- // the "name " param will be used to set conditions in the status field. It will be suffixed with "WorkloadController",
75+ // the "instanceName " param will be used to set conditions in the status field. It will be suffixed with "WorkloadController",
7576// so it can end up in the condition in the form of "OAuthAPIWorkloadControllerDeploymentAvailable"
7677//
7778// the "operatorNamespace" is used to set "version-mapping" in the correct namespace
7879//
7980// the "targetNamespace" represent the namespace for the managed resource (DaemonSet)
80- func NewController (name , operatorNamespace , targetNamespace , targetOperandVersion , operandNamePrefix , conditionsPrefix string ,
81+ func NewController (instanceName , operatorNamespace , targetNamespace , targetOperandVersion , operandNamePrefix , conditionsPrefix string ,
8182 operatorClient v1helpers.OperatorClient ,
8283 kubeClient kubernetes.Interface ,
8384 podLister corev1listers.PodLister ,
@@ -89,6 +90,7 @@ func NewController(name, operatorNamespace, targetNamespace, targetOperandVersio
8990 versionRecorder status.VersionGetter ,
9091) factory.Controller {
9192 controllerRef := & Controller {
93+ controllerInstanceName : factory .ControllerInstanceName (instanceName , "Workload" ),
9294 operatorNamespace : operatorNamespace ,
9395 targetNamespace : targetNamespace ,
9496 targetOperandVersion : targetOperandVersion ,
@@ -100,7 +102,7 @@ func NewController(name, operatorNamespace, targetNamespace, targetOperandVersio
100102 delegate : delegate ,
101103 openshiftClusterConfigClient : openshiftClusterConfigClient ,
102104 versionRecorder : versionRecorder ,
103- queue : workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), name ),
105+ queue : workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), instanceName ),
104106 }
105107
106108 c := factory .New ()
@@ -111,7 +113,7 @@ func NewController(name, operatorNamespace, targetNamespace, targetOperandVersio
111113 return c .WithSync (controllerRef .sync ).
112114 WithInformers (informers ... ).
113115 ToController (
114- fmt .Sprintf ("%sWorkloadController" , name ), // don't change what is passed here unless you also remove the old FooDegraded condition
116+ fmt .Sprintf ("%sWorkloadController" , controllerRef . controllerInstanceName ),
115117 eventRecorder ,
116118 )
117119}
@@ -161,40 +163,40 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
161163 errs = []error {}
162164 }
163165
164- deploymentAvailableCondition := operatorv1.OperatorCondition {
165- Type : fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeAvailable ),
166- Status : operatorv1 .ConditionTrue ,
167- }
166+ deploymentAvailableCondition := applyoperatorv1 .OperatorCondition ().
167+ WithType (fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeAvailable ))
168168
169- workloadDegradedCondition := operatorv1.OperatorCondition {
170- Type : fmt .Sprintf ("%sWorkloadDegraded" , c .conditionsPrefix ),
171- Status : operatorv1 .ConditionFalse ,
172- }
169+ workloadDegradedCondition := applyoperatorv1 .OperatorCondition ().
170+ WithType (fmt .Sprintf ("%sWorkloadDegraded" , c .conditionsPrefix ))
173171
174- deploymentDegradedCondition := operatorv1.OperatorCondition {
175- Type : fmt .Sprintf ("%sDeploymentDegraded" , c .conditionsPrefix ),
176- Status : operatorv1 .ConditionFalse ,
177- }
172+ deploymentDegradedCondition := applyoperatorv1 .OperatorCondition ().
173+ WithType (fmt .Sprintf ("%sDeploymentDegraded" , c .conditionsPrefix ))
178174
179- deploymentProgressingCondition := operatorv1.OperatorCondition {
180- Type : fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeProgressing ),
181- Status : operatorv1 .ConditionFalse ,
175+ deploymentProgressingCondition := applyoperatorv1 .OperatorCondition ().
176+ WithType (fmt .Sprintf ("%sDeployment%s" , c .conditionsPrefix , operatorv1 .OperatorStatusTypeProgressing ))
177+
178+ status := applyoperatorv1 .OperatorStatus ()
179+ if workload != nil {
180+ // The Hash field is not required since the LastGeneration field is enough to uniquely identify a Deployment's desired state
181+ status = status .WithGenerations (applyoperatorv1 .GenerationStatus ().
182+ WithGroup ("apps" ).
183+ WithResource ("deployments" ).
184+ WithNamespace (workload .Namespace ).
185+ WithName (workload .Name ).
186+ WithLastGeneration (workload .Generation ),
187+ )
182188 }
183189
184- // only set updateGenerationFn to update the observed generation if everything is available
185- var updateGenerationFn func (newStatus * operatorv1.OperatorStatus ) error
186190 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
191+ status = status .WithConditions (
192+ deploymentAvailableCondition ,
193+ deploymentDegradedCondition ,
194+ deploymentProgressingCondition ,
195+ workloadDegradedCondition ,
196+ )
197+
198+ if applyError := c .operatorClient .ApplyOperatorStatus (ctx , c .controllerInstanceName , status ); applyError != nil {
199+ err = applyError
198200 }
199201 }()
200202
@@ -209,15 +211,23 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
209211
210212 // we are degraded, not available and we are not progressing
211213
212- deploymentDegradedCondition .Status = operatorv1 .ConditionTrue
213- deploymentDegradedCondition .Reason = "PreconditionNotFulfilled"
214- deploymentDegradedCondition .Message = message
214+ deploymentDegradedCondition = deploymentDegradedCondition .
215+ WithStatus (operatorv1 .ConditionTrue ).
216+ WithReason ("PreconditionNotFulfilled" ).
217+ WithMessage (message )
215218
216- deploymentAvailableCondition .Status = operatorv1 .ConditionFalse
217- deploymentAvailableCondition .Reason = "PreconditionNotFulfilled"
219+ deploymentAvailableCondition = deploymentAvailableCondition .
220+ WithStatus (operatorv1 .ConditionFalse ).
221+ WithReason ("PreconditionNotFulfilled" )
218222
219- deploymentProgressingCondition .Status = operatorv1 .ConditionFalse
220- deploymentProgressingCondition .Reason = "PreconditionNotFulfilled"
223+ deploymentProgressingCondition = deploymentProgressingCondition .
224+ WithStatus (operatorv1 .ConditionFalse ).
225+ WithReason ("PreconditionNotFulfilled" )
226+
227+ workloadDegradedCondition = workloadDegradedCondition .
228+ WithStatus (operatorv1 .ConditionTrue ).
229+ WithReason ("PreconditionNotFulfilled" ).
230+ WithMessage (message )
221231
222232 return kerrors .NewAggregate (errs )
223233 }
@@ -227,37 +237,49 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
227237 for _ , err := range errs {
228238 message = message + err .Error () + "\n "
229239 }
230- workloadDegradedCondition .Status = operatorv1 .ConditionTrue
231- workloadDegradedCondition .Reason = "SyncError"
232- workloadDegradedCondition .Message = message
240+ workloadDegradedCondition = workloadDegradedCondition .
241+ WithStatus (operatorv1 .ConditionTrue ).
242+ WithReason ("SyncError" ).
243+ WithMessage (message )
244+ } else if workload == nil {
245+ workloadDegradedCondition = workloadDegradedCondition .
246+ WithStatus (operatorv1 .ConditionTrue ).
247+ WithReason ("NoDeployment" ).
248+ WithMessage (fmt .Sprintf ("deployment/%s: could not be retrieved" , c .targetNamespace ))
233249 } else {
234- workloadDegradedCondition .Status = operatorv1 .ConditionFalse
250+ workloadDegradedCondition = workloadDegradedCondition .
251+ WithStatus (operatorv1 .ConditionFalse )
235252 }
236253
237254 if workload == nil {
238255 message := fmt .Sprintf ("deployment/%s: could not be retrieved" , c .targetNamespace )
239- deploymentAvailableCondition .Status = operatorv1 .ConditionFalse
240- deploymentAvailableCondition .Reason = "NoDeployment"
241- deploymentAvailableCondition .Message = message
256+ deploymentAvailableCondition = deploymentAvailableCondition .
257+ WithStatus (operatorv1 .ConditionFalse ).
258+ WithReason ("NoDeployment" ).
259+ WithMessage (message )
242260
243- deploymentProgressingCondition .Status = operatorv1 .ConditionTrue
244- deploymentProgressingCondition .Reason = "NoDeployment"
245- deploymentProgressingCondition .Message = message
261+ deploymentProgressingCondition = deploymentProgressingCondition .
262+ WithStatus (operatorv1 .ConditionTrue ).
263+ WithReason ("NoDeployment" ).
264+ WithMessage (message )
246265
247- deploymentDegradedCondition .Status = operatorv1 .ConditionTrue
248- deploymentDegradedCondition .Reason = "NoDeployment"
249- deploymentDegradedCondition .Message = message
266+ deploymentDegradedCondition = deploymentDegradedCondition .
267+ WithStatus (operatorv1 .ConditionTrue ).
268+ WithReason ("NoDeployment" ).
269+ WithMessage (message )
250270
251271 return kerrors .NewAggregate (errs )
252272 }
253273
254274 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 )
275+ deploymentAvailableCondition = deploymentAvailableCondition .
276+ WithStatus (operatorv1 .ConditionFalse ).
277+ WithReason ("NoPod" ).
278+ WithMessage (fmt .Sprintf ("no %s.%s pods available on any node." , workload .Name , c .targetNamespace ))
258279 } else {
259- deploymentAvailableCondition .Status = operatorv1 .ConditionTrue
260- deploymentAvailableCondition .Reason = "AsExpected"
280+ deploymentAvailableCondition = deploymentAvailableCondition .
281+ WithStatus (operatorv1 .ConditionTrue ).
282+ WithReason ("AsExpected" )
261283 }
262284
263285 desiredReplicas := int32 (1 )
@@ -268,18 +290,21 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
268290 // If the workload is up to date, then we are no longer progressing
269291 workloadAtHighestGeneration := workload .ObjectMeta .Generation == workload .Status .ObservedGeneration
270292 workloadIsBeingUpdated := workload .Status .UpdatedReplicas < desiredReplicas
271- workloadIsBeingUpdatedTooLong , err := isUpdatingTooLong (previousStatus , deploymentProgressingCondition .Type )
293+ workloadIsBeingUpdatedTooLong , err := isUpdatingTooLong (previousStatus , * deploymentProgressingCondition .Type )
272294 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 )
295+ deploymentProgressingCondition = deploymentProgressingCondition .
296+ WithStatus (operatorv1 .ConditionTrue ).
297+ WithReason ("NewGeneration" ).
298+ WithMessage (fmt .Sprintf ("deployment/%s.%s: observed generation is %d, desired generation is %d." , workload .Name , c .targetNamespace , workload .Status .ObservedGeneration , workload .ObjectMeta .Generation ))
276299 } 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 )
300+ deploymentProgressingCondition = deploymentProgressingCondition .
301+ WithStatus (operatorv1 .ConditionTrue ).
302+ WithReason ("PodsUpdating" ).
303+ WithMessage (fmt .Sprintf ("deployment/%s.%s: %d/%d pods have been updated to the latest generation" , workload .Name , c .targetNamespace , workload .Status .UpdatedReplicas , desiredReplicas ))
280304 } else {
281- deploymentProgressingCondition .Status = operatorv1 .ConditionFalse
282- deploymentProgressingCondition .Reason = "AsExpected"
305+ deploymentProgressingCondition = deploymentProgressingCondition .
306+ WithStatus (operatorv1 .ConditionFalse ).
307+ WithReason ("AsExpected" )
283308 }
284309
285310 // During a rollout the default maxSurge (25%) will allow the available
@@ -288,17 +313,19 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
288313 workloadHasAllPodsAvailable := workload .Status .AvailableReplicas >= desiredReplicas
289314 if ! workloadHasAllPodsAvailable && (! workloadIsBeingUpdated || workloadIsBeingUpdatedTooLong ) {
290315 numNonAvailablePods := desiredReplicas - workload .Status .AvailableReplicas
291- deploymentDegradedCondition .Status = operatorv1 .ConditionTrue
292- deploymentDegradedCondition .Reason = "UnavailablePod"
316+ deploymentDegradedCondition = deploymentDegradedCondition .
317+ WithStatus (operatorv1 .ConditionTrue ).
318+ WithReason ("UnavailablePod" )
293319 podContainersStatus , err := deployment .PodContainersStatus (workload , c .podsLister )
294320 if err != nil {
295321 podContainersStatus = []string {fmt .Sprintf ("failed to get pod containers details: %v" , err )}
296322 }
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 , ", " ))
323+ deploymentDegradedCondition = deploymentDegradedCondition .
324+ WithMessage ( fmt . Sprintf ( "%v of %v requested instances are unavailable for %s.%s (%s)" , numNonAvailablePods , desiredReplicas , workload . Name , c . targetNamespace , strings .Join (podContainersStatus , ", " ) ))
299325 } else {
300- deploymentDegradedCondition .Status = operatorv1 .ConditionFalse
301- deploymentDegradedCondition .Reason = "AsExpected"
326+ deploymentDegradedCondition = deploymentDegradedCondition .
327+ WithStatus (operatorv1 .ConditionFalse ).
328+ WithReason ("AsExpected" )
302329 }
303330
304331 // if the deployment is all available and at the expected generation, then update the version to the latest
@@ -313,12 +340,6 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
313340 c .versionRecorder .SetVersion (operandName , c .targetOperandVersion )
314341 }
315342
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- }
321-
322343 if len (errs ) > 0 {
323344 return kerrors .NewAggregate (errs )
324345 }
0 commit comments