@@ -33,20 +33,42 @@ import (
33
33
)
34
34
35
35
const (
36
- storageCleanupFinalizer = "storage.controller.devfile.io"
36
+ storageCleanupFinalizer = "storage.controller.devfile.io"
37
+ serviceAccountCleanupFinalizer = "serviceaccount.controller.devfile.io"
37
38
)
38
39
39
- func (r * DevWorkspaceReconciler ) finalize (ctx context.Context , log logr.Logger , workspace * dw.DevWorkspace ) (reconcile.Result , error ) {
40
- if ! coputil .HasFinalizer (workspace , storageCleanupFinalizer ) {
41
- return reconcile.Result {}, nil
40
+ func (r * DevWorkspaceReconciler ) workspaceNeedsFinalize (workspace * dw.DevWorkspace ) bool {
41
+ for _ , finalizer := range workspace .Finalizers {
42
+ if finalizer == storageCleanupFinalizer {
43
+ return true
44
+ }
45
+ if finalizer == serviceAccountCleanupFinalizer {
46
+ return true
47
+ }
42
48
}
49
+ return false
50
+ }
51
+
52
+ func (r * DevWorkspaceReconciler ) finalize (ctx context.Context , log logr.Logger , workspace * dw.DevWorkspace ) (reconcile.Result , error ) {
43
53
workspace .Status .Message = "Cleaning up resources for deletion"
44
54
workspace .Status .Phase = devworkspacePhaseTerminating
45
55
err := r .Client .Status ().Update (ctx , workspace )
46
56
if err != nil && ! k8sErrors .IsConflict (err ) {
47
57
return reconcile.Result {}, err
48
58
}
49
59
60
+ for _ , finalizer := range workspace .Finalizers {
61
+ switch finalizer {
62
+ case storageCleanupFinalizer :
63
+ return r .finalizeStorage (ctx , log , workspace )
64
+ case serviceAccountCleanupFinalizer :
65
+ return r .finalizeServiceAccount (ctx , log , workspace )
66
+ }
67
+ }
68
+ return reconcile.Result {}, nil
69
+ }
70
+
71
+ func (r * DevWorkspaceReconciler ) finalizeStorage (ctx context.Context , log logr.Logger , workspace * dw.DevWorkspace ) (reconcile.Result , error ) {
50
72
// Need to make sure Deployment is cleaned up before starting job to avoid mounting issues for RWO PVCs
51
73
wait , err := wsprovision .DeleteWorkspaceDeployment (ctx , workspace , r .Client )
52
74
if err != nil {
@@ -98,8 +120,20 @@ func (r *DevWorkspaceReconciler) finalize(ctx context.Context, log logr.Logger,
98
120
return reconcile.Result {}, r .Update (ctx , workspace )
99
121
}
100
122
101
- func isFinalizerNecessary (workspace * dw.DevWorkspace , provisioner storage.Provisioner ) bool {
102
- return provisioner .NeedsStorage (& workspace .Spec .Template )
123
+ func (r * DevWorkspaceReconciler ) finalizeServiceAccount (ctx context.Context , log logr.Logger , workspace * dw.DevWorkspace ) (reconcile.Result , error ) {
124
+ retry , err := wsprovision .FinalizeServiceAccount (workspace , ctx , r .NonCachingClient )
125
+ if err != nil {
126
+ log .Error (err , "Failed to finalize workspace ServiceAccount" )
127
+ failedStatus := currentStatus {phase : dw .DevWorkspaceStatusError }
128
+ failedStatus .setConditionTrue (dw .DevWorkspaceError , err .Error ())
129
+ return r .updateWorkspaceStatus (workspace , r .Log , & failedStatus , reconcile.Result {}, nil )
130
+ }
131
+ if retry {
132
+ return reconcile.Result {Requeue : true }, nil
133
+ }
134
+ log .Info ("ServiceAccount clean up successful; clearing finalizer" )
135
+ coputil .RemoveFinalizer (workspace , serviceAccountCleanupFinalizer )
136
+ return reconcile.Result {}, r .Update (ctx , workspace )
103
137
}
104
138
105
139
func (r * DevWorkspaceReconciler ) namespaceIsTerminating (ctx context.Context , namespace string ) (bool , error ) {
0 commit comments