1package state 2 3import ( 4 "fmt" 5 "github.com/roboll/helmfile/pkg/helmexec" 6 "github.com/roboll/helmfile/pkg/remote" 7 "github.com/variantdev/chartify" 8 "os" 9 "path/filepath" 10 "strings" 11) 12 13type Dependency struct { 14 Chart string `yaml:"chart"` 15 Version string `yaml:"version"` 16 Alias string `yaml:"alias"` 17} 18 19func (st *HelmState) appendHelmXFlags(flags []string, release *ReleaseSpec) ([]string, error) { 20 for _, adopt := range release.Adopt { 21 flags = append(flags, "--adopt", adopt) 22 } 23 24 return flags, nil 25} 26 27func fileExistsAt(path string) bool { 28 fileInfo, err := os.Stat(path) 29 return err == nil && fileInfo.Mode().IsRegular() 30} 31 32func directoryExistsAt(path string) bool { 33 fileInfo, err := os.Stat(path) 34 return err == nil && fileInfo.Mode().IsDir() 35} 36 37type Chartify struct { 38 Opts *chartify.ChartifyOpts 39 Clean func() 40} 41 42func (st *HelmState) downloadChartWithGoGetter(r *ReleaseSpec) (string, error) { 43 pathElems := []string{ 44 remote.DefaultCacheDir, 45 } 46 47 if r.Namespace != "" { 48 pathElems = append(pathElems, r.Namespace) 49 } 50 51 if r.KubeContext != "" { 52 pathElems = append(pathElems, r.KubeContext) 53 } 54 55 pathElems = append(pathElems, r.Name, r.Chart) 56 57 cacheDir := filepath.Join(pathElems...) 58 59 return st.goGetterChart(r.Chart, r.Directory, cacheDir, r.ForceGoGetter) 60} 61 62func (st *HelmState) goGetterChart(chart, dir, cacheDir string, force bool) (string, error) { 63 if dir != "" && chart == "" { 64 chart = dir 65 } 66 67 _, err := remote.Parse(chart) 68 if err != nil { 69 if force { 70 return "", fmt.Errorf("Parsing url from dir failed due to error %q.\nContinuing the process assuming this is a regular Helm chart or a local dir.", err.Error()) 71 } 72 } else { 73 r := remote.NewRemote(st.logger, st.basePath, st.readFile, directoryExistsAt, fileExistsAt) 74 75 fetchedDir, err := r.Fetch(chart, cacheDir) 76 if err != nil { 77 return "", fmt.Errorf("fetching %q: %v", chart, err) 78 } 79 80 chart = fetchedDir 81 } 82 83 return chart, nil 84} 85 86func (st *HelmState) PrepareChartify(helm helmexec.Interface, release *ReleaseSpec, chart string, workerIndex int) (*Chartify, func(), error) { 87 chartify := &Chartify{ 88 Opts: &chartify.ChartifyOpts{ 89 WorkaroundOutputDirIssue: true, 90 EnableKustomizeAlphaPlugins: true, 91 ChartVersion: release.Version, 92 Namespace: release.Namespace, 93 }, 94 } 95 96 var filesNeedCleaning []string 97 98 clean := func() { 99 st.removeFiles(filesNeedCleaning) 100 } 101 102 var shouldRun bool 103 104 dir := filepath.Join(st.basePath, chart) 105 if stat, _ := os.Stat(dir); stat != nil && stat.IsDir() { 106 if exists, err := st.fileExists(filepath.Join(dir, "Chart.yaml")); err == nil && !exists { 107 shouldRun = true 108 } 109 } 110 111 for _, d := range release.Dependencies { 112 var dep string 113 114 if d.Alias != "" { 115 dep += d.Alias + "=" 116 } else { 117 a := strings.Split(d.Chart, "/") 118 119 chart := a[len(a)-1] 120 121 dep += chart + "=" 122 } 123 124 dep += d.Chart 125 126 if d.Version != "" { 127 dep += ":" + d.Version 128 } 129 130 chartify.Opts.AdhocChartDependencies = append(chartify.Opts.AdhocChartDependencies, dep) 131 132 shouldRun = true 133 } 134 135 jsonPatches := release.JSONPatches 136 if len(jsonPatches) > 0 { 137 generatedFiles, err := st.generateTemporaryReleaseValuesFiles(release, jsonPatches, release.MissingFileHandler) 138 if err != nil { 139 return nil, clean, err 140 } 141 142 filesNeedCleaning = append(filesNeedCleaning, generatedFiles...) 143 144 for _, f := range generatedFiles { 145 chartify.Opts.JsonPatches = append(chartify.Opts.JsonPatches, f) 146 } 147 148 shouldRun = true 149 } 150 151 strategicMergePatches := release.StrategicMergePatches 152 if len(strategicMergePatches) > 0 { 153 generatedFiles, err := st.generateTemporaryReleaseValuesFiles(release, strategicMergePatches, release.MissingFileHandler) 154 if err != nil { 155 return nil, clean, err 156 } 157 158 for _, f := range generatedFiles { 159 chartify.Opts.StrategicMergePatches = append(chartify.Opts.StrategicMergePatches, f) 160 } 161 162 filesNeedCleaning = append(filesNeedCleaning, generatedFiles...) 163 164 shouldRun = true 165 } 166 167 transformers := release.Transformers 168 if len(transformers) > 0 { 169 generatedFiles, err := st.generateTemporaryReleaseValuesFiles(release, transformers, release.MissingFileHandler) 170 if err != nil { 171 return nil, clean, err 172 } 173 174 for _, f := range generatedFiles { 175 chartify.Opts.Transformers = append(chartify.Opts.Transformers, f) 176 } 177 178 filesNeedCleaning = append(filesNeedCleaning, generatedFiles...) 179 180 shouldRun = true 181 } 182 183 if release.ForceNamespace != "" { 184 chartify.Opts.OverrideNamespace = release.ForceNamespace 185 186 shouldRun = true 187 } 188 189 if shouldRun { 190 generatedFiles, err := st.generateValuesFiles(helm, release, workerIndex) 191 if err != nil { 192 return nil, clean, err 193 } 194 195 filesNeedCleaning = append(filesNeedCleaning, generatedFiles...) 196 197 chartify.Opts.ValuesFiles = generatedFiles 198 199 return chartify, clean, nil 200 } 201 202 return nil, clean, nil 203} 204