Skip to content

Commit 2a2e2e5

Browse files
committed
controller: cleanup old secrets after renaming template
1 parent 159e8a0 commit 2a2e2e5

File tree

1 file changed

+113
-11
lines changed

1 file changed

+113
-11
lines changed

pkg/controllers/configmapsecret_controller.go

Lines changed: 113 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ import (
1818
apierrors "k8s.io/apimachinery/pkg/api/errors"
1919
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2020
"k8s.io/apimachinery/pkg/runtime"
21+
"k8s.io/apimachinery/pkg/runtime/schema"
2122
"k8s.io/apimachinery/pkg/types"
23+
"k8s.io/client-go/util/workqueue"
2224
"sigs.k8s.io/controller-runtime/pkg/builder"
2325
"sigs.k8s.io/controller-runtime/pkg/client"
2426
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
2527
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
28+
"sigs.k8s.io/controller-runtime/pkg/event"
2629
"sigs.k8s.io/controller-runtime/pkg/handler"
2730
"sigs.k8s.io/controller-runtime/pkg/log"
2831
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -41,6 +44,7 @@ type ConfigMapSecret struct {
4144
mu sync.RWMutex
4245
secrets refMap
4346
configMaps refMap
47+
owned refMap
4448

4549
testNotifyFn func(types.NamespacedName)
4650
}
@@ -68,10 +72,23 @@ func (r *ConfigMapSecret) SetupWithManager(manager manager.Manager) error {
6872
if r.logger == nil {
6973
r.InjectLogger(pkgLog)
7074
}
75+
7176
return builder.ControllerManagedBy(manager).
7277
For(&v1alpha1.ConfigMapSecret{}).
73-
Owns(&corev1.Secret{}).
74-
Watches(&source.Kind{Type: &corev1.Secret{}}, r.secretEventHandler()).
78+
Watches(&source.Kind{Type: &corev1.Secret{}}, handler.Funcs{
79+
CreateFunc: func(e event.CreateEvent, q workqueue.RateLimitingInterface) {
80+
r.secretEventHandler(q, e.Object.(*corev1.Secret), false)
81+
},
82+
UpdateFunc: func(e event.UpdateEvent, q workqueue.RateLimitingInterface) {
83+
r.secretEventHandler(q, e.ObjectNew.(*corev1.Secret), false)
84+
},
85+
DeleteFunc: func(e event.DeleteEvent, q workqueue.RateLimitingInterface) {
86+
r.secretEventHandler(q, e.Object.(*corev1.Secret), true)
87+
},
88+
GenericFunc: func(e event.GenericEvent, q workqueue.RateLimitingInterface) {
89+
r.secretEventHandler(q, e.Object.(*corev1.Secret), false)
90+
},
91+
}).
7592
Watches(&source.Kind{Type: &corev1.ConfigMap{}}, r.configMapEventHandler()).
7693
Complete(r)
7794
}
@@ -89,16 +106,38 @@ func (r *ConfigMapSecret) configMapEventHandler() handler.EventHandler {
89106
}
90107
}
91108

92-
func (r *ConfigMapSecret) secretEventHandler() handler.EventHandler {
93-
return &handler.EnqueueRequestsFromMapFunc{
94-
ToRequests: handler.ToRequestsFunc(func(obj handler.MapObject) []reconcile.Request {
95-
namespace := obj.Meta.GetNamespace()
96-
name := obj.Meta.GetName()
109+
func (r *ConfigMapSecret) secretEventHandler(q workqueue.RateLimitingInterface, secret *corev1.Secret, deleted bool) {
110+
name := secret.Name
111+
namespace := secret.Namespace
112+
owner := getOwner(secret)
97113

98-
r.mu.RLock()
99-
defer r.mu.RUnlock()
100-
return toReqs(namespace, r.secrets.srcs(namespace, name))
101-
}),
114+
r.mu.Lock()
115+
if deleted || owner == nil {
116+
r.owned.set(namespace, name, nil)
117+
} else {
118+
r.owned.set(namespace, name, map[string]bool{string(owner.UID): true})
119+
}
120+
cmsNames := keys(r.secrets.srcs(namespace, name))
121+
r.mu.Unlock()
122+
123+
if owner != nil {
124+
q.Add(reconcile.Request{
125+
NamespacedName: types.NamespacedName{
126+
Namespace: namespace,
127+
Name: owner.Name,
128+
},
129+
})
130+
}
131+
for _, cmsName := range cmsNames {
132+
if owner != nil && owner.Name == cmsName {
133+
continue
134+
}
135+
q.Add(reconcile.Request{
136+
NamespacedName: types.NamespacedName{
137+
Namespace: namespace,
138+
Name: cmsName,
139+
},
140+
})
102141
}
103142
}
104143

@@ -143,10 +182,50 @@ func (r *ConfigMapSecret) Reconcile(req reconcile.Request) (reconcile.Result, er
143182
secretNames, configMapNames := varRefs(cms.Spec.Vars)
144183
r.setRefs(cms.Namespace, cms.Name, secretNames, configMapNames)
145184

185+
// Sync and cleanup
146186
requeue, err := r.sync(ctx, log, cms)
187+
if cleanupErr := r.cleanup(ctx, log, cms); cleanupErr != nil && err == nil {
188+
err = cleanupErr
189+
}
147190
return reconcile.Result{Requeue: requeue}, err
148191
}
149192

193+
func (r *ConfigMapSecret) cleanup(ctx context.Context, log logr.Logger, cms *v1alpha1.ConfigMapSecret) error {
194+
secretName := cms.Spec.Template.Name
195+
if secretName == "" {
196+
secretName = cms.Name
197+
}
198+
199+
r.mu.Lock()
200+
owned := keys(r.owned.srcs(cms.Namespace, string(cms.UID)))
201+
r.mu.Unlock()
202+
203+
for _, name := range owned {
204+
if name == secretName {
205+
continue
206+
}
207+
208+
key := types.NamespacedName{Namespace: cms.Namespace, Name: name}
209+
secretLog := log.WithValues("secret", key)
210+
secretLog.Info("Cleaning up secret")
211+
212+
secret := &corev1.Secret{}
213+
if err := r.client.Get(ctx, key, secret); err != nil {
214+
if apierrors.IsNotFound(err) {
215+
secretLog.Info("Cleaning up secret unnecessary, already removed")
216+
continue
217+
}
218+
secretLog.Error(err, "Cleaning up secret, get failed")
219+
return err
220+
}
221+
if err := r.client.Delete(ctx, secret); err != nil {
222+
secretLog.Error(err, "Cleaning up secret, delete failed")
223+
return err
224+
}
225+
}
226+
return nil
227+
}
228+
150229
func (r *ConfigMapSecret) sync(ctx context.Context, log logr.Logger, cms *v1alpha1.ConfigMapSecret) (bool, error) {
151230
secret, reason, err := r.renderSecret(ctx, cms)
152231
if err != nil {
@@ -386,6 +465,29 @@ func (r *ConfigMapSecret) syncStatus(ctx context.Context, log logr.Logger, cms *
386465
return nil
387466
}
388467

468+
func getOwner(secret *corev1.Secret) *metav1.OwnerReference {
469+
owner := metav1.GetControllerOf(secret)
470+
if owner == nil || owner.Kind != "ConfigMapSecret" {
471+
return nil
472+
}
473+
if gv, _ := schema.ParseGroupVersion(owner.APIVersion); gv.Group != v1alpha1.GroupVersion.Group {
474+
return nil
475+
}
476+
return owner
477+
}
478+
479+
func keys(set map[string]bool) []string {
480+
n := len(set)
481+
if n == 0 {
482+
return nil
483+
}
484+
s := make([]string, 0, n)
485+
for k := range set {
486+
s = append(s, k)
487+
}
488+
return s
489+
}
490+
389491
func toReqs(namespace string, names map[string]bool) []reconcile.Request {
390492
var reqs []reconcile.Request
391493
for name := range names {

0 commit comments

Comments
 (0)