Merge pull request #4048 from adamreese/dev-v3-ref-test-help

ref(tests): simplify cmd test setup/teardown
pull/4068/head
Adam Reese 7 years ago committed by GitHub
commit 53ea80b2d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -74,7 +74,7 @@ test: test-unit
test-unit: test-unit:
@echo @echo
@echo "==> Running unit tests <==" @echo "==> Running unit tests <=="
HELM_HOME=/no/such/dir $(GO) test $(GOFLAGS) -run $(TESTS) $(PKG) $(TESTFLAGS) HELM_HOME=/no_such_dir $(GO) test $(GOFLAGS) -run $(TESTS) $(PKG) $(TESTFLAGS)
.PHONY: test-style .PHONY: test-style
test-style: test-style:

@ -26,7 +26,6 @@ import (
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
"k8s.io/helm/pkg/helm/helmpath"
) )
const createDesc = ` const createDesc = `
@ -51,11 +50,7 @@ will be overwritten, but other files will be left alone.
type createOptions struct { type createOptions struct {
starter string // --starter starter string // --starter
name string
// args
name string
home helmpath.Home
} }
func newCreateCmd(out io.Writer) *cobra.Command { func newCreateCmd(out io.Writer) *cobra.Command {
@ -66,7 +61,6 @@ func newCreateCmd(out io.Writer) *cobra.Command {
Short: "create a new chart with the given name", Short: "create a new chart with the given name",
Long: createDesc, Long: createDesc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
o.home = settings.Home
if len(args) == 0 { if len(args) == 0 {
return errors.New("the name of the new chart is required") return errors.New("the name of the new chart is required")
} }
@ -93,7 +87,7 @@ func (o *createOptions) run(out io.Writer) error {
if o.starter != "" { if o.starter != "" {
// Create from the starter // Create from the starter
lstarter := filepath.Join(o.home.Starters(), o.starter) lstarter := filepath.Join(settings.Home.Starters(), o.starter)
return chartutil.CreateFrom(cfile, filepath.Dir(o.name), lstarter) return chartutil.CreateFrom(cfile, filepath.Dir(o.name), lstarter)
} }

@ -28,23 +28,10 @@ import (
) )
func TestCreateCmd(t *testing.T) { func TestCreateCmd(t *testing.T) {
cname := "testchart" tdir := testTempDir(t)
// Make a temp dir defer testChdir(t, tdir)()
tdir, err := ioutil.TempDir("", "helm-create-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tdir)
// CD into it cname := "testchart"
pwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
if err := os.Chdir(tdir); err != nil {
t.Fatal(err)
}
defer os.Chdir(pwd)
// Run a create // Run a create
if _, err := executeCommand(nil, "create "+cname); err != nil { if _, err := executeCommand(nil, "create "+cname); err != nil {
@ -73,28 +60,17 @@ func TestCreateCmd(t *testing.T) {
} }
func TestCreateStarterCmd(t *testing.T) { func TestCreateStarterCmd(t *testing.T) {
defer resetEnv()()
cname := "testchart" cname := "testchart"
// Make a temp dir // Make a temp dir
tdir, err := ioutil.TempDir("", "helm-create-") tdir := testTempDir(t)
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tdir)
thome, err := tempHelmHome(t)
if err != nil {
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(thome.String())
cleanup()
}()
settings.Home = thome hh := testHelmHome(t)
settings.Home = hh
// Create a starter. // Create a starter.
starterchart := filepath.Join(thome.String(), "starters") starterchart := hh.Starters()
os.Mkdir(starterchart, 0755) os.Mkdir(starterchart, 0755)
if dest, err := chartutil.Create(&chart.Metadata{Name: "starterchart"}, starterchart); err != nil { if dest, err := chartutil.Create(&chart.Metadata{Name: "starterchart"}, starterchart); err != nil {
t.Fatalf("Could not create chart: %s", err) t.Fatalf("Could not create chart: %s", err)
@ -106,18 +82,10 @@ func TestCreateStarterCmd(t *testing.T) {
t.Fatalf("Could not write template: %s", err) t.Fatalf("Could not write template: %s", err)
} }
// CD into it defer testChdir(t, tdir)()
pwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
if err := os.Chdir(tdir); err != nil {
t.Fatal(err)
}
defer os.Chdir(pwd)
// Run a create // Run a create
if _, err := executeCommand(nil, fmt.Sprintf("--home=%s create --starter=starterchart %s", thome, cname)); err != nil { if _, err := executeCommand(nil, fmt.Sprintf("--home=%s create --starter=starterchart %s", hh, cname)); err != nil {
t.Errorf("Failed to run create: %s", err) t.Errorf("Failed to run create: %s", err)
return return
} }
@ -149,9 +117,8 @@ func TestCreateStarterCmd(t *testing.T) {
for _, tpl := range c.Templates { for _, tpl := range c.Templates {
if tpl.Name == "templates/foo.tpl" { if tpl.Name == "templates/foo.tpl" {
found = true found = true
data := tpl.Data if data := string(tpl.Data); data != "test" {
if string(data) != "test" { t.Errorf("Expected template 'test', got %q", data)
t.Errorf("Expected template 'test', got %q", string(data))
} }
} }
} }

@ -27,7 +27,7 @@ func TestDelete(t *testing.T) {
rels := []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})} rels := []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})}
tests := []releaseCase{ tests := []cmdTestCase{
{ {
name: "basic delete", name: "basic delete",
cmd: "delete aeneas", cmd: "delete aeneas",
@ -59,5 +59,5 @@ func TestDelete(t *testing.T) {
wantError: true, wantError: true,
}, },
} }
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -22,7 +22,6 @@ import (
"k8s.io/helm/pkg/downloader" "k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath"
) )
const dependencyBuildDesc = ` const dependencyBuildDesc = `
@ -40,10 +39,7 @@ type dependencyBuildOptions struct {
keyring string // --keyring keyring string // --keyring
verify bool // --verify verify bool // --verify
// args
chartpath string chartpath string
helmhome helmpath.Home
} }
func newDependencyBuildCmd(out io.Writer) *cobra.Command { func newDependencyBuildCmd(out io.Writer) *cobra.Command {
@ -56,7 +52,6 @@ func newDependencyBuildCmd(out io.Writer) *cobra.Command {
Short: "rebuild the charts/ directory based on the requirements.lock file", Short: "rebuild the charts/ directory based on the requirements.lock file",
Long: dependencyBuildDesc, Long: dependencyBuildDesc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
o.helmhome = settings.Home
if len(args) > 0 { if len(args) > 0 {
o.chartpath = args[0] o.chartpath = args[0]
} }
@ -75,7 +70,7 @@ func (o *dependencyBuildOptions) run(out io.Writer) error {
man := &downloader.Manager{ man := &downloader.Manager{
Out: out, Out: out,
ChartPath: o.chartpath, ChartPath: o.chartpath,
HelmHome: o.helmhome, HelmHome: settings.Home,
Keyring: o.keyring, Keyring: o.keyring,
Getters: getter.All(settings), Getters: getter.All(settings),
} }

@ -27,22 +27,14 @@ import (
) )
func TestDependencyBuildCmd(t *testing.T) { func TestDependencyBuildCmd(t *testing.T) {
hh, err := tempHelmHome(t) defer resetEnv()()
if err != nil {
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(hh.String())
cleanup()
}()
hh := testHelmHome(t)
settings.Home = hh settings.Home = hh
srv := repotest.NewServer(hh.String()) srv := repotest.NewServer(hh.String())
defer srv.Stop() defer srv.Stop()
_, err = srv.CopyCharts("testdata/testcharts/*.tgz") if _, err := srv.CopyCharts("testdata/testcharts/*.tgz"); err != nil {
if err != nil {
t.Fatal(err) t.Fatal(err)
} }

@ -20,7 +20,7 @@ import (
) )
func TestDependencyListCmd(t *testing.T) { func TestDependencyListCmd(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "No such chart", name: "No such chart",
cmd: "dependency list /no/such/chart", cmd: "dependency list /no/such/chart",
golden: "output/dependency-list-no-chart.txt", golden: "output/dependency-list-no-chart.txt",
@ -38,5 +38,5 @@ func TestDependencyListCmd(t *testing.T) {
cmd: "dependency list testdata/testcharts/reqtest-0.1.0.tgz", cmd: "dependency list testdata/testcharts/reqtest-0.1.0.tgz",
golden: "output/dependency-list-archive.txt", golden: "output/dependency-list-archive.txt",
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -35,16 +35,9 @@ import (
) )
func TestDependencyUpdateCmd(t *testing.T) { func TestDependencyUpdateCmd(t *testing.T) {
hh, err := tempHelmHome(t) defer resetEnv()()
if err != nil {
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(hh.String())
cleanup()
}()
hh := testHelmHome(t)
settings.Home = hh settings.Home = hh
srv := repotest.NewServer(hh.String()) srv := repotest.NewServer(hh.String())
@ -125,16 +118,9 @@ func TestDependencyUpdateCmd(t *testing.T) {
} }
func TestDependencyUpdateCmd_SkipRefresh(t *testing.T) { func TestDependencyUpdateCmd_SkipRefresh(t *testing.T) {
hh, err := tempHelmHome(t) defer resetEnv()()
if err != nil {
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(hh.String())
cleanup()
}()
hh := testHelmHome(t)
settings.Home = hh settings.Home = hh
srv := repotest.NewServer(hh.String()) srv := repotest.NewServer(hh.String())
@ -163,16 +149,9 @@ func TestDependencyUpdateCmd_SkipRefresh(t *testing.T) {
} }
func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) { func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
hh, err := tempHelmHome(t) defer resetEnv()()
if err != nil {
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(hh.String())
cleanup()
}()
hh := testHelmHome(t)
settings.Home = hh settings.Home = hh
srv := repotest.NewServer(hh.String()) srv := repotest.NewServer(hh.String())

@ -28,20 +28,14 @@ import (
) )
func TestFetchCmd(t *testing.T) { func TestFetchCmd(t *testing.T) {
hh, err := tempHelmHome(t) defer resetEnv()()
if err != nil {
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(hh.String())
cleanup()
}()
srv := repotest.NewServer(hh.String())
defer srv.Stop()
hh := testHelmHome(t)
settings.Home = hh settings.Home = hh
srv := repotest.NewServer(hh.String())
defer srv.Stop()
// all flags will get "--home=TMDIR -d outdir" appended. // all flags will get "--home=TMDIR -d outdir" appended.
tests := []struct { tests := []struct {
name string name string
@ -131,7 +125,7 @@ func TestFetchCmd(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
outdir := filepath.Join(hh.String(), "testout") outdir := hh.Path("testout")
os.RemoveAll(outdir) os.RemoveAll(outdir)
os.Mkdir(outdir, 0755) os.Mkdir(outdir, 0755)

@ -24,7 +24,7 @@ import (
) )
func TestGetHooks(t *testing.T) { func TestGetHooks(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "get hooks with release", name: "get hooks with release",
cmd: "get hooks aeneas", cmd: "get hooks aeneas",
golden: "output/get-hooks.txt", golden: "output/get-hooks.txt",
@ -35,5 +35,5 @@ func TestGetHooks(t *testing.T) {
golden: "output/get-hooks-no-args.txt", golden: "output/get-hooks-no-args.txt",
wantError: true, wantError: true,
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -24,7 +24,7 @@ import (
) )
func TestGetManifest(t *testing.T) { func TestGetManifest(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "get manifest with release", name: "get manifest with release",
cmd: "get manifest juno", cmd: "get manifest juno",
golden: "output/get-manifest.txt", golden: "output/get-manifest.txt",
@ -35,5 +35,5 @@ func TestGetManifest(t *testing.T) {
golden: "output/get-manifest-no-args.txt", golden: "output/get-manifest-no-args.txt",
wantError: true, wantError: true,
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -24,7 +24,7 @@ import (
) )
func TestGetCmd(t *testing.T) { func TestGetCmd(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "get with a release", name: "get with a release",
cmd: "get thomas-guide", cmd: "get thomas-guide",
golden: "output/get-release.txt", golden: "output/get-release.txt",
@ -35,5 +35,5 @@ func TestGetCmd(t *testing.T) {
golden: "output/get-no-args.txt", golden: "output/get-no-args.txt",
wantError: true, wantError: true,
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -24,7 +24,7 @@ import (
) )
func TestGetValuesCmd(t *testing.T) { func TestGetValuesCmd(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "get values with a release", name: "get values with a release",
cmd: "get values thomas-guide", cmd: "get values thomas-guide",
golden: "output/get-values.txt", golden: "output/get-values.txt",
@ -35,5 +35,5 @@ func TestGetValuesCmd(t *testing.T) {
golden: "output/get-values-args.txt", golden: "output/get-values-args.txt",
wantError: true, wantError: true,
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -18,14 +18,12 @@ package main // import "k8s.io/helm/cmd/helm"
import ( import (
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"strings" "strings"
"sync" "sync"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra"
// Import to initialize client auth plugins. // Import to initialize client auth plugins.
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
@ -42,83 +40,6 @@ var (
configOnce sync.Once configOnce sync.Once
) )
var globalUsage = `The Kubernetes package manager
To begin working with Helm, run the 'helm init' command:
$ helm init
This will set up any necessary local configuration.
Common actions from this point include:
- helm search: search for charts
- helm fetch: download a chart to your local directory to view
- helm install: upload the chart to Kubernetes
- helm list: list releases of charts
Environment:
$HELM_HOME set an alternative location for Helm files. By default, these are stored in ~/.helm
$HELM_NO_PLUGINS disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins.
$KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config")
`
func newRootCmd(c helm.Interface, out io.Writer, args []string) *cobra.Command {
cmd := &cobra.Command{
Use: "helm",
Short: "The Helm package manager for Kubernetes.",
Long: globalUsage,
SilenceUsage: true,
}
flags := cmd.PersistentFlags()
settings.AddFlags(flags)
cmd.AddCommand(
// chart commands
newCreateCmd(out),
newDependencyCmd(out),
newFetchCmd(out),
newInspectCmd(out),
newLintCmd(out),
newPackageCmd(out),
newRepoCmd(out),
newSearchCmd(out),
newVerifyCmd(out),
// release commands
newDeleteCmd(c, out),
newGetCmd(c, out),
newHistoryCmd(c, out),
newInstallCmd(c, out),
newListCmd(c, out),
newReleaseTestCmd(c, out),
newRollbackCmd(c, out),
newStatusCmd(c, out),
newUpgradeCmd(c, out),
newCompletionCmd(out),
newHomeCmd(out),
newInitCmd(out),
newPluginCmd(out),
newTemplateCmd(out),
newVersionCmd(out),
// Hidden documentation generator command: 'helm docs'
newDocsCmd(out),
)
flags.Parse(args)
// set defaults from environment
settings.Init(flags)
// Find and add plugins
loadPlugins(cmd, out)
return cmd
}
func init() { func init() {
log.SetFlags(log.Lshortfile) log.SetFlags(log.Lshortfile)
} }

@ -20,12 +20,10 @@ import (
"bytes" "bytes"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath"
"strings" "strings"
"testing" "testing"
shellwords "github.com/mattn/go-shellwords" shellwords "github.com/mattn/go-shellwords"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/internal/test" "k8s.io/helm/internal/test"
@ -35,30 +33,40 @@ import (
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
) )
func executeCommand(c helm.Interface, cmd string) (string, error) { // base temp directory
_, output, err := executeCommandC(c, cmd) var testingDir string
return output, err
}
func executeCommandC(client helm.Interface, cmd string) (*cobra.Command, string, error) { func init() {
args, err := shellwords.Parse(cmd) var err error
testingDir, err = ioutil.TempDir(testingDir, "helm")
if err != nil { if err != nil {
return nil, "", err panic(err)
} }
buf := new(bytes.Buffer) }
root := newRootCmd(client, buf, args)
root.SetOutput(buf)
root.SetArgs(args)
c, err := root.ExecuteC() func TestMain(m *testing.M) {
os.Unsetenv("HELM_HOME")
return c, buf.String(), err exitCode := m.Run()
os.RemoveAll(testingDir)
os.Exit(exitCode)
} }
func testReleaseCmd(t *testing.T, tests []releaseCase) { func testTempDir(t *testing.T) string {
t.Helper()
d, err := ioutil.TempDir(testingDir, "helm")
if err != nil {
t.Fatal(err)
}
return d
}
func runTestCmd(t *testing.T, tests []cmdTestCase) {
t.Helper() t.Helper()
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
defer resetEnv()()
c := &helm.FakeClient{ c := &helm.FakeClient{
Rels: tt.rels, Rels: tt.rels,
TestRunStatus: tt.testRunStatus, TestRunStatus: tt.testRunStatus,
@ -74,8 +82,8 @@ func testReleaseCmd(t *testing.T, tests []releaseCase) {
} }
} }
// releaseCase describes a test case that works with releases. // cmdTestCase describes a test case that works with releases.
type releaseCase struct { type cmdTestCase struct {
name string name string
cmd string cmd string
golden string golden string
@ -85,29 +93,28 @@ type releaseCase struct {
testRunStatus map[string]release.TestRunStatus testRunStatus map[string]release.TestRunStatus
} }
// tempHelmHome sets up a Helm Home in a temp dir. func executeCommand(c helm.Interface, cmd string) (string, error) {
// _, output, err := executeCommandC(c, cmd)
// This does not clean up the directory. You must do that yourself. return output, err
// You must also set helmHome yourself. }
func tempHelmHome(t *testing.T) (helmpath.Home, error) {
oldhome := settings.Home func executeCommandC(client helm.Interface, cmd string) (*cobra.Command, string, error) {
dir, err := ioutil.TempDir("", "helm_home-") args, err := shellwords.Parse(cmd)
if err != nil { if err != nil {
return helmpath.Home("n/"), err return nil, "", err
} }
buf := new(bytes.Buffer)
root := newRootCmd(client, buf, args)
root.SetOutput(buf)
root.SetArgs(args)
settings.Home = helmpath.Home(dir) c, err := root.ExecuteC()
if err := ensureTestHome(t, settings.Home); err != nil {
return helmpath.Home("n/"), err return c, buf.String(), err
}
settings.Home = oldhome
return helmpath.Home(dir), nil
} }
// ensureTestHome creates a home directory like ensureHome, but without remote references. // ensureTestHome creates a home directory like ensureHome, but without remote references.
// func ensureTestHome(t *testing.T, home helmpath.Home) {
// t is used only for logging.
func ensureTestHome(t *testing.T, home helmpath.Home) error {
t.Helper() t.Helper()
for _, p := range []string{ for _, p := range []string{
home.String(), home.String(),
@ -117,7 +124,7 @@ func ensureTestHome(t *testing.T, home helmpath.Home) error {
home.Starters(), home.Starters(),
} { } {
if err := os.MkdirAll(p, 0755); err != nil { if err := os.MkdirAll(p, 0755); err != nil {
return errors.Wrapf(err, "could not create %s", p) t.Fatal(err)
} }
} }
@ -130,96 +137,30 @@ func ensureTestHome(t *testing.T, home helmpath.Home) error {
Cache: "charts-index.yaml", Cache: "charts-index.yaml",
}) })
if err := rf.WriteFile(repoFile, 0644); err != nil { if err := rf.WriteFile(repoFile, 0644); err != nil {
return err t.Fatal(err)
} }
} }
if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate { if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate {
t.Log("Updating repository file format...") t.Log("Updating repository file format...")
if err := r.WriteFile(repoFile, 0644); err != nil { if err := r.WriteFile(repoFile, 0644); err != nil {
return err t.Fatal(err)
} }
} }
t.Logf("$HELM_HOME has been configured at %s.\n", home) t.Logf("$HELM_HOME has been configured at %s.\n", home)
return nil
} }
func TestRootCmd(t *testing.T) { // testHelmHome sets up a Helm Home in a temp dir.
cleanup := resetEnv() func testHelmHome(t *testing.T) helmpath.Home {
defer cleanup() t.Helper()
dir := helmpath.Home(testTempDir(t))
tests := []struct { ensureTestHome(t, dir)
name, args, home string return dir
envars map[string]string
}{
{
name: "defaults",
args: "home",
home: filepath.Join(os.Getenv("HOME"), "/.helm"),
},
{
name: "with --home set",
args: "--home /foo",
home: "/foo",
},
{
name: "subcommands with --home set",
args: "home --home /foo",
home: "/foo",
},
{
name: "with $HELM_HOME set",
args: "home",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "subcommands with $HELM_HOME set",
args: "home",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "with $HELM_HOME and --home set",
args: "home --home /foo",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/foo",
},
}
// ensure not set locally
os.Unsetenv("HELM_HOME")
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer os.Unsetenv("HELM_HOME")
for k, v := range tt.envars {
os.Setenv(k, v)
}
cmd, _, err := executeCommandC(nil, tt.args)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if settings.Home.String() != tt.home {
t.Errorf("expected home %q, got %q", tt.home, settings.Home)
}
homeFlag := cmd.Flag("home").Value.String()
homeFlag = os.ExpandEnv(homeFlag)
if homeFlag != tt.home {
t.Errorf("expected home %q, got %q", tt.home, homeFlag)
}
})
}
} }
func resetEnv() func() { func resetEnv() func() {
origSettings := settings origSettings, origEnv := settings, os.Environ()
origEnv := os.Environ()
return func() { return func() {
os.Clearenv()
settings = origSettings settings = origSettings
for _, pair := range origEnv { for _, pair := range origEnv {
kv := strings.SplitN(pair, "=", 2) kv := strings.SplitN(pair, "=", 2)
@ -227,3 +168,15 @@ func resetEnv() func() {
} }
} }
} }
func testChdir(t *testing.T, dir string) func() {
t.Helper()
old, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
if err := os.Chdir(dir); err != nil {
t.Fatal(err)
}
return func() { os.Chdir(old) }
}

@ -32,7 +32,7 @@ func TestHistoryCmd(t *testing.T) {
}) })
} }
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "get history for release", name: "get history for release",
cmd: "history angry-bird", cmd: "history angry-bird",
rels: []*rpb.Release{ rels: []*rpb.Release{
@ -67,5 +67,5 @@ func TestHistoryCmd(t *testing.T) {
}, },
golden: "output/history.json", golden: "output/history.json",
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -18,7 +18,6 @@ package main
import ( import (
"bytes" "bytes"
"io/ioutil"
"os" "os"
"testing" "testing"
@ -26,14 +25,9 @@ import (
) )
func TestEnsureHome(t *testing.T) { func TestEnsureHome(t *testing.T) {
home, err := ioutil.TempDir("", "helm_home") hh := helmpath.Home(testTempDir(t))
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(home)
b := bytes.NewBuffer(nil) b := bytes.NewBuffer(nil)
hh := helmpath.Home(home)
settings.Home = hh settings.Home = hh
if err := ensureDirectories(hh, b); err != nil { if err := ensureDirectories(hh, b); err != nil {
t.Error(err) t.Error(err)

@ -23,7 +23,7 @@ import (
) )
func TestInstall(t *testing.T) { func TestInstall(t *testing.T) {
tests := []releaseCase{ tests := []cmdTestCase{
// Install, base case // Install, base case
{ {
name: "basic install", name: "basic install",
@ -120,7 +120,7 @@ func TestInstall(t *testing.T) {
}, },
} }
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }
type nameTemplateTestCase struct { type nameTemplateTestCase struct {

@ -24,7 +24,7 @@ import (
) )
func TestListCmd(t *testing.T) { func TestListCmd(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "with a release", name: "with a release",
cmd: "list", cmd: "list",
rels: []*release.Release{ rels: []*release.Release{
@ -111,5 +111,5 @@ func TestListCmd(t *testing.T) {
golden: "output/list-with-old-releases.txt", golden: "output/list-with-old-releases.txt",
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -53,6 +53,7 @@ func TestSetVersion(t *testing.T) {
} }
func TestPackage(t *testing.T) { func TestPackage(t *testing.T) {
defer resetEnv()()
tests := []struct { tests := []struct {
name string name string
@ -132,32 +133,20 @@ func TestPackage(t *testing.T) {
}, },
} }
// Because these tests are destructive, we run them in a tempdir.
origDir, err := os.Getwd() origDir, err := os.Getwd()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
tmp, err := ioutil.TempDir("", "helm-package-test-") tmp := testTempDir(t)
if err != nil {
t.Fatal(err)
}
t.Logf("Running tests in %s", tmp) t.Logf("Running tests in %s", tmp)
if err := os.Chdir(tmp); err != nil { defer testChdir(t, tmp)()
t.Fatal(err)
}
if err := os.Mkdir("toot", 0777); err != nil { if err := os.Mkdir("toot", 0777); err != nil {
t.Fatal(err) t.Fatal(err)
} }
ensureTestHome(t, helmpath.Home(tmp)) ensureTestHome(t, helmpath.Home(tmp))
cleanup := resetEnv()
defer func() {
os.Chdir(origDir)
os.RemoveAll(tmp)
cleanup()
}()
settings.Home = helmpath.Home(tmp) settings.Home = helmpath.Home(tmp)
@ -210,22 +199,14 @@ func TestPackage(t *testing.T) {
} }
func TestSetAppVersion(t *testing.T) { func TestSetAppVersion(t *testing.T) {
defer resetEnv()()
var ch *chart.Chart var ch *chart.Chart
expectedAppVersion := "app-version-foo" expectedAppVersion := "app-version-foo"
tmp, _ := ioutil.TempDir("", "helm-package-app-version-") tmp := testTempDir(t)
thome, err := tempHelmHome(t) hh := testHelmHome(t)
if err != nil { settings.Home = helmpath.Home(hh)
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(tmp)
os.RemoveAll(thome.String())
cleanup()
}()
settings.Home = helmpath.Home(thome)
c := newPackageCmd(&bytes.Buffer{}) c := newPackageCmd(&bytes.Buffer{})
flags := map[string]string{ flags := map[string]string{
@ -233,8 +214,7 @@ func TestSetAppVersion(t *testing.T) {
"app-version": expectedAppVersion, "app-version": expectedAppVersion,
} }
setFlags(c, flags) setFlags(c, flags)
err = c.RunE(c, []string{"testdata/testcharts/alpine"}) if err := c.RunE(c, []string{"testdata/testcharts/alpine"}); err != nil {
if err != nil {
t.Errorf("unexpected error %q", err) t.Errorf("unexpected error %q", err)
} }
@ -244,7 +224,7 @@ func TestSetAppVersion(t *testing.T) {
} else if fi.Size() == 0 { } else if fi.Size() == 0 {
t.Errorf("file %q has zero bytes.", chartPath) t.Errorf("file %q has zero bytes.", chartPath)
} }
ch, err = chartutil.Load(chartPath) ch, err := chartutil.Load(chartPath)
if err != nil { if err != nil {
t.Errorf("unexpected error loading packaged chart: %v", err) t.Errorf("unexpected error loading packaged chart: %v", err)
} }
@ -254,6 +234,8 @@ func TestSetAppVersion(t *testing.T) {
} }
func TestPackageValues(t *testing.T) { func TestPackageValues(t *testing.T) {
defer resetEnv()()
testCases := []struct { testCases := []struct {
desc string desc string
args []string args []string
@ -288,26 +270,13 @@ func TestPackageValues(t *testing.T) {
}, },
} }
thome, err := tempHelmHome(t) hh := testHelmHome(t)
if err != nil { settings.Home = hh
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(thome.String())
cleanup()
}()
settings.Home = thome
for _, tc := range testCases { for _, tc := range testCases {
var files []string var files []string
for _, contents := range tc.valuefilesContents { for _, contents := range tc.valuefilesContents {
f, err := createValuesFile(contents) f := createValuesFile(t, contents)
if err != nil {
t.Errorf("%q unexpected error creating temporary values file: %q", tc.desc, err)
}
defer os.RemoveAll(filepath.Dir(f))
files = append(files, f) files = append(files, f)
} }
valueFiles := strings.Join(files, ",") valueFiles := strings.Join(files, ",")
@ -322,11 +291,7 @@ func TestPackageValues(t *testing.T) {
} }
func runAndVerifyPackageCommandValues(t *testing.T, args []string, flags map[string]string, valueFiles string, expected chartutil.Values) { func runAndVerifyPackageCommandValues(t *testing.T, args []string, flags map[string]string, valueFiles string, expected chartutil.Values) {
outputDir, err := ioutil.TempDir("", "helm-package") outputDir := testTempDir(t)
if err != nil {
t.Errorf("unexpected error creating temporary output directory: %q", err)
}
defer os.RemoveAll(outputDir)
if len(flags) == 0 { if len(flags) == 0 {
flags = make(map[string]string) flags = make(map[string]string)
@ -339,16 +304,14 @@ func runAndVerifyPackageCommandValues(t *testing.T, args []string, flags map[str
cmd := newPackageCmd(&bytes.Buffer{}) cmd := newPackageCmd(&bytes.Buffer{})
setFlags(cmd, flags) setFlags(cmd, flags)
err = cmd.RunE(cmd, args) if err := cmd.RunE(cmd, args); err != nil {
if err != nil {
t.Errorf("unexpected error: %q", err) t.Errorf("unexpected error: %q", err)
} }
outputFile := filepath.Join(outputDir, "alpine-0.1.0.tgz") outputFile := filepath.Join(outputDir, "alpine-0.1.0.tgz")
verifyOutputChartExists(t, outputFile) verifyOutputChartExists(t, outputFile)
var actual chartutil.Values actual, err := getChartValues(outputFile)
actual, err = getChartValues(outputFile)
if err != nil { if err != nil {
t.Errorf("unexpected error extracting chart values: %q", err) t.Errorf("unexpected error extracting chart values: %q", err)
} }
@ -356,19 +319,15 @@ func runAndVerifyPackageCommandValues(t *testing.T, args []string, flags map[str
verifyValues(t, actual, expected) verifyValues(t, actual, expected)
} }
func createValuesFile(data string) (string, error) { func createValuesFile(t *testing.T, data string) string {
outputDir, err := ioutil.TempDir("", "values-file") outputDir := testTempDir(t)
if err != nil {
return "", err
}
outputFile := filepath.Join(outputDir, "values.yaml") outputFile := filepath.Join(outputDir, "values.yaml")
if err = ioutil.WriteFile(outputFile, []byte(data), 0755); err != nil { if err := ioutil.WriteFile(outputFile, []byte(data), 0755); err != nil {
os.RemoveAll(outputFile) t.Fatalf("err: %s", err)
return "", err
} }
return outputFile, nil return outputFile
} }
func getChartValues(chartPath string) (chartutil.Values, error) { func getChartValues(chartPath string) (chartutil.Values, error) {

@ -62,8 +62,7 @@ func TestManuallyProcessArgs(t *testing.T) {
} }
func TestLoadPlugins(t *testing.T) { func TestLoadPlugins(t *testing.T) {
cleanup := resetEnv() defer resetEnv()()
defer cleanup()
settings.Home = "testdata/helmhome" settings.Home = "testdata/helmhome"
@ -133,8 +132,7 @@ func TestLoadPlugins(t *testing.T) {
} }
func TestLoadPlugins_HelmNoPlugins(t *testing.T) { func TestLoadPlugins_HelmNoPlugins(t *testing.T) {
cleanup := resetEnv() defer resetEnv()()
defer cleanup()
settings.Home = "testdata/helmhome" settings.Home = "testdata/helmhome"
@ -151,6 +149,7 @@ func TestLoadPlugins_HelmNoPlugins(t *testing.T) {
} }
func TestSetupEnv(t *testing.T) { func TestSetupEnv(t *testing.T) {
defer resetEnv()()
name := "pequod" name := "pequod"
settings.Home = helmpath.Home("testdata/helmhome") settings.Home = helmpath.Home("testdata/helmhome")
base := filepath.Join(settings.Home.Plugins(), name) base := filepath.Join(settings.Home.Plugins(), name)

@ -23,7 +23,7 @@ import (
) )
func TestReleaseTesting(t *testing.T) { func TestReleaseTesting(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "basic test", name: "basic test",
cmd: "test example-release", cmd: "test example-release",
testRunStatus: map[string]release.TestRunStatus{"PASSED: green lights everywhere": release.TestRunSuccess}, testRunStatus: map[string]release.TestRunStatus{"PASSED: green lights everywhere": release.TestRunSuccess},
@ -62,5 +62,5 @@ func TestReleaseTesting(t *testing.T) {
"PASSED: feel free to party again": release.TestRunSuccess}, "PASSED: feel free to party again": release.TestRunSuccess},
wantError: true, wantError: true,
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -26,50 +26,43 @@ import (
) )
func TestRepoAddCmd(t *testing.T) { func TestRepoAddCmd(t *testing.T) {
srv, thome, err := repotest.NewTempServer("testdata/testserver/*.*") defer resetEnv()()
srv, hh, err := repotest.NewTempServer("testdata/testserver/*.*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
cleanup := resetEnv()
defer func() { defer func() {
srv.Stop() srv.Stop()
os.RemoveAll(thome.String()) os.RemoveAll(hh.String())
cleanup()
}() }()
if err := ensureTestHome(t, thome); err != nil { ensureTestHome(t, hh)
t.Fatal(err) settings.Home = hh
}
settings.Home = thome
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "add a repository", name: "add a repository",
cmd: fmt.Sprintf("repo add test-name %s --home %s", srv.URL(), thome), cmd: fmt.Sprintf("repo add test-name %s --home %s", srv.URL(), hh),
golden: "output/repo-add.txt", golden: "output/repo-add.txt",
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }
func TestRepoAdd(t *testing.T) { func TestRepoAdd(t *testing.T) {
ts, thome, err := repotest.NewTempServer("testdata/testserver/*.*") defer resetEnv()()
ts, hh, err := repotest.NewTempServer("testdata/testserver/*.*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
cleanup := resetEnv()
hh := thome
defer func() { defer func() {
ts.Stop() ts.Stop()
os.RemoveAll(thome.String()) os.RemoveAll(hh.String())
cleanup()
}() }()
if err := ensureTestHome(t, hh); err != nil { ensureTestHome(t, hh)
t.Fatal(err) settings.Home = hh
}
settings.Home = thome
const testRepoName = "test-name" const testRepoName = "test-name"

@ -19,7 +19,6 @@ package main
import ( import (
"bytes" "bytes"
"io" "io"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -29,11 +28,7 @@ import (
func TestRepoIndexCmd(t *testing.T) { func TestRepoIndexCmd(t *testing.T) {
dir, err := ioutil.TempDir("", "helm-") dir := testTempDir(t)
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
comp := filepath.Join(dir, "compressedchart-0.1.0.tgz") comp := filepath.Join(dir, "compressedchart-0.1.0.tgz")
if err := linkOrCopy("testdata/testcharts/compressedchart-0.1.0.tgz", comp); err != nil { if err := linkOrCopy("testdata/testcharts/compressedchart-0.1.0.tgz", comp); err != nil {

@ -22,29 +22,24 @@ import (
"strings" "strings"
"testing" "testing"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
"k8s.io/helm/pkg/repo/repotest" "k8s.io/helm/pkg/repo/repotest"
) )
func TestRepoRemove(t *testing.T) { func TestRepoRemove(t *testing.T) {
ts, thome, err := repotest.NewTempServer("testdata/testserver/*.*") defer resetEnv()()
ts, hh, err := repotest.NewTempServer("testdata/testserver/*.*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
hh := helmpath.Home(thome)
cleanup := resetEnv()
defer func() { defer func() {
ts.Stop() ts.Stop()
os.RemoveAll(thome.String()) os.RemoveAll(hh.String())
cleanup()
}() }()
if err := ensureTestHome(t, hh); err != nil { ensureTestHome(t, hh)
t.Fatal(err) settings.Home = hh
}
settings.Home = thome
const testRepoName = "test-name" const testRepoName = "test-name"

@ -30,18 +30,10 @@ import (
) )
func TestUpdateCmd(t *testing.T) { func TestUpdateCmd(t *testing.T) {
thome, err := tempHelmHome(t) defer resetEnv()()
if err != nil {
t.Fatal(err)
}
cleanup := resetEnv()
defer func() {
os.RemoveAll(thome.String())
cleanup()
}()
settings.Home = thome hh := testHelmHome(t)
settings.Home = hh
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
// Instead of using the HTTP updater, we provide our own for this test. // Instead of using the HTTP updater, we provide our own for this test.
@ -53,7 +45,7 @@ func TestUpdateCmd(t *testing.T) {
} }
o := &repoUpdateOptions{ o := &repoUpdateOptions{
update: updater, update: updater,
home: helmpath.Home(thome), home: helmpath.Home(hh),
} }
if err := o.run(out); err != nil { if err := o.run(out); err != nil {
t.Fatal(err) t.Fatal(err)
@ -65,23 +57,19 @@ func TestUpdateCmd(t *testing.T) {
} }
func TestUpdateCharts(t *testing.T) { func TestUpdateCharts(t *testing.T) {
ts, thome, err := repotest.NewTempServer("testdata/testserver/*.*") defer resetEnv()()
ts, hh, err := repotest.NewTempServer("testdata/testserver/*.*")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
hh := helmpath.Home(thome)
cleanup := resetEnv()
defer func() { defer func() {
ts.Stop() ts.Stop()
os.RemoveAll(thome.String()) os.RemoveAll(hh.String())
cleanup()
}() }()
if err := ensureTestHome(t, hh); err != nil { ensureTestHome(t, hh)
t.Fatal(err) settings.Home = hh
}
settings.Home = thome
r, err := repo.NewChartRepository(&repo.Entry{ r, err := repo.NewChartRepository(&repo.Entry{
Name: "charts", Name: "charts",

@ -21,7 +21,7 @@ import (
) )
func TestRollbackCmd(t *testing.T) { func TestRollbackCmd(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "rollback a release", name: "rollback a release",
cmd: "rollback funny-honey 1", cmd: "rollback funny-honey 1",
golden: "output/rollback.txt", golden: "output/rollback.txt",
@ -39,5 +39,5 @@ func TestRollbackCmd(t *testing.T) {
golden: "output/rollback-no-args.txt", golden: "output/rollback-no-args.txt",
wantError: true, wantError: true,
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -0,0 +1,102 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main // import "k8s.io/helm/cmd/helm"
import (
"io"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)
var globalUsage = `The Kubernetes package manager
To begin working with Helm, run the 'helm init' command:
$ helm init
This will set up any necessary local configuration.
Common actions from this point include:
- helm search: search for charts
- helm fetch: download a chart to your local directory to view
- helm install: upload the chart to Kubernetes
- helm list: list releases of charts
Environment:
$HELM_HOME set an alternative location for Helm files. By default, these are stored in ~/.helm
$HELM_NO_PLUGINS disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins.
$KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config")
`
func newRootCmd(c helm.Interface, out io.Writer, args []string) *cobra.Command {
cmd := &cobra.Command{
Use: "helm",
Short: "The Helm package manager for Kubernetes.",
Long: globalUsage,
SilenceUsage: true,
}
flags := cmd.PersistentFlags()
settings.AddFlags(flags)
cmd.AddCommand(
// chart commands
newCreateCmd(out),
newDependencyCmd(out),
newFetchCmd(out),
newInspectCmd(out),
newLintCmd(out),
newPackageCmd(out),
newRepoCmd(out),
newSearchCmd(out),
newVerifyCmd(out),
// release commands
newDeleteCmd(c, out),
newGetCmd(c, out),
newHistoryCmd(c, out),
newInstallCmd(c, out),
newListCmd(c, out),
newReleaseTestCmd(c, out),
newRollbackCmd(c, out),
newStatusCmd(c, out),
newUpgradeCmd(c, out),
newCompletionCmd(out),
newHomeCmd(out),
newInitCmd(out),
newPluginCmd(out),
newTemplateCmd(out),
newVersionCmd(out),
// Hidden documentation generator command: 'helm docs'
newDocsCmd(out),
)
flags.Parse(args)
// set defaults from environment
settings.Init(flags)
// Find and add plugins
loadPlugins(cmd, out)
return cmd
}

@ -0,0 +1,93 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"os"
"path/filepath"
"testing"
)
func TestRootCmd(t *testing.T) {
defer resetEnv()()
tests := []struct {
name, args, home string
envars map[string]string
}{
{
name: "defaults",
args: "home",
home: filepath.Join(os.Getenv("HOME"), "/.helm"),
},
{
name: "with --home set",
args: "--home /foo",
home: "/foo",
},
{
name: "subcommands with --home set",
args: "home --home /foo",
home: "/foo",
},
{
name: "with $HELM_HOME set",
args: "home",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "subcommands with $HELM_HOME set",
args: "home",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "with $HELM_HOME and --home set",
args: "home --home /foo",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/foo",
},
}
// ensure not set locally
os.Unsetenv("HELM_HOME")
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer os.Unsetenv("HELM_HOME")
for k, v := range tt.envars {
os.Setenv(k, v)
}
cmd, _, err := executeCommandC(nil, tt.args)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if settings.Home.String() != tt.home {
t.Errorf("expected home %q, got %q", tt.home, settings.Home)
}
homeFlag := cmd.Flag("home").Value.String()
homeFlag = os.ExpandEnv(homeFlag)
if homeFlag != tt.home {
t.Errorf("expected home %q, got %q", tt.home, homeFlag)
}
})
}
}

@ -21,51 +21,52 @@ import (
) )
func TestSearchCmd(t *testing.T) { func TestSearchCmd(t *testing.T) {
tests := []releaseCase{{ defer resetEnv()()
setHome := func(cmd string) string {
return cmd + " --home=testdata/helmhome"
}
tests := []cmdTestCase{{
name: "search for 'maria', expect one match", name: "search for 'maria', expect one match",
cmd: "search maria", cmd: setHome("search maria"),
golden: "output/search-single.txt", golden: "output/search-single.txt",
}, { }, {
name: "search for 'alpine', expect two matches", name: "search for 'alpine', expect two matches",
cmd: "search alpine", cmd: setHome("search alpine"),
golden: "output/search-multiple.txt", golden: "output/search-multiple.txt",
}, { }, {
name: "search for 'alpine' with versions, expect three matches", name: "search for 'alpine' with versions, expect three matches",
cmd: "search alpine --versions", cmd: setHome("search alpine --versions"),
golden: "output/search-multiple-versions.txt", golden: "output/search-multiple-versions.txt",
}, { }, {
name: "search for 'alpine' with version constraint, expect one match with version 0.1.0", name: "search for 'alpine' with version constraint, expect one match with version 0.1.0",
cmd: "search alpine --version '>= 0.1, < 0.2'", cmd: setHome("search alpine --version '>= 0.1, < 0.2'"),
golden: "output/search-constraint.txt", golden: "output/search-constraint.txt",
}, { }, {
name: "search for 'alpine' with version constraint, expect one match with version 0.1.0", name: "search for 'alpine' with version constraint, expect one match with version 0.1.0",
cmd: "search alpine --versions --version '>= 0.1, < 0.2'", cmd: setHome("search alpine --versions --version '>= 0.1, < 0.2'"),
golden: "output/search-versions-constraint.txt", golden: "output/search-versions-constraint.txt",
}, { }, {
name: "search for 'alpine' with version constraint, expect one match with version 0.2.0", name: "search for 'alpine' with version constraint, expect one match with version 0.2.0",
cmd: "search alpine --version '>= 0.1'", cmd: setHome("search alpine --version '>= 0.1'"),
golden: "output/search-constraint-single.txt", golden: "output/search-constraint-single.txt",
}, { }, {
name: "search for 'alpine' with version constraint and --versions, expect two matches", name: "search for 'alpine' with version constraint and --versions, expect two matches",
cmd: "search alpine --versions --version '>= 0.1'", cmd: setHome("search alpine --versions --version '>= 0.1'"),
golden: "output/search-multiple-versions-constraints.txt", golden: "output/search-multiple-versions-constraints.txt",
}, { }, {
name: "search for 'syzygy', expect no matches", name: "search for 'syzygy', expect no matches",
cmd: "search syzygy", cmd: setHome("search syzygy"),
golden: "output/search-not-found.txt", golden: "output/search-not-found.txt",
}, { }, {
name: "search for 'alp[a-z]+', expect two matches", name: "search for 'alp[a-z]+', expect two matches",
cmd: "search alp[a-z]+ --regexp", cmd: setHome("search alp[a-z]+ --regexp"),
golden: "output/search-regex.txt", golden: "output/search-regex.txt",
}, { }, {
name: "search for 'alp[', expect failure to compile regexp", name: "search for 'alp[', expect failure to compile regexp",
cmd: "search alp[ --regexp", cmd: setHome("search alp[ --regexp"),
wantError: true, wantError: true,
}} }}
runTestCmd(t, tests)
cleanup := resetEnv()
defer cleanup()
settings.Home = "testdata/helmhome"
testReleaseCmd(t, tests)
} }

@ -32,7 +32,7 @@ func TestStatusCmd(t *testing.T) {
}} }}
} }
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "get status of a deployed release", name: "get status of a deployed release",
cmd: "status flummoxed-chickadee", cmd: "status flummoxed-chickadee",
golden: "output/status.txt", golden: "output/status.txt",
@ -89,5 +89,5 @@ func TestStatusCmd(t *testing.T) {
}, },
}), }),
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -1,47 +1,3 @@
REVISION: 1
RELEASED: Fri Sep 2 22:04:05 1977
CHART: testUpgradeChart-0.1.0
USER-SUPPLIED VALUES:
name: "value"
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- chart-example.local
path: /
tls: []
name: value
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
---
# pre-install-hook
apiVersion: v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-install
MANIFEST:
apiVersion: v1
kind: Secret
metadata:
name: fixture
Release "crazy-bunny" has been upgraded. Happy Helming! Release "crazy-bunny" has been upgraded. Happy Helming!
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default NAMESPACE: default

@ -1,47 +1,3 @@
REVISION: 1
RELEASED: Fri Sep 2 22:04:05 1977
CHART: testUpgradeChart-0.1.0
USER-SUPPLIED VALUES:
name: "value"
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- chart-example.local
path: /
tls: []
name: value
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
---
# pre-install-hook
apiVersion: v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-install
MANIFEST:
apiVersion: v1
kind: Secret
metadata:
name: fixture
Release "zany-bunny" has been upgraded. Happy Helming! Release "zany-bunny" has been upgraded. Happy Helming!
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default NAMESPACE: default

@ -1,47 +1,3 @@
REVISION: 4
RELEASED: Fri Sep 2 22:04:05 1977
CHART: testUpgradeChart-0.1.0
USER-SUPPLIED VALUES:
name: "value"
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- chart-example.local
path: /
tls: []
name: value
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
---
# pre-install-hook
apiVersion: v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-install
MANIFEST:
apiVersion: v1
kind: Secret
metadata:
name: fixture
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default NAMESPACE: default

@ -1,47 +1,3 @@
REVISION: 5
RELEASED: Fri Sep 2 22:04:05 1977
CHART: testUpgradeChart-0.1.0
USER-SUPPLIED VALUES:
name: "value"
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- chart-example.local
path: /
tls: []
name: value
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
---
# pre-install-hook
apiVersion: v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-install
MANIFEST:
apiVersion: v1
kind: Secret
metadata:
name: fixture
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default NAMESPACE: default

@ -1,47 +1,3 @@
REVISION: 3
RELEASED: Fri Sep 2 22:04:05 1977
CHART: testUpgradeChart-0.1.0
USER-SUPPLIED VALUES:
name: "value"
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- chart-example.local
path: /
tls: []
name: value
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
---
# pre-install-hook
apiVersion: v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-install
MANIFEST:
apiVersion: v1
kind: Secret
metadata:
name: fixture
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default NAMESPACE: default

@ -1,47 +1,3 @@
REVISION: 2
RELEASED: Fri Sep 2 22:04:05 1977
CHART: testUpgradeChart-0.1.0
USER-SUPPLIED VALUES:
name: "value"
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- chart-example.local
path: /
tls: []
name: value
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
---
# pre-install-hook
apiVersion: v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-install
MANIFEST:
apiVersion: v1
kind: Secret
metadata:
name: fixture
Release "crazy-bunny" has been upgraded. Happy Helming! Release "crazy-bunny" has been upgraded. Happy Helming!
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default NAMESPACE: default

@ -1,47 +1,3 @@
REVISION: 2
RELEASED: Fri Sep 2 22:04:05 1977
CHART: testUpgradeChart-0.1.0
USER-SUPPLIED VALUES:
name: "value"
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- chart-example.local
path: /
tls: []
name: value
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
---
# pre-install-hook
apiVersion: v1
kind: Job
metadata:
annotations:
"helm.sh/hook": pre-install
MANIFEST:
apiVersion: v1
kind: Secret
metadata:
name: fixture
Release "funny-bunny" has been upgraded. Happy Helming! Release "funny-bunny" has been upgraded. Happy Helming!
LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC LAST DEPLOYED: 1977-09-02 22:04:05 +0000 UTC
NAMESPACE: default NAMESPACE: default

@ -17,9 +17,6 @@ limitations under the License.
package main package main
import ( import (
"io/ioutil"
"os"
"path/filepath"
"testing" "testing"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
@ -29,8 +26,7 @@ import (
) )
func TestUpgradeCmd(t *testing.T) { func TestUpgradeCmd(t *testing.T) {
tmpChart, _ := ioutil.TempDir("testdata", "tmp") tmpChart := testTempDir(t)
defer os.RemoveAll(tmpChart)
cfile := &chart.Metadata{ cfile := &chart.Metadata{
Name: "testUpgradeChart", Name: "testUpgradeChart",
Description: "A Helm chart for Kubernetes", Description: "A Helm chart for Kubernetes",
@ -38,9 +34,12 @@ func TestUpgradeCmd(t *testing.T) {
} }
chartPath, err := chartutil.Create(cfile, tmpChart) chartPath, err := chartutil.Create(cfile, tmpChart)
if err != nil { if err != nil {
t.Errorf("Error creating chart for upgrade: %v", err) t.Fatalf("Error creating chart for upgrade: %v", err)
}
ch, err := chartutil.Load(chartPath)
if err != nil {
t.Fatalf("Error loading chart: %v", err)
} }
ch, _ := chartutil.Load(chartPath)
_ = helm.ReleaseMock(&helm.MockReleaseOptions{ _ = helm.ReleaseMock(&helm.MockReleaseOptions{
Name: "funny-bunny", Name: "funny-bunny",
Chart: ch, Chart: ch,
@ -55,11 +54,11 @@ func TestUpgradeCmd(t *testing.T) {
chartPath, err = chartutil.Create(cfile, tmpChart) chartPath, err = chartutil.Create(cfile, tmpChart)
if err != nil { if err != nil {
t.Errorf("Error creating chart: %v", err) t.Fatalf("Error creating chart: %v", err)
} }
ch, err = chartutil.Load(chartPath) ch, err = chartutil.Load(chartPath)
if err != nil { if err != nil {
t.Errorf("Error loading updated chart: %v", err) t.Fatalf("Error loading updated chart: %v", err)
} }
// update chart version again // update chart version again
@ -71,22 +70,22 @@ func TestUpgradeCmd(t *testing.T) {
chartPath, err = chartutil.Create(cfile, tmpChart) chartPath, err = chartutil.Create(cfile, tmpChart)
if err != nil { if err != nil {
t.Errorf("Error creating chart: %v", err) t.Fatalf("Error creating chart: %v", err)
} }
var ch2 *chart.Chart var ch2 *chart.Chart
ch2, err = chartutil.Load(chartPath) ch2, err = chartutil.Load(chartPath)
if err != nil { if err != nil {
t.Errorf("Error loading updated chart: %v", err) t.Fatalf("Error loading updated chart: %v", err)
} }
missingDepsPath := filepath.Join("testdata/testcharts/chart-missing-deps") missingDepsPath := "testdata/testcharts/chart-missing-deps"
badDepsPath := filepath.Join("testdata/testcharts/chart-bad-requirements") badDepsPath := "testdata/testcharts/chart-bad-requirements"
relMock := func(n string, v int, ch *chart.Chart) *release.Release { relMock := func(n string, v int, ch *chart.Chart) *release.Release {
return helm.ReleaseMock(&helm.MockReleaseOptions{Name: n, Version: v, Chart: ch}) return helm.ReleaseMock(&helm.MockReleaseOptions{Name: n, Version: v, Chart: ch})
} }
tests := []releaseCase{ tests := []cmdTestCase{
{ {
name: "upgrade a release", name: "upgrade a release",
cmd: "upgrade funny-bunny " + chartPath, cmd: "upgrade funny-bunny " + chartPath,
@ -142,5 +141,5 @@ func TestUpgradeCmd(t *testing.T) {
wantError: true, wantError: true,
}, },
} }
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -20,7 +20,7 @@ import (
) )
func TestVersion(t *testing.T) { func TestVersion(t *testing.T) {
tests := []releaseCase{{ tests := []cmdTestCase{{
name: "default", name: "default",
cmd: "version", cmd: "version",
golden: "output/version.txt", golden: "output/version.txt",
@ -29,5 +29,5 @@ func TestVersion(t *testing.T) {
cmd: "version --template='Version: {{.Version}}'", cmd: "version --template='Version: {{.Version}}'",
golden: "output/version-template.txt", golden: "output/version-template.txt",
}} }}
testReleaseCmd(t, tests) runTestCmd(t, tests)
} }

@ -42,7 +42,7 @@ func AssertGoldenBytes(t TestingT, actual []byte, filename string) {
t.Helper() t.Helper()
if err := compare(actual, path(filename)); err != nil { if err := compare(actual, path(filename)); err != nil {
t.Fatalf("%+v", err) t.Fatalf("%v", err)
} }
} }
@ -50,7 +50,7 @@ func AssertGoldenString(t TestingT, actual, filename string) {
t.Helper() t.Helper()
if err := compare([]byte(actual), path(filename)); err != nil { if err := compare([]byte(actual), path(filename)); err != nil {
t.Fatalf("%+v", err) t.Fatalf("%v", err)
} }
} }

@ -71,11 +71,10 @@ func TestEnvSettings(t *testing.T) {
}, },
} }
cleanup := resetEnv()
defer cleanup()
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
defer resetEnv()()
for k, v := range tt.envars { for k, v := range tt.envars {
os.Setenv(k, v) os.Setenv(k, v)
} }
@ -103,8 +102,6 @@ func TestEnvSettings(t *testing.T) {
if settings.KubeContext != tt.kcontext { if settings.KubeContext != tt.kcontext {
t.Errorf("expected kube-context %q, got %q", tt.kcontext, settings.KubeContext) t.Errorf("expected kube-context %q, got %q", tt.kcontext, settings.KubeContext)
} }
cleanup()
}) })
} }
} }

Loading…
Cancel
Save