66 "fmt"
77 "log/slog"
88 "os"
9+ "path/filepath"
10+ "slices"
911 "sort"
1012 "strconv"
1113 "strings"
@@ -14,6 +16,7 @@ import (
1416 "github.com/deckhouse/deckhouse/pkg/log"
1517 logContext "github.com/deckhouse/deckhouse/pkg/log/context"
1618 "helm.sh/helm/v3/pkg/action"
19+ "helm.sh/helm/v3/pkg/chart"
1720 "helm.sh/helm/v3/pkg/chart/loader"
1821 "helm.sh/helm/v3/pkg/chartutil"
1922 "helm.sh/helm/v3/pkg/cli"
@@ -164,15 +167,15 @@ func (h *LibClient) LastReleaseStatus(releaseName string) (string /*revision*/,
164167 return strconv .FormatInt (int64 (lastRelease .Version ), 10 ), lastRelease .Info .Status .String (), nil
165168}
166169
167- func (h * LibClient ) UpgradeRelease (releaseName string , chartName string , valuesPaths []string , setValues []string , labels map [string ]string , namespace string ) error {
168- err := h .upgradeRelease (releaseName , chartName , valuesPaths , setValues , labels , namespace )
170+ func (h * LibClient ) UpgradeRelease (releaseName , modulePath string , valuesPaths []string , setValues []string , labels map [string ]string , namespace string ) error {
171+ err := h .upgradeRelease (releaseName , modulePath , valuesPaths , setValues , labels , namespace )
169172 if err != nil {
170173 // helm validation can fail because FeatureGate was enabled for example
171174 // handling this case we can reinitialize kubeClient and repeat one more time by backoff
172175 if err := actionConfigInit (h .Logger ); err != nil {
173176 return err
174177 }
175- return h .upgradeRelease (releaseName , chartName , valuesPaths , setValues , labels , namespace )
178+ return h .upgradeRelease (releaseName , modulePath , valuesPaths , setValues , labels , namespace )
176179 }
177180 h .Logger .Debug ("helm release upgraded" , slog .String ("version" , releaseName ))
178181 return nil
@@ -182,7 +185,7 @@ func (h *LibClient) hasLabelsToApply() bool {
182185 return len (h .labels ) > 0
183186}
184187
185- func (h * LibClient ) upgradeRelease (releaseName string , chartName string , valuesPaths []string , setValues []string , labels map [string ]string , namespace string ) error {
188+ func (h * LibClient ) upgradeRelease (releaseName , modulePath string , valuesPaths []string , setValues []string , labels map [string ]string , namespace string ) error {
186189 upg := action .NewUpgrade (actionConfig )
187190 if namespace != "" {
188191 upg .Namespace = namespace
@@ -197,11 +200,6 @@ func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesP
197200 upg .Timeout = options .Timeout
198201 upg .Labels = labels
199202
200- chart , err := loader .Load (chartName )
201- if err != nil {
202- return err
203- }
204-
205203 var resultValues chartutil.Values
206204
207205 for _ , vp := range valuesPaths {
@@ -224,9 +222,14 @@ func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesP
224222 resultValues = chartutil .CoalesceTables (resultValues , m )
225223 }
226224
225+ loaded , err := loadChart (releaseName , modulePath )
226+ if err != nil {
227+ return err
228+ }
229+
227230 h .Logger .Info ("Running helm upgrade for release" ,
228231 slog .String ("release" , releaseName ),
229- slog .String ("chart" , chartName ),
232+ slog .String ("chart" , modulePath ),
230233 slog .String ("namespace" , namespace ))
231234 histClient := action .NewHistory (actionConfig )
232235 // Max is not working!!! Sort the final of releases by your own
@@ -247,7 +250,7 @@ func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesP
247250 instClient .UseReleaseName = true
248251 instClient .Labels = labels
249252
250- _ , err = instClient .Run (chart , resultValues )
253+ _ , err = instClient .Run (loaded , resultValues )
251254 return err
252255 }
253256 h .Logger .Debug ("old releases found" , slog .Int ("count" , len (releases )))
@@ -306,13 +309,13 @@ func (h *LibClient) upgradeRelease(releaseName string, chartName string, valuesP
306309 }
307310 }
308311
309- _ , err = upg .Run (releaseName , chart , resultValues )
312+ _ , err = upg .Run (releaseName , loaded , resultValues )
310313 if err != nil {
311314 return fmt .Errorf ("helm upgrade failed: %s\n " , err )
312315 }
313316 h .Logger .Info ("Helm upgrade successful" ,
314317 slog .String ("release" , releaseName ),
315- slog .String ("chart" , chartName ),
318+ slog .String ("chart" , modulePath ),
316319 slog .String ("namespace" , namespace ))
317320
318321 return nil
@@ -451,12 +454,7 @@ func (h *LibClient) ListReleasesNames() ([]string, error) {
451454 return releases , nil
452455}
453456
454- func (h * LibClient ) Render (releaseName , chartName string , valuesPaths , setValues []string , _ map [string ]string , namespace string , debug bool ) (string , error ) {
455- chart , err := loader .Load (chartName )
456- if err != nil {
457- return "" , err
458- }
459-
457+ func (h * LibClient ) Render (releaseName , modulePath string , valuesPaths , setValues []string , _ map [string ]string , namespace string , debug bool ) (string , error ) {
460458 var resultValues chartutil.Values
461459
462460 for _ , vp := range valuesPaths {
@@ -480,19 +478,24 @@ func (h *LibClient) Render(releaseName, chartName string, valuesPaths, setValues
480478 }
481479
482480 h .Logger .Debug ("Render helm templates for chart ..." ,
483- slog .String ("chart" , chartName ),
481+ slog .String ("chart" , modulePath ),
484482 slog .String ("namespace" , namespace ))
485483
484+ loaded , err := loadChart (releaseName , modulePath )
485+ if err != nil {
486+ return "" , err
487+ }
488+
486489 inst := h .newDryRunInstAction (namespace , releaseName )
487490
488- rs , err := inst .Run (chart , resultValues )
491+ rs , err := inst .Run (loaded , resultValues )
489492 if err != nil {
490493 // helm render can fail because the CRD were previously created
491494 // handling this case we can reinitialize RESTClient and repeat one more time by backoff
492495 _ = actionConfigInit (h .Logger )
493496 inst = h .newDryRunInstAction (namespace , releaseName )
494497
495- rs , err = inst .Run (chart , resultValues )
498+ rs , err = inst .Run (loaded , resultValues )
496499 }
497500
498501 if err != nil {
@@ -506,7 +509,7 @@ func (h *LibClient) Render(releaseName, chartName string, valuesPaths, setValues
506509 rs .Manifest += fmt .Sprintf ("\n \n \n %v" , err )
507510 }
508511
509- h .Logger .Info ("Render helm templates for chart was successful" , slog .String ("chart" , chartName ))
512+ h .Logger .Info ("Render helm templates for chart was successful" , slog .String ("chart" , modulePath ))
510513
511514 return rs .Manifest , nil
512515}
@@ -543,3 +546,70 @@ func (h *LibClient) ListReleases() ([]*release.Release, error) {
543546
544547 return list , nil
545548}
549+
550+ func loadChart (moduleName , modulePath string ) (* chart.Chart , error ) {
551+ if _ , err := os .Stat (filepath .Join (modulePath , "Chart.yaml" )); err == nil {
552+ return loader .Load (modulePath )
553+ }
554+
555+ var files []* loader.BufferedFile
556+
557+ chartYaml := fmt .Sprintf (`
558+ name: %s
559+ version: 0.2.0
560+ ` , moduleName )
561+
562+ files = append (files , & loader.BufferedFile {
563+ Name : "Chart.yaml" ,
564+ Data : []byte (chartYaml ),
565+ })
566+
567+ ignored := []string {
568+ "crds" ,
569+ "docs" ,
570+ "hooks" ,
571+ "images" ,
572+ "lib" ,
573+ }
574+
575+ err := filepath .Walk (modulePath , func (path string , info os.FileInfo , err error ) error {
576+ if err != nil {
577+ return err
578+ }
579+
580+ if info .IsDir () {
581+ if slices .Contains (ignored , info .Name ()) {
582+ return filepath .SkipDir
583+ }
584+
585+ return nil
586+ }
587+
588+ relPath , err := filepath .Rel (modulePath , path )
589+ if err != nil {
590+ return err
591+ }
592+
593+ data , err := os .ReadFile (path )
594+ if err != nil {
595+ return err
596+ }
597+
598+ files = append (files , & loader.BufferedFile {
599+ Name : relPath ,
600+ Data : data ,
601+ })
602+
603+ return nil
604+ })
605+ if err != nil {
606+ return nil , fmt .Errorf ("read module files: %w" , err )
607+ }
608+
609+ loaded , err := loader .LoadFiles (files )
610+ if err != nil {
611+ return nil , fmt .Errorf ("load chart from files: %w" , err )
612+ }
613+
614+ return loaded , nil
615+ }
0 commit comments