diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 4da64f5cc32..8c3536a5462 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -260,6 +260,7 @@ func (e Engine) renderWithReferences(tpls, referenceTpls map[string]renderable) if err := t.ExecuteTemplate(&buf, filename, vals); err != nil { return map[string]string{}, cleanupExecError(filename, err) } + delete(vals, "Template") // Work around the issue where Go will emit "" even if Options(missing=zero) // is set. Since missing=error will never get here, we do not need to handle @@ -344,13 +345,15 @@ func allTemplates(c *chart.Chart, vals chartutil.Values) map[string]renderable { // // As it recurses, it also sets the values to be appropriate for the template // scope. -func recAllTpls(c *chart.Chart, templates map[string]renderable, vals chartutil.Values) { +func recAllTpls(c *chart.Chart, templates map[string]renderable, vals chartutil.Values) map[string]interface{} { + subCharts := make(map[string]interface{}) next := map[string]interface{}{ "Chart": c.Metadata, "Files": newFiles(c.Files), "Release": vals["Release"], "Capabilities": vals["Capabilities"], "Values": make(chartutil.Values), + "Subcharts": subCharts, } // If there is a {{.Values.ThisChart}} in the parent metadata, @@ -362,7 +365,7 @@ func recAllTpls(c *chart.Chart, templates map[string]renderable, vals chartutil. } for _, child := range c.Dependencies() { - recAllTpls(child, templates, next) + subCharts[child.Name()] = recAllTpls(child, templates, next) } newParentID := c.ChartFullPath() @@ -376,6 +379,8 @@ func recAllTpls(c *chart.Chart, templates map[string]renderable, vals chartutil. basePath: path.Join(newParentID, "templates"), } } + + return next } // isTemplateValid returns true if the template is valid for the chart type diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go index 72ee0262658..35be42a631d 100644 --- a/pkg/engine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -384,6 +384,8 @@ func TestRenderNestedValues(t *testing.T) { // Ensure namespacing rules are working. deepestpath := "templates/inner.tpl" checkrelease := "templates/release.tpl" + // Ensure subcharts scopes are working. + subchartspath := "templates/subcharts.tpl" deepest := &chart.Chart{ Metadata: &chart.Metadata{Name: "deepest"}, @@ -391,7 +393,7 @@ func TestRenderNestedValues(t *testing.T) { {Name: deepestpath, Data: []byte(`And this same {{.Values.what}} that smiles {{.Values.global.when}}`)}, {Name: checkrelease, Data: []byte(`Tomorrow will be {{default "happy" .Release.Name }}`)}, }, - Values: map[string]interface{}{"what": "milkshake"}, + Values: map[string]interface{}{"what": "milkshake", "where": "here"}, } inner := &chart.Chart{ @@ -399,7 +401,7 @@ func TestRenderNestedValues(t *testing.T) { Templates: []*chart.File{ {Name: innerpath, Data: []byte(`Old {{.Values.who}} is still a-flyin'`)}, }, - Values: map[string]interface{}{"who": "Robert"}, + Values: map[string]interface{}{"who": "Robert", "what": "glasses"}, } inner.AddDependency(deepest) @@ -407,12 +409,14 @@ func TestRenderNestedValues(t *testing.T) { Metadata: &chart.Metadata{Name: "top"}, Templates: []*chart.File{ {Name: outerpath, Data: []byte(`Gather ye {{.Values.what}} while ye may`)}, + {Name: subchartspath, Data: []byte(`The glorious Lamp of {{.Subcharts.herrick.Subcharts.deepest.Values.where}}, the {{.Subcharts.herrick.Values.what}}`)}, }, Values: map[string]interface{}{ "what": "stinkweed", "who": "me", "herrick": map[string]interface{}{ - "who": "time", + "who": "time", + "what": "Sun", }, }, } @@ -422,7 +426,8 @@ func TestRenderNestedValues(t *testing.T) { "what": "rosebuds", "herrick": map[string]interface{}{ "deepest": map[string]interface{}{ - "what": "flower", + "what": "flower", + "where": "Heaven", }, }, "global": map[string]interface{}{ @@ -469,6 +474,11 @@ func TestRenderNestedValues(t *testing.T) { if out[fullcheckrelease] != "Tomorrow will be dyin" { t.Errorf("Unexpected release: %q", out[fullcheckrelease]) } + + fullchecksubcharts := "top/" + subchartspath + if out[fullchecksubcharts] != "The glorious Lamp of Heaven, the Sun" { + t.Errorf("Unexpected subcharts: %q", out[fullchecksubcharts]) + } } func TestRenderBuiltinValues(t *testing.T) { @@ -488,6 +498,7 @@ func TestRenderBuiltinValues(t *testing.T) { Metadata: &chart.Metadata{Name: "Troy"}, Templates: []*chart.File{ {Name: "templates/Aeneas", Data: []byte(`{{.Template.Name}}{{.Chart.Name}}{{.Release.Name}}`)}, + {Name: "templates/Amata", Data: []byte(`{{.Subcharts.Latium.Chart.Name}} {{.Subcharts.Latium.Files.author | printf "%s"}}`)}, }, } outer.AddDependency(inner) @@ -510,6 +521,7 @@ func TestRenderBuiltinValues(t *testing.T) { expects := map[string]string{ "Troy/charts/Latium/templates/Lavinia": "Troy/charts/Latium/templates/LaviniaLatiumAeneid", "Troy/templates/Aeneas": "Troy/templates/AeneasTroyAeneid", + "Troy/templates/Amata": "Latium Virgil", "Troy/charts/Latium/templates/From": "Virgil Aeneid", } for file, expect := range expects {