feat(list-dependencies): Implement -with-dependencies args to list command (#8081)

Signed-off-by: Ilan Zerath <ilan.prims@gmail.com>
pull/8169/head
Ilan Zerath 5 years ago
parent a9709334f5
commit 7ff393d4d7

@ -28,6 +28,7 @@ import (
"helm.sh/helm/v3/cmd/helm/require" "helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/internal/completion" "helm.sh/helm/v3/internal/completion"
"helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/cli/output" "helm.sh/helm/v3/pkg/cli/output"
"helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/release"
) )
@ -61,6 +62,7 @@ flag with the '--offset' flag allows you to page through results.
func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
client := action.NewList(cfg) client := action.NewList(cfg)
var outfmt output.Format var outfmt output.Format
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -75,14 +77,22 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return err return err
} }
} }
client.SetStateMask() client.SetStateMask()
results, err := client.Run() results, err := client.Run()
if err != nil { if err != nil {
return err return err
} }
if client.Short { if client.WithDependencies {
return outfmt.Write(out, newReleaseListWriter(results, true))
}
if !client.Short {
return outfmt.Write(out, newReleaseListWriter(results, false))
}
names := make([]string, 0) names := make([]string, 0)
for _, res := range results { for _, res := range results {
@ -104,11 +114,8 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
} }
return nil return nil
default: default:
return outfmt.Write(out, newReleaseListWriter(results)) return outfmt.Write(out, newReleaseListWriter(results, false))
}
} }
return outfmt.Write(out, newReleaseListWriter(results))
}, },
} }
@ -117,6 +124,7 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date") f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date")
f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order") f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order")
f.BoolVarP(&client.All, "all", "a", false, "show all releases without any filter applied") f.BoolVarP(&client.All, "all", "a", false, "show all releases without any filter applied")
f.BoolVarP(&client.WithDependencies, "with-dependencies", "p", false, "show all releases without any filter applied and dependencies")
f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases (if 'helm uninstall --keep-history' was used)") f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases (if 'helm uninstall --keep-history' was used)")
f.BoolVar(&client.Superseded, "superseded", false, "show superseded releases") f.BoolVar(&client.Superseded, "superseded", false, "show superseded releases")
f.BoolVar(&client.Uninstalling, "uninstalling", false, "show releases that are currently being uninstalled") f.BoolVar(&client.Uninstalling, "uninstalling", false, "show releases that are currently being uninstalled")
@ -132,6 +140,13 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
return cmd return cmd
} }
type releaseElementChart struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
Repository string `json:"repository"`
Enabled bool `json:"enabled,omitempty"`
}
type releaseElement struct { type releaseElement struct {
Name string `json:"name"` Name string `json:"name"`
Namespace string `json:"namespace"` Namespace string `json:"namespace"`
@ -140,16 +155,24 @@ type releaseElement struct {
Status string `json:"status"` Status string `json:"status"`
Chart string `json:"chart"` Chart string `json:"chart"`
AppVersion string `json:"app_version"` AppVersion string `json:"app_version"`
Dependencies []releaseElementChart `json:"dependencies"`
} }
type releaseListWriter struct { type releaseListWriter struct {
releases []releaseElement releases []releaseElement
} }
func newReleaseListWriter(releases []*release.Release) *releaseListWriter { func newReleaseListWriter(releases []*release.Release, withDependencies bool) *releaseListWriter {
// Initialize the array so no results returns an empty array instead of null // Initialize the array so no results returns an empty array instead of null
elements := make([]releaseElement, 0, len(releases)) elements := make([]releaseElement, 0, len(releases))
for _, r := range releases { for _, r := range releases {
dependencies := []releaseElementChart{}
if withDependencies {
dependencies = handleChartDependencies(r.Chart.Metadata.Dependencies)
}
element := releaseElement{ element := releaseElement{
Name: r.Name, Name: r.Name,
Namespace: r.Namespace, Namespace: r.Namespace,
@ -157,22 +180,38 @@ func newReleaseListWriter(releases []*release.Release) *releaseListWriter {
Status: r.Info.Status.String(), Status: r.Info.Status.String(),
Chart: fmt.Sprintf("%s-%s", r.Chart.Metadata.Name, r.Chart.Metadata.Version), Chart: fmt.Sprintf("%s-%s", r.Chart.Metadata.Name, r.Chart.Metadata.Version),
AppVersion: r.Chart.Metadata.AppVersion, AppVersion: r.Chart.Metadata.AppVersion,
Dependencies: dependencies,
} }
t := "-" t := "-"
if tspb := r.Info.LastDeployed; !tspb.IsZero() { if tspb := r.Info.LastDeployed; !tspb.IsZero() {
t = tspb.String() t = tspb.String()
} }
element.Updated = t element.Updated = t
elements = append(elements, element) elements = append(elements, element)
} }
return &releaseListWriter{elements} return &releaseListWriter{elements}
} }
func (r *releaseListWriter) WriteTable(out io.Writer) error { func (r *releaseListWriter) WriteTable(out io.Writer) error {
table := uitable.New() table := uitable.New()
tableDependencies := uitable.New()
table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION") table.AddRow("NAME", "NAMESPACE", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION")
for _, r := range r.releases { for _, r := range r.releases {
table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion) table.AddRow(r.Name, r.Namespace, r.Revision, r.Updated, r.Status, r.Chart, r.AppVersion)
if len(r.Dependencies) < 1 {
continue
}
table.Wrap = true
buildDependenciesTable(tableDependencies, r.Dependencies)
table.AddRow(tableDependencies)
} }
return output.EncodeTable(out, table) return output.EncodeTable(out, table)
} }
@ -207,3 +246,35 @@ func compListReleases(toComplete string, cfg *action.Configuration) ([]string, c
return choices, completion.BashCompDirectiveNoFileComp return choices, completion.BashCompDirectiveNoFileComp
} }
func buildDependenciesTable(table *uitable.Table, dependencies []releaseElementChart) {
table.AddRow("======== DEPENDENCIES ========")
table.AddRow("NAME", "Version", "Repository", "Enabled")
for _, d := range dependencies {
table.AddRow(d.Name, d.Version, d.Repository, d.Enabled)
}
table.AddRow("================")
}
func handleChartDependencies(chartDependencies []*chart.Dependency) []releaseElementChart {
if len(chartDependencies) < 1 {
return []releaseElementChart{}
}
dependencies := []releaseElementChart{}
for _, d := range chartDependencies {
chart := releaseElementChart{
Name: d.Name,
Version: d.Version,
Repository: d.Repository,
Enabled: d.Enabled,
}
dependencies = append(dependencies, chart)
}
return dependencies
}

@ -40,6 +40,23 @@ func TestListCmd(t *testing.T) {
}, },
} }
chartWithDependencies := &chart.Chart{
Metadata: &chart.Metadata{
Name: "prims47",
Version: "4.7.7",
AppVersion: "0.0.1",
Home: "https://charts.com/prims47",
Dependencies: []*chart.Dependency{
{
Name: "benArfa",
Version: "4.7.7",
Repository: "https://helm.com/prims47",
Enabled: true,
},
},
},
}
releaseFixture := []*release.Release{ releaseFixture := []*release.Release{
{ {
Name: "starlord", Name: "starlord",
@ -61,6 +78,16 @@ func TestListCmd(t *testing.T) {
}, },
Chart: chartInfo, Chart: chartInfo,
}, },
{
Name: "fuegoPepito",
Version: 1,
Namespace: defaultNamespace,
Info: &release.Info{
LastDeployed: timestamp1,
Status: release.StatusPendingInstall,
},
Chart: chartWithDependencies,
},
{ {
Name: "groot", Name: "groot",
Version: 1, Version: 1,
@ -153,6 +180,11 @@ func TestListCmd(t *testing.T) {
cmd: "list --all", cmd: "list --all",
golden: "output/list-all.txt", golden: "output/list-all.txt",
rels: releaseFixture, rels: releaseFixture,
}, {
name: "list all releases with dependencies",
cmd: "list --with-dependencies",
golden: "output/list-with-dependencies.txt",
rels: releaseFixture,
}, { }, {
name: "list releases sorted by release date", name: "list releases sorted by release date",
cmd: "list --date", cmd: "list --date",
@ -208,6 +240,11 @@ func TestListCmd(t *testing.T) {
cmd: "list --short --output json", cmd: "list --short --output json",
golden: "output/list-short-json.txt", golden: "output/list-short-json.txt",
rels: releaseFixture, rels: releaseFixture,
}, {
name: "list releases in short output format",
cmd: "list --short --output table",
golden: "output/list-short-table.txt",
rels: releaseFixture,
}, { }, {
name: "list superseded releases", name: "list superseded releases",
cmd: "list --superseded", cmd: "list --superseded",

@ -1,5 +1,6 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
drax default 1 2016-01-16 00:00:01 +0000 UTC uninstalling chickadee-1.0.0 0.0.1 drax default 1 2016-01-16 00:00:01 +0000 UTC uninstalling chickadee-1.0.0 0.0.1
fuegoPepito default 1 2016-01-16 00:00:01 +0000 UTC pending-install prims47-4.7.7 0.0.1
gamora default 1 2016-01-16 00:00:01 +0000 UTC superseded chickadee-1.0.0 0.0.1 gamora default 1 2016-01-16 00:00:01 +0000 UTC superseded chickadee-1.0.0 0.0.1
groot default 1 2016-01-16 00:00:01 +0000 UTC uninstalled chickadee-1.0.0 0.0.1 groot default 1 2016-01-16 00:00:01 +0000 UTC uninstalled chickadee-1.0.0 0.0.1
hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0 0.0.1 hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0 0.0.1

@ -1,2 +1,3 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
fuegoPepito default 1 2016-01-16 00:00:01 +0000 UTC pending-install prims47-4.7.7 0.0.1
thanos default 1 2016-01-16 00:00:01 +0000 UTC pending-install chickadee-1.0.0 0.0.1 thanos default 1 2016-01-16 00:00:01 +0000 UTC pending-install chickadee-1.0.0 0.0.1

@ -0,0 +1,4 @@
hummingbird
iguana
rocket
starlord

@ -0,0 +1,14 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
drax default 1 2016-01-16 00:00:01 +0000 UTC uninstalling chickadee-1.0.0 0.0.1
fuegoPepito default 1 2016-01-16 00:00:01 +0000 UTC pending-install prims47-4.7.7 0.0.1
======== DEPENDENCIES ========
NAME Version Repository Enabled
benArfa 4.7.7 https://helm.com/prims47 true
================
gamora default 1 2016-01-16 00:00:01 +0000 UTC superseded chickadee-1.0.0 0.0.1
groot default 1 2016-01-16 00:00:01 +0000 UTC uninstalled chickadee-1.0.0 0.0.1
hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0 0.0.1
iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0 0.0.1
rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0 0.0.1
starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0 0.0.1
thanos default 1 2016-01-16 00:00:01 +0000 UTC pending-install chickadee-1.0.0 0.0.1
Loading…
Cancel
Save