Skip to content

Commit adfa251

Browse files
committed
workload: add workload deletion condition method to the delegate interface
This determines whether the delegate controller has deleted the workload, and indicates to the workload controller that it must clear the respective operator status fields.
1 parent 17cb27e commit adfa251

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

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

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"strings"
8+
79
appsv1 "k8s.io/api/apps/v1"
810
corev1 "k8s.io/api/core/v1"
911
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -14,7 +16,6 @@ import (
1416
corev1listers "k8s.io/client-go/listers/core/v1"
1517
"k8s.io/client-go/tools/cache"
1618
"k8s.io/client-go/util/workqueue"
17-
"strings"
1819

1920
operatorv1 "github.com/openshift/api/operator/v1"
2021
openshiftconfigclientv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
@@ -41,6 +42,12 @@ type Delegate interface {
4142
// operator will be degraded, not available and not progressing
4243
// returned errors (if any) will be added to the Message field
4344
PreconditionFulfilled(ctx context.Context) (bool, error)
45+
46+
// WorkloadDeleted indicates whether the delegate workload has been deleted or not. It returns a bool
47+
// flag to indicate this, a string representing the workload's name and an error. When true, this
48+
// controller will remove any fields from the operator status that the controller is managing, and
49+
// will also remove the version field.
50+
WorkloadDeleted(ctx context.Context) (bool, string, error)
4451
}
4552

4653
// Controller is a generic workload controller that deals with Deployment resource.
@@ -133,6 +140,20 @@ func (c *Controller) sync(ctx context.Context, controllerContext factory.SyncCon
133140
return c.updateOperatorStatus(ctx, operatorStatus, nil, false, false, nil)
134141
}
135142

143+
if deleted, operandName, err := c.delegate.WorkloadDeleted(ctx); err != nil {
144+
return c.updateOperatorStatus(ctx, operatorStatus, nil, false, false, []error{err})
145+
} else if deleted {
146+
// Server-Side-Apply with an empty operator status for the specific field manager will effectively
147+
// remove any conditions and generations owned by it, because the respective API fields have 'map'
148+
// as the list type where field managers can be list element-specific
149+
if err := c.operatorClient.ApplyOperatorStatus(ctx, c.controllerInstanceName, applyoperatorv1.OperatorStatus()); err != nil {
150+
return err
151+
}
152+
153+
c.versionRecorder.UnsetVersion(c.constructOperandNameFor(operandName))
154+
return nil
155+
}
156+
136157
workload, operatorConfigAtHighestGeneration, errs := c.delegate.Sync(ctx, controllerContext)
137158

138159
return c.updateOperatorStatus(ctx, operatorStatus, workload, operatorConfigAtHighestGeneration, true, errs)
@@ -341,11 +362,7 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
341362
// which should immediately result in a deployment generation diff, which should cause this block to be skipped until it is ready.
342363
workloadHasAllPodsUpdated := workload.Status.UpdatedReplicas == desiredReplicas
343364
if workloadAtHighestGeneration && workloadHasAllPodsAvailable && workloadHasAllPodsUpdated && operatorConfigAtHighestGeneration {
344-
operandName := workload.Name
345-
if len(c.operandNamePrefix) > 0 {
346-
operandName = fmt.Sprintf("%s-%s", c.operandNamePrefix, workload.Name)
347-
}
348-
c.versionRecorder.SetVersion(operandName, c.targetOperandVersion)
365+
c.versionRecorder.SetVersion(c.constructOperandNameFor(workload.Name), c.targetOperandVersion)
349366
}
350367

351368
if len(errs) > 0 {
@@ -354,6 +371,14 @@ func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *o
354371
return nil
355372
}
356373

374+
func (c *Controller) constructOperandNameFor(name string) string {
375+
if len(c.operandNamePrefix) > 0 {
376+
return fmt.Sprintf("%s-%s", c.operandNamePrefix, name)
377+
}
378+
379+
return name
380+
}
381+
357382
// hasDeploymentProgressed returns true if the deployment reports NewReplicaSetAvailable
358383
// via the DeploymentProgressing condition
359384
func hasDeploymentProgressed(status appsv1.DeploymentStatus) bool {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package workload
33
import (
44
"context"
55
"fmt"
6-
clocktesting "k8s.io/utils/clock/testing"
76
"testing"
87
"time"
98

109
corev1 "k8s.io/api/core/v1"
1110
"k8s.io/apimachinery/pkg/labels"
1211
corev1listers "k8s.io/client-go/listers/core/v1"
12+
clocktesting "k8s.io/utils/clock/testing"
1313
"k8s.io/utils/ptr"
1414

1515
operatorv1 "github.com/openshift/api/operator/v1"
@@ -39,6 +39,10 @@ type testDelegate struct {
3939
syncErrrors []error
4040
}
4141

42+
func (d *testDelegate) WorkloadDeleted(_ context.Context) (bool, string, error) {
43+
return false, "", nil
44+
}
45+
4246
func (d *testDelegate) PreconditionFulfilled(_ context.Context) (bool, error) {
4347
return d.preconditionReady, d.preconditionErr
4448
}

0 commit comments

Comments
 (0)