@@ -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+
150229func (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+
389491func toReqs (namespace string , names map [string ]bool ) []reconcile.Request {
390492 var reqs []reconcile.Request
391493 for name := range names {
0 commit comments