diff --git a/cmd/list.go b/cmd/list.go index e16a8695..201da3e5 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -32,6 +32,7 @@ func NewListCmd(globalCfg *config.GlobalImpl) *cobra.Command { f := cmd.Flags() f.BoolVar(&listOptions.KeepTempDir, "keep-temp-dir", false, "Keep temporary directory") + f.BoolVar(&listOptions.WithPreparedCharts, "with-prepared-charts", true, "prepare charts when listing releases") f.StringVar(&listOptions.Output, "output", "", "output releases list as a json string") return cmd diff --git a/pkg/app/app.go b/pkg/app/app.go index 04f028cd..7070c2f9 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -547,44 +547,30 @@ func (a *App) ListReleases(c ListConfigProvider) error { var releases []*HelmRelease err := a.ForEachState(func(run *Run) (_ bool, errs []error) { - for _, r := range run.state.Releases { - labels := "" - if r.Labels == nil { - r.Labels = map[string]string{} - } - for k, v := range run.state.CommonLabels { - r.Labels[k] = v - } + var stateReleases []*HelmRelease + var err error - var keys []string - for k := range r.Labels { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, k := range keys { - v := r.Labels[k] - labels = fmt.Sprintf("%s,%s:%s", labels, k, v) - } - labels = strings.Trim(labels, ",") - - enabled, err := state.ConditionEnabled(r, run.state.Values()) - if err != nil { - panic(err) - } - - installed := r.Installed == nil || *r.Installed - releases = append(releases, &HelmRelease{ - Name: r.Name, - Namespace: r.Namespace, - Installed: installed, - Enabled: enabled, - Labels: labels, - Chart: r.Chart, - Version: r.Version, + if c.WithPreparedCharts() { + err = run.withPreparedCharts("list", state.ChartPrepareOptions{ + SkipRepos: true, + SkipDeps: true, + }, func() { + rel, err := a.list(run) + if err != nil { + panic(err) + } + stateReleases = rel }) + } else { + stateReleases, err = a.list(run) } + if err != nil { + errs = append(errs, err) + } + + releases = append(releases, stateReleases...) + return }, false, SetFilter(true)) @@ -601,6 +587,50 @@ func (a *App) ListReleases(c ListConfigProvider) error { return err } +func (a *App) list(run *Run) ([]*HelmRelease, error) { + var releases []*HelmRelease + + for _, r := range run.state.Releases { + labels := "" + if r.Labels == nil { + r.Labels = map[string]string{} + } + for k, v := range run.state.CommonLabels { + r.Labels[k] = v + } + + var keys []string + for k := range r.Labels { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + v := r.Labels[k] + labels = fmt.Sprintf("%s,%s:%s", labels, k, v) + } + labels = strings.Trim(labels, ",") + + enabled, err := state.ConditionEnabled(r, run.state.Values()) + if err != nil { + return nil, err + } + + installed := r.Installed == nil || *r.Installed + releases = append(releases, &HelmRelease{ + Name: r.Name, + Namespace: r.Namespace, + Installed: installed, + Enabled: enabled, + Labels: labels, + Chart: r.Chart, + Version: r.Version, + }) + } + + return releases, nil +} + func (a *App) within(dir string, do func() error) error { if dir == "." { return do() diff --git a/pkg/app/app_list_test.go b/pkg/app/app_list_test.go index 0ec63bba..4ed6c603 100644 --- a/pkg/app/app_list_test.go +++ b/pkg/app/app_list_test.go @@ -17,7 +17,7 @@ import ( "github.com/helmfile/helmfile/pkg/testutil" ) -func TestListWithEnvironment(t *testing.T) { +func testListWithConfig(t *testing.T, cfg configImpl) { type testcase struct { environment string ns string @@ -26,7 +26,7 @@ func TestListWithEnvironment(t *testing.T) { expected string } - check := func(t *testing.T, tc testcase) { + check := func(t *testing.T, tc testcase, cfg configImpl) { t.Helper() bs := &bytes.Buffer{} @@ -164,7 +164,7 @@ releases: var listErr error out := testutil.CaptureStdout(func() { - listErr = app.ListReleases(configImpl{}) + listErr = app.ListReleases(cfg) }) var gotErr string @@ -197,14 +197,14 @@ cache my-app true true app:test bitnami/redis database my-app true true bitnami/postgres 11.6.22 global kube-system true true incubator/raw `, - }) + }, cfg) }) t.Run("fail on unknown environment", func(t *testing.T) { check(t, testcase{ environment: "staging", error: `err: no releases found that matches specified selector() and environment(staging), in any helmfile`, - }) + }, cfg) }) t.Run("list releases matching selector and environment", func(t *testing.T) { @@ -215,7 +215,7 @@ global kube-system true true incubator/raw external-secrets default true true app:test,chart:raw,name:external-secrets,namespace:default incubator/raw my-release default true true app:test,chart:raw,name:my-release,namespace:default incubator/raw `, - }) + }, cfg) }) t.Run("filters releases for environment used in one file only", func(t *testing.T) { @@ -225,7 +225,7 @@ my-release default true true app:test,chart:raw,name:my-release, cache my-app true true app:test bitnami/redis 17.0.7 database my-app true true bitnami/postgres 11.6.22 `, - }) + }, cfg) }) t.Run("filters releases for environment used in multiple files", func(t *testing.T) { @@ -243,6 +243,15 @@ test3 true true incubator/raw cache my-app true true app:test bitnami/redis 17.0.7 database my-app true true bitnami/postgres 11.6.22 `, - }) + }, cfg) + }) +} + +func TestListWithEnvironment(t *testing.T) { + t.Run("with prepared charts", func(t *testing.T) { + testListWithConfig(t, configImpl{withPreparedCharts: true}) + }) + t.Run("without prepared charts", func(t *testing.T) { + testListWithConfig(t, configImpl{withPreparedCharts: false}) }) } diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 3bd91916..d2ed95ec 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -2220,6 +2220,7 @@ type configImpl struct { skipNeeds bool includeNeeds bool includeTransitiveNeeds bool + withPreparedCharts bool } func (c configImpl) Selectors() []string { @@ -2294,6 +2295,10 @@ func (c configImpl) Output() string { return c.output } +func (c configImpl) WithPreparedCharts() bool { + return c.withPreparedCharts +} + type applyConfig struct { args string values []string diff --git a/pkg/app/config.go b/pkg/app/config.go index 30e2053e..1e268508 100644 --- a/pkg/app/config.go +++ b/pkg/app/config.go @@ -236,6 +236,7 @@ type interactive interface { type ListConfigProvider interface { Output() string + WithPreparedCharts() bool } type CacheConfigProvider interface{} diff --git a/pkg/config/list.go b/pkg/config/list.go index 1529a742..64645847 100644 --- a/pkg/config/list.go +++ b/pkg/config/list.go @@ -6,6 +6,8 @@ type ListOptions struct { Output string // KeepTempDir is the keep temp dir flag KeepTempDir bool + // WithPreparedCharts makes list call `withPreparedCharts` when listing + WithPreparedCharts bool } // NewListOptions creates a new Apply @@ -36,3 +38,8 @@ func (c *ListImpl) Args() string { func (c *ListImpl) Output() string { return c.ListOptions.Output } + +// WithPreparedCharts returns withPreparedCharts flag +func (c *ListImpl) WithPreparedCharts() bool { + return c.ListOptions.WithPreparedCharts +}