diff --git a/cmd/helm/dependency.go b/cmd/helm/dependency.go index 2cc4c5045..afdc1afc4 100644 --- a/cmd/helm/dependency.go +++ b/cmd/helm/dependency.go @@ -100,7 +100,7 @@ func newDependencyCmd(out io.Writer) *cobra.Command { func newDependencyListCmd(out io.Writer) *cobra.Command { client := action.NewDependency() - + var transitive *bool cmd := &cobra.Command{ Use: "list CHART", Aliases: []string{"ls"}, @@ -112,8 +112,11 @@ func newDependencyListCmd(out io.Writer) *cobra.Command { if len(args) > 0 { chartpath = filepath.Clean(args[0]) } - return client.List(chartpath, out) + return client.List(chartpath, out, *transitive) }, } + + transitive = cmd.Flags().Bool("transitive", false, "show transitive dependencies (dependencies of dependencies)") + return cmd } diff --git a/pkg/action/dependency.go b/pkg/action/dependency.go index 4a4b8ebad..d87a467d1 100644 --- a/pkg/action/dependency.go +++ b/pkg/action/dependency.go @@ -44,7 +44,7 @@ func NewDependency() *Dependency { } // List executes 'helm dependency list'. -func (d *Dependency) List(chartpath string, out io.Writer) error { +func (d *Dependency) List(chartpath string, out io.Writer, transitive bool) error { c, err := loader.Load(chartpath) if err != nil { return err @@ -55,7 +55,17 @@ func (d *Dependency) List(chartpath string, out io.Writer) error { return nil } - d.printDependencies(chartpath, out, c) + table := uitable.New() + table.MaxColWidth = 80 + table.AddRow("NAME", "VERSION", "REPOSITORY", "STATUS") + + d.printDependencies(table, chartpath, c) + + if transitive { + d.printTransitiveDependencies(table, c) + } + + fmt.Fprintln(out, table) fmt.Fprintln(out) d.printMissing(chartpath, out, c.Metadata.Dependencies) return nil @@ -138,14 +148,23 @@ func (d *Dependency) dependencyStatus(chartpath string, dep *chart.Dependency, p } // printDependencies prints all of the dependencies in the yaml file. -func (d *Dependency) printDependencies(chartpath string, out io.Writer, c *chart.Chart) { - table := uitable.New() - table.MaxColWidth = 80 - table.AddRow("NAME", "VERSION", "REPOSITORY", "STATUS") +func (d *Dependency) printDependencies(table *uitable.Table, chartpath string, c *chart.Chart) { for _, row := range c.Metadata.Dependencies { table.AddRow(row.Name, row.Version, row.Repository, d.dependencyStatus(chartpath, row, c)) } - fmt.Fprintln(out, table) +} + +// printTransitiveDependencies prints all the transitive dependencies in a given chart. +func (d *Dependency) printTransitiveDependencies(table *uitable.Table, c *chart.Chart) { + for _, sc := range c.Dependencies() { + if sc.Lock != nil { + for _, td := range sc.Lock.Dependencies { + table.AddRow(td.Name, td.Version, td.Repository, "transitive") + } + } + + d.printTransitiveDependencies(table, sc) + } } // printMissing prints warnings about charts that are present on disk, but are diff --git a/pkg/action/dependency_test.go b/pkg/action/dependency_test.go index 158acbfb9..fe0e571d2 100644 --- a/pkg/action/dependency_test.go +++ b/pkg/action/dependency_test.go @@ -25,8 +25,9 @@ import ( func TestList(t *testing.T) { for _, tcase := range []struct { - chart string - golden string + chart string + golden string + transitive bool }{ { chart: "testdata/charts/chart-with-compressed-dependencies", @@ -48,9 +49,14 @@ func TestList(t *testing.T) { chart: "testdata/charts/chart-missing-deps", golden: "output/missing-deps.txt", }, + { + chart: "testdata/charts/transitive-dependencies", + golden: "output/transitive-dependencies.txt", + transitive: true, + }, } { buf := bytes.Buffer{} - if err := NewDependency().List(tcase.chart, &buf); err != nil { + if err := NewDependency().List(tcase.chart, &buf, tcase.transitive); err != nil { t.Fatal(err) } test.AssertGoldenBytes(t, buf.Bytes(), tcase.golden) diff --git a/pkg/action/testdata/charts/transitive-dependencies/Chart.yaml b/pkg/action/testdata/charts/transitive-dependencies/Chart.yaml new file mode 100644 index 000000000..1ea0fe624 --- /dev/null +++ b/pkg/action/testdata/charts/transitive-dependencies/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart +name: my-chart +version: 0.1.0 +dependencies: +- name: wordpress + version: 5.0.2 + repository: https://kubernetes-charts.storage.googleapis.com diff --git a/pkg/action/testdata/charts/transitive-dependencies/charts/wordpress-5.0.2.tgz b/pkg/action/testdata/charts/transitive-dependencies/charts/wordpress-5.0.2.tgz new file mode 100644 index 000000000..6ec987053 Binary files /dev/null and b/pkg/action/testdata/charts/transitive-dependencies/charts/wordpress-5.0.2.tgz differ diff --git a/pkg/action/testdata/charts/transitive-dependencies/requirements.lock b/pkg/action/testdata/charts/transitive-dependencies/requirements.lock new file mode 100644 index 000000000..734e0e5bc --- /dev/null +++ b/pkg/action/testdata/charts/transitive-dependencies/requirements.lock @@ -0,0 +1,6 @@ +dependencies: +- name: wordpress + repository: https://kubernetes-charts.storage.googleapis.com + version: 5.0.2 +digest: sha256:47874170647e0698d5fc4cb23bbc97e3e2bf80d841cffa0a2fb2688aa4a35372 +generated: "2020-05-21T22:52:53.59605223+03:00" diff --git a/pkg/action/testdata/output/transitive-dependencies.txt b/pkg/action/testdata/output/transitive-dependencies.txt new file mode 100644 index 000000000..cf39cf1c6 --- /dev/null +++ b/pkg/action/testdata/output/transitive-dependencies.txt @@ -0,0 +1,4 @@ +NAME VERSION REPOSITORY STATUS +wordpress 5.0.2 https://kubernetes-charts.storage.googleapis.com ok +mariadb 5.2.5 https://kubernetes-charts.storage.googleapis.com/ transitive +