88 "path/filepath"
99 "time"
1010
11+ "github.com/krateoplatformops/composition-dynamic-controller/internal/chartinspector"
1112 compositionMeta "github.com/krateoplatformops/composition-dynamic-controller/internal/meta"
1213
1314 "github.com/krateoplatformops/composition-dynamic-controller/internal/helmclient"
@@ -59,13 +60,7 @@ const (
5960
6061var _ controller.ExternalClient = (* handler )(nil )
6162
62- func NewHandler (cfg * rest.Config , log logging.Logger , pig archive.Getter , event event.APIRecorder , pluralizer pluralizer.PluralizerInterface , rbacgen rbacgen.RBACGenInterface ) controller.ExternalClient {
63- dyn , err := dynamic .NewForConfig (cfg )
64- if err != nil {
65- log .Error (err , "Creating dynamic client." )
66- return nil
67- }
68-
63+ func NewHandler (cfg * rest.Config , log logging.Logger , pig archive.Getter , event event.APIRecorder , pluralizer pluralizer.PluralizerInterface , chartInspectorUrl string , saName string , saNamespace string ) controller.ExternalClient {
6964 val , ok := os .LookupEnv (helmRegistryConfigPathEnvVar )
7065 if ok {
7166 helmRegistryConfigPath = val
@@ -75,35 +70,46 @@ func NewHandler(cfg *rest.Config, log logging.Logger, pig archive.Getter, event
7570
7671 return & handler {
7772 kubeconfig : cfg ,
78- rbacgen : rbacgen ,
7973 pluralizer : pluralizer ,
8074 logger : log ,
81- dynamicClient : dyn ,
8275 packageInfoGetter : pig ,
8376 eventRecorder : event ,
77+
78+ chartInspectorUrl : chartInspectorUrl ,
79+ saName : saName ,
80+ saNamespace : saNamespace ,
8481 }
8582}
8683
8784type handler struct {
8885 kubeconfig * rest.Config
89- rbacgen rbacgen.RBACGenInterface
9086 logger logging.Logger
9187 pluralizer pluralizer.PluralizerInterface
92- dynamicClient dynamic.Interface
9388 packageInfoGetter archive.Getter
9489 eventRecorder event.APIRecorder
90+
91+ chartInspectorUrl string
92+ saName string
93+ saNamespace string
9594}
9695
9796func (h * handler ) Observe (ctx context.Context , mg * unstructured.Unstructured ) (controller.ExternalObservation , error ) {
97+ mg = mg .DeepCopy ()
9898 log := h .logger .WithValues ("op" , "Observe" ).
9999 WithValues ("apiVersion" , mg .GetAPIVersion ()).
100100 WithValues ("kind" , mg .GetKind ()).
101101 WithValues ("name" , mg .GetName ()).
102102 WithValues ("namespace" , mg .GetNamespace ())
103103
104+ dyn , err := dynamic .NewForConfig (h .kubeconfig )
105+ if err != nil {
106+ log .Error (err , "Creating dynamic client." )
107+ return controller.ExternalObservation {}, err
108+ }
109+
104110 updateOpts := tools.UpdateOptions {
105111 Pluralizer : h .pluralizer ,
106- DynamicClient : h . dynamicClient ,
112+ DynamicClient : dyn ,
107113 }
108114
109115 compositionMeta .SetReleaseName (mg , mg .GetName ())
@@ -117,7 +123,7 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
117123 }
118124 // Immediately remove the gracefully paused time annotation if the composition is not gracefully paused.
119125 meta .RemoveAnnotations (mg , compositionMeta .AnnotationKeyReconciliationGracefullyPausedTime )
120- mg , err : = tools .Update (ctx , mg , updateOpts )
126+ mg , err = tools .Update (ctx , mg , updateOpts )
121127 if err != nil {
122128 log .Error (err , "Updating cr with values" )
123129 return controller.ExternalObservation {}, fmt .Errorf ("updating cr with values: %w" , err )
@@ -185,8 +191,11 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
185191 log .Error (err , "Converting GVK to GVR" )
186192 return controller.ExternalObservation {}, fmt .Errorf ("converting GVK to GVR: %w" , err )
187193 }
194+
195+ chartInspector := chartinspector .NewChartInspector (h .chartInspectorUrl )
196+ rbgen := rbacgen .NewRBACGen (h .saName , h .saNamespace , & chartInspector )
188197 // Get Resources and generate RBAC
189- generated , err := h . rbacgen .
198+ generated , err := rbgen .
190199 WithBaseName (meta .GetReleaseName (mg )).
191200 Generate (rbacgen.Parameters {
192201 CompositionName : mg .GetName (),
@@ -200,7 +209,7 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
200209 log .Error (err , "Generating RBAC using chart-inspector" )
201210 return controller.ExternalObservation {}, err
202211 }
203- rbInstaller := rbac .NewRBACInstaller (h . dynamicClient )
212+ rbInstaller := rbac .NewRBACInstaller (dyn )
204213 err = rbInstaller .ApplyRBAC (generated )
205214 if err != nil {
206215 log .Error (err , "Installing RBAC" )
@@ -218,7 +227,7 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
218227
219228 opts := helmchart.UpdateOptions {
220229 CheckResourceOptions : helmchart.CheckResourceOptions {
221- DynamicClient : h . dynamicClient ,
230+ DynamicClient : dyn ,
222231 Pluralizer : h .pluralizer ,
223232 },
224233 HelmClient : hc ,
@@ -269,7 +278,7 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
269278 return controller.ExternalObservation {}, err
270279 }
271280
272- mg , err = tools .UpdateStatus (ctx , mg , updateOpts )
281+ _ , err = tools .UpdateStatus (ctx , mg , updateOpts )
273282 if err != nil {
274283 log .Error (err , "Updating cr status with values" )
275284 return controller.ExternalObservation {}, err
@@ -284,15 +293,22 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
284293}
285294
286295func (h * handler ) Create (ctx context.Context , mg * unstructured.Unstructured ) error {
296+ mg = mg .DeepCopy ()
287297 log := h .logger .WithValues ("op" , "Create" ).
288298 WithValues ("apiVersion" , mg .GetAPIVersion ()).
289299 WithValues ("kind" , mg .GetKind ()).
290300 WithValues ("name" , mg .GetName ()).
291301 WithValues ("namespace" , mg .GetNamespace ())
292302
303+ dyn , err := dynamic .NewForConfig (h .kubeconfig )
304+ if err != nil {
305+ log .Error (err , "Creating dynamic client." )
306+ return fmt .Errorf ("creating dynamic client: %w" , err )
307+ }
308+
293309 updateOpts := tools.UpdateOptions {
294310 Pluralizer : h .pluralizer ,
295- DynamicClient : h . dynamicClient ,
311+ DynamicClient : dyn ,
296312 }
297313
298314 if _ , p := compositionMeta .GetGracefullyPausedTime (mg ); p && compositionMeta .IsGracefullyPaused (mg ) {
@@ -302,7 +318,7 @@ func (h *handler) Create(ctx context.Context, mg *unstructured.Unstructured) err
302318 }
303319
304320 compositionMeta .SetReleaseName (mg , mg .GetName ())
305- mg , err : = tools .Update (ctx , mg , updateOpts )
321+ mg , err = tools .Update (ctx , mg , updateOpts )
306322 if err != nil {
307323 log .Error (err , "Updating cr with values" )
308324 return fmt .Errorf ("updating cr with values: %w" , err )
@@ -323,8 +339,11 @@ func (h *handler) Create(ctx context.Context, mg *unstructured.Unstructured) err
323339 log .Error (err , "Converting GVK to GVR" )
324340 return fmt .Errorf ("converting GVK to GVR: %w" , err )
325341 }
342+
343+ chartInspector := chartinspector .NewChartInspector (h .chartInspectorUrl )
344+ rbgen := rbacgen .NewRBACGen (h .saName , h .saNamespace , & chartInspector )
326345 // Get Resources and generate RBAC
327- generated , err := h . rbacgen .
346+ generated , err := rbgen .
328347 WithBaseName (meta .GetReleaseName (mg )).
329348 Generate (rbacgen.Parameters {
330349 CompositionName : mg .GetName (),
@@ -338,7 +357,7 @@ func (h *handler) Create(ctx context.Context, mg *unstructured.Unstructured) err
338357 log .Error (err , "Generating RBAC using chart-inspector" )
339358 return err
340359 }
341- rbInstaller := rbac .NewRBACInstaller (h . dynamicClient )
360+ rbInstaller := rbac .NewRBACInstaller (dyn )
342361 err = rbInstaller .ApplyRBAC (generated )
343362 if err != nil {
344363 log .Error (err , "Installing RBAC" )
@@ -354,7 +373,7 @@ func (h *handler) Create(ctx context.Context, mg *unstructured.Unstructured) err
354373
355374 opts := helmchart.InstallOptions {
356375 CheckResourceOptions : helmchart.CheckResourceOptions {
357- DynamicClient : h . dynamicClient ,
376+ DynamicClient : dyn ,
358377 Pluralizer : h .pluralizer ,
359378 },
360379 HelmClient : hc ,
@@ -416,15 +435,23 @@ func (h *handler) Create(ctx context.Context, mg *unstructured.Unstructured) err
416435}
417436
418437func (h * handler ) Update (ctx context.Context , mg * unstructured.Unstructured ) error {
438+ mg = mg .DeepCopy ()
439+
419440 log := h .logger .WithValues ("op" , "Update" ).
420441 WithValues ("apiVersion" , mg .GetAPIVersion ()).
421442 WithValues ("kind" , mg .GetKind ()).
422443 WithValues ("name" , mg .GetName ()).
423444 WithValues ("namespace" , mg .GetNamespace ())
424445
446+ dyn , err := dynamic .NewForConfig (h .kubeconfig )
447+ if err != nil {
448+ log .Error (err , "Creating dynamic client." )
449+ return fmt .Errorf ("creating dynamic client: %w" , err )
450+ }
451+
425452 updateOpts := tools.UpdateOptions {
426453 Pluralizer : h .pluralizer ,
427- DynamicClient : h . dynamicClient ,
454+ DynamicClient : dyn ,
428455 }
429456
430457 if _ , p := compositionMeta .GetGracefullyPausedTime (mg ); p && compositionMeta .IsGracefullyPaused (mg ) {
@@ -482,7 +509,7 @@ func (h *handler) Update(ctx context.Context, mg *unstructured.Unstructured) err
482509 }
483510 mg , err = tools .UpdateStatus (ctx , mg , tools.UpdateOptions {
484511 Pluralizer : h .pluralizer ,
485- DynamicClient : h . dynamicClient ,
512+ DynamicClient : dyn ,
486513 })
487514 if err != nil {
488515 log .Error (err , "Updating cr status with values" )
@@ -501,7 +528,7 @@ func (h *handler) Update(ctx context.Context, mg *unstructured.Unstructured) err
501528 }
502529 mg , err = tools .UpdateStatus (ctx , mg , tools.UpdateOptions {
503530 Pluralizer : h .pluralizer ,
504- DynamicClient : h . dynamicClient ,
531+ DynamicClient : dyn ,
505532 })
506533 if err != nil {
507534 log .Error (err , "Updating cr status with values" )
@@ -520,15 +547,23 @@ func (h *handler) Update(ctx context.Context, mg *unstructured.Unstructured) err
520547}
521548
522549func (h * handler ) Delete (ctx context.Context , mg * unstructured.Unstructured ) error {
550+ mg = mg .DeepCopy ()
551+
523552 log := h .logger .WithValues ("op" , "Delete" ).
524553 WithValues ("apiVersion" , mg .GetAPIVersion ()).
525554 WithValues ("kind" , mg .GetKind ()).
526555 WithValues ("name" , mg .GetName ()).
527556 WithValues ("namespace" , mg .GetNamespace ())
528557
558+ dyn , err := dynamic .NewForConfig (h .kubeconfig )
559+ if err != nil {
560+ log .Error (err , "Creating dynamic client." )
561+ return fmt .Errorf ("creating dynamic client: %w" , err )
562+ }
563+
529564 updateOpts := tools.UpdateOptions {
530565 Pluralizer : h .pluralizer ,
531- DynamicClient : h . dynamicClient ,
566+ DynamicClient : dyn ,
532567 }
533568
534569 if _ , p := compositionMeta .GetGracefullyPausedTime (mg ); p && compositionMeta .IsGracefullyPaused (mg ) {
@@ -562,7 +597,7 @@ func (h *handler) Delete(ctx context.Context, mg *unstructured.Unstructured) err
562597 }
563598
564599 // Check if the release exists before uninstalling
565- rel , err := helmchart .FindAnyRelease (hc , meta .GetReleaseName (mg ))
600+ rel , err := helmchart .FindRelease (hc , meta .GetReleaseName (mg ))
566601 if err != nil {
567602 return fmt .Errorf ("finding helm release: %w" , err )
568603 }
@@ -578,7 +613,7 @@ func (h *handler) Delete(ctx context.Context, mg *unstructured.Unstructured) err
578613 return fmt .Errorf ("uninstalling helm chart: %w" , err )
579614 }
580615
581- rel , err = helmchart .FindAnyRelease (hc , meta .GetReleaseName (mg ))
616+ rel , err = helmchart .FindRelease (hc , meta .GetReleaseName (mg ))
582617 if err != nil {
583618 log .Error (err , "Finding helm release" )
584619 return fmt .Errorf ("finding helm release: %w" , err )
@@ -595,8 +630,10 @@ func (h *handler) Delete(ctx context.Context, mg *unstructured.Unstructured) err
595630 log .Error (err , "Converting GVK to GVR" )
596631 return fmt .Errorf ("converting GVK to GVR: %w" , err )
597632 }
633+ chartInspector := chartinspector .NewChartInspector (h .chartInspectorUrl )
634+ rbgen := rbacgen .NewRBACGen (h .saName , h .saNamespace , & chartInspector )
598635 // Get Resources and generate RBAC
599- generated , err := h . rbacgen .
636+ generated , err := rbgen .
600637 WithBaseName (meta .GetReleaseName (mg )).
601638 Generate (rbacgen.Parameters {
602639 CompositionName : mg .GetName (),
@@ -606,7 +643,11 @@ func (h *handler) Delete(ctx context.Context, mg *unstructured.Unstructured) err
606643 CompositionDefinitionNamespace : pkg .CompositionDefinitionInfo .Namespace ,
607644 CompositionDefintionGVR : pkg .CompositionDefinitionInfo .GVR ,
608645 })
609- rbInstaller := rbac .NewRBACInstaller (h .dynamicClient )
646+ if err != nil {
647+ log .Error (err , "Generating RBAC using chart-inspector" )
648+ return err
649+ }
650+ rbInstaller := rbac .NewRBACInstaller (dyn )
610651 err = rbInstaller .UninstallRBAC (generated )
611652 if err != nil {
612653 log .Error (err , "Uninstalling RBAC" )
@@ -632,6 +673,12 @@ func (h *handler) helmClientForResource(mg *unstructured.Unstructured, registryA
632673 WithValues ("name" , mg .GetName ()).
633674 WithValues ("namespace" , mg .GetNamespace ())
634675
676+ clientSet , err := helmclient .NewCachedClients (h .kubeconfig )
677+ if err != nil {
678+ log .Error (err , "Creating cached helm client set." )
679+ return nil , err
680+ }
681+
635682 opts := & helmclient.Options {
636683 Namespace : mg .GetNamespace (),
637684 RepositoryCache : "/tmp/.helmcache" ,
@@ -653,10 +700,13 @@ func (h *handler) helmClientForResource(mg *unstructured.Unstructured, registryA
653700 RegistryAuth : (registryAuth ),
654701 }
655702
656- return helmclient .NewClientFromRestConf (& helmclient.RestConfClientOptions {
657- Options : opts ,
658- RestConfig : h .kubeconfig ,
659- })
703+ return helmclient .NewCachedClientFromRestConf (
704+ & helmclient.RestConfClientOptions {
705+ Options : opts ,
706+ RestConfig : h .kubeconfig ,
707+ },
708+ & clientSet ,
709+ )
660710}
661711
662712func (h * handler ) helmClientForResourceWithTransportWrapper (mg * unstructured.Unstructured , registryAuth * helmclient.RegistryAuth , transportWrapper func (http.RoundTripper ) http.RoundTripper ) (helmclient.Client , error ) {
@@ -671,10 +721,19 @@ func (h *handler) helmClientForResourceWithTransportWrapper(mg *unstructured.Uns
671721 RegistryAuth : registryAuth ,
672722 }
673723
674- h .kubeconfig .WrapTransport = transportWrapper
724+ clientSet , err := helmclient .NewCachedClients (h .kubeconfig )
725+ if err != nil {
726+ return nil , err
727+ }
675728
676- return helmclient .NewClientFromRestConf (& helmclient.RestConfClientOptions {
677- Options : opts ,
678- RestConfig : h .kubeconfig ,
679- })
729+ cfg := rest .CopyConfig (h .kubeconfig )
730+ cfg .WrapTransport = transportWrapper
731+
732+ return helmclient .NewCachedClientFromRestConf (
733+ & helmclient.RestConfClientOptions {
734+ Options : opts ,
735+ RestConfig : cfg ,
736+ },
737+ & clientSet ,
738+ )
680739}
0 commit comments