ref(cmd): simplify cmd test setup

pull/3976/head
Adam Reese 6 years ago
parent 7bf0cb6c46
commit a5b7cde9e5
No known key found for this signature in database
GPG Key ID: 06F35E60A7A18DD6

14
Gopkg.lock generated

@ -337,6 +337,12 @@
revision = "d6bea18f789704b5f83375793155289da36a3c7f"
version = "v0.0.1"
[[projects]]
name = "github.com/mattn/go-shellwords"
packages = ["."]
revision = "02e3cf038dcea8290e44424da473dd12be796a8a"
version = "v1.0.3"
[[projects]]
name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"]
@ -431,12 +437,14 @@
".",
"doc"
]
revision = "f62e98d28ab7ad31d707ba837a966378465c7b57"
revision = "a1f051bc3eba734da4772d60e2d677f47cf93ef4"
version = "v0.0.2"
[[projects]]
name = "github.com/spf13/pflag"
packages = ["."]
revision = "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.1"
[[projects]]
name = "github.com/stretchr/testify"
@ -1063,6 +1071,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "d27aa9378f7846f9dc4de8168f8a2dd6d9584fefddd26e2a9e172b9d8fc075c9"
inputs-digest = "82526354be9627a0e3796098ee9bed433a3e7958495f65e371ecc27d8c71c111"
solver-name = "gps-cdcl"
solver-version = 1

@ -17,57 +17,51 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
func TestDelete(t *testing.T) {
resp := helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})
rels := []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})}
tests := []releaseCase{
{
name: "basic delete",
args: []string{"aeneas"},
flags: []string{},
expected: "", // Output of a delete is an empty string and exit 0.
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
name: "basic delete",
cmd: "delete aeneas",
matches: `release "aeneas" deleted`,
resp: resp,
rels: rels,
},
{
name: "delete with timeout",
args: []string{"aeneas"},
flags: []string{"--timeout", "120"},
expected: "",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
name: "delete with timeout",
cmd: "delete aeneas --timeout 120",
matches: `release "aeneas" deleted`,
resp: resp,
rels: rels,
},
{
name: "delete without hooks",
args: []string{"aeneas"},
flags: []string{"--no-hooks"},
expected: "",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
name: "delete without hooks",
cmd: "delete aeneas --no-hooks",
matches: `release "aeneas" deleted`,
resp: resp,
rels: rels,
},
{
name: "purge",
args: []string{"aeneas"},
flags: []string{"--purge"},
expected: "",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
name: "purge",
cmd: "delete aeneas --purge",
matches: `release "aeneas" deleted`,
resp: resp,
rels: rels,
},
{
name: "delete without release",
args: []string{},
err: true,
name: "delete without release",
cmd: "delete",
wantError: true,
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newDeleteCmd(c, out)
})
testReleaseCmd(t, tests)
}

@ -16,43 +16,35 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)
func TestDependencyListCmd(t *testing.T) {
tests := []releaseCase{
{
name: "No such chart",
args: []string{"/no/such/chart"},
err: true,
name: "No such chart",
cmd: "dependency list /no/such/chart",
wantError: true,
},
{
name: "No requirements.yaml",
args: []string{"testdata/testcharts/alpine"},
expected: "WARNING: no requirements at ",
name: "No requirements.yaml",
cmd: "dependency list testdata/testcharts/alpine",
matches: "WARNING: no requirements at ",
},
{
name: "Requirements in chart dir",
args: []string{"testdata/testcharts/reqtest"},
expected: "NAME \tVERSION\tREPOSITORY \tSTATUS \n" +
cmd: "dependency list testdata/testcharts/reqtest",
matches: "NAME \tVERSION\tREPOSITORY \tSTATUS \n" +
"reqsubchart \t0.1.0 \thttps://example.com/charts\tunpacked\n" +
"reqsubchart2\t0.2.0 \thttps://example.com/charts\tunpacked\n" +
"reqsubchart3\t>=0.1.0\thttps://example.com/charts\tok \n\n",
},
{
name: "Requirements in chart archive",
args: []string{"testdata/testcharts/reqtest-0.1.0.tgz"},
expected: "NAME \tVERSION\tREPOSITORY \tSTATUS \nreqsubchart \t0.1.0 \thttps://example.com/charts\tmissing\nreqsubchart2\t0.2.0 \thttps://example.com/charts\tmissing\n",
name: "Requirements in chart archive",
cmd: "dependency list testdata/testcharts/reqtest-0.1.0.tgz",
matches: "NAME \tVERSION\tREPOSITORY \tSTATUS \nreqsubchart \t0.1.0 \thttps://example.com/charts\tmissing\nreqsubchart2\t0.2.0 \thttps://example.com/charts\tmissing\n",
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newDependencyListCmd(out)
})
testReleaseCmd(t, tests)
}

@ -42,9 +42,10 @@ var errReleaseRequired = errors.New("release name is required")
type getCmd struct {
release string
out io.Writer
client helm.Interface
version int
out io.Writer
client helm.Interface
}
func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command {
@ -69,9 +70,9 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command {
cmd.Flags().IntVar(&get.version, "revision", 0, "get the named release with revision")
cmd.AddCommand(newGetValuesCmd(nil, out))
cmd.AddCommand(newGetManifestCmd(nil, out))
cmd.AddCommand(newGetHooksCmd(nil, out))
cmd.AddCommand(newGetValuesCmd(client, out))
cmd.AddCommand(newGetManifestCmd(client, out))
cmd.AddCommand(newGetHooksCmd(client, out))
return cmd
}

@ -17,11 +17,8 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
@ -29,19 +26,17 @@ import (
func TestGetHooks(t *testing.T) {
tests := []releaseCase{
{
name: "get hooks with release",
args: []string{"aeneas"},
expected: helm.MockHookTemplate,
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
name: "get hooks with release",
cmd: "get hooks aeneas",
matches: helm.MockHookTemplate,
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
},
{
name: "get hooks without args",
args: []string{},
err: true,
name: "get hooks without args",
cmd: "get hooks",
wantError: true,
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newGetHooksCmd(c, out)
})
testReleaseCmd(t, tests)
}

@ -17,11 +17,8 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
@ -29,19 +26,17 @@ import (
func TestGetManifest(t *testing.T) {
tests := []releaseCase{
{
name: "get manifest with release",
args: []string{"juno"},
expected: helm.MockManifest,
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "juno"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "juno"})},
name: "get manifest with release",
cmd: "get manifest juno",
matches: helm.MockManifest,
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "juno"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "juno"})},
},
{
name: "get manifest without args",
args: []string{},
err: true,
name: "get manifest without args",
cmd: "get manifest",
wantError: true,
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newGetManifestCmd(c, out)
})
testReleaseCmd(t, tests)
}

@ -17,11 +17,8 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
@ -29,20 +26,17 @@ import (
func TestGetCmd(t *testing.T) {
tests := []releaseCase{
{
name: "get with a release",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
args: []string{"thomas-guide"},
expected: "REVISION: 1\nRELEASED: (.*)\nCHART: foo-0.1.0-beta.1\nUSER-SUPPLIED VALUES:\nname: \"value\"\nCOMPUTED VALUES:\nname: value\n\nHOOKS:\n---\n# pre-install-hook\n" + helm.MockHookTemplate + "\nMANIFEST:",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"})},
name: "get with a release",
cmd: "get thomas-guide",
matches: "REVISION: 1\nRELEASED: (.*)\nCHART: foo-0.1.0-beta.1\nUSER-SUPPLIED VALUES:\nname: \"value\"\nCOMPUTED VALUES:\nname: value\n\nHOOKS:\n---\n# pre-install-hook\n" + helm.MockHookTemplate + "\nMANIFEST:",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"})},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
},
{
name: "get requires release name arg",
err: true,
name: "get requires release name arg",
cmd: "get",
wantError: true,
},
}
cmd := func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newGetCmd(c, out)
}
runReleaseCases(t, tests, cmd)
testReleaseCmd(t, tests)
}

@ -17,11 +17,8 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
@ -29,19 +26,17 @@ import (
func TestGetValuesCmd(t *testing.T) {
tests := []releaseCase{
{
name: "get values with a release",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
args: []string{"thomas-guide"},
expected: "name: \"value\"",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"})},
name: "get values with a release",
cmd: "get values thomas-guide",
matches: "name: \"value\"",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"})},
},
{
name: "get values requires release name arg",
err: true,
name: "get values requires release name arg",
cmd: "get values",
wantError: true,
},
}
cmd := func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newGetValuesCmd(c, out)
}
runReleaseCases(t, tests, cmd)
testReleaseCmd(t, tests)
}

@ -18,6 +18,7 @@ package main // import "k8s.io/helm/cmd/helm"
import (
"fmt"
"io"
"log"
"os"
"strings"
@ -61,7 +62,7 @@ Environment:
$KUBECONFIG set an alternative Kubernetes configuration file (default "~/.kube/config")
`
func newRootCmd(args []string) *cobra.Command {
func newRootCmd(c helm.Interface, out io.Writer, args []string) *cobra.Command {
cmd := &cobra.Command{
Use: "helm",
Short: "The Helm package manager for Kubernetes.",
@ -72,8 +73,6 @@ func newRootCmd(args []string) *cobra.Command {
settings.AddFlags(flags)
out := cmd.OutOrStdout()
cmd.AddCommand(
// chart commands
newCreateCmd(out),
@ -87,15 +86,15 @@ func newRootCmd(args []string) *cobra.Command {
newVerifyCmd(out),
// release commands
newDeleteCmd(nil, out),
newGetCmd(nil, out),
newHistoryCmd(nil, out),
newInstallCmd(nil, out),
newListCmd(nil, out),
newReleaseTestCmd(nil, out),
newRollbackCmd(nil, out),
newStatusCmd(nil, out),
newUpgradeCmd(nil, out),
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),
@ -131,7 +130,7 @@ func logf(format string, v ...interface{}) {
}
func main() {
cmd := newRootCmd(os.Args[1:])
cmd := newRootCmd(nil, os.Stdout, os.Args[1:])
if err := cmd.Execute(); err != nil {
os.Exit(1)
}

@ -19,7 +19,6 @@ package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
@ -27,6 +26,7 @@ import (
"strings"
"testing"
shellwords "github.com/mattn/go-shellwords"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
@ -35,42 +35,53 @@ import (
"k8s.io/helm/pkg/repo"
)
// releaseCmd is a command that works with a FakeClient
type releaseCmd func(c *helm.FakeClient, out io.Writer) *cobra.Command
func executeCommand(c helm.Interface, cmd string) (string, error) {
_, output, err := executeCommandC(c, cmd)
return output, err
}
func executeCommandC(client helm.Interface, cmd string) (*cobra.Command, string, error) {
args, err := shellwords.Parse(cmd)
if err != nil {
return nil, "", err
}
buf := new(bytes.Buffer)
root := newRootCmd(client, buf, args)
root.SetOutput(buf)
root.SetArgs(args)
c, err := root.ExecuteC()
return c, buf.String(), err
}
// runReleaseCases runs a set of release cases through the given releaseCmd.
func runReleaseCases(t *testing.T, tests []releaseCase, rcmd releaseCmd) {
var buf bytes.Buffer
func testReleaseCmd(t *testing.T, tests []releaseCase) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &helm.FakeClient{
Rels: tt.rels,
Responses: tt.responses,
}
cmd := rcmd(c, &buf)
cmd.ParseFlags(tt.flags)
err := cmd.RunE(cmd, tt.args)
if (err != nil) != tt.err {
out, err := executeCommand(c, tt.cmd)
if (err != nil) != tt.wantError {
t.Errorf("expected error, got '%v'", err)
}
re := regexp.MustCompile(tt.expected)
if !re.Match(buf.Bytes()) {
t.Errorf("expected\n%q\ngot\n%q", tt.expected, buf.String())
re := regexp.MustCompile(tt.matches)
if !re.MatchString(out) {
t.Errorf("expected\n%q\ngot\n%q", tt.matches, out)
}
buf.Reset()
})
}
}
// releaseCase describes a test case that works with releases.
type releaseCase struct {
name string
args []string
flags []string
// expected is the string to be matched. This supports regular expressions.
expected string
err bool
resp *release.Release
name string
cmd string
// matches is the string to be matched. This supports regular expressions.
matches string
wantError bool
resp *release.Release
// Rels are the available releases at the start of the test.
rels []*release.Release
responses map[string]release.TestRunStatus
@ -131,7 +142,7 @@ func ensureTestHome(home helmpath.Home, t *testing.T) error {
}
}
t.Logf("$HELM_HOME has been configured at %s.\n", settings.Home.String())
t.Logf("$HELM_HOME has been configured at %s.\n", home)
return nil
}
@ -141,41 +152,39 @@ func TestRootCmd(t *testing.T) {
defer cleanup()
tests := []struct {
name string
args []string
envars map[string]string
home string
name, args, home string
envars map[string]string
}{
{
name: "defaults",
args: []string{"home"},
args: "home",
home: filepath.Join(os.Getenv("HOME"), "/.helm"),
},
{
name: "with --home set",
args: []string{"--home", "/foo"},
args: "--home /foo",
home: "/foo",
},
{
name: "subcommands with --home set",
args: []string{"home", "--home", "/foo"},
args: "home --home /foo",
home: "/foo",
},
{
name: "with $HELM_HOME set",
args: []string{"home"},
args: "home",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "subcommands with $HELM_HOME set",
args: []string{"home"},
args: "home",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/bar",
},
{
name: "with $HELM_HOME and --home set",
args: []string{"home", "--home", "/foo"},
args: "home --home /foo",
envars: map[string]string{"HELM_HOME": "/bar"},
home: "/foo",
},
@ -192,12 +201,9 @@ func TestRootCmd(t *testing.T) {
os.Setenv(k, v)
}
cmd := newRootCmd(tt.args)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tt.args)
cmd.Run = func(*cobra.Command, []string) {}
if err := cmd.Execute(); err != nil {
t.Errorf("unexpected error: %s", err)
cmd, _, err := executeCommandC(nil, tt.args)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if settings.Home.String() != tt.home {

@ -17,11 +17,8 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
rpb "k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
@ -38,48 +35,42 @@ func TestHistoryCmd(t *testing.T) {
tests := []releaseCase{
{
name: "get history for release",
args: []string{"angry-bird"},
cmd: "history angry-bird",
rels: []*rpb.Release{
mk("angry-bird", 4, rpb.Status_DEPLOYED),
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
mk("angry-bird", 2, rpb.Status_SUPERSEDED),
mk("angry-bird", 1, rpb.Status_SUPERSEDED),
},
expected: `REVISION\s+UPDATED\s+STATUS\s+CHART\s+DESCRIPTION \n1\s+(.*)\s+SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n2(.*)SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n3(.*)SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n4(.*)DEPLOYED\s+foo-0.1.0-beta.1\s+Release mock\n`,
matches: `REVISION\s+UPDATED\s+STATUS\s+CHART\s+DESCRIPTION \n1\s+(.*)\s+SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n2(.*)SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n3(.*)SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n4(.*)DEPLOYED\s+foo-0.1.0-beta.1\s+Release mock\n`,
},
{
name: "get history with max limit set",
args: []string{"angry-bird"},
flags: []string{"--max", "2"},
name: "get history with max limit set",
cmd: "history angry-bird --max 2",
rels: []*rpb.Release{
mk("angry-bird", 4, rpb.Status_DEPLOYED),
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
},
expected: `REVISION\s+UPDATED\s+STATUS\s+CHART\s+DESCRIPTION \n3\s+(.*)\s+SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n4\s+(.*)\s+DEPLOYED\s+foo-0.1.0-beta.1\s+Release mock\n`,
matches: `REVISION\s+UPDATED\s+STATUS\s+CHART\s+DESCRIPTION \n3\s+(.*)\s+SUPERSEDED\s+foo-0.1.0-beta.1\s+Release mock\n4\s+(.*)\s+DEPLOYED\s+foo-0.1.0-beta.1\s+Release mock\n`,
},
{
name: "get history with yaml output format",
args: []string{"angry-bird"},
flags: []string{"--output", "yaml"},
name: "get history with yaml output format",
cmd: "history angry-bird --output yaml",
rels: []*rpb.Release{
mk("angry-bird", 4, rpb.Status_DEPLOYED),
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
},
expected: "- chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 3\n status: SUPERSEDED\n updated: (.*)\n- chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 4\n status: DEPLOYED\n updated: (.*)\n\n",
matches: "- chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 3\n status: SUPERSEDED\n updated: (.*)\n- chart: foo-0.1.0-beta.1\n description: Release mock\n revision: 4\n status: DEPLOYED\n updated: (.*)\n\n",
},
{
name: "get history with json output format",
args: []string{"angry-bird"},
flags: []string{"--output", "json"},
name: "get history with json output format",
cmd: "history angry-bird --output json",
rels: []*rpb.Release{
mk("angry-bird", 4, rpb.Status_DEPLOYED),
mk("angry-bird", 3, rpb.Status_SUPERSEDED),
},
expected: `[{"revision":3,"updated":".*","status":"SUPERSEDED","chart":"foo\-0.1.0-beta.1","description":"Release mock"},{"revision":4,"updated":".*","status":"DEPLOYED","chart":"foo\-0.1.0-beta.1","description":"Release mock"}]\n`,
matches: `[{"revision":3,"updated":".*","status":"SUPERSEDED","chart":"foo\-0.1.0-beta.1","description":"Release mock"},{"revision":4,"updated":".*","status":"DEPLOYED","chart":"foo\-0.1.0-beta.1","description":"Release mock"}]\n`,
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newHistoryCmd(c, out)
})
testReleaseCmd(t, tests)
}

@ -105,31 +105,31 @@ charts in a repository, use 'helm search'.
`
type installCmd struct {
name string
valueFiles valueFiles
chartPath string
dryRun bool
disableHooks bool
replace bool
verify bool
keyring string
out io.Writer
client helm.Interface
values []string
stringValues []string
nameTemplate string
version string
timeout int64
wait bool
repoURL string
username string
password string
devel bool
depUp bool
certFile string
keyFile string
caFile string
name string // --name
valueFiles valueFiles // --values
dryRun bool // --dry-run
disableHooks bool // --disable-hooks
replace bool // --replace
verify bool // --verify
keyring string // --keyring
values []string // --set
stringValues []string // --set-string
nameTemplate string // --name-template
version string // --version
timeout int64 // --timeout
wait bool // --wait
repoURL string // --repo
username string // --username
password string // --password
devel bool // --devel
depUp bool // --dep-up
certFile string // --cert-file
keyFile string // --key-file
caFile string // --ca-file
chartPath string // arg
out io.Writer
client helm.Interface
}
type valueFiles []string
@ -291,7 +291,7 @@ func (i *installCmd) run() error {
}
// Merges source and destination map, preferring values from the source map
func mergeValues(dest map[string]interface{}, src map[string]interface{}) map[string]interface{} {
func mergeValues(dest, src map[string]interface{}) map[string]interface{} {
for k, v := range src {
// If the key doesn't exist already, then just set the key to that value
if _, exists := dest[k]; !exists {

@ -17,14 +17,10 @@ limitations under the License.
package main
import (
"io"
"reflect"
"regexp"
"strings"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)
@ -32,125 +28,110 @@ func TestInstall(t *testing.T) {
tests := []releaseCase{
// Install, base case
{
name: "basic install",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name aeneas", " "),
expected: "aeneas",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
name: "basic install",
cmd: "install testdata/testcharts/alpine --name aeneas",
matches: "aeneas",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
},
// Install, no hooks
{
name: "install without hooks",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name aeneas --no-hooks", " "),
expected: "aeneas",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
name: "install without hooks",
cmd: "install testdata/testcharts/alpine --name aeneas --no-hooks",
matches: "aeneas",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
},
// Install, values from cli
{
name: "install with values",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name virgil --set foo=bar", " "),
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
expected: "virgil",
name: "install with values",
cmd: "install testdata/testcharts/alpine --name virgil --set foo=bar",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
matches: "virgil",
},
// Install, values from cli via multiple --set
{
name: "install with multiple values",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name virgil --set foo=bar --set bar=foo", " "),
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
expected: "virgil",
name: "install with multiple values",
cmd: "install testdata/testcharts/alpine --name virgil --set foo=bar --set bar=foo",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
matches: "virgil",
},
// Install, values from yaml
{
name: "install with values",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name virgil -f testdata/testcharts/alpine/extra_values.yaml", " "),
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
expected: "virgil",
name: "install with values",
cmd: "install testdata/testcharts/alpine --name virgil -f testdata/testcharts/alpine/extra_values.yaml",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
matches: "virgil",
},
// Install, values from multiple yaml
{
name: "install with values",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name virgil -f testdata/testcharts/alpine/extra_values.yaml -f testdata/testcharts/alpine/more_values.yaml", " "),
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
expected: "virgil",
name: "install with values",
cmd: "install testdata/testcharts/alpine --name virgil -f testdata/testcharts/alpine/extra_values.yaml -f testdata/testcharts/alpine/more_values.yaml",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}),
matches: "virgil",
},
// Install, no charts
{
name: "install with no chart specified",
args: []string{},
err: true,
name: "install with no chart specified",
cmd: "install",
wantError: true,
},
// Install, re-use name
{
name: "install and replace release",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name aeneas --replace", " "),
expected: "aeneas",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
name: "install and replace release",
cmd: "install testdata/testcharts/alpine --name aeneas --replace",
matches: "aeneas",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
},
// Install, with timeout
{
name: "install with a timeout",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name foobar --timeout 120", " "),
expected: "foobar",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "foobar"}),
name: "install with a timeout",
cmd: "install testdata/testcharts/alpine --name foobar --timeout 120",
matches: "foobar",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "foobar"}),
},
// Install, with wait
{
name: "install with a wait",
args: []string{"testdata/testcharts/alpine"},
flags: strings.Split("--name apollo --wait", " "),
expected: "apollo",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "apollo"}),
name: "install with a wait",
cmd: "install testdata/testcharts/alpine --name apollo --wait",
matches: "apollo",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "apollo"}),
},
// Install, using the name-template
{
name: "install with name-template",
args: []string{"testdata/testcharts/alpine"},
flags: []string{"--name-template", "{{upper \"foobar\"}}"},
expected: "FOOBAR",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "FOOBAR"}),
name: "install with name-template",
cmd: "install testdata/testcharts/alpine --name-template '{{upper \"foobar\"}}'",
matches: "FOOBAR",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "FOOBAR"}),
},
// Install, perform chart verification along the way.
{
name: "install with verification, missing provenance",
args: []string{"testdata/testcharts/compressedchart-0.1.0.tgz"},
flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "),
err: true,
name: "install with verification, missing provenance",
cmd: "install testdata/testcharts/compressedchart-0.1.0.tgz --verify --keyring testdata/helm-test-key.pub",
wantError: true,
},
{
name: "install with verification, directory instead of file",
args: []string{"testdata/testcharts/signtest"},
flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "),
err: true,
name: "install with verification, directory instead of file",
cmd: "install testdata/testcharts/signtest --verify --keyring testdata/helm-test-key.pub",
wantError: true,
},
{
name: "install with verification, valid",
args: []string{"testdata/testcharts/signtest-0.1.0.tgz"},
flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "),
name: "install with verification, valid",
cmd: "install testdata/testcharts/signtest-0.1.0.tgz --verify --keyring testdata/helm-test-key.pub",
},
// Install, chart with missing dependencies in /charts
{
name: "install chart with missing dependencies",
args: []string{"testdata/testcharts/chart-missing-deps"},
err: true,
name: "install chart with missing dependencies",
cmd: "install testdata/testcharts/chart-missing-deps",
wantError: true,
},
// Install, chart with bad requirements.yaml in /charts
{
name: "install chart with bad requirements.yaml",
args: []string{"testdata/testcharts/chart-bad-requirements"},
err: true,
name: "install chart with bad requirements.yaml",
cmd: "install testdata/testcharts/chart-bad-requirements",
wantError: true,
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newInstallCmd(c, out)
})
testReleaseCmd(t, tests)
}
type nameTemplateTestCase struct {

@ -17,11 +17,8 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
@ -30,99 +27,100 @@ func TestListCmd(t *testing.T) {
tests := []releaseCase{
{
name: "with a release",
cmd: "list",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
},
expected: "thomas-guide",
matches: "thomas-guide",
},
{
name: "list",
cmd: "list",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas"}),
},
expected: `NAME\s+REVISION\s+UPDATED\s+STATUS\s+CHART\s+NAMESPACE\natlas\s+1\s+(.*)\s+DEPLOYED\s+foo-0.1.0-beta.1\s+default`,
matches: `NAME\s+REVISION\s+UPDATED\s+STATUS\s+CHART\s+NAMESPACE\natlas\s+1\s+(.*)\s+DEPLOYED\s+foo-0.1.0-beta.1\s+default`,
},
{
name: "list, one deployed, one failed",
flags: []string{"-q"},
name: "list, one deployed, one failed",
cmd: "list -q",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", StatusCode: release.Status_FAILED}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", StatusCode: release.Status_DEPLOYED}),
},
expected: "thomas-guide\natlas-guide",
matches: "thomas-guide\natlas-guide",
},
{
name: "with a release, multiple flags",
flags: []string{"--deleted", "--deployed", "--failed", "-q"},
name: "with a release, multiple flags",
cmd: "list --deleted --deployed --failed -q",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", StatusCode: release.Status_DELETED}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", StatusCode: release.Status_DEPLOYED}),
},
// Note: We're really only testing that the flags parsed correctly. Which results are returned
// depends on the backend. And until pkg/helm is done, we can't mock this.
expected: "thomas-guide\natlas-guide",
matches: "thomas-guide\natlas-guide",
},
{
name: "with a release, multiple flags",
flags: []string{"--all", "-q"},
name: "with a release, multiple flags",
cmd: "list --all -q",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", StatusCode: release.Status_DELETED}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", StatusCode: release.Status_DEPLOYED}),
},
// See note on previous test.
expected: "thomas-guide\natlas-guide",
matches: "thomas-guide\natlas-guide",
},
{
name: "with a release, multiple flags, deleting",
flags: []string{"--all", "-q"},
name: "with a release, multiple flags, deleting",
cmd: "list --all -q",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", StatusCode: release.Status_DELETING}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", StatusCode: release.Status_DEPLOYED}),
},
// See note on previous test.
expected: "thomas-guide\natlas-guide",
matches: "thomas-guide\natlas-guide",
},
{
name: "namespace defined, multiple flags",
flags: []string{"--all", "-q", "--namespace test123"},
name: "namespace defined, multiple flags",
cmd: "list --all -q --namespace test123",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", Namespace: "test123"}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", Namespace: "test321"}),
},
// See note on previous test.
expected: "thomas-guide",
matches: "thomas-guide",
},
{
name: "with a pending release, multiple flags",
flags: []string{"--all", "-q"},
name: "with a pending release, multiple flags",
cmd: "list --all -q",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", StatusCode: release.Status_PENDING_INSTALL}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", StatusCode: release.Status_DEPLOYED}),
},
expected: "thomas-guide\natlas-guide",
matches: "thomas-guide\natlas-guide",
},
{
name: "with a pending release, pending flag",
flags: []string{"--pending", "-q"},
name: "with a pending release, pending flag",
cmd: "list --pending -q",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", StatusCode: release.Status_PENDING_INSTALL}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "wild-idea", StatusCode: release.Status_PENDING_UPGRADE}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "crazy-maps", StatusCode: release.Status_PENDING_ROLLBACK}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide", StatusCode: release.Status_DEPLOYED}),
},
expected: "thomas-guide\nwild-idea\ncrazy-maps",
matches: "thomas-guide\nwild-idea\ncrazy-maps",
},
{
name: "with old releases",
cmd: "list",
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide", StatusCode: release.Status_FAILED}),
},
expected: "thomas-guide",
matches: "thomas-guide",
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newListCmd(c, out)
})
testReleaseCmd(t, tests)
}

@ -17,56 +17,46 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
func TestReleaseTesting(t *testing.T) {
tests := []releaseCase{
{
name: "basic test",
args: []string{"example-release"},
flags: []string{},
cmd: "test example-release",
responses: map[string]release.TestRunStatus{"PASSED: green lights everywhere": release.TestRun_SUCCESS},
err: false,
wantError: false,
},
{
name: "test failure",
args: []string{"example-fail"},
flags: []string{},
cmd: "test example-fail",
responses: map[string]release.TestRunStatus{"FAILURE: red lights everywhere": release.TestRun_FAILURE},
err: true,
wantError: true,
},
{
name: "test unknown",
args: []string{"example-unknown"},
flags: []string{},
cmd: "test example-unknown",
responses: map[string]release.TestRunStatus{"UNKNOWN: yellow lights everywhere": release.TestRun_UNKNOWN},
err: false,
wantError: false,
},
{
name: "test error",
args: []string{"example-error"},
flags: []string{},
cmd: "test example-error",
responses: map[string]release.TestRunStatus{"ERROR: yellow lights everywhere": release.TestRun_FAILURE},
err: true,
wantError: true,
},
{
name: "test running",
args: []string{"example-running"},
flags: []string{},
cmd: "test example-running",
responses: map[string]release.TestRunStatus{"RUNNING: things are happpeningggg": release.TestRun_RUNNING},
err: false,
wantError: false,
},
{
name: "multiple tests example",
args: []string{"example-suite"},
flags: []string{},
name: "multiple tests example",
cmd: "test example-suite",
responses: map[string]release.TestRunStatus{
"RUNNING: things are happpeningggg": release.TestRun_RUNNING,
"PASSED: party time": release.TestRun_SUCCESS,
@ -74,11 +64,8 @@ func TestReleaseTesting(t *testing.T) {
"FAILURE: good thing u checked :)": release.TestRun_FAILURE,
"RUNNING: things are happpeningggg yet again": release.TestRun_RUNNING,
"PASSED: feel free to party again": release.TestRun_SUCCESS},
err: true,
wantError: true,
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newReleaseTestCmd(c, out)
})
testReleaseCmd(t, tests)
}

@ -17,13 +17,10 @@ limitations under the License.
package main
import (
"io"
"fmt"
"os"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/repo"
"k8s.io/helm/pkg/repo/repotest"
)
@ -48,17 +45,13 @@ func TestRepoAddCmd(t *testing.T) {
settings.Home = thome
tests := []releaseCase{
{
name: "add a repository",
args: []string{testName, srv.URL()},
expected: "\"" + testName + "\" has been added to your repositories",
},
}
tests := []releaseCase{{
name: "add a repository",
cmd: fmt.Sprintf("repo add %s %s --home %s", testName, srv.URL(), thome),
matches: "\"" + testName + "\" has been added to your repositories",
}}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newRepoAddCmd(out)
})
testReleaseCmd(t, tests)
}
func TestRepoAdd(t *testing.T) {

@ -17,45 +17,32 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)
func TestRollbackCmd(t *testing.T) {
tests := []releaseCase{
{
name: "rollback a release",
args: []string{"funny-honey", "1"},
expected: "Rollback was a success! Happy Helming!",
name: "rollback a release",
cmd: "rollback funny-honey 1",
matches: "Rollback was a success! Happy Helming!",
},
{
name: "rollback a release with timeout",
args: []string{"funny-honey", "1"},
flags: []string{"--timeout", "120"},
expected: "Rollback was a success! Happy Helming!",
name: "rollback a release with timeout",
cmd: "rollback funny-honey 1 --timeout 120",
matches: "Rollback was a success! Happy Helming!",
},
{
name: "rollback a release with wait",
args: []string{"funny-honey", "1"},
flags: []string{"--wait"},
expected: "Rollback was a success! Happy Helming!",
name: "rollback a release with wait",
cmd: "rollback funny-honey 1 --wait",
matches: "Rollback was a success! Happy Helming!",
},
{
name: "rollback a release without revision",
args: []string{"funny-honey"},
err: true,
name: "rollback a release without revision",
cmd: "rollback funny-honey",
wantError: true,
},
}
cmd := func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newRollbackCmd(c, out)
}
runReleaseCases(t, tests, cmd)
testReleaseCmd(t, tests)
}

@ -236,36 +236,38 @@ func TestSearchByName(t *testing.T) {
i := loadTestIndex(t, false)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
charts, err := i.Search(tt.query, 100, tt.regexp)
if err != nil {
if tt.fail {
if !strings.Contains(err.Error(), tt.failMsg) {
t.Fatalf("%s: Unexpected error message: %s", tt.name, err)
charts, err := i.Search(tt.query, 100, tt.regexp)
if err != nil {
if tt.fail {
if !strings.Contains(err.Error(), tt.failMsg) {
t.Fatalf("Unexpected error message: %s", err)
}
return
}
continue
t.Fatalf("%s: %s", tt.name, err)
}
t.Fatalf("%s: %s", tt.name, err)
}
// Give us predictably ordered results.
SortScore(charts)
// Give us predictably ordered results.
SortScore(charts)
l := len(charts)
if l != len(tt.expect) {
t.Fatalf("%s: Expected %d result, got %d", tt.name, len(tt.expect), l)
}
// For empty result sets, just keep going.
if l == 0 {
continue
}
l := len(charts)
if l != len(tt.expect) {
t.Fatalf("Expected %d result, got %d", len(tt.expect), l)
}
// For empty result sets, just keep going.
if l == 0 {
return
}
for i, got := range charts {
ex := tt.expect[i]
if got.Name != ex.Name {
t.Errorf("%s[%d]: Expected name %q, got %q", tt.name, i, ex.Name, got.Name)
for i, got := range charts {
ex := tt.expect[i]
if got.Name != ex.Name {
t.Errorf("[%d]: Expected name %q, got %q", i, ex.Name, got.Name)
}
}
}
})
}
}

@ -17,72 +17,60 @@ limitations under the License.
package main
import (
"io"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)
func TestSearchCmd(t *testing.T) {
tests := []releaseCase{
{
name: "search for 'maria', expect one match",
args: []string{"maria"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/mariadb\t0.3.0 \t \tChart for MariaDB",
name: "search for 'maria', expect one match",
cmd: "search maria",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/mariadb\t0.3.0 \t \tChart for MariaDB",
},
{
name: "search for 'alpine', expect two matches",
args: []string{"alpine"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod",
name: "search for 'alpine', expect two matches",
cmd: "search alpine",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod",
},
{
name: "search for 'alpine' with versions, expect three matches",
args: []string{"alpine"},
flags: []string{"--versions"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod\ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
name: "search for 'alpine' with versions, expect three matches",
cmd: "search alpine --versions",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod\ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
},
{
name: "search for 'alpine' with version constraint, expect one match with version 0.1.0",
args: []string{"alpine"},
flags: []string{"--version", ">= 0.1, < 0.2"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
name: "search for 'alpine' with version constraint, expect one match with version 0.1.0",
cmd: "search alpine --version '>= 0.1, < 0.2'",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
},
{
name: "search for 'alpine' with version constraint, expect one match with version 0.1.0",
args: []string{"alpine"},
flags: []string{"--versions", "--version", ">= 0.1, < 0.2"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
name: "search for 'alpine' with version constraint, expect one match with version 0.1.0",
cmd: "search alpine --versions --version '>= 0.1, < 0.2'",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
},
{
name: "search for 'alpine' with version constraint, expect one match with version 0.2.0",
args: []string{"alpine"},
flags: []string{"--version", ">= 0.1"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod",
name: "search for 'alpine' with version constraint, expect one match with version 0.2.0",
cmd: "search alpine --version '>= 0.1'",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod",
},
{
name: "search for 'alpine' with version constraint and --versions, expect two matches",
args: []string{"alpine"},
flags: []string{"--versions", "--version", ">= 0.1"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod\ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
name: "search for 'alpine' with version constraint and --versions, expect two matches",
cmd: "search alpine --versions --version '>= 0.1'",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod\ntesting/alpine\t0.1.0 \t1.2.3 \tDeploy a basic Alpine Linux pod",
},
{
name: "search for 'syzygy', expect no matches",
args: []string{"syzygy"},
expected: "No results found",
name: "search for 'syzygy', expect no matches",
cmd: "search syzygy",
matches: "No results found",
},
{
name: "search for 'alp[a-z]+', expect two matches",
args: []string{"alp[a-z]+"},
flags: []string{"--regexp"},
expected: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod",
name: "search for 'alp[a-z]+', expect two matches",
cmd: "search alp[a-z]+ --regexp",
matches: "NAME \tCHART VERSION\tAPP VERSION\tDESCRIPTION \ntesting/alpine\t0.2.0 \t2.3.4 \tDeploy a basic Alpine Linux pod",
},
{
name: "search for 'alp[', expect failure to compile regexp",
args: []string{"alp["},
flags: []string{"--regexp"},
err: true,
name: "search for 'alp[', expect failure to compile regexp",
cmd: "search alp[ --regexp",
wantError: true,
},
}
@ -90,8 +78,5 @@ func TestSearchCmd(t *testing.T) {
defer cleanup()
settings.Home = "testdata/helmhome"
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newSearchCmd(out)
})
testReleaseCmd(t, tests)
}

@ -18,22 +18,18 @@ package main
import (
"fmt"
"io"
"testing"
"time"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/helm"
)
func TestStatusCmd(t *testing.T) {
tests := []releaseCase{
{
name: "get status of a deployed release",
args: []string{"flummoxed-chickadee"},
expected: outputWithStatus("DEPLOYED"),
name: "get status of a deployed release",
cmd: "status flummoxed-chickadee",
matches: outputWithStatus("DEPLOYED"),
rels: []*release.Release{
releaseMockWithStatus(&release.Status{
Code: release.Status_DEPLOYED,
@ -41,9 +37,9 @@ func TestStatusCmd(t *testing.T) {
},
},
{
name: "get status of a deployed release with notes",
args: []string{"flummoxed-chickadee"},
expected: outputWithStatus("DEPLOYED\n\nNOTES:\nrelease notes\n"),
name: "get status of a deployed release with notes",
cmd: "status flummoxed-chickadee",
matches: outputWithStatus("DEPLOYED\n\nNOTES:\nrelease notes\n"),
rels: []*release.Release{
releaseMockWithStatus(&release.Status{
Code: release.Status_DEPLOYED,
@ -52,10 +48,9 @@ func TestStatusCmd(t *testing.T) {
},
},
{
name: "get status of a deployed release with notes in json",
args: []string{"flummoxed-chickadee"},
flags: []string{"-o", "json"},
expected: `{"name":"flummoxed-chickadee","info":{"status":{"code":1,"notes":"release notes"},"first_deployed":(.*),"last_deployed":(.*)}}`,
name: "get status of a deployed release with notes in json",
cmd: "status flummoxed-chickadee -o json",
matches: `{"name":"flummoxed-chickadee","info":{"status":{"code":1,"notes":"release notes"},"first_deployed":(.*),"last_deployed":(.*)}}`,
rels: []*release.Release{
releaseMockWithStatus(&release.Status{
Code: release.Status_DEPLOYED,
@ -64,9 +59,9 @@ func TestStatusCmd(t *testing.T) {
},
},
{
name: "get status of a deployed release with resources",
args: []string{"flummoxed-chickadee"},
expected: outputWithStatus("DEPLOYED\n\nRESOURCES:\nresource A\nresource B\n\n"),
name: "get status of a deployed release with resources",
cmd: "status flummoxed-chickadee",
matches: outputWithStatus("DEPLOYED\n\nRESOURCES:\nresource A\nresource B\n\n"),
rels: []*release.Release{
releaseMockWithStatus(&release.Status{
Code: release.Status_DEPLOYED,
@ -75,10 +70,9 @@ func TestStatusCmd(t *testing.T) {
},
},
{
name: "get status of a deployed release with resources in YAML",
args: []string{"flummoxed-chickadee"},
flags: []string{"-o", "yaml"},
expected: "info:\n (.*)first_deployed:\n (.*)seconds: 242085845\n (.*)last_deployed:\n (.*)seconds: 242085845\n (.*)status:\n code: 1\n (.*)resources: |\n (.*)resource A\n (.*)resource B\nname: flummoxed-chickadee\n",
name: "get status of a deployed release with resources in YAML",
cmd: "status flummoxed-chickadee -o yaml",
matches: "info:\n (.*)first_deployed:\n (.*)seconds: 242085845\n (.*)last_deployed:\n (.*)seconds: 242085845\n (.*)status:\n code: 1\n (.*)resources: |\n (.*)resource A\n (.*)resource B\nname: flummoxed-chickadee\n",
rels: []*release.Release{
releaseMockWithStatus(&release.Status{
Code: release.Status_DEPLOYED,
@ -88,8 +82,8 @@ func TestStatusCmd(t *testing.T) {
},
{
name: "get status of a deployed release with test suite",
args: []string{"flummoxed-chickadee"},
expected: outputWithStatus(
cmd: "status flummoxed-chickadee",
matches: outputWithStatus(
"DEPLOYED\n\nTEST SUITE:\nLast Started: (.*)\nLast Completed: (.*)\n\n" +
"TEST \tSTATUS (.*)\tINFO (.*)\tSTARTED (.*)\tCOMPLETED (.*)\n" +
"test run 1\tSUCCESS (.*)\textra info\t(.*)\t(.*)\n" +
@ -120,11 +114,7 @@ func TestStatusCmd(t *testing.T) {
},
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newStatusCmd(c, out)
})
testReleaseCmd(t, tests)
}
func outputWithStatus(status string) string {

@ -17,14 +17,11 @@ limitations under the License.
package main
import (
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi/chart"
"k8s.io/helm/pkg/hapi/release"
@ -91,80 +88,73 @@ func TestUpgradeCmd(t *testing.T) {
t.Errorf("Error loading chart with missing dependencies: %v", err)
}
relMock := func(n string, v int, ch *chart.Chart) *release.Release {
return helm.ReleaseMock(&helm.MockReleaseOptions{Name: n, Version: v, Chart: ch})
}
tests := []releaseCase{
{
name: "upgrade a release",
args: []string{"funny-bunny", chartPath},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 2, Chart: ch}),
expected: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 2, Chart: ch})},
name: "upgrade a release",
cmd: "upgrade funny-bunny " + chartPath,
resp: relMock("funny-bunny", 2, ch),
matches: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{relMock("funny-bunny", 2, ch)},
},
{
name: "upgrade a release with timeout",
args: []string{"funny-bunny", chartPath},
flags: []string{"--timeout", "120"},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 3, Chart: ch2}),
expected: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 3, Chart: ch2})},
name: "upgrade a release with timeout",
cmd: "upgrade funny-bunny --timeout 120 " + chartPath,
resp: relMock("funny-bunny", 3, ch2),
matches: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{relMock("funny-bunny", 3, ch2)},
},
{
name: "upgrade a release with --reset-values",
args: []string{"funny-bunny", chartPath},
flags: []string{"--reset-values", "true"},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 4, Chart: ch2}),
expected: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 4, Chart: ch2})},
name: "upgrade a release with --reset-values",
cmd: "upgrade funny-bunny --reset-values " + chartPath,
resp: relMock("funny-bunny", 4, ch2),
matches: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{relMock("funny-bunny", 4, ch2)},
},
{
name: "upgrade a release with --reuse-values",
args: []string{"funny-bunny", chartPath},
flags: []string{"--reuse-values", "true"},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 5, Chart: ch2}),
expected: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "funny-bunny", Version: 5, Chart: ch2})},
name: "upgrade a release with --reuse-values",
cmd: "upgrade funny-bunny --reuse-values " + chartPath,
resp: relMock("funny-bunny", 5, ch2),
matches: "Release \"funny-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{relMock("funny-bunny", 5, ch2)},
},
{
name: "install a release with 'upgrade --install'",
args: []string{"zany-bunny", chartPath},
flags: []string{"-i"},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "zany-bunny", Version: 1, Chart: ch}),
expected: "Release \"zany-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "zany-bunny", Version: 1, Chart: ch})},
name: "install a release with 'upgrade --install'",
cmd: "upgrade zany-bunny -i " + chartPath,
resp: relMock("zany-bunny", 1, ch),
matches: "Release \"zany-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{relMock("zany-bunny", 1, ch)},
},
{
name: "install a release with 'upgrade --install' and timeout",
args: []string{"crazy-bunny", chartPath},
flags: []string{"-i", "--timeout", "120"},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "crazy-bunny", Version: 1, Chart: ch}),
expected: "Release \"crazy-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "crazy-bunny", Version: 1, Chart: ch})},
name: "install a release with 'upgrade --install' and timeout",
cmd: "upgrade crazy-bunny -i --timeout 120 " + chartPath,
resp: relMock("crazy-bunny", 1, ch),
matches: "Release \"crazy-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{relMock("crazy-bunny", 1, ch)},
},
{
name: "upgrade a release with wait",
args: []string{"crazy-bunny", chartPath},
flags: []string{"--wait"},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "crazy-bunny", Version: 2, Chart: ch2}),
expected: "Release \"crazy-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "crazy-bunny", Version: 2, Chart: ch2})},
name: "upgrade a release with wait",
cmd: "upgrade crazy-bunny --wait " + chartPath,
resp: relMock("crazy-bunny", 2, ch2),
matches: "Release \"crazy-bunny\" has been upgraded. Happy Helming!\n",
rels: []*release.Release{relMock("crazy-bunny", 2, ch2)},
},
{
name: "upgrade a release with missing dependencies",
args: []string{"bonkers-bunny", missingDepsPath},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "bonkers-bunny", Version: 1, Chart: ch3}),
err: true,
name: "upgrade a release with missing dependencies",
cmd: "upgrade bonkers-bunny" + missingDepsPath,
resp: relMock("bonkers-bunny", 1, ch3),
wantError: true,
},
{
name: "upgrade a release with bad dependencies",
args: []string{"bonkers-bunny", badDepsPath},
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "bonkers-bunny", Version: 1, Chart: ch3}),
err: true,
name: "upgrade a release with bad dependencies",
cmd: "upgrade bonkers-bunny " + badDepsPath,
resp: relMock("bonkers-bunny", 1, ch3),
wantError: true,
},
}
cmd := func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newUpgradeCmd(c, out)
}
runReleaseCases(t, tests, cmd)
testReleaseCmd(t, tests)
}

@ -17,13 +17,9 @@ package main
import (
"fmt"
"io"
"regexp"
"testing"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/version"
)
@ -33,18 +29,15 @@ func TestVersion(t *testing.T) {
tests := []releaseCase{
{
name: "default",
args: []string{},
expected: clientVersion,
name: "default",
cmd: "version",
matches: clientVersion,
},
{
name: "template",
args: []string{},
flags: []string{"--template", "{{ .Client.SemVer }}"},
expected: lver,
name: "template",
cmd: "version --template='{{.Client.SemVer}}'",
matches: lver,
},
}
runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command {
return newVersionCmd(out)
})
testReleaseCmd(t, tests)
}

Loading…
Cancel
Save