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"
) )
@ -52,15 +53,16 @@ of the README file
` `
type inspectCmd struct { type inspectCmd struct {
chartpath string chartpath string
output string output string
verify bool verify bool
keyring string withSubcharts bool
out io.Writer keyring string
version string out io.Writer
repoURL string version string
username string repoURL string
password string username string
password string
certFile string certFile string
keyFile string keyFile 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,7 +244,17 @@ func (i *inspectCmd) run() error {
if i.output == all { if i.output == all {
fmt.Fprintln(i.out, "---") fmt.Fprintln(i.out, "---")
} }
fmt.Fprintln(i.out, chrt.Values.Raw) 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)
}
} }
if i.output == readmeOnly || i.output == all { if i.output == readmeOnly || 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