feat(helm): add --with-subcharts option for "helm inspect values"

Running helm inspect values [CHART] outputs the contents of a chart's values.yaml verbatim. This is often used to determine which configuration options a chart exposes. However, it does not provide the contents of values.yaml files of potential subcharts bundled in the charts subdirectory. The new command-line option --with-subcharts causes Helm to merge the values.yaml files of a chart and all its subcharts and output the result.

Closes #3926
pull/3955/head
Andreas Bieber 8 years ago
parent 9e9dd90e8d
commit 18a57ce30f

@ -26,6 +26,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/kubernetes/pkg/util/slice" "k8s.io/kubernetes/pkg/util/slice"
) )
@ -55,6 +56,7 @@ type inspectCmd struct {
chartpath string chartpath string
output string output string
verify bool verify bool
withSubcharts bool
keyring string keyring string
out io.Writer out io.Writer
version string version string
@ -164,6 +166,10 @@ func newInspectCmd(out io.Writer) *cobra.Command {
subCmd.Flags().BoolVar(&insp.verify, vflag, false, vdesc) subCmd.Flags().BoolVar(&insp.verify, vflag, false, vdesc)
} }
withSubcharts := "with-subcharts"
withSubchartsDescr := "recursively merges values.yaml files of this chart and all of its subcharts"
valuesSubCmd.Flags().BoolVar(&insp.withSubcharts, withSubcharts, false, withSubchartsDescr)
kflag := "keyring" kflag := "keyring"
kdesc := "path to the keyring containing public verification keys" kdesc := "path to the keyring containing public verification keys"
kdefault := defaultKeyring() kdefault := defaultKeyring()
@ -238,8 +244,18 @@ func (i *inspectCmd) run() error {
if i.output == all { if i.output == all {
fmt.Fprintln(i.out, "---") fmt.Fprintln(i.out, "---")
} }
if i.withSubcharts {
mergedOutput, err := coalesceValues(chrt)
if err != nil {
return err
}
fmt.Fprintln(i.out, mergedOutput)
} else {
fmt.Fprintln(i.out, chrt.Values.Raw) fmt.Fprintln(i.out, chrt.Values.Raw)
} }
}
if i.output == readmeOnly || i.output == all { if i.output == readmeOnly || i.output == all {
if i.output == all { if i.output == all {
@ -254,6 +270,58 @@ func (i *inspectCmd) run() error {
return nil return nil
} }
func coalesceValues(chrt *chart.Chart) (string, error) {
mainVal, err := chartutil.CoalesceValues(chrt, chrt.Values)
if err != nil {
return "", err
}
mainValMap := mainVal.AsMap()
coalescedGlobals := map[string]interface{}{}
coalesceGlobals(&mainVal, &coalescedGlobals)
if len(coalescedGlobals) > 0 {
mainValMap[chartutil.GlobalKey] = &coalescedGlobals
}
s, err := chartutil.Values(mainValMap).YAML()
return s, err
}
func coalesceGlobals(src *chartutil.Values, destGlob *map[string]interface{}) {
for key, val := range *src {
if key == chartutil.GlobalKey || val == nil {
continue
}
if subVal, ok := val.(map[string]interface{}); ok {
coalesceGlobalsRecursive(&subVal, destGlob)
}
}
}
func coalesceGlobalsRecursive(src *map[string]interface{}, destGlob *map[string]interface{}) {
for key, val := range *src {
if key == chartutil.GlobalKey && val != nil {
valMap := val.(map[string]interface{})
for globKey, globVal := range valMap {
if _, exists := (*destGlob)[globKey]; !exists {
(*destGlob)[globKey] = globVal
}
}
delete(*src, chartutil.GlobalKey)
continue
}
if valMap, ok := val.(map[string]interface{}); ok {
if _, globExists := valMap[chartutil.GlobalKey]; globExists {
coalesceGlobalsRecursive(&valMap, destGlob)
}
}
}
}
func findReadme(files []*any.Any) (file *any.Any) { func findReadme(files []*any.Any) (file *any.Any) {
for _, file := range files { for _, file := range files {
if slice.ContainsString(readmeFileNames, strings.ToLower(file.TypeUrl), nil) { if slice.ContainsString(readmeFileNames, strings.ToLower(file.TypeUrl), nil) {

@ -78,3 +78,20 @@ func TestInspect(t *testing.T) {
t.Errorf("expected empty values buffer, got %q", b.String()) t.Errorf("expected empty values buffer, got %q", b.String())
} }
} }
func TestInspectWithSubCharts(t *testing.T) {
expected, _ := ioutil.ReadFile("testdata/testcharts/chart-globals-inspect-values-with-subcharts/expected.yml")
b := bytes.NewBuffer(nil)
insp := &inspectCmd{
chartpath: "testdata/testcharts/chart-globals-inspect-values-with-subcharts",
output: all,
out: b,
withSubcharts: true,
}
insp.run()
if b.String() != string(expected) {
t.Fatalf("Expected:\n%s \nbut got:\n%s", expected, b.String())
}
}

@ -0,0 +1,3 @@
description: A Helm chart for Kubernetes
name: chart-globals-inspect-values-with-subcharts
version: 0.1.0

@ -0,0 +1,3 @@
description: A Helm chart for Kubernetes
name: chart-globals-inspect-values-with-subcharts-subchart1
version: 0.1.0

@ -0,0 +1,3 @@
description: A Helm chart for Kubernetes
name: chart-globals-inspect-values-with-subcharts-subchart1-subsubchart
version: 0.1.0

@ -0,0 +1,5 @@
global:
key1: from subsubchart
key5: from subsubchart
subsubchartKey: 'subsubchart'

@ -0,0 +1,7 @@
global:
key3: from subchart 1
key4:
key41: from subchart 1
subchart1Key: 'subchart1'
mainchartKey: from subchart 1

@ -0,0 +1,3 @@
description: A Helm chart for Kubernetes
name: chart-globals-inspect-values-with-subcharts-subchart2
version: 0.1.0

@ -0,0 +1,6 @@
global:
key1: from subchart 2
key6:
key61: from subchart 2
subchart2Key: 'subchart2'

@ -0,0 +1,25 @@
description: A Helm chart for Kubernetes
name: chart-globals-inspect-values-with-subcharts
version: 0.1.0
---
chart-globals-inspect-values-with-subcharts-subchart1:
chart-globals-inspect-values-with-subcharts-subchart1-subsubchart:
subsubchartKey: subsubchart
mainchartKey: from subchart 1
subchart1Key: subchart1
chart-globals-inspect-values-with-subcharts-subchart2:
subchart2Key: subchart2
global:
key1: from mainchart
key2:
key21: from mainchart
key3: from subchart 1
key4:
key41: from subchart 1
key5: from subsubchart
key6:
key61: from subchart 2
mainchartKey: foo
---

@ -0,0 +1,6 @@
global:
key1: from mainchart
key2:
key21: from mainchart
mainchartKey: 'foo'

@ -26,6 +26,7 @@ helm inspect values [CHART]
--username string chart repository username where to locate the requested chart --username string chart repository username where to locate the requested chart
--verify verify the provenance data for this chart --verify verify the provenance data for this chart
--version string version of the chart. By default, the newest chart is shown --version string version of the chart. By default, the newest chart is shown
--with-subcharts recursively merges values.yaml files of this chart and all of its subcharts
``` ```
### Options inherited from parent commands ### Options inherited from parent commands
@ -42,4 +43,4 @@ helm inspect values [CHART]
### SEE ALSO ### SEE ALSO
* [helm inspect](helm_inspect.md) - inspect a chart * [helm inspect](helm_inspect.md) - inspect a chart
###### Auto generated by spf13/cobra on 8-Mar-2018 ###### Auto generated by spf13/cobra on 24-Apr-2018

Loading…
Cancel
Save