Commit 59806b40 authored by Matt Butcher's avatar Matt Butcher Committed by GitHub

Merge pull request #873 from technosophos/feat/859-namespace-values

feat(*): add Values namespace to templates
parents 1dc95be1 225d3a8a
......@@ -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
}
......
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"
......
......@@ -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}}
......@@ -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
......@@ -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.
......
......@@ -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
......
......@@ -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 map[string]interface{}{}, ErrNoTable
}
// ReadValues will parse YAML byte data into a Values.
......
......@@ -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 {
cvals = tmp
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 = 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)
}
......
......@@ -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])
}
}
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