From 53dea091e3833ac7bcf4c9fe6e0f8faaa7d74165 Mon Sep 17 00:00:00 2001 From: Karl Stoney Date: Tue, 4 Sep 2018 12:55:32 +0100 Subject: [PATCH] Fix set in `helmfile template` and `helmfile lint` (#289) This removes --concurrenty flag from `helmfile template` and `helmfile lint`. YAGNI. Also separates out the downloadCharts into a function so it can be used by lint too. Fixes #288 --- main.go | 21 +--- state/state.go | 288 +++++++++++++++++++------------------------------ 2 files changed, 112 insertions(+), 197 deletions(-) diff --git a/main.go b/main.go index 9bc58de2..96229942 100644 --- a/main.go +++ b/main.go @@ -200,11 +200,6 @@ func main() { Name: "values", Usage: "additional value files to be merged into the command", }, - cli.IntFlag{ - Name: "concurrency", - Value: 0, - Usage: "maximum number of concurrent helm processes to run, 0 is unlimited", - }, }, Action: func(c *cli.Context) error { return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error { @@ -225,26 +220,17 @@ func main() { Name: "values", Usage: "additional value files to be merged into the command", }, - cli.IntFlag{ - Name: "concurrency", - Value: 0, - Usage: "maximum number of concurrent helm processes to run, 0 is unlimited", - }, }, Action: func(c *cli.Context) error { return findAndIterateOverDesiredStatesUsingFlags(c, func(state *state.HelmState, helm helmexec.Interface) []error { - args := args.GetArgs(c.String("args"), state) - if len(args) > 0 { - helm.SetExtraArgs(args...) - } if c.GlobalString("helm-binary") != "" { helm.SetHelmBinary(c.GlobalString("helm-binary")) } values := c.StringSlice("values") - workers := c.Int("concurrency") + args := args.GetArgs(c.String("args"), state) - return state.LintReleases(helm, values, workers) + return state.LintReleases(helm, values, args) }) }, }, @@ -490,9 +476,8 @@ func executeTemplateCommand(c *cli.Context, state *state.HelmState, helm helmexe args := args.GetArgs(c.String("args"), state) values := c.StringSlice("values") - workers := c.Int("concurrency") - return state.TemplateReleases(helm, values, workers, args) + return state.TemplateReleases(helm, values, args) } func executeDiffCommand(c *cli.Context, state *state.HelmState, helm helmexec.Interface, detailedExitCode, suppressSecrets bool) []error { diff --git a/state/state.go b/state/state.go index c4f9a626..fe789c27 100644 --- a/state/state.go +++ b/state/state.go @@ -271,20 +271,41 @@ func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues [ return nil } -// TemplateReleases wrapper for executing helm template on the releases -func (state *HelmState) TemplateReleases(helm helmexec.Interface, additionalValues []string, workerLimit int, args []string) []error { - var wgRelease sync.WaitGroup - var wgError sync.WaitGroup - errs := []error{} - jobQueue := make(chan *ReleaseSpec, len(state.Releases)) - errQueue := make(chan error) +// downloadCharts will download and untar charts for Lint and Template +func (state *HelmState) downloadCharts(helm helmexec.Interface, dir string) (map[string]string, error) { + temp := make(map[string]string, len(state.Releases)) - if workerLimit < 1 { - workerLimit = len(state.Releases) + for _, release := range state.Releases { + chartPath := "" + if pathExists(normalizeChart(state.basePath, release.Chart)) { + chartPath = normalizeChart(state.basePath, release.Chart) + } else { + fetchFlags := []string{} + if release.Version != "" { + chartPath = path.Join(dir, release.Name, release.Version, release.Chart) + fetchFlags = append(fetchFlags, "--version", release.Version) + } else { + chartPath = path.Join(dir, release.Name, "latest", release.Chart) + } + + // only fetch chart if it is not already fetched + if _, err := os.Stat(chartPath); os.IsNotExist(err) { + fetchFlags = append(fetchFlags, "--untar", "--untardir", chartPath) + if err := helm.Fetch(release.Chart, fetchFlags...); err != nil { + return nil, err + } + } + chartPath = path.Join(chartPath, chartNameWithoutRepository(release.Chart)) + } + temp[release.Name] = chartPath } - wgRelease.Add(len(state.Releases)) + return temp, nil +} +// TemplateReleases wrapper for executing helm template on the releases +func (state *HelmState) TemplateReleases(helm helmexec.Interface, additionalValues []string, args []string) []error { + errs := []error{} // Create tmp directory and bail immediately if it fails dir, err := ioutil.TempDir("", "") if err != nil { @@ -293,81 +314,91 @@ func (state *HelmState) TemplateReleases(helm helmexec.Interface, additionalValu } defer os.RemoveAll(dir) - for w := 1; w <= workerLimit; w++ { - go func() { - for release := range jobQueue { - errs := []error{} - flags, err := state.flagsForTemplate(helm, release) - if err != nil { - errs = append(errs, err) - } - for _, value := range additionalValues { - valfile, err := filepath.Abs(value) - if err != nil { - errs = append(errs, err) - } - - if _, err := os.Stat(valfile); os.IsNotExist(err) { - errs = append(errs, err) - } - flags = append(flags, "--values", valfile) - } - - chartPath := "" - if pathExists(normalizeChart(state.basePath, release.Chart)) { - chartPath = normalizeChart(state.basePath, release.Chart) - } else { - fetchFlags := []string{} - if release.Version != "" { - chartPath = path.Join(dir, release.Name, release.Version, release.Chart) - fetchFlags = append(fetchFlags, "--version", release.Version) - } else { - chartPath = path.Join(dir, release.Name, "latest", release.Chart) - } - - // only fetch chart if it is not already fetched - if _, err := os.Stat(chartPath); os.IsNotExist(err) { - fetchFlags = append(fetchFlags, "--untar", "--untardir", chartPath) - if err := helm.Fetch(release.Chart, fetchFlags...); err != nil { - errs = append(errs, err) - } - } - chartPath = path.Join(chartPath, chartNameWithoutRepository(release.Chart)) - } - - if len(args) > 0 { - helm.SetExtraArgs(args...) - } - - if len(errs) == 0 { - if err := helm.TemplateRelease(chartPath, flags...); err != nil { - errs = append(errs, err) - } - } - for _, err := range errs { - errQueue <- err - } - wgRelease.Done() - } - }() + temp, err := state.downloadCharts(helm, dir) + if err != nil { + errs = append(errs, err) + return errs } - wgError.Add(1) - go func() { - for err := range errQueue { + + if len(args) > 0 { + helm.SetExtraArgs(args...) + } + + for _, release := range state.Releases { + flags, err := state.flagsForTemplate(helm, &release) + if err != nil { errs = append(errs, err) } - wgError.Done() - }() + for _, value := range additionalValues { + valfile, err := filepath.Abs(value) + if err != nil { + errs = append(errs, err) + } - for i := 0; i < len(state.Releases); i++ { - jobQueue <- &state.Releases[i] + if _, err := os.Stat(valfile); os.IsNotExist(err) { + errs = append(errs, err) + } + flags = append(flags, "--values", valfile) + } + + if len(errs) == 0 { + if err := helm.TemplateRelease(temp[release.Name], flags...); err != nil { + errs = append(errs, err) + } + } } - close(jobQueue) - wgRelease.Wait() + if len(errs) != 0 { + return errs + } - close(errQueue) - wgError.Wait() + return nil +} + +// LintReleases wrapper for executing helm lint on the releases +func (state *HelmState) LintReleases(helm helmexec.Interface, additionalValues []string, args []string) []error { + errs := []error{} + // Create tmp directory and bail immediately if it fails + dir, err := ioutil.TempDir("", "") + if err != nil { + errs = append(errs, err) + return errs + } + defer os.RemoveAll(dir) + + temp, err := state.downloadCharts(helm, dir) + if err != nil { + errs = append(errs, err) + return errs + } + + if len(args) > 0 { + helm.SetExtraArgs(args...) + } + + for _, release := range state.Releases { + flags, err := state.flagsForLint(helm, &release) + if err != nil { + errs = append(errs, err) + } + for _, value := range additionalValues { + valfile, err := filepath.Abs(value) + if err != nil { + errs = append(errs, err) + } + + if _, err := os.Stat(valfile); os.IsNotExist(err) { + errs = append(errs, err) + } + flags = append(flags, "--values", valfile) + } + + if len(errs) == 0 { + if err := helm.Lint(temp[release.Name], flags...); err != nil { + errs = append(errs, err) + } + } + } if len(errs) != 0 { return errs @@ -459,107 +490,6 @@ func (state *HelmState) DiffReleases(helm helmexec.Interface, additionalValues [ return nil } -// LintReleases wrapper for executing helm lint on the releases -func (state *HelmState) LintReleases(helm helmexec.Interface, additionalValues []string, workerLimit int) []error { - var wgRelease sync.WaitGroup - var wgError sync.WaitGroup - errs := []error{} - jobQueue := make(chan *ReleaseSpec, len(state.Releases)) - errQueue := make(chan error) - - if workerLimit < 1 { - workerLimit = len(state.Releases) - } - - wgRelease.Add(len(state.Releases)) - - // Create tmp directory and bail immediately if it fails - dir, err := ioutil.TempDir("", "") - if err != nil { - errs = append(errs, err) - return errs - } - defer os.RemoveAll(dir) - - for w := 1; w <= workerLimit; w++ { - go func() { - for release := range jobQueue { - errs := []error{} - flags, err := state.flagsForLint(helm, release) - if err != nil { - errs = append(errs, err) - } - for _, value := range additionalValues { - valfile, err := filepath.Abs(value) - if err != nil { - errs = append(errs, err) - } - - if _, err := os.Stat(valfile); os.IsNotExist(err) { - errs = append(errs, err) - } - flags = append(flags, "--values", valfile) - } - - chartPath := "" - if pathExists(normalizeChart(state.basePath, release.Chart)) { - chartPath = normalizeChart(state.basePath, release.Chart) - } else { - fetchFlags := []string{} - if release.Version != "" { - chartPath = path.Join(dir, release.Name, release.Version, release.Chart) - fetchFlags = append(fetchFlags, "--version", release.Version) - } else { - chartPath = path.Join(dir, release.Name, "latest", release.Chart) - } - - // only fetch chart if it is not already fetched - if _, err := os.Stat(chartPath); os.IsNotExist(err) { - fetchFlags = append(fetchFlags, "--untar", "--untardir", chartPath) - if err := helm.Fetch(release.Chart, fetchFlags...); err != nil { - errs = append(errs, err) - } - } - chartPath = path.Join(chartPath, chartNameWithoutRepository(release.Chart)) - } - - if len(errs) == 0 { - if err := helm.Lint(chartPath, flags...); err != nil { - errs = append(errs, err) - } - } - for _, err := range errs { - errQueue <- err - } - wgRelease.Done() - } - }() - } - wgError.Add(1) - go func() { - for err := range errQueue { - errs = append(errs, err) - } - wgError.Done() - }() - - for i := 0; i < len(state.Releases); i++ { - jobQueue <- &state.Releases[i] - } - - close(jobQueue) - wgRelease.Wait() - - close(errQueue) - wgError.Wait() - - if len(errs) != 0 { - return errs - } - - return nil -} - func (state *HelmState) ReleaseStatuses(helm helmexec.Interface, workerLimit int) []error { var errs []error jobQueue := make(chan ReleaseSpec)