Unverified Commit 30f236b7 authored by Nikhil Manchanda's avatar Nikhil Manchanda Committed by GitHub

Merge pull request #3877 from chancez/enhance_helm_template_handling

Update helm template -x to support children chart manifests in more cases
parents 28d87e17 fb1dd48b
...@@ -117,31 +117,10 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { ...@@ -117,31 +117,10 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
} else { } else {
return err return err
} }
// verify specified templates exist relative to chart
rf := []string{}
var af string
var err error
if len(t.renderFiles) > 0 {
for _, f := range t.renderFiles {
if !filepath.IsAbs(f) {
af, err = filepath.Abs(filepath.Join(t.chartPath, f))
if err != nil {
return fmt.Errorf("could not resolve template path: %s", err)
}
} else {
af = f
}
rf = append(rf, af)
if _, err := os.Stat(af); err != nil {
return fmt.Errorf("could not resolve template path: %s", err)
}
}
}
// verify that output-dir exists if provided // verify that output-dir exists if provided
if t.outputDir != "" { if t.outputDir != "" {
_, err = os.Stat(t.outputDir) _, err := os.Stat(t.outputDir)
if os.IsNotExist(err) { if os.IsNotExist(err) {
return fmt.Errorf("output-dir '%s' does not exist", t.outputDir) return fmt.Errorf("output-dir '%s' does not exist", t.outputDir)
} }
...@@ -232,19 +211,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { ...@@ -232,19 +211,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
m := tiller.Manifest{Name: k, Content: v, Head: &util.SimpleHead{Kind: h}} m := tiller.Manifest{Name: k, Content: v, Head: &util.SimpleHead{Kind: h}}
listManifests = append(listManifests, m) listManifests = append(listManifests, m)
} }
in := func(needle string, haystack []string) bool {
// make needle path absolute
d := strings.Split(needle, string(os.PathSeparator))
dd := d[1:]
an := filepath.Join(t.chartPath, strings.Join(dd, string(os.PathSeparator)))
for _, h := range haystack {
if h == an {
return true
}
}
return false
}
if settings.Debug { if settings.Debug {
rel := &release.Release{ rel := &release.Release{
Name: t.releaseName, Name: t.releaseName,
...@@ -257,10 +224,45 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { ...@@ -257,10 +224,45 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error {
printRelease(os.Stdout, rel) printRelease(os.Stdout, rel)
} }
for _, m := range tiller.SortByKind(listManifests) { var manifestsToRender []tiller.Manifest
if len(t.renderFiles) > 0 && !in(m.Name, rf) {
continue // if we have a list of files to render, then check that each of the
// provided files exists in the chart.
if len(t.renderFiles) > 0 {
for _, f := range t.renderFiles {
missing := true
if !filepath.IsAbs(f) {
newF, err := filepath.Abs(filepath.Join(t.chartPath, f))
if err != nil {
return fmt.Errorf("could not turn template path %s into absolute path: %s", f, err)
}
f = newF
}
for _, manifest := range listManifests {
manifestPathSplit := strings.Split(manifest.Name, string(filepath.Separator))
// remove the chart name from the path
manifestPathSplit = manifestPathSplit[1:]
toJoin := append([]string{t.chartPath}, manifestPathSplit...)
manifestPath := filepath.Join(toJoin...)
// if the filepath provided matches a manifest path in the
// chart, render that manifest
if f == manifestPath {
manifestsToRender = append(manifestsToRender, manifest)
missing = false
}
}
if missing {
return fmt.Errorf("could not find template %s in chart", f)
}
} }
} else {
// no renderFiles provided, render all manifests in the chart
manifestsToRender = listManifests
}
for _, m := range tiller.SortByKind(manifestsToRender) {
data := m.Content data := m.Content
b := filepath.Base(m.Name) b := filepath.Base(m.Name)
if !t.showNotes && b == "NOTES.txt" { if !t.showNotes && b == "NOTES.txt" {
......
...@@ -27,10 +27,13 @@ import ( ...@@ -27,10 +27,13 @@ import (
"testing" "testing"
) )
var chartPath = "./../../pkg/chartutil/testdata/subpop/charts/subchart1" var (
subchart1ChartPath = "./../../pkg/chartutil/testdata/subpop/charts/subchart1"
frobnitzChartPath = "./../../pkg/chartutil/testdata/frobnitz"
)
func TestTemplateCmd(t *testing.T) { func TestTemplateCmd(t *testing.T) {
absChartPath, err := filepath.Abs(chartPath) subchart1AbsChartPath, err := filepath.Abs(subchart1ChartPath)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -40,74 +43,95 @@ func TestTemplateCmd(t *testing.T) { ...@@ -40,74 +43,95 @@ func TestTemplateCmd(t *testing.T) {
args []string args []string
expectKey string expectKey string
expectValue string expectValue string
expectError string
}{ }{
{ {
name: "check_name", name: "check_name",
desc: "check for a known name in chart", desc: "check for a known name in chart",
args: []string{chartPath}, args: []string{subchart1ChartPath},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "protocol: TCP\n name: nginx", expectValue: "protocol: TCP\n name: nginx",
}, },
{ {
name: "check_set_name", name: "check_set_name",
desc: "verify --set values exist", desc: "verify --set values exist",
args: []string{chartPath, "-x", "templates/service.yaml", "--set", "service.name=apache"}, args: []string{subchart1ChartPath, "-x", "templates/service.yaml", "--set", "service.name=apache"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "protocol: TCP\n name: apache", expectValue: "protocol: TCP\n name: apache",
}, },
{ {
name: "check_execute", name: "check_execute",
desc: "verify --execute single template", desc: "verify --execute single template",
args: []string{chartPath, "-x", "templates/service.yaml", "--set", "service.name=apache"}, args: []string{subchart1ChartPath, "-x", "templates/service.yaml", "--set", "service.name=apache"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "protocol: TCP\n name: apache", expectValue: "protocol: TCP\n name: apache",
}, },
{
name: "check_execute_non_existent",
desc: "verify --execute fails on a template that doesnt exist",
args: []string{subchart1ChartPath, "-x", "templates/thisdoesntexist.yaml"},
expectError: "could not find template",
},
{ {
name: "check_execute_absolute", name: "check_execute_absolute",
desc: "verify --execute single template", desc: "verify --execute single template",
args: []string{chartPath, "-x", absChartPath + "/" + "templates/service.yaml", "--set", "service.name=apache"}, args: []string{subchart1ChartPath, "-x", subchart1AbsChartPath + "/" + "templates/service.yaml", "--set", "service.name=apache"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "protocol: TCP\n name: apache", expectValue: "protocol: TCP\n name: apache",
}, },
{
name: "check_execute_subchart_template",
desc: "verify --execute single template on a subchart template",
args: []string{subchart1ChartPath, "-x", "charts/subcharta/templates/service.yaml", "--set", "subcharta.service.name=foobar"},
expectKey: "subchart1/charts/subcharta/templates/service.yaml",
expectValue: "protocol: TCP\n name: foobar",
},
{
name: "check_execute_subchart_template_for_tgz_subchart",
desc: "verify --execute single template on a subchart template where the subchart is a .tgz in the chart directory",
args: []string{frobnitzChartPath, "-x", "charts/mariner/templates/placeholder.tpl", "--set", "mariner.name=moon"},
expectKey: "frobnitz/charts/mariner/templates/placeholder.tpl",
expectValue: "Goodbye moon",
},
{ {
name: "check_namespace", name: "check_namespace",
desc: "verify --namespace", desc: "verify --namespace",
args: []string{chartPath, "--namespace", "test"}, args: []string{subchart1ChartPath, "--namespace", "test"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "namespace: \"test\"", expectValue: "namespace: \"test\"",
}, },
{ {
name: "check_release_name", name: "check_release_name",
desc: "verify --release exists", desc: "verify --release exists",
args: []string{chartPath, "--name", "test"}, args: []string{subchart1ChartPath, "--name", "test"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "release-name: \"test\"", expectValue: "release-name: \"test\"",
}, },
{ {
name: "check_notes", name: "check_notes",
desc: "verify --notes shows notes", desc: "verify --notes shows notes",
args: []string{chartPath, "--notes", "true"}, args: []string{subchart1ChartPath, "--notes", "true"},
expectKey: "subchart1/templates/NOTES.txt", expectKey: "subchart1/templates/NOTES.txt",
expectValue: "Sample notes for subchart1", expectValue: "Sample notes for subchart1",
}, },
{ {
name: "check_values_files", name: "check_values_files",
desc: "verify --values files values exist", desc: "verify --values files values exist",
args: []string{chartPath, "--values", chartPath + "/charts/subchartA/values.yaml"}, args: []string{subchart1ChartPath, "--values", subchart1ChartPath + "/charts/subchartA/values.yaml"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "name: apache", expectValue: "name: apache",
}, },
{ {
name: "check_name_template", name: "check_name_template",
desc: "verify --name-template result exists", desc: "verify --name-template result exists",
args: []string{chartPath, "--name-template", "foobar-{{ b64enc \"abc\" }}-baz"}, args: []string{subchart1ChartPath, "--name-template", "foobar-{{ b64enc \"abc\" }}-baz"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "release-name: \"foobar-YWJj-baz\"", expectValue: "release-name: \"foobar-YWJj-baz\"",
}, },
{ {
name: "check_kube_version", name: "check_kube_version",
desc: "verify --kube-version overrides the kubernetes version", desc: "verify --kube-version overrides the kubernetes version",
args: []string{chartPath, "--kube-version", "1.6"}, args: []string{subchart1ChartPath, "--kube-version", "1.6"},
expectKey: "subchart1/templates/service.yaml", expectKey: "subchart1/templates/service.yaml",
expectValue: "kube-version/major: \"1\"\n kube-version/minor: \"6\"\n kube-version/gitversion: \"v1.6.0\"", expectValue: "kube-version/major: \"1\"\n kube-version/minor: \"6\"\n kube-version/gitversion: \"v1.6.0\"",
}, },
...@@ -115,7 +139,8 @@ func TestTemplateCmd(t *testing.T) { ...@@ -115,7 +139,8 @@ func TestTemplateCmd(t *testing.T) {
var buf bytes.Buffer var buf bytes.Buffer
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(T *testing.T) { tt := tt
t.Run(tt.name, func(t *testing.T) {
// capture stdout // capture stdout
old := os.Stdout old := os.Stdout
r, w, _ := os.Pipe() r, w, _ := os.Pipe()
...@@ -125,8 +150,21 @@ func TestTemplateCmd(t *testing.T) { ...@@ -125,8 +150,21 @@ func TestTemplateCmd(t *testing.T) {
cmd := newTemplateCmd(out) cmd := newTemplateCmd(out)
cmd.SetArgs(tt.args) cmd.SetArgs(tt.args)
err := cmd.Execute() err := cmd.Execute()
if err != nil {
t.Errorf("expected: %v, got %v", tt.expectValue, err) if tt.expectError != "" {
if err == nil {
t.Errorf("expected err: %s, but no error occurred", tt.expectError)
}
// non nil error, check if it contains the expected error
if strings.Contains(err.Error(), tt.expectError) {
// had the error we were looking for, this test case is
// done
return
} else {
t.Fatalf("expected err: %q, got: %q", tt.expectError, err)
}
} else if err != nil {
t.Errorf("expected no error, got %v", err)
} }
// restore stdout // restore stdout
w.Close() w.Close()
......
# This is a placeholder. # This is a placeholder.
Goodbye {{.Values.name | default "world"}}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment