diff --git a/cmd/tiller/release_server.go b/cmd/tiller/release_server.go index 3f73129b8..c422cb0a7 100644 --- a/cmd/tiller/release_server.go +++ b/cmd/tiller/release_server.go @@ -238,13 +238,15 @@ func (s *releaseServer) InstallRelease(c ctx.Context, req *services.InstallRelea // Render the templates // TODO: Fix based on whether chart has `engine: SOMETHING` set. - vals, err := chartutil.CoalesceValues(req.Chart, req.Values, overrides) + vals, err := chartutil.CoalesceValues(req.Chart, req.Values, nil) if err != nil { return nil, err } + overrides["Values"] = vals + renderer := s.engine(req.Chart) - files, err := renderer.Render(req.Chart, vals) + files, err := renderer.Render(req.Chart, overrides) if err != nil { return nil, err } diff --git a/docs/examples/alpine/templates/alpine-pod.yaml b/docs/examples/alpine/templates/alpine-pod.yaml index 2294cfd03..c15ab8efc 100644 --- a/docs/examples/alpine/templates/alpine-pod.yaml +++ b/docs/examples/alpine/templates/alpine-pod.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Pod metadata: - name: "{{.Release.Name}}-{{.Chart.Name}}" + name: "{{.Release.Name}}-{{.Values.Name}}" labels: # The "heritage" label is used to track which tool deployed a given chart. # It is useful for admins who want to see what releases a particular tool @@ -19,7 +19,7 @@ spec: # called restartPolicy. If it is not found, it will use the default value. # {{default "Never" .restartPolicy}} is a slightly optimized version of the # more conventional syntax: {{.restartPolicy | default "Never"}} - restartPolicy: {{default "Never" .restartPolicy}} + restartPolicy: {{default "Never" .Values.restartPolicy}} containers: - name: waiter image: "alpine:3.3" diff --git a/docs/examples/nginx/templates/_helpers.tpl b/docs/examples/nginx/templates/_helpers.tpl index 1727e9b09..1af41a2e3 100644 --- a/docs/examples/nginx/templates/_helpers.tpl +++ b/docs/examples/nginx/templates/_helpers.tpl @@ -2,7 +2,7 @@ {{/* Expand the name of the chart. */}} -{{define "name"}}{{default "nginx" .nameOverride | trunc 24 }}{{end}} +{{define "name"}}{{default "nginx" .Values.nameOverride | trunc 24 }}{{end}} {{/* Create a default fully qualified app name. @@ -10,4 +10,4 @@ Create a default fully qualified app name. We truncate at 24 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). */}} -{{define "fullname"}}{{.Release.Name}}-{{default "nginx" .nameOverride | trunc 24 }}{{end}} +{{define "fullname"}}{{.Release.Name}}-{{default "nginx" .Values.nameOverride | trunc 24 }}{{end}} diff --git a/docs/examples/nginx/templates/configmap.yaml b/docs/examples/nginx/templates/configmap.yaml index f6dc2011f..ec4b9e5c3 100644 --- a/docs/examples/nginx/templates/configmap.yaml +++ b/docs/examples/nginx/templates/configmap.yaml @@ -11,5 +11,5 @@ metadata: data: # When the config map is mounted as a volume, these will be created as # files. - index.html: {{ default "Hello" .index | quote }} + index.html: {{default "Hello" .Values.index | quote}} test.txt: test diff --git a/docs/examples/nginx/templates/deployment.yaml b/docs/examples/nginx/templates/deployment.yaml index f291aa44e..1443a5136 100644 --- a/docs/examples/nginx/templates/deployment.yaml +++ b/docs/examples/nginx/templates/deployment.yaml @@ -15,7 +15,7 @@ metadata: # This makes it easy to audit chart usage. chart: "{{.Chart.Name}}-{{.Chart.Version}}" spec: - replicas: {{ default 1 .replicaCount | quote }} + replicas: {{default 1 .Values.replicaCount | quote}} template: metadata: labels: @@ -28,8 +28,8 @@ spec: # is a nice option for the user. Especially in the strange cases like # nginx where the base distro is determined by the tag. Using :latest # is frowned upon, using :stable isn't that great either. - image: "{{default "nginx" .image}}:{{default "stable-alpine" .imageTag}}" - imagePullPolicy: {{default "IfNotPresent" .pullPolicy}} + image: "{{default "nginx" .Values.image}}:{{default "stable-alpine" .Values.imageTag}}" + imagePullPolicy: {{default "IfNotPresent" .Values.pullPolicy}} ports: - containerPort: 80 # This (and the volumes section below) mount the config map as a volume. diff --git a/docs/examples/nginx/templates/svc.yaml b/docs/examples/nginx/templates/svc.yaml index 62c55a759..dbbb3bb21 100644 --- a/docs/examples/nginx/templates/svc.yaml +++ b/docs/examples/nginx/templates/svc.yaml @@ -10,7 +10,7 @@ metadata: chart: "{{.Chart.Name}}-{{.Chart.Version}}" spec: ports: - - port: {{ default 80 .httpPort | quote }} + - port: {{default 80 .Values.httpPort | quote}} targetPort: 80 protocol: TCP name: http diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go index 4a403a9ce..3987c5a16 100644 --- a/pkg/chartutil/values.go +++ b/pkg/chartutil/values.go @@ -94,11 +94,18 @@ func tableLookup(v Values, simple string) (Values, error) { if !ok { return v, ErrNoTable } - vv, ok := v2.(map[string]interface{}) - if !ok { - return vv, ErrNoTable + if vv, ok := v2.(map[string]interface{}); ok { + return vv, nil + } + + // This catches a case where a value is of type Values, but doesn't (for some + // reason) match the map[string]interface{}. This has been observed in the + // wild, and might be a result of a nil map of type Values. + if vv, ok := v2.(Values); ok { + return vv, nil } - return vv, nil + + return map[string]interface{}{}, ErrNoTable } // ReadValues will parse YAML byte data into a Values. diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 2499e1c77..f5cd9df21 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -71,6 +71,7 @@ func New() *Engine { func (e *Engine) Render(chrt *chart.Chart, values chartutil.Values) (map[string]string, error) { // Render the charts tmap := allTemplates(chrt, values) + fmt.Printf("%v", tmap) return e.render(tmap) } @@ -104,7 +105,6 @@ func (e *Engine) render(tpls map[string]renderable) (map[string]string, error) { rendered := make(map[string]string, len(files)) var buf bytes.Buffer for _, file := range files { - // log.Printf("Exec %s with %v (%s)", file, tpls[file].vals, tpls[file].tpl) if err := t.ExecuteTemplate(&buf, file, tpls[file].vals); err != nil { return map[string]string{}, fmt.Errorf("render error in %q: %s", file, err) } @@ -137,13 +137,25 @@ func recAllTpls(c *chart.Chart, templates map[string]renderable, parentVals char } else if c.Metadata != nil && c.Metadata.Name != "" { // An error indicates that the table doesn't exist. So we leave it as // an empty map. - tmp, err := parentVals.Table(c.Metadata.Name) + + var tmp chartutil.Values + vs, err := parentVals.Table("Values") + if err == nil { + tmp, err = vs.Table(c.Metadata.Name) + } else { + tmp, err = parentVals.Table(c.Metadata.Name) + } + + //tmp, err := parentVals["Values"].(chartutil.Values).Table(c.Metadata.Name) if err == nil { - cvals = tmp + cvals = map[string]interface{}{ + "Values": tmp, + "Release": parentVals["Release"], + "Chart": c, + } } } - //log.Printf("racAllTpls values: %v", cvals) for _, child := range c.Dependencies { recAllTpls(child, templates, cvals, false) } diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go index 661939d5c..e8c8e54cc 100644 --- a/pkg/engine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -215,11 +215,13 @@ func TestRenderNestedValues(t *testing.T) { innerpath := "charts/inner/templates/inner.tpl" outerpath := "templates/outer.tpl" deepestpath := "charts/inner/charts/deepest/templates/deepest.tpl" + checkrelease := "charts/inner/charts/deepest/templates/release.tpl" deepest := &chart.Chart{ Metadata: &chart.Metadata{Name: "deepest"}, Templates: []*chart.Template{ - {Name: deepestpath, Data: []byte(`And this same {{.what}} that smiles {{.global.when}}`)}, + {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: &chart.Config{Raw: `what: "milkshake"`}, } @@ -227,7 +229,7 @@ func TestRenderNestedValues(t *testing.T) { inner := &chart.Chart{ Metadata: &chart.Metadata{Name: "herrick"}, Templates: []*chart.Template{ - {Name: innerpath, Data: []byte(`Old {{.who}} is still a-flyin'`)}, + {Name: innerpath, Data: []byte(`Old {{.Values.who}} is still a-flyin'`)}, }, Values: &chart.Config{Raw: `who: "Robert"`}, Dependencies: []*chart.Chart{deepest}, @@ -236,7 +238,7 @@ func TestRenderNestedValues(t *testing.T) { outer := &chart.Chart{ Metadata: &chart.Metadata{Name: "top"}, Templates: []*chart.Template{ - {Name: outerpath, Data: []byte(`Gather ye {{.what}} while ye may`)}, + {Name: outerpath, Data: []byte(`Gather ye {{.Values.what}} while ye may`)}, }, Values: &chart.Config{ Raw: ` @@ -258,11 +260,19 @@ global: when: to-day`, } - inject, err := chartutil.CoalesceValues(outer, &injValues, map[string]interface{}{}) + tmp, err := chartutil.CoalesceValues(outer, &injValues, map[string]interface{}{}) if err != nil { t.Fatalf("Failed to coalesce values: %s", err) } + inject := chartutil.Values{ + "Values": tmp, + "Chart": outer.Metadata, + "Release": chartutil.Values{ + "Name": "dyin", + }, + } + t.Logf("Calculated values: %v", inject) out, err := e.Render(outer, inject) @@ -281,4 +291,8 @@ global: if out[deepestpath] != "And this same flower that smiles to-day" { t.Errorf("Unexpected deepest: %q", out[deepestpath]) } + + if out[checkrelease] != "Tomorrow will be dyin" { + t.Errorf("Unexpected release: %q", out[checkrelease]) + } }