mirror of
https://github.com/helm/helm.git
synced 2026-04-26 00:27:36 -04:00
Support Linter for Values
This commit is contained in:
parent
bb875b5657
commit
7bb4893cad
7 changed files with 93 additions and 39 deletions
|
|
@ -220,33 +220,20 @@ func (s *releaseServer) InstallRelease(c ctx.Context, req *services.InstallRelea
|
|||
return nil, errMissingChart
|
||||
}
|
||||
|
||||
ts := timeconv.Now()
|
||||
name, err := s.uniqName(req.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
overrides := map[string]interface{}{
|
||||
"Release": map[string]interface{}{
|
||||
"Name": name,
|
||||
"Time": ts,
|
||||
"Namespace": s.env.Namespace,
|
||||
"Service": "Tiller",
|
||||
},
|
||||
"Chart": req.Chart.Metadata,
|
||||
}
|
||||
|
||||
// Render the templates
|
||||
// TODO: Fix based on whether chart has `engine: SOMETHING` set.
|
||||
vals, err := chartutil.CoalesceValues(req.Chart, req.Values, nil)
|
||||
ts := timeconv.Now()
|
||||
options := map[string]interface{}{"namespace": s.env.Namespace, "releaseName": name, "releaseTime": ts}
|
||||
valuesToRender, err := chartutil.ToRenderValues(req.Chart, req.Values, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
overrides["Values"] = vals
|
||||
|
||||
renderer := s.engine(req.Chart)
|
||||
files, err := renderer.Render(req.Chart, overrides)
|
||||
files, err := renderer.Render(req.Chart, valuesToRender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,6 +288,27 @@ func coalesceTables(dst, src map[string]interface{}) map[string]interface{} {
|
|||
return dst
|
||||
}
|
||||
|
||||
// ToRenderValues composes the struct from the data coming from the Releases, Charts and Values files
|
||||
func ToRenderValues(chrt *chart.Chart, chrtVals *chart.Config, options map[string]interface{}) (Values, error) {
|
||||
overrides := map[string]interface{}{
|
||||
"Release": map[string]interface{}{
|
||||
"Name": options["releaseName"],
|
||||
"Time": options["releaseTime"],
|
||||
"Namespace": options["namespace"],
|
||||
"Service": "Tiller",
|
||||
},
|
||||
"Chart": chrt.Metadata,
|
||||
}
|
||||
|
||||
vals, err := CoalesceValues(chrt, chrtVals, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
overrides["Values"] = vals
|
||||
return overrides, nil
|
||||
}
|
||||
|
||||
// istable is a special-purpose function to see if the present thing matches the definition of a YAML table.
|
||||
func istable(v interface{}) bool {
|
||||
_, ok := v.(map[string]interface{})
|
||||
|
|
|
|||
|
|
@ -19,17 +19,18 @@ package rules
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Masterminds/sprig"
|
||||
"gopkg.in/yaml.v2"
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
"k8s.io/helm/pkg/engine"
|
||||
"k8s.io/helm/pkg/lint/support"
|
||||
"k8s.io/helm/pkg/timeconv"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func Templates(linter *support.Linter) {
|
||||
|
|
@ -51,18 +52,9 @@ func Templates(linter *support.Linter) {
|
|||
return
|
||||
}
|
||||
|
||||
// Based on cmd/tiller/release_server.go
|
||||
overrides := map[string]interface{}{
|
||||
"Release": map[string]interface{}{
|
||||
"Name": "testRelease",
|
||||
"Service": "Tiller",
|
||||
"Time": timeconv.Now(),
|
||||
},
|
||||
"Chart": chart.Metadata,
|
||||
}
|
||||
|
||||
chartValues, _ := chartutil.CoalesceValues(chart, chart.Values, overrides)
|
||||
renderedContentMap, err := engine.New().Render(chart, chartValues)
|
||||
options := map[string]interface{}{"namespace": "testNamespace", "releaseName": "testRelease", "releaseTime": timeconv.Now()}
|
||||
valuesToRender, err := chartutil.ToRenderValues(chart, chart.Values, options)
|
||||
renderedContentMap, err := engine.New().Render(chart, valuesToRender)
|
||||
|
||||
renderOk := linter.RunLinterRule(support.ErrorSev, validateNoError(err))
|
||||
|
||||
|
|
@ -88,7 +80,7 @@ func Templates(linter *support.Linter) {
|
|||
}
|
||||
|
||||
// Check that all the templates have a matching value
|
||||
linter.RunLinterRule(support.WarningSev, validateNonMissingValues(fileName, templatesPath, chartValues, preExecutedTemplate))
|
||||
linter.RunLinterRule(support.WarningSev, validateNonMissingValues(fileName, templatesPath, valuesToRender, preExecutedTemplate))
|
||||
|
||||
linter.RunLinterRule(support.WarningSev, validateQuotes(fileName, string(preExecutedTemplate)))
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,12 @@ limitations under the License.
|
|||
package rules
|
||||
|
||||
import (
|
||||
"k8s.io/helm/pkg/lint/support"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/helm/pkg/lint/support"
|
||||
)
|
||||
|
||||
const templateTestBasedir = "./testdata/albatross"
|
||||
|
|
@ -73,7 +76,7 @@ func TestValidateQuotes(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func TestTemplate(t *testing.T) {
|
||||
func TestTemplateParsing(t *testing.T) {
|
||||
linter := support.Linter{ChartDir: templateTestBasedir}
|
||||
Templates(&linter)
|
||||
res := linter.Messages
|
||||
|
|
@ -86,3 +89,22 @@ func TestTemplate(t *testing.T) {
|
|||
t.Errorf("Unexpected error: %s", res[0])
|
||||
}
|
||||
}
|
||||
|
||||
var wrongTemplatePath string = filepath.Join(templateTestBasedir, "templates", "fail.yaml")
|
||||
var ignoredTemplatePath string = filepath.Join(templateTestBasedir, "fail.yaml.ignored")
|
||||
|
||||
// Test a template with all the existing features:
|
||||
// namespaces, partial templates
|
||||
func TestTemplateIntegrationHappyPath(t *testing.T) {
|
||||
// Rename file so it gets ignored by the linter
|
||||
os.Rename(wrongTemplatePath, ignoredTemplatePath)
|
||||
defer os.Rename(ignoredTemplatePath, wrongTemplatePath)
|
||||
|
||||
linter := support.Linter{ChartDir: templateTestBasedir}
|
||||
Templates(&linter)
|
||||
res := linter.Messages
|
||||
|
||||
if len(res) != 0 {
|
||||
t.Fatalf("Expected no error, got %d, %v", len(res), res)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
pkg/lint/rules/testdata/albatross/templates/_helpers.tpl
vendored
Normal file
16
pkg/lint/rules/testdata/albatross/templates/_helpers.tpl
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{define "name"}}{{default "nginx" .Values.nameOverride | trunc 24 }}{{end}}
|
||||
|
||||
{{/*
|
||||
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"}}
|
||||
{{- $name := default "nginx" .Values.nameOverride -}}
|
||||
{{printf "%s-%s" .Release.Name $name | trunc 24 -}}
|
||||
{{end}}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
metadata:
|
||||
name: {{.name | default "foo" | title}}
|
||||
18
pkg/lint/rules/testdata/albatross/templates/svc.yaml
vendored
Normal file
18
pkg/lint/rules/testdata/albatross/templates/svc.yaml
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# This is a service gateway to the replica set created by the deployment.
|
||||
# Take a look at the deployment.yaml for general notes about this chart.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: "{{ .Values.name }}"
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{.Chart.Name}}-{{.Chart.Version}}"
|
||||
spec:
|
||||
ports:
|
||||
- port: {{default 80 .Values.httpPort | quote}}
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: {{template "fullname" .}}
|
||||
Loading…
Reference in a new issue