feat(template): introduce --validate

This feature flag allows `helm template` to be used against a live cluster. Some charts need CRDs to be applied to the cluster before calling `helm install`. This allows users to validate their templates will render with those resources set.

Signed-off-by: Matthew Fisher <matt.fisher@microsoft.com>
pull/6049/head
Matthew Fisher 5 years ago
parent 880f4456b3
commit 7de91248ce
No known key found for this signature in database
GPG Key ID: 92AA783CBAAE8E3B

@ -172,6 +172,7 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
newReleaseTestCmd(actionConfig, out),
newRollbackCmd(actionConfig, out),
newStatusCmd(actionConfig, out),
newTemplateCmd(actionConfig, out),
newUninstallCmd(actionConfig, out),
newUpgradeCmd(actionConfig, out),
@ -179,7 +180,6 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string
newHomeCmd(out),
newInitCmd(out),
newPluginCmd(out),
newTemplateCmd(out),
newVersionCmd(out),
// Hidden documentation generator command: 'helm docs'

@ -19,18 +19,12 @@ package main
import (
"fmt"
"io"
"io/ioutil"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"helm.sh/helm/cmd/helm/require"
"helm.sh/helm/pkg/action"
"helm.sh/helm/pkg/chartutil"
kubefake "helm.sh/helm/pkg/kube/fake"
"helm.sh/helm/pkg/storage"
"helm.sh/helm/pkg/storage/driver"
)
const templateDesc = `
@ -42,18 +36,9 @@ of the server-side testing of chart validity (e.g. whether an API is supported)
is done.
`
func newTemplateCmd(out io.Writer) *cobra.Command {
customConfig := &action.Configuration{
// Add mock objects in here so it doesn't use Kube API server
Releases: storage.Init(driver.NewMemory()),
KubeClient: &kubefake.PrintingKubeClient{Out: ioutil.Discard},
Capabilities: chartutil.DefaultCapabilities,
Log: func(format string, v ...interface{}) {
fmt.Fprintf(out, format, v...)
},
}
client := action.NewInstall(customConfig)
func newTemplateCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
var validate bool
client := action.NewInstall(cfg)
cmd := &cobra.Command{
Use: "template [NAME] [CHART]",
@ -64,6 +49,7 @@ func newTemplateCmd(out io.Writer) *cobra.Command {
client.DryRun = true
client.ReleaseName = "RELEASE-NAME"
client.Replace = true // Skip the name check
client.ClientOnly = !validate
rel, err := runInstall(args, client, out)
if err != nil {
return err
@ -73,12 +59,10 @@ func newTemplateCmd(out io.Writer) *cobra.Command {
},
}
addInstallFlags(cmd.Flags(), client)
addTemplateFlags(cmd.Flags(), client)
f := cmd.Flags()
addInstallFlags(f, client)
f.StringVar(&client.OutputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout")
f.BoolVar(&validate, "validate", false, "establish a connection to Kubernetes for schema validation")
return cmd
}
func addTemplateFlags(f *pflag.FlagSet, client *action.Install) {
f.StringVar(&client.OutputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout")
}

@ -41,9 +41,12 @@ import (
"helm.sh/helm/pkg/engine"
"helm.sh/helm/pkg/getter"
"helm.sh/helm/pkg/hooks"
kubefake "helm.sh/helm/pkg/kube/fake"
"helm.sh/helm/pkg/release"
"helm.sh/helm/pkg/releaseutil"
"helm.sh/helm/pkg/repo"
"helm.sh/helm/pkg/storage"
"helm.sh/helm/pkg/storage/driver"
"helm.sh/helm/pkg/strvals"
"helm.sh/helm/pkg/version"
)
@ -70,6 +73,7 @@ type Install struct {
ChartPathOptions
ValueOptions
ClientOnly bool
DryRun bool
DisableHooks bool
Replace bool
@ -119,6 +123,14 @@ func (i *Install) Run(chrt *chart.Chart) (*release.Release, error) {
return nil, err
}
if i.ClientOnly {
// Add mock objects in here so it doesn't use Kube API server
// NOTE(bacongobbler): used for `helm template`
i.cfg.Capabilities = chartutil.DefaultCapabilities
i.cfg.KubeClient = &kubefake.PrintingKubeClient{Out: ioutil.Discard}
i.cfg.Releases = storage.Init(driver.NewMemory())
}
// Make sure if Atomic is set, that wait is set as well. This makes it so
// the user doesn't have to specify both
i.Wait = i.Wait || i.Atomic

@ -29,9 +29,10 @@ import (
"github.com/stretchr/testify/assert"
"helm.sh/helm/internal/test"
"helm.sh/helm/pkg/chartutil"
kubefake "helm.sh/helm/pkg/kube/fake"
"helm.sh/helm/pkg/release"
"helm.sh/helm/pkg/storage/driver"
kubefake "helm.sh/helm/pkg/kube/fake"
)
type nameTemplateTestCase struct {
@ -74,6 +75,16 @@ func TestInstallRelease(t *testing.T) {
is.Equal(rel.Info.Description, "Install complete")
}
func TestInstallReleaseClientOnly(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ClientOnly = true
instAction.Run(buildChart()) // disregard output
is.Equal(instAction.cfg.Capabilities, chartutil.DefaultCapabilities)
is.Equal(instAction.cfg.KubeClient, &kubefake.PrintingKubeClient{Out: ioutil.Discard})
}
func TestInstallRelease_NoName(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = ""
@ -278,7 +289,7 @@ func TestInstallRelease_Atomic(t *testing.T) {
is.Error(err)
is.Equal(err, driver.ErrReleaseNotFound)
})
t.Run("atomic uninstall fails", func(t *testing.T) {
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away-with-me"

Loading…
Cancel
Save