@@ -3,16 +3,18 @@ package controller
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "sync"
6
7
"time"
7
8
8
9
"github.com/sirupsen/logrus"
9
10
10
11
apierrors "k8s.io/apimachinery/pkg/api/errors"
12
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
11
13
"k8s.io/apimachinery/pkg/runtime/schema"
14
+ "k8s.io/apimachinery/pkg/types"
12
15
"sigs.k8s.io/controller-runtime/pkg/client"
13
16
"sigs.k8s.io/controller-runtime/pkg/reconcile"
14
17
15
- appv1alpha1 "github.com/operator-framework/helm-app-operator-kit/helm-app-operator/pkg/apis/app/v1alpha1"
16
18
"github.com/operator-framework/helm-app-operator-kit/helm-app-operator/pkg/helm"
17
19
)
18
20
@@ -21,26 +23,61 @@ type helmOperatorReconciler struct {
21
23
GVK schema.GroupVersionKind
22
24
Installer helm.Installer
23
25
ResyncPeriod time.Duration
26
+
27
+ lastResourceVersions map [types.NamespacedName ]string
28
+ mutex sync.RWMutex
24
29
}
25
30
26
- var lastResourceVersion string
31
+ const (
32
+ finalizer = "uninstall-helm-release"
33
+ )
27
34
28
- func (r helmOperatorReconciler ) Reconcile (request reconcile.Request ) (reconcile.Result , error ) {
35
+ func (r * helmOperatorReconciler ) Reconcile (request reconcile.Request ) (reconcile.Result , error ) {
29
36
logrus .Infof ("processing %s" , request .NamespacedName )
30
37
31
- o := & appv1alpha1.HelmApp {}
32
- err := r .Client .Get (context .TODO (), request .NamespacedName , o )
38
+ o := & unstructured.Unstructured {}
33
39
o .SetGroupVersionKind (r .GVK )
34
- o .SetNamespace (request .Namespace )
35
- o .SetName (request .Name )
40
+ err := r .Client .Get (context .TODO (), request .NamespacedName , o )
41
+ if apierrors .IsNotFound (err ) {
42
+ return reconcile.Result {}, nil
43
+ }
36
44
if err != nil {
37
- if apierrors .IsNotFound (err ) {
38
- _ , err = r .Installer .UninstallRelease (o )
45
+ return reconcile.Result {}, err
46
+ }
47
+
48
+ deleted := o .GetDeletionTimestamp () != nil
49
+ pendingFinalizers := o .GetFinalizers ()
50
+ if ! deleted && ! contains (pendingFinalizers , finalizer ) {
51
+ logrus .Debugf ("adding finalizer %s to resource" , finalizer )
52
+ finalizers := append (pendingFinalizers , finalizer )
53
+ o .SetFinalizers (finalizers )
54
+ err := r .Client .Update (context .TODO (), o )
55
+ return reconcile.Result {}, err
56
+ }
57
+ if deleted {
58
+ if ! contains (pendingFinalizers , finalizer ) {
59
+ logrus .Info ("resouce is terminated, skipping reconciliation" )
60
+ return reconcile.Result {}, nil
61
+ }
62
+
63
+ _ , err = r .Installer .UninstallRelease (o )
64
+ if err != nil {
65
+ return reconcile.Result {}, err
66
+ }
67
+
68
+ finalizers := []string {}
69
+ for _ , pendingFinalizer := range pendingFinalizers {
70
+ if pendingFinalizer != finalizer {
71
+ finalizers = append (finalizers , pendingFinalizer )
72
+ }
39
73
}
74
+ o .SetFinalizers (finalizers )
75
+ err := r .Client .Update (context .TODO (), o )
40
76
return reconcile.Result {}, err
41
77
}
42
78
43
- if o .GetResourceVersion () == lastResourceVersion {
79
+ lastResourceVersion , ok := r .getLastResourceVersion (request .NamespacedName )
80
+ if ok && o .GetResourceVersion () == lastResourceVersion {
44
81
logrus .Infof ("skipping %s because resource version has not changed" , request .NamespacedName )
45
82
return reconcile.Result {RequeueAfter : r .ResyncPeriod }, nil
46
83
}
@@ -56,7 +93,29 @@ func (r helmOperatorReconciler) Reconcile(request reconcile.Request) (reconcile.
56
93
logrus .Errorf (err .Error ())
57
94
return reconcile.Result {}, fmt .Errorf ("failed to update custom resource status: %v" , err )
58
95
}
59
- lastResourceVersion = o .GetResourceVersion ()
96
+ r . setLastResourceVersion ( request . NamespacedName , o .GetResourceVersion () )
60
97
61
98
return reconcile.Result {RequeueAfter : r .ResyncPeriod }, nil
62
99
}
100
+
101
+ func contains (l []string , s string ) bool {
102
+ for _ , elem := range l {
103
+ if elem == s {
104
+ return true
105
+ }
106
+ }
107
+ return false
108
+ }
109
+
110
+ func (r * helmOperatorReconciler ) getLastResourceVersion (n types.NamespacedName ) (string , bool ) {
111
+ r .mutex .RLock ()
112
+ defer r .mutex .RUnlock ()
113
+ v , ok := r .lastResourceVersions [n ]
114
+ return v , ok
115
+ }
116
+
117
+ func (r * helmOperatorReconciler ) setLastResourceVersion (n types.NamespacedName , v string ) {
118
+ r .mutex .Lock ()
119
+ defer r .mutex .Unlock ()
120
+ r .lastResourceVersions [n ] = v
121
+ }
0 commit comments