@@ -2,31 +2,22 @@ package controller
22
33import (
44 "context"
5- "sync"
65 "time"
76
87 corev1 "k8s.io/api/core/v1"
98 "k8s.io/apimachinery/pkg/runtime"
10- "k8s.io/client-go/util/workqueue"
119 ctrl "sigs.k8s.io/controller-runtime"
1210 "sigs.k8s.io/controller-runtime/pkg/builder"
1311 "sigs.k8s.io/controller-runtime/pkg/client"
14- "sigs.k8s.io/controller-runtime/pkg/controller"
1512 "sigs.k8s.io/controller-runtime/pkg/event"
1613 "sigs.k8s.io/controller-runtime/pkg/log"
1714 "sigs.k8s.io/controller-runtime/pkg/predicate"
18- "sigs.k8s.io/controller-runtime/pkg/reconcile"
1915
2016 helmv2 "github.com/fluxcd/helm-controller/api/v2"
2117)
2218
2319const (
24- ConfigMapReconcilerName = "configmap-reconciler"
25- LabelConfigMapReconcilerNameSourceKey = "uburro.github.com/fluxcd-trigger-operator"
26- AnnotationHelmReleaseNameKey = "uburro.github.com/helmreleases-name"
27- AnnotationHelmReleaseNamespaceKey = "uburro.github.com/helmreleases-namespace"
28- AnnotationDigistKey = "uburro.github.com/config-digest"
29- DefaultFluxcdNamespace = "flux-system"
20+ ConfigMapReconcilerName = "configmap-reconciler"
3021)
3122
3223// ConfigMapReconciler reconciles ConfigMap resources in a Kubernetes cluster.
@@ -56,8 +47,8 @@ func (r *ConfigMapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
5647 return ctrl.Result {}, err
5748 }
5849
59- hrName := configMap .GetAnnotations ()[AnnotationHelmReleaseNameKey ]
60- hrNamespace := configMap .GetAnnotations ()[AnnotationHelmReleaseNamespaceKey ]
50+ hrName := configMap .GetAnnotations ()[HRAnnotation ]
51+ hrNamespace := configMap .GetAnnotations ()[NSAnnotation ]
6152
6253 if hrName == "" {
6354 logger .V (1 ).Info ("No HelmRelease name found in ConfigMap annotations" , "configMap" , req .Name )
@@ -73,32 +64,56 @@ func (r *ConfigMapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
7364 Name : hrName ,
7465 Namespace : hrNamespace ,
7566 }, hr ); err != nil {
76- logger .V (1 ).Error (err , "Getting HelmRelease produced an error" , "helmRelease" , hrName , "namespace" , hrNamespace )
67+ logger .V (1 ).Error (err , "Getting HelmRelease produced an error" ,
68+ "helmRelease" , hrName , "namespace" , hrNamespace )
7769 return ctrl.Result {}, err
7870 }
7971
80- oldDigest := configMap .GetAnnotations ()[AnnotationDigistKey ]
81- newDigest := hr .Status .History [0 ].Digest
72+ if len (hr .Status .History ) == 0 {
73+ logger .V (1 ).Info ("No history found in HelmRelease, skipping helmRelease patch" ,
74+ "helmRelease" , hrName , "namespace" , hrNamespace )
75+ return ctrl.Result {}, nil
76+ }
77+
78+ if hr .Status .History [0 ].Status != "deployed" {
79+ logger .V (1 ).Info ("HelmRelease is not deployed, skipping patch" , "helmRelease" ,
80+ hrName , "namespace" , hrNamespace , "status" , hr .Status .History [0 ].Status )
81+ return ctrl.Result {}, nil
82+ }
83+
84+ oldDigest := configMap .GetAnnotations ()[HashAnnotation ]
85+ newDigest := getDataHashCM (configMap .Data )
86+
87+ logger .V (1 ).Info ("old digest" , "digest" , oldDigest )
88+ logger .V (1 ).Info ("new digest" , "digest" , newDigest )
8289
8390 if oldDigest == newDigest {
8491 logger .V (1 ).Info ("No changes detected in ConfigMap, skipping HelmRelease patch" , "configMap" , req .Name )
8592 return ctrl.Result {}, nil
8693 }
8794
88- patchTarget := hr .DeepCopy ()
95+ patchTargetHR := hr .DeepCopy ()
8996
9097 ts := time .Now ().Format (time .RFC3339Nano )
91- patchTarget .Annotations [AnnotationDigistKey ] = newDigest
92- patchTarget .Annotations ["reconcile.fluxcd.io/forceAt" ] = ts
93- patchTarget .Annotations ["reconcile.fluxcd.io/requestedAt" ] = ts
98+ patchTargetHR .Annotations ["reconcile.fluxcd.io/forceAt" ] = ts
99+ patchTargetHR .Annotations ["reconcile.fluxcd.io/requestedAt" ] = ts
94100
95- patch := client .MergeFrom (hr .DeepCopy ())
101+ patchHR := client .MergeFrom (hr .DeepCopy ())
102+ if err := r .Patch (ctx , patchTargetHR , patchHR ); err != nil {
103+ logger .Error (err , "failed to patch HelmRelease" , "name" , patchTargetHR .Name )
104+ }
96105
97- if err := r .Patch (ctx , patchTarget , patch ); err != nil {
98- logger .Error (err , "failed to patch HelmRelease" , "name" , patchTarget .Name )
106+ patchCM := client .MergeFrom (configMap .DeepCopy ())
107+ patchTargetCM := configMap .DeepCopy ()
108+ patchTargetCM .Annotations [HashAnnotation ] = newDigest
109+ if err := r .Patch (ctx , patchTargetCM , patchCM ); err != nil {
110+ logger .Error (err , "failed to patch HelmRelease" , "name" , patchTargetHR .Name )
99111 }
100112
101- logger .Info ("patched HelmRelease with new digest" , "name" , patchTarget .Name , "digest" , newDigest , "version" , hr .Status .History [0 ].Version )
113+ logger .Info ("patched HelmRelease with new digest" ,
114+ "name" , patchTargetHR .Name ,
115+ "digest" , newDigest ,
116+ "version" , hr .Status .History [0 ].Version )
102117
103118 return ctrl.Result {}, nil
104119}
@@ -116,13 +131,19 @@ func (r *ConfigMapReconciler) SetupWithManager(
116131
117132 return isValidConfigMap (configMap )
118133 },
134+
119135 UpdateFunc : func (e event.UpdateEvent ) bool {
120- configMap , ok := e .ObjectNew .(* corev1.ConfigMap )
121- if ! ok {
136+ configMapOld , okOld := e .ObjectOld .(* corev1.ConfigMap )
137+ configMapNew , okNew := e .ObjectNew .(* corev1.ConfigMap )
138+
139+ if ! okOld || ! okNew || ! isValidConfigMap (configMapNew ) {
122140 return false
123141 }
124142
125- return isValidConfigMap (configMap )
143+ oldHash := getDataHashCM (configMapOld .Data )
144+ newHash := getDataHashCM (configMapNew .Data )
145+
146+ return oldHash != newHash
126147 },
127148 DeleteFunc : func (e event.DeleteEvent ) bool {
128149 return false
@@ -141,25 +162,8 @@ func (r *ConfigMapReconciler) SetupWithManager(
141162}
142163
143164func isValidConfigMap (cm * corev1.ConfigMap ) bool {
144- if v , ok := cm .Labels [LabelConfigMapReconcilerNameSourceKey ]; ok {
165+ if v , ok := cm .Labels [LabelReconcilerNameSourceKey ]; ok {
145166 return v == "true"
146167 }
147168 return false
148169}
149-
150- var (
151- optionsInit sync.Once
152- defaultOptions * controller.Options
153- )
154-
155- func ControllerOptions (maxConcurrency int , cacheSyncTimeout time.Duration ) controller.Options {
156- rateLimiters := workqueue .NewTypedItemExponentialFailureRateLimiter [reconcile.Request ](30 * time .Second , 5 * time .Minute )
157- optionsInit .Do (func () {
158- defaultOptions = & controller.Options {
159- RateLimiter : rateLimiters ,
160- CacheSyncTimeout : cacheSyncTimeout ,
161- MaxConcurrentReconciles : maxConcurrency ,
162- }
163- })
164- return * defaultOptions
165- }
0 commit comments