Correct enabled property in helmfile list (#1921)

Use the value of the `condition` field instead of the `installed` field of a release in the `enabled` column of helmfile list.
The value of the `installed` field is shown in a new `installed` column.

Fixes #1920

Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
This commit is contained in:
Christoph Petrausch 2022-01-10 09:24:07 +01:00 committed by GitHub
parent 753de35ee0
commit 346e318fd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 27 deletions

View File

@ -61,6 +61,7 @@ type HelmRelease struct {
Name string `json:"name"` Name string `json:"name"`
Namespace string `json:"namespace"` Namespace string `json:"namespace"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Installed bool `json:"installed"`
Labels string `json:"labels"` Labels string `json:"labels"`
Chart string `json:"chart"` Chart string `json:"chart"`
Version string `json:"version"` Version string `json:"version"`
@ -575,11 +576,17 @@ func (a *App) ListReleases(c ListConfigProvider) error {
} }
labels = strings.Trim(labels, ",") labels = strings.Trim(labels, ",")
enabled, err := state.ConditionEnabled(r, run.state.Values())
if err != nil {
panic(err)
}
installed := r.Installed == nil || *r.Installed installed := r.Installed == nil || *r.Installed
releases = append(releases, &HelmRelease{ releases = append(releases, &HelmRelease{
Name: r.Name, Name: r.Name,
Namespace: r.Namespace, Namespace: r.Namespace,
Enabled: installed, Installed: installed,
Enabled: enabled,
Labels: labels, Labels: labels,
Chart: r.Chart, Chart: r.Chart,
Version: r.Version, Version: r.Version,

View File

@ -16,15 +16,18 @@ import (
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/roboll/helmfile/pkg/remote" "github.com/roboll/helmfile/pkg/remote"
"github.com/roboll/helmfile/pkg/exectest"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
"github.com/roboll/helmfile/pkg/exectest"
"github.com/variantdev/vals"
"github.com/roboll/helmfile/pkg/helmexec" "github.com/roboll/helmfile/pkg/helmexec"
"github.com/roboll/helmfile/pkg/state" "github.com/roboll/helmfile/pkg/state"
"github.com/roboll/helmfile/pkg/testhelper" "github.com/roboll/helmfile/pkg/testhelper"
"github.com/variantdev/vals"
"go.uber.org/zap" "go.uber.org/zap"
"gotest.tools/v3/env" "gotest.tools/v3/env"
@ -4803,6 +4806,11 @@ func TestList(t *testing.T) {
"/path/to/helmfile.d/first.yaml": ` "/path/to/helmfile.d/first.yaml": `
commonLabels: commonLabels:
common: label common: label
environments:
default:
values:
- myrelease2:
enabled: false
releases: releases:
- name: myrelease1 - name: myrelease1
chart: mychart1 chart: mychart1
@ -4811,6 +4819,7 @@ releases:
id: myrelease1 id: myrelease1
- name: myrelease2 - name: myrelease2
chart: mychart1 chart: mychart1
condition: myrelease2.enabled
`, `,
"/path/to/helmfile.d/second.yaml": ` "/path/to/helmfile.d/second.yaml": `
releases: releases:
@ -4846,18 +4855,24 @@ releases:
assert.NilError(t, err) assert.NilError(t, err)
}) })
expected := `NAME NAMESPACE ENABLED LABELS CHART VERSION expected := `NAME NAMESPACE ENABLED INSTALLED LABELS CHART VERSION
myrelease1 false common:label,id:myrelease1 mychart1 myrelease1 true false common:label,id:myrelease1 mychart1
myrelease2 true common:label mychart1 myrelease2 false true common:label mychart1
myrelease3 true mychart1 myrelease3 true true mychart1
myrelease4 true id:myrelease1 mychart1 myrelease4 true true id:myrelease1 mychart1
` `
assert.Equal(t, expected, out) assert.Equal(t, expected, out)
} }
func TestListWithJsonOutput(t *testing.T) { func TestListWithJsonOutput(t *testing.T) {
files := map[string]string{ files := map[string]string{
"/path/to/helmfile.d/first.yaml": ` "/path/to/helmfile.d/first.yaml": `
environments:
default:
values:
- myrelease2:
enabled: false
releases: releases:
- name: myrelease1 - name: myrelease1
chart: mychart1 chart: mychart1
@ -4866,6 +4881,7 @@ releases:
id: myrelease1 id: myrelease1
- name: myrelease2 - name: myrelease2
chart: mychart1 chart: mychart1
condition: myrelease2.enabled
`, `,
"/path/to/helmfile.d/second.yaml": ` "/path/to/helmfile.d/second.yaml": `
releases: releases:
@ -4903,7 +4919,7 @@ releases:
assert.NilError(t, err) assert.NilError(t, err)
}) })
expected := `[{"name":"myrelease1","namespace":"","enabled":false,"labels":"id:myrelease1","chart":"mychart1","version":""},{"name":"myrelease2","namespace":"","enabled":true,"labels":"","chart":"mychart1","version":""},{"name":"myrelease3","namespace":"","enabled":true,"labels":"","chart":"mychart1","version":""},{"name":"myrelease4","namespace":"","enabled":true,"labels":"id:myrelease1","chart":"mychart1","version":""}] expected := `[{"name":"myrelease1","namespace":"","enabled":true,"installed":false,"labels":"id:myrelease1","chart":"mychart1","version":""},{"name":"myrelease2","namespace":"","enabled":false,"installed":true,"labels":"","chart":"mychart1","version":""},{"name":"myrelease3","namespace":"","enabled":true,"installed":true,"labels":"","chart":"mychart1","version":""},{"name":"myrelease4","namespace":"","enabled":true,"installed":true,"labels":"id:myrelease1","chart":"mychart1","version":""}]
` `
assert.Equal(t, expected, out) assert.Equal(t, expected, out)
} }

View File

@ -9,10 +9,10 @@ import (
func FormatAsTable(releases []*HelmRelease) error { func FormatAsTable(releases []*HelmRelease) error {
table := uitable.New() table := uitable.New()
table.AddRow("NAME", "NAMESPACE", "ENABLED", "LABELS", "CHART", "VERSION") table.AddRow("NAME", "NAMESPACE", "ENABLED", "INSTALLED", "LABELS", "CHART", "VERSION")
for _, r := range releases { for _, r := range releases {
table.AddRow(r.Name, r.Namespace, fmt.Sprintf("%t", r.Enabled), r.Labels, r.Chart, r.Version) table.AddRow(r.Name, r.Namespace, fmt.Sprintf("%t", r.Enabled), fmt.Sprintf("%t", r.Installed), r.Labels, r.Chart, r.Version)
} }
fmt.Println(table.String()) fmt.Println(table.String())

View File

@ -2075,10 +2075,30 @@ func markExcludedReleases(releases []ReleaseSpec, selectors []string, commonLabe
} }
} }
var conditionMatch bool var conditionMatch bool
if len(r.Condition) > 0 { conditionMatch, err := ConditionEnabled(r, values)
if err != nil {
return nil, fmt.Errorf("failed to parse condition in release %s: %w", r.Name, err)
}
res := Release{
ReleaseSpec: r,
Filtered: (len(filters) > 0 && !filterMatch) || (!conditionMatch),
}
filteredReleases = append(filteredReleases, res)
}
if includeTransitiveNeeds {
unmarkNeedsAndTransitives(filteredReleases, releases)
}
return filteredReleases, nil
}
func ConditionEnabled(r ReleaseSpec, values map[string]interface{}) (bool, error) {
var conditionMatch bool
if len(r.Condition) == 0 {
return true, nil
}
conditionSplit := strings.Split(r.Condition, ".") conditionSplit := strings.Split(r.Condition, ".")
if len(conditionSplit) != 2 { if len(conditionSplit) != 2 {
return nil, fmt.Errorf("Condition value must be in the form 'foo.enabled' where 'foo' can be modified as necessary") return false, fmt.Errorf("Condition value must be in the form 'foo.enabled' where 'foo' can be modified as necessary")
} }
if v, ok := values[conditionSplit[0]]; ok { if v, ok := values[conditionSplit[0]]; ok {
if v == nil { if v == nil {
@ -2090,17 +2110,8 @@ func markExcludedReleases(releases []ReleaseSpec, selectors []string, commonLabe
} else { } else {
panic(fmt.Sprintf("environment values does not contain field '%s'", conditionSplit[0])) panic(fmt.Sprintf("environment values does not contain field '%s'", conditionSplit[0]))
} }
}
res := Release{ return conditionMatch, nil
ReleaseSpec: r,
Filtered: (len(filters) > 0 && !filterMatch) || (len(r.Condition) > 0 && !conditionMatch),
}
filteredReleases = append(filteredReleases, res)
}
if includeTransitiveNeeds {
unmarkNeedsAndTransitives(filteredReleases, releases)
}
return filteredReleases, nil
} }
func unmarkNeedsAndTransitives(filteredReleases []Release, allReleases []ReleaseSpec) { func unmarkNeedsAndTransitives(filteredReleases []Release, allReleases []ReleaseSpec) {