Skip to content

Commit c111ff1

Browse files
committed
workloadscontroller: migrate to SSA
1 parent c31b2ce commit c111ff1

File tree

1 file changed

+93
-79
lines changed

1 file changed

+93
-79
lines changed

pkg/operator/apiserver/controller/workload/workload.go

Lines changed: 93 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
5152
type 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

Comments
 (0)