From 496ca54183bb22c6bf51f98d060e601886f5039e Mon Sep 17 00:00:00 2001 From: Adam Reese Date: Sat, 14 Apr 2018 13:31:31 -0700 Subject: [PATCH] ref(*): bypass grpc for helm client --- cmd/helm/delete.go | 3 +- cmd/helm/get.go | 9 +- cmd/helm/get_hooks.go | 9 +- cmd/helm/get_manifest.go | 9 +- cmd/helm/get_values.go | 9 +- cmd/helm/helm.go | 80 +----- cmd/helm/history.go | 11 +- cmd/helm/install.go | 22 +- cmd/helm/list.go | 3 +- cmd/helm/load_plugins.go | 6 +- cmd/helm/release_testing.go | 11 +- cmd/helm/rollback.go | 9 +- cmd/helm/status.go | 11 +- cmd/helm/template.go | 4 +- cmd/helm/upgrade.go | 21 +- pkg/helm/client.go | 278 ++++++------------- pkg/helm/client_test.go | 34 --- pkg/helm/environment/environment.go | 1 - pkg/helm/fake.go | 30 +- pkg/helm/fake_test.go | 12 +- pkg/helm/helm_test.go | 17 +- pkg/helm/interface.go | 14 +- pkg/helm/option.go | 82 ++---- pkg/helm/portforwarder/pod.go | 60 ---- pkg/helm/portforwarder/portforwarder.go | 72 ----- pkg/helm/portforwarder/portforwarder_test.go | 87 ------ pkg/kube/tunnel.go | 122 -------- pkg/kube/tunnel_test.go | 31 --- pkg/plugin/installer/http_installer.go | 9 +- pkg/plugin/installer/http_installer_test.go | 3 +- pkg/releasetesting/environment_test.go | 5 - pkg/releasetesting/test_suite.go | 13 +- pkg/releasetesting/test_suite_test.go | 16 +- pkg/tiller/release_content.go | 11 +- pkg/tiller/release_content_test.go | 8 +- pkg/tiller/release_history.go | 11 +- pkg/tiller/release_history_test.go | 20 +- pkg/tiller/release_install.go | 24 +- pkg/tiller/release_install_test.go | 130 ++++----- pkg/tiller/release_rollback.go | 17 +- pkg/tiller/release_rollback_test.go | 54 ++-- pkg/tiller/release_server.go | 5 + pkg/tiller/release_server_test.go | 16 +- pkg/tiller/release_status.go | 4 +- pkg/tiller/release_status_test.go | 8 +- pkg/tiller/release_testing.go | 6 +- pkg/tiller/release_uninstall.go | 4 +- pkg/tiller/release_uninstall_test.go | 25 +- pkg/tiller/release_update.go | 38 ++- pkg/tiller/release_update_test.go | 119 ++++---- pkg/tiller/release_version.go | 30 -- pkg/tiller/server.go | 96 ------- 52 files changed, 434 insertions(+), 1295 deletions(-) delete mode 100644 pkg/helm/client_test.go delete mode 100644 pkg/helm/portforwarder/pod.go delete mode 100644 pkg/helm/portforwarder/portforwarder.go delete mode 100644 pkg/helm/portforwarder/portforwarder_test.go delete mode 100644 pkg/kube/tunnel.go delete mode 100644 pkg/kube/tunnel_test.go delete mode 100644 pkg/tiller/release_version.go delete mode 100644 pkg/tiller/server.go diff --git a/cmd/helm/delete.go b/cmd/helm/delete.go index e0ac8c4f6..08f965520 100755 --- a/cmd/helm/delete.go +++ b/cmd/helm/delete.go @@ -57,7 +57,6 @@ func newDeleteCmd(c helm.Interface, out io.Writer) *cobra.Command { SuggestFor: []string{"remove", "rm"}, Short: "given a release name, delete the release from Kubernetes", Long: deleteDesc, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errors.New("command 'delete' requires a release name") @@ -97,5 +96,5 @@ func (d *deleteCmd) run() error { fmt.Fprintln(d.out, res.Info) } - return prettyError(err) + return err } diff --git a/cmd/helm/get.go b/cmd/helm/get.go index aba508e34..9c69e2682 100644 --- a/cmd/helm/get.go +++ b/cmd/helm/get.go @@ -54,10 +54,9 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "get [flags] RELEASE_NAME", - Short: "download a named release", - Long: getHelp, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "get [flags] RELEASE_NAME", + Short: "download a named release", + Long: getHelp, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errReleaseRequired @@ -83,7 +82,7 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { func (g *getCmd) run() error { res, err := g.client.ReleaseContent(g.release, g.version) if err != nil { - return prettyError(err) + return err } return printRelease(g.out, res) } diff --git a/cmd/helm/get_hooks.go b/cmd/helm/get_hooks.go index 9da290682..55ecd0e2a 100644 --- a/cmd/helm/get_hooks.go +++ b/cmd/helm/get_hooks.go @@ -44,10 +44,9 @@ func newGetHooksCmd(client helm.Interface, out io.Writer) *cobra.Command { client: client, } cmd := &cobra.Command{ - Use: "hooks [flags] RELEASE_NAME", - Short: "download all hooks for a named release", - Long: getHooksHelp, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "hooks [flags] RELEASE_NAME", + Short: "download all hooks for a named release", + Long: getHooksHelp, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errReleaseRequired @@ -65,7 +64,7 @@ func (g *getHooksCmd) run() error { res, err := g.client.ReleaseContent(g.release, g.version) if err != nil { fmt.Fprintln(g.out, g.release) - return prettyError(err) + return err } for _, hook := range res.Hooks { diff --git a/cmd/helm/get_manifest.go b/cmd/helm/get_manifest.go index 96f754936..b7f764eef 100644 --- a/cmd/helm/get_manifest.go +++ b/cmd/helm/get_manifest.go @@ -46,10 +46,9 @@ func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command { client: client, } cmd := &cobra.Command{ - Use: "manifest [flags] RELEASE_NAME", - Short: "download the manifest for a named release", - Long: getManifestHelp, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "manifest [flags] RELEASE_NAME", + Short: "download the manifest for a named release", + Long: getManifestHelp, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errReleaseRequired @@ -68,7 +67,7 @@ func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command { func (g *getManifestCmd) run() error { res, err := g.client.ReleaseContent(g.release, g.version) if err != nil { - return prettyError(err) + return err } fmt.Fprintln(g.out, res.Manifest) return nil diff --git a/cmd/helm/get_values.go b/cmd/helm/get_values.go index 98e6290c2..532ad75ff 100644 --- a/cmd/helm/get_values.go +++ b/cmd/helm/get_values.go @@ -44,10 +44,9 @@ func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command { client: client, } cmd := &cobra.Command{ - Use: "values [flags] RELEASE_NAME", - Short: "download the values file for a named release", - Long: getValuesHelp, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "values [flags] RELEASE_NAME", + Short: "download the values file for a named release", + Long: getValuesHelp, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errReleaseRequired @@ -67,7 +66,7 @@ func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command { func (g *getValuesCmd) run() error { res, err := g.client.ReleaseContent(g.release, g.version) if err != nil { - return prettyError(err) + return err } // If the user wants all values, compute the values and return. diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index 1caa4ecc5..8b109636f 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -18,14 +18,10 @@ package main // import "k8s.io/helm/cmd/helm" import ( "fmt" - "io/ioutil" - "log" "os" "strings" "github.com/spf13/cobra" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/status" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -34,14 +30,11 @@ import ( "k8s.io/helm/pkg/helm" helm_env "k8s.io/helm/pkg/helm/environment" - "k8s.io/helm/pkg/helm/portforwarder" "k8s.io/helm/pkg/kube" + "k8s.io/helm/pkg/storage/driver" ) -var ( - tillerTunnel *kube.Tunnel - settings helm_env.EnvSettings -) +var settings helm_env.EnvSettings var globalUsage = `The Kubernetes package manager @@ -73,9 +66,6 @@ func newRootCmd(args []string) *cobra.Command { Short: "The Helm package manager for Kubernetes.", Long: globalUsage, SilenceUsage: true, - PersistentPostRun: func(*cobra.Command, []string) { - teardown() - }, } flags := cmd.PersistentFlags() @@ -102,18 +92,17 @@ func newRootCmd(args []string) *cobra.Command { newHistoryCmd(nil, out), newInstallCmd(nil, out), newListCmd(nil, out), + newReleaseTestCmd(nil, out), newRollbackCmd(nil, out), newStatusCmd(nil, out), newUpgradeCmd(nil, out), - newReleaseTestCmd(nil, out), - newVersionCmd(out), - newCompletionCmd(out), newHomeCmd(out), newInitCmd(out), newPluginCmd(out), newTemplateCmd(out), + newVersionCmd(out), // Hidden documentation generator command: 'helm docs' newDocsCmd(out), @@ -130,11 +119,6 @@ func newRootCmd(args []string) *cobra.Command { return cmd } -func init() { - // Tell gRPC not to log to console. - grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags)) -} - func main() { cmd := newRootCmd(os.Args[1:]) if err := cmd.Execute(); err != nil { @@ -142,35 +126,6 @@ func main() { } } -func setupConnection() error { - if settings.TillerHost == "" { - config, client, err := getKubeClient(settings.KubeContext) - if err != nil { - return err - } - - tunnel, err := portforwarder.New(settings.TillerNamespace, client, config) - if err != nil { - return err - } - - settings.TillerHost = fmt.Sprintf("127.0.0.1:%d", tunnel.Local) - debug("Created tunnel using local port: '%d'\n", tunnel.Local) - } - - // Set up the gRPC config. - debug("SERVER: %q\n", settings.TillerHost) - - // Plugin support. - return nil -} - -func teardown() { - if tillerTunnel != nil { - tillerTunnel.Close() - } -} - func checkArgsLength(argsReceived int, requiredArgs ...string) error { expectedNum := len(requiredArgs) if argsReceived != expectedNum { @@ -183,20 +138,6 @@ func checkArgsLength(argsReceived int, requiredArgs ...string) error { return nil } -// prettyError unwraps or rewrites certain errors to make them more user-friendly. -func prettyError(err error) error { - // Add this check can prevent the object creation if err is nil. - if err == nil { - return nil - } - // If it's grpc's error, make it more user-friendly. - if s, ok := status.FromError(err); ok { - return fmt.Errorf(s.Message()) - } - // Else return the original error. - return err -} - // configForContext creates a Kubernetes REST client configuration for a given kubeconfig context. func configForContext(context string) (*rest.Config, error) { config, err := kube.GetConfig(context).ClientConfig() @@ -228,6 +169,15 @@ func ensureHelmClient(h helm.Interface) helm.Interface { } func newClient() helm.Interface { - options := []helm.Option{helm.Host(settings.TillerHost), helm.ConnectTimeout(settings.TillerConnectionTimeout)} - return helm.NewClient(options...) + clientset, err := kube.New(nil).ClientSet() + if err != nil { + // TODO return error + panic(err) + } + // TODO add other backends + cfgmaps := driver.NewConfigMaps(clientset.Core().ConfigMaps(settings.TillerNamespace)) + return helm.NewClient( + helm.Driver(cfgmaps), + helm.ClientSet(clientset), + ) } diff --git a/cmd/helm/history.go b/cmd/helm/history.go index e6366d31d..2a2007aea 100644 --- a/cmd/helm/history.go +++ b/cmd/helm/history.go @@ -74,7 +74,6 @@ func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command { Long: historyHelp, Short: "fetch release history", Aliases: []string{"hist"}, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, RunE: func(cmd *cobra.Command, args []string) error { switch { case len(args) == 0: @@ -96,15 +95,15 @@ func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command { } func (cmd *historyCmd) run() error { - r, err := cmd.helmc.ReleaseHistory(cmd.rls, helm.WithMaxHistory(cmd.max)) + rels, err := cmd.helmc.ReleaseHistory(cmd.rls, cmd.max) if err != nil { - return prettyError(err) + return err } - if len(r.Releases) == 0 { + if len(rels) == 0 { return nil } - releaseHistory := getReleaseHistory(r.Releases) + releaseHistory := getReleaseHistory(rels) var history []byte var formattingError error @@ -121,7 +120,7 @@ func (cmd *historyCmd) run() error { } if formattingError != nil { - return prettyError(formattingError) + return formattingError } fmt.Fprintln(cmd.out, string(history)) diff --git a/cmd/helm/install.go b/cmd/helm/install.go index d52dbc667..df0454e11 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -158,10 +158,9 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "install [CHART]", - Short: "install a chart archive", - Long: installDesc, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "install [CHART]", + Short: "install a chart archive", + Long: installDesc, RunE: func(cmd *cobra.Command, args []string) error { if err := checkArgsLength(len(args), "chart name"); err != nil { return err @@ -236,7 +235,7 @@ func (i *installCmd) run() error { // Check chart requirements to make sure all dependencies are present in /charts chartRequested, err := chartutil.Load(i.chartPath) if err != nil { - return prettyError(err) + return err } if req, err := chartutil.LoadRequirements(chartRequested); err == nil { @@ -254,10 +253,10 @@ func (i *installCmd) run() error { Getters: getter.All(settings), } if err := man.Update(); err != nil { - return prettyError(err) + return err } } else { - return prettyError(err) + return err } } @@ -265,7 +264,7 @@ func (i *installCmd) run() error { return fmt.Errorf("cannot load requirements: %v", err) } - res, err := i.client.InstallReleaseFromChart( + rel, err := i.client.InstallReleaseFromChart( chartRequested, i.namespace, helm.ValueOverrides(rawVals), @@ -276,10 +275,9 @@ func (i *installCmd) run() error { helm.InstallTimeout(i.timeout), helm.InstallWait(i.wait)) if err != nil { - return prettyError(err) + return err } - rel := res.GetRelease() if rel == nil { return nil } @@ -291,9 +289,9 @@ func (i *installCmd) run() error { } // Print the status like status command does - status, err := i.client.ReleaseStatus(rel.Name) + status, err := i.client.ReleaseStatus(rel.Name, 0) if err != nil { - return prettyError(err) + return err } PrintStatus(i.out, status) return nil diff --git a/cmd/helm/list.go b/cmd/helm/list.go index ec5027a8a..887c8a9db 100644 --- a/cmd/helm/list.go +++ b/cmd/helm/list.go @@ -88,7 +88,6 @@ func newListCmd(client helm.Interface, out io.Writer) *cobra.Command { Short: "list releases", Long: listHelp, Aliases: []string{"ls"}, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { list.filter = strings.Join(args, " ") @@ -145,7 +144,7 @@ func (l *listCmd) run() error { ) if err != nil { - return prettyError(err) + return err } if len(res) == 0 { diff --git a/cmd/helm/load_plugins.go b/cmd/helm/load_plugins.go index ef24e7883..19de5d676 100644 --- a/cmd/helm/load_plugins.go +++ b/cmd/helm/load_plugins.go @@ -100,10 +100,8 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) { if md.UseTunnel { c.PreRunE = func(cmd *cobra.Command, args []string) error { // Parse the parent flag, but not the local flags. - if _, err := processParent(cmd, args); err != nil { - return err - } - return setupConnection() + _, err := processParent(cmd, args) + return err } } diff --git a/cmd/helm/release_testing.go b/cmd/helm/release_testing.go index bdfa87a60..34ada1ddf 100644 --- a/cmd/helm/release_testing.go +++ b/cmd/helm/release_testing.go @@ -48,10 +48,9 @@ func newReleaseTestCmd(c helm.Interface, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "test [RELEASE]", - Short: "test a release", - Long: releaseTestDesc, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "test [RELEASE]", + Short: "test a release", + Long: releaseTestDesc, RunE: func(cmd *cobra.Command, args []string) error { if err := checkArgsLength(len(args), "release name"); err != nil { return err @@ -81,10 +80,10 @@ func (t *releaseTestCmd) run() (err error) { for { select { case err := <-errc: - if prettyError(err) == nil && testErr.failed > 0 { + if err == nil && testErr.failed > 0 { return testErr.Error() } - return prettyError(err) + return err case res, ok := <-c: if !ok { break diff --git a/cmd/helm/rollback.go b/cmd/helm/rollback.go index 889b6ae28..4892f808d 100644 --- a/cmd/helm/rollback.go +++ b/cmd/helm/rollback.go @@ -54,10 +54,9 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "rollback [flags] [RELEASE] [REVISION]", - Short: "roll back a release to a previous revision", - Long: rollbackDesc, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "rollback [flags] [RELEASE] [REVISION]", + Short: "roll back a release to a previous revision", + Long: rollbackDesc, RunE: func(cmd *cobra.Command, args []string) error { if err := checkArgsLength(len(args), "release name", "revision number"); err != nil { return err @@ -98,7 +97,7 @@ func (r *rollbackCmd) run() error { helm.RollbackTimeout(r.timeout), helm.RollbackWait(r.wait)) if err != nil { - return prettyError(err) + return err } fmt.Fprintf(r.out, "Rollback was a success! Happy Helming!\n") diff --git a/cmd/helm/status.go b/cmd/helm/status.go index b73b6f56e..3041f779f 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -60,10 +60,9 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "status [flags] RELEASE_NAME", - Short: "displays the status of the named release", - Long: statusHelp, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "status [flags] RELEASE_NAME", + Short: "displays the status of the named release", + Long: statusHelp, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errReleaseRequired @@ -83,9 +82,9 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { } func (s *statusCmd) run() error { - res, err := s.client.ReleaseStatus(s.release, helm.StatusReleaseVersion(s.version)) + res, err := s.client.ReleaseStatus(s.release, s.version) if err != nil { - return prettyError(err) + return err } switch s.outfmt { diff --git a/cmd/helm/template.go b/cmd/helm/template.go index c04bc2dc8..54d612fa7 100644 --- a/cmd/helm/template.go +++ b/cmd/helm/template.go @@ -168,12 +168,12 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { // Check chart requirements to make sure all dependencies are present in /charts c, err := chartutil.Load(t.chartPath) if err != nil { - return prettyError(err) + return err } if req, err := chartutil.LoadRequirements(c); err == nil { if err := checkDependencies(c, req); err != nil { - return prettyError(err) + return err } } else if err != chartutil.ErrRequirementsNotFound { return fmt.Errorf("cannot load requirements: %v", err) diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 66c4a3657..554b24a6e 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -92,10 +92,9 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { } cmd := &cobra.Command{ - Use: "upgrade [RELEASE] [CHART]", - Short: "upgrade a release", - Long: upgradeDesc, - PreRunE: func(_ *cobra.Command, _ []string) error { return setupConnection() }, + Use: "upgrade [RELEASE] [CHART]", + Short: "upgrade a release", + Long: upgradeDesc, RunE: func(cmd *cobra.Command, args []string) error { if err := checkArgsLength(len(args), "release name", "chart path"); err != nil { return err @@ -158,13 +157,13 @@ func (u *upgradeCmd) run() error { // The returned error is a grpc.rpcError that wraps the message from the original error. // So we're stuck doing string matching against the wrapped error, which is nested somewhere // inside of the grpc.rpcError message. - releaseHistory, err := u.client.ReleaseHistory(u.release, helm.WithMaxHistory(1)) + releaseHistory, err := u.client.ReleaseHistory(u.release, 1) if err == nil { if u.namespace == "" { u.namespace = defaultNamespace() } - previousReleaseNamespace := releaseHistory.Releases[0].Namespace + previousReleaseNamespace := releaseHistory[0].Namespace if previousReleaseNamespace != u.namespace { fmt.Fprintf(u.out, "WARNING: Namespace %q doesn't match with previous. Release will be deployed to %s\n", @@ -210,7 +209,7 @@ func (u *upgradeCmd) run() error { return fmt.Errorf("cannot load requirements: %v", err) } } else { - return prettyError(err) + return err } resp, err := u.client.UpdateRelease( @@ -226,19 +225,19 @@ func (u *upgradeCmd) run() error { helm.ReuseValues(u.reuseValues), helm.UpgradeWait(u.wait)) if err != nil { - return fmt.Errorf("UPGRADE FAILED: %v", prettyError(err)) + return fmt.Errorf("UPGRADE FAILED: %v", err) } if settings.Debug { - printRelease(u.out, resp.Release) + printRelease(u.out, resp) } fmt.Fprintf(u.out, "Release %q has been upgraded. Happy Helming!\n", u.release) // Print the status like status command does - status, err := u.client.ReleaseStatus(u.release) + status, err := u.client.ReleaseStatus(u.release, 0) if err != nil { - return prettyError(err) + return err } PrintStatus(u.out, status) diff --git a/pkg/helm/client.go b/pkg/helm/client.go index ea888b747..01ece8fee 100644 --- a/pkg/helm/client.go +++ b/pkg/helm/client.go @@ -25,76 +25,78 @@ import ( "google.golang.org/grpc/keepalive" "k8s.io/helm/pkg/chartutil" + "k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/release" rls "k8s.io/helm/pkg/proto/hapi/services" "k8s.io/helm/pkg/storage" - "k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/tiller" + "k8s.io/helm/pkg/tiller/environment" ) // maxMsgSize use 20MB as the default message size limit. // grpc library default is 4MB const maxMsgSize = 1024 * 1024 * 20 -type Tiller = tiller.ReleaseServer - // Client manages client side of the Helm-Tiller protocol. type Client struct { opts options - store *storage.Storage - tiller *Tiller + tiller *tiller.ReleaseServer } // NewClient creates a new client. func NewClient(opts ...Option) *Client { var c Client - c.store = storage.Init(driver.NewMemory()) - // set some sane defaults - c.Option(ConnectTimeout(5)) - return c.Option(opts...) + return c.Option(opts...).init() +} + +func (c *Client) init() *Client { + env := environment.New() + env.Releases = storage.Init(c.opts.driver) + + // TODO + env.KubeClient = kube.New(nil) + + c.tiller = tiller.NewReleaseServer(env, c.opts.clientset) + return c } // Option configures the Helm client with the provided options. -func (h *Client) Option(opts ...Option) *Client { +func (c *Client) Option(opts ...Option) *Client { for _, opt := range opts { - opt(&h.opts) + opt(&c.opts) } - return h + return c } // ListReleases lists the current releases. -func (h *Client) ListReleases(opts ...ReleaseListOption) ([]*release.Release, error) { - reqOpts := h.opts +func (c *Client) ListReleases(opts ...ReleaseListOption) ([]*release.Release, error) { + reqOpts := c.opts for _, opt := range opts { opt(&reqOpts) } req := &reqOpts.listReq - ctx := NewContext() - - if reqOpts.before != nil { - if err := reqOpts.before(ctx, req); err != nil { - return nil, err - } + if err := reqOpts.runBefore(req); err != nil { + return nil, err } - return h.tiller.ListReleases(req) + return c.tiller.ListReleases(req) } // InstallRelease loads a chart from chstr, installs it, and returns the release response. -func (h *Client) InstallRelease(chstr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { +func (c *Client) InstallRelease(chstr, ns string, opts ...InstallOption) (*release.Release, error) { // load the chart to install chart, err := chartutil.Load(chstr) if err != nil { return nil, err } - return h.InstallReleaseFromChart(chart, ns, opts...) + return c.InstallReleaseFromChart(chart, ns, opts...) } // InstallReleaseFromChart installs a new chart and returns the release response. -func (h *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { +func (c *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*release.Release, error) { // apply the install options - reqOpts := h.opts + reqOpts := c.opts for _, opt := range opts { opt(&reqOpts) } @@ -104,12 +106,9 @@ func (h *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ... req.DryRun = reqOpts.dryRun req.DisableHooks = reqOpts.disableHooks req.ReuseName = reqOpts.reuseName - ctx := NewContext() - if reqOpts.before != nil { - if err := reqOpts.before(ctx, req); err != nil { - return nil, err - } + if err := reqOpts.runBefore(req); err != nil { + return nil, err } err := chartutil.ProcessRequirementsEnabled(req.Chart, req.Values) if err != nil { @@ -120,20 +119,20 @@ func (h *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ... return nil, err } - return h.install(ctx, req) + return c.tiller.InstallRelease(req) } // DeleteRelease uninstalls a named release and returns the response. -func (h *Client) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) { +func (c *Client) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) { // apply the uninstall options - reqOpts := h.opts + reqOpts := c.opts for _, opt := range opts { opt(&reqOpts) } if reqOpts.dryRun { // In the dry run case, just see if the release exists - r, err := h.ReleaseContent(rlsName, 0) + r, err := c.ReleaseContent(rlsName, 0) if err != nil { return &rls.UninstallReleaseResponse{}, err } @@ -143,31 +142,28 @@ func (h *Client) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.Unins req := &reqOpts.uninstallReq req.Name = rlsName req.DisableHooks = reqOpts.disableHooks - ctx := NewContext() - if reqOpts.before != nil { - if err := reqOpts.before(ctx, req); err != nil { - return nil, err - } + if err := reqOpts.runBefore(req); err != nil { + return nil, err } - return h.delete(ctx, req) + return c.tiller.UninstallRelease(req) } // UpdateRelease loads a chart from chstr and updates a release to a new/different chart. -func (h *Client) UpdateRelease(rlsName string, chstr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { +func (c *Client) UpdateRelease(rlsName string, chstr string, opts ...UpdateOption) (*release.Release, error) { // load the chart to update chart, err := chartutil.Load(chstr) if err != nil { return nil, err } - return h.UpdateReleaseFromChart(rlsName, chart, opts...) + return c.UpdateReleaseFromChart(rlsName, chart, opts...) } // UpdateReleaseFromChart updates a release to a new/different chart. -func (h *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { +func (c *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*release.Release, error) { // apply the update options - reqOpts := h.opts + reqOpts := c.opts for _, opt := range opts { opt(&reqOpts) } @@ -180,12 +176,9 @@ func (h *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts req.Force = reqOpts.force req.ResetValues = reqOpts.resetValues req.ReuseValues = reqOpts.reuseValues - ctx := NewContext() - if reqOpts.before != nil { - if err := reqOpts.before(ctx, req); err != nil { - return nil, err - } + if err := reqOpts.runBefore(req); err != nil { + return nil, err } err := chartutil.ProcessRequirementsEnabled(req.Chart, req.Values) if err != nil { @@ -196,12 +189,12 @@ func (h *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts return nil, err } - return h.update(ctx, req) + return c.tiller.UpdateRelease(req) } // RollbackRelease rolls back a release to the previous version. -func (h *Client) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) { - reqOpts := h.opts +func (c *Client) RollbackRelease(rlsName string, opts ...RollbackOption) (*release.Release, error) { + reqOpts := c.opts for _, opt := range opts { opt(&reqOpts) } @@ -211,78 +204,68 @@ func (h *Client) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.R req.DisableHooks = reqOpts.disableHooks req.DryRun = reqOpts.dryRun req.Name = rlsName - ctx := NewContext() - if reqOpts.before != nil { - if err := reqOpts.before(ctx, req); err != nil { - return nil, err - } + if err := reqOpts.runBefore(req); err != nil { + return nil, err } - return h.rollback(ctx, req) + return c.tiller.RollbackRelease(req) } // ReleaseStatus returns the given release's status. -func (h *Client) ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) { - reqOpts := h.opts - for _, opt := range opts { - opt(&reqOpts) - } +func (c *Client) ReleaseStatus(rlsName string, version int32) (*rls.GetReleaseStatusResponse, error) { + reqOpts := c.opts req := &reqOpts.statusReq req.Name = rlsName - ctx := NewContext() + req.Version = version - if reqOpts.before != nil { - if err := reqOpts.before(ctx, req); err != nil { - return nil, err - } + if err := reqOpts.runBefore(req); err != nil { + return nil, err } - return h.status(ctx, req) + return c.tiller.GetReleaseStatus(req) } // ReleaseContent returns the configuration for a given release. func (c *Client) ReleaseContent(name string, version int32) (*release.Release, error) { - if version <= 0 { - return c.store.Last(name) + reqOpts := c.opts + req := &reqOpts.contentReq + req.Name = name + req.Version = version + + if err := reqOpts.runBefore(req); err != nil { + return nil, err } - return c.store.Get(name, version) + return c.tiller.GetReleaseContent(req) } // ReleaseHistory returns a release's revision history. -func (h *Client) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) { - reqOpts := h.opts - for _, opt := range opts { - opt(&reqOpts) - } - +func (c *Client) ReleaseHistory(rlsName string, max int32) ([]*release.Release, error) { + reqOpts := c.opts req := &reqOpts.histReq req.Name = rlsName - ctx := NewContext() + req.Max = max - if reqOpts.before != nil { - if err := reqOpts.before(ctx, req); err != nil { - return nil, err - } + if err := reqOpts.runBefore(req); err != nil { + return nil, err } - return h.history(ctx, req) + return c.tiller.GetHistory(req) } // RunReleaseTest executes a pre-defined test on a release. -func (h *Client) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) { - reqOpts := h.opts +func (c *Client) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) { + reqOpts := c.opts for _, opt := range opts { opt(&reqOpts) } req := &reqOpts.testReq req.Name = rlsName - ctx := NewContext() - return h.test(ctx, req) + return c.test(req) } // connect returns a gRPC connection to Tiller or error. The gRPC dial options // are constructed here. -func (h *Client) connect(ctx context.Context) (conn *grpc.ClientConn, err error) { +func (c *Client) connect() (conn *grpc.ClientConn, err error) { opts := []grpc.DialOption{ grpc.WithBlock(), grpc.WithKeepaliveParams(keepalive.ClientParameters{ @@ -293,121 +276,18 @@ func (h *Client) connect(ctx context.Context) (conn *grpc.ClientConn, err error) grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize)), } opts = append(opts, grpc.WithInsecure()) - ctx, cancel := context.WithTimeout(ctx, h.opts.connectTimeout) + ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) defer cancel() - if conn, err = grpc.DialContext(ctx, h.opts.host, opts...); err != nil { + if conn, err = grpc.DialContext(ctx, c.opts.host, opts...); err != nil { return nil, err } return conn, nil } -// Executes tiller.ListReleases RPC. -func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) { - c, err := h.connect(ctx) - if err != nil { - return nil, err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - s, err := rlc.ListReleases(ctx, req) - if err != nil { - return nil, err - } - var resp *rls.ListReleasesResponse - for { - r, err := s.Recv() - if err == io.EOF { - break - } - if err != nil { - return nil, err - } - if resp == nil { - resp = r - continue - } - resp.Releases = append(resp.Releases, r.GetReleases()[0]) - } - return resp, nil -} - -// Executes tiller.InstallRelease RPC. -func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) { - c, err := h.connect(ctx) - if err != nil { - return nil, err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - return rlc.InstallRelease(ctx, req) -} - -// Executes tiller.UninstallRelease RPC. -func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) { - c, err := h.connect(ctx) - if err != nil { - return nil, err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - return rlc.UninstallRelease(ctx, req) -} - -// Executes tiller.UpdateRelease RPC. -func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) { - c, err := h.connect(ctx) - if err != nil { - return nil, err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - return rlc.UpdateRelease(ctx, req) -} - -// Executes tiller.RollbackRelease RPC. -func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) { - c, err := h.connect(ctx) - if err != nil { - return nil, err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - return rlc.RollbackRelease(ctx, req) -} - -// Executes tiller.GetReleaseStatus RPC. -func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) { - c, err := h.connect(ctx) - if err != nil { - return nil, err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - return rlc.GetReleaseStatus(ctx, req) -} - -// Executes tiller.GetHistory RPC. -func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) { - c, err := h.connect(ctx) - if err != nil { - return nil, err - } - defer c.Close() - - rlc := rls.NewReleaseServiceClient(c) - return rlc.GetHistory(ctx, req) -} - // Executes tiller.TestRelease RPC. -func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) { +func (c *Client) test(req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) { errc := make(chan error, 1) - c, err := h.connect(ctx) + conn, err := c.connect() if err != nil { errc <- err return nil, errc @@ -417,10 +297,10 @@ func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan go func() { defer close(errc) defer close(ch) - defer c.Close() + defer conn.Close() - rlc := rls.NewReleaseServiceClient(c) - s, err := rlc.RunReleaseTest(ctx, req) + rlc := rls.NewReleaseServiceClient(conn) + s, err := rlc.RunReleaseTest(context.TODO(), req) if err != nil { errc <- err return diff --git a/pkg/helm/client_test.go b/pkg/helm/client_test.go deleted file mode 100644 index 95e044499..000000000 --- a/pkg/helm/client_test.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -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 helm - -import ( - "testing" - "time" -) - -func TestNewClient(t *testing.T) { - helmClient := NewClient() - if helmClient.opts.connectTimeout != 5*time.Second { - t.Errorf("expected default timeout duration to be 5 seconds, got %v", helmClient.opts.connectTimeout) - } - - helmClient = NewClient(ConnectTimeout(60)) - if helmClient.opts.connectTimeout != time.Minute { - t.Errorf("expected timeout duration to be 1 minute, got %v", helmClient.opts.connectTimeout) - } -} diff --git a/pkg/helm/environment/environment.go b/pkg/helm/environment/environment.go index 2980e6dc9..873f6d23f 100644 --- a/pkg/helm/environment/environment.go +++ b/pkg/helm/environment/environment.go @@ -27,7 +27,6 @@ import ( "path/filepath" "github.com/spf13/pflag" - "k8s.io/client-go/util/homedir" "k8s.io/helm/pkg/helm/helmpath" ) diff --git a/pkg/helm/fake.go b/pkg/helm/fake.go index 897d93238..dd678c234 100644 --- a/pkg/helm/fake.go +++ b/pkg/helm/fake.go @@ -53,13 +53,13 @@ func (c *FakeClient) ListReleases(opts ...ReleaseListOption) ([]*release.Release } // InstallRelease creates a new release and returns a InstallReleaseResponse containing that release -func (c *FakeClient) InstallRelease(chStr, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { +func (c *FakeClient) InstallRelease(chStr, ns string, opts ...InstallOption) (*release.Release, error) { chart := &chart.Chart{} return c.InstallReleaseFromChart(chart, ns, opts...) } // InstallReleaseFromChart adds a new MockRelease to the fake client and returns a InstallReleaseResponse containing that release -func (c *FakeClient) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) { +func (c *FakeClient) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...InstallOption) (*release.Release, error) { for _, opt := range opts { opt(&c.Opts) } @@ -67,17 +67,14 @@ func (c *FakeClient) InstallReleaseFromChart(chart *chart.Chart, ns string, opts releaseName := c.Opts.instReq.Name // Check to see if the release already exists. - rel, err := c.ReleaseStatus(releaseName, nil) + rel, err := c.ReleaseStatus(releaseName, 0) if err == nil && rel != nil { return nil, errors.New("cannot re-use a name that is still in use") } release := ReleaseMock(&MockReleaseOptions{Name: releaseName, Namespace: ns}) c.Rels = append(c.Rels, release) - - return &rls.InstallReleaseResponse{ - Release: release, - }, nil + return release, nil } // DeleteRelease deletes a release from the FakeClient @@ -95,28 +92,23 @@ func (c *FakeClient) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.U } // UpdateRelease returns an UpdateReleaseResponse containing the updated release, if it exists -func (c *FakeClient) UpdateRelease(rlsName string, chStr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { +func (c *FakeClient) UpdateRelease(rlsName string, chStr string, opts ...UpdateOption) (*release.Release, error) { return c.UpdateReleaseFromChart(rlsName, &chart.Chart{}, opts...) } // UpdateReleaseFromChart returns an UpdateReleaseResponse containing the updated release, if it exists -func (c *FakeClient) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) { +func (c *FakeClient) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*release.Release, error) { // Check to see if the release already exists. - rel, err := c.ReleaseContent(rlsName, 0) - if err != nil { - return nil, err - } - - return &rls.UpdateReleaseResponse{Release: rel}, nil + return c.ReleaseContent(rlsName, 0) } // RollbackRelease returns nil, nil -func (c *FakeClient) RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) { +func (c *FakeClient) RollbackRelease(rlsName string, opts ...RollbackOption) (*release.Release, error) { return nil, nil } // ReleaseStatus returns a release status response with info from the matching release name. -func (c *FakeClient) ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) { +func (c *FakeClient) ReleaseStatus(rlsName string, version int32) (*rls.GetReleaseStatusResponse, error) { for _, rel := range c.Rels { if rel.Name == rlsName { return &rls.GetReleaseStatusResponse{ @@ -140,8 +132,8 @@ func (c *FakeClient) ReleaseContent(rlsName string, version int32) (*release.Rel } // ReleaseHistory returns a release's revision history. -func (c *FakeClient) ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) { - return &rls.GetHistoryResponse{Releases: c.Rels}, nil +func (c *FakeClient) ReleaseHistory(rlsName string, max int32) ([]*release.Release, error) { + return c.Rels, nil } // RunReleaseTest executes a pre-defined tests on a release diff --git a/pkg/helm/fake_test.go b/pkg/helm/fake_test.go index 9c0a53759..626f372b6 100644 --- a/pkg/helm/fake_test.go +++ b/pkg/helm/fake_test.go @@ -34,7 +34,6 @@ func TestFakeClient_ReleaseStatus(t *testing.T) { } type args struct { rlsName string - opts []StatusOption } tests := []struct { name string @@ -52,7 +51,6 @@ func TestFakeClient_ReleaseStatus(t *testing.T) { }, args: args{ rlsName: releasePresent.Name, - opts: nil, }, want: &rls.GetReleaseStatusResponse{ Name: releasePresent.Name, @@ -71,7 +69,6 @@ func TestFakeClient_ReleaseStatus(t *testing.T) { }, args: args{ rlsName: releaseNotPresent.Name, - opts: nil, }, want: nil, wantErr: true, @@ -87,7 +84,6 @@ func TestFakeClient_ReleaseStatus(t *testing.T) { }, args: args{ rlsName: releasePresent.Name, - opts: nil, }, want: &rls.GetReleaseStatusResponse{ Name: releasePresent.Name, @@ -104,7 +100,7 @@ func TestFakeClient_ReleaseStatus(t *testing.T) { c := &FakeClient{ Rels: tt.fields.Rels, } - got, err := c.ReleaseStatus(tt.args.rlsName, tt.args.opts...) + got, err := c.ReleaseStatus(tt.args.rlsName, 0) if (err != nil) != tt.wantErr { t.Errorf("FakeClient.ReleaseStatus() error = %v, wantErr %v", err, tt.wantErr) return @@ -129,7 +125,7 @@ func TestFakeClient_InstallReleaseFromChart(t *testing.T) { name string fields fields args args - want *rls.InstallReleaseResponse + want *release.Release relsAfter []*release.Release wantErr bool }{ @@ -142,9 +138,7 @@ func TestFakeClient_InstallReleaseFromChart(t *testing.T) { ns: "default", opts: []InstallOption{ReleaseName("new-release")}, }, - want: &rls.InstallReleaseResponse{ - Release: ReleaseMock(&MockReleaseOptions{Name: "new-release"}), - }, + want: ReleaseMock(&MockReleaseOptions{Name: "new-release"}), relsAfter: []*release.Release{ ReleaseMock(&MockReleaseOptions{Name: "new-release"}), }, diff --git a/pkg/helm/helm_test.go b/pkg/helm/helm_test.go index 5fae82141..b304cafd1 100644 --- a/pkg/helm/helm_test.go +++ b/pkg/helm/helm_test.go @@ -23,7 +23,6 @@ import ( "testing" "github.com/golang/protobuf/proto" - "golang.org/x/net/context" "k8s.io/helm/pkg/chartutil" cpb "k8s.io/helm/pkg/proto/hapi/chart" @@ -76,7 +75,7 @@ func TestListReleases_VerifyOptions(t *testing.T) { } // BeforeCall option to intercept Helm client ListReleasesRequest - b4c := BeforeCall(func(_ context.Context, msg proto.Message) error { + b4c := BeforeCall(func(msg proto.Message) error { switch act := msg.(type) { case *tpb.ListReleasesRequest: t.Logf("ListReleasesRequest: %#+v\n", act) @@ -130,7 +129,7 @@ func TestInstallRelease_VerifyOptions(t *testing.T) { } // BeforeCall option to intercept Helm client InstallReleaseRequest - b4c := BeforeCall(func(_ context.Context, msg proto.Message) error { + b4c := BeforeCall(func(msg proto.Message) error { switch act := msg.(type) { case *tpb.InstallReleaseRequest: t.Logf("InstallReleaseRequest: %#+v\n", act) @@ -171,7 +170,7 @@ func TestDeleteRelease_VerifyOptions(t *testing.T) { } // BeforeCall option to intercept Helm client DeleteReleaseRequest - b4c := BeforeCall(func(_ context.Context, msg proto.Message) error { + b4c := BeforeCall(func(msg proto.Message) error { switch act := msg.(type) { case *tpb.UninstallReleaseRequest: t.Logf("UninstallReleaseRequest: %#+v\n", act) @@ -218,7 +217,7 @@ func TestUpdateRelease_VerifyOptions(t *testing.T) { } // BeforeCall option to intercept Helm client UpdateReleaseRequest - b4c := BeforeCall(func(_ context.Context, msg proto.Message) error { + b4c := BeforeCall(func(msg proto.Message) error { switch act := msg.(type) { case *tpb.UpdateReleaseRequest: t.Logf("UpdateReleaseRequest: %#+v\n", act) @@ -262,7 +261,7 @@ func TestRollbackRelease_VerifyOptions(t *testing.T) { } // BeforeCall option to intercept Helm client RollbackReleaseRequest - b4c := BeforeCall(func(_ context.Context, msg proto.Message) error { + b4c := BeforeCall(func(msg proto.Message) error { switch act := msg.(type) { case *tpb.RollbackReleaseRequest: t.Logf("RollbackReleaseRequest: %#+v\n", act) @@ -295,7 +294,7 @@ func TestReleaseStatus_VerifyOptions(t *testing.T) { } // BeforeCall option to intercept Helm client GetReleaseStatusRequest - b4c := BeforeCall(func(_ context.Context, msg proto.Message) error { + b4c := BeforeCall(func(msg proto.Message) error { switch act := msg.(type) { case *tpb.GetReleaseStatusRequest: t.Logf("GetReleaseStatusRequest: %#+v\n", act) @@ -307,7 +306,7 @@ func TestReleaseStatus_VerifyOptions(t *testing.T) { }) client := NewClient(b4c) - if _, err := client.ReleaseStatus(releaseName, StatusReleaseVersion(revision)); err != errSkip { + if _, err := client.ReleaseStatus(releaseName, revision); err != errSkip { t.Fatalf("did not expect error but got (%v)\n``", err) } @@ -329,7 +328,7 @@ func TestReleaseContent_VerifyOptions(t *testing.T) { } // BeforeCall option to intercept Helm client GetReleaseContentRequest - b4c := BeforeCall(func(_ context.Context, msg proto.Message) error { + b4c := BeforeCall(func(msg proto.Message) error { switch act := msg.(type) { case *tpb.GetReleaseContentRequest: t.Logf("GetReleaseContentRequest: %#+v\n", act) diff --git a/pkg/helm/interface.go b/pkg/helm/interface.go index 07bc298f1..666e3f510 100644 --- a/pkg/helm/interface.go +++ b/pkg/helm/interface.go @@ -25,14 +25,14 @@ import ( // Interface for helm client for mocking in tests type Interface interface { ListReleases(opts ...ReleaseListOption) ([]*release.Release, error) - InstallRelease(chStr, namespace string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) - InstallReleaseFromChart(chart *chart.Chart, namespace string, opts ...InstallOption) (*rls.InstallReleaseResponse, error) + InstallRelease(chStr, namespace string, opts ...InstallOption) (*release.Release, error) + InstallReleaseFromChart(chart *chart.Chart, namespace string, opts ...InstallOption) (*release.Release, error) DeleteRelease(rlsName string, opts ...DeleteOption) (*rls.UninstallReleaseResponse, error) - ReleaseStatus(rlsName string, opts ...StatusOption) (*rls.GetReleaseStatusResponse, error) - UpdateRelease(rlsName, chStr string, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) - UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*rls.UpdateReleaseResponse, error) - RollbackRelease(rlsName string, opts ...RollbackOption) (*rls.RollbackReleaseResponse, error) + ReleaseStatus(rlsName string, version int32) (*rls.GetReleaseStatusResponse, error) + UpdateRelease(rlsName, chStr string, opts ...UpdateOption) (*release.Release, error) + UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts ...UpdateOption) (*release.Release, error) + RollbackRelease(rlsName string, opts ...RollbackOption) (*release.Release, error) ReleaseContent(rlsName string, version int32) (*release.Release, error) - ReleaseHistory(rlsName string, opts ...HistoryOption) (*rls.GetHistoryResponse, error) + ReleaseHistory(rlsName string, max int32) ([]*release.Release, error) RunReleaseTest(rlsName string, opts ...ReleaseTestOption) (<-chan *rls.TestReleaseResponse, <-chan error) } diff --git a/pkg/helm/option.go b/pkg/helm/option.go index 8f8e0a243..0ccafcb63 100644 --- a/pkg/helm/option.go +++ b/pkg/helm/option.go @@ -17,16 +17,13 @@ limitations under the License. package helm import ( - "time" - "github.com/golang/protobuf/proto" - "golang.org/x/net/context" - "google.golang.org/grpc/metadata" + "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" cpb "k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/release" rls "k8s.io/helm/pkg/proto/hapi/services" - "k8s.io/helm/pkg/version" + "k8s.io/helm/pkg/storage/driver" ) // Option allows specifying various settings configurable by @@ -63,7 +60,7 @@ type options struct { // release rollback options are applied directly to the rollback release request rollbackReq rls.RollbackReleaseRequest // before intercepts client calls before sending - before func(context.Context, proto.Message) error + before func(proto.Message) error // release history options are applied directly to the get release history request histReq rls.GetHistoryRequest // resetValues instructs Tiller to reset values to their defaults. @@ -72,21 +69,22 @@ type options struct { reuseValues bool // release test options are applied directly to the test release history request testReq rls.TestReleaseRequest - // connectTimeout specifies the time duration Helm will wait to establish a connection to tiller - connectTimeout time.Duration + + driver driver.Driver + clientset internalclientset.Interface } -// Host specifies the host address of the Tiller release server, (default = ":44134"). -func Host(host string) Option { - return func(opts *options) { - opts.host = host +func (opts *options) runBefore(msg proto.Message) error { + if opts.before != nil { + return opts.before(msg) } + return nil } // BeforeCall returns an option that allows intercepting a helm client rpc // before being sent OTA to tiller. The intercepting function should return // an error to indicate that the call should not proceed or nil otherwise. -func BeforeCall(fn func(context.Context, proto.Message) error) Option { +func BeforeCall(fn func(proto.Message) error) Option { return func(opts *options) { opts.before = fn } @@ -168,13 +166,6 @@ func ReleaseName(name string) InstallOption { } } -// ConnectTimeout specifies the duration (in seconds) Helm will wait to establish a connection to tiller -func ConnectTimeout(timeout int64) Option { - return func(opts *options) { - opts.connectTimeout = time.Duration(timeout) * time.Second - } -} - // InstallTimeout specifies the number of seconds before kubernetes calls timeout func InstallTimeout(timeout int64) InstallOption { return func(opts *options) { @@ -365,37 +356,10 @@ func UpgradeForce(force bool) UpdateOption { } } -// ContentOption allows setting optional attributes when -// performing a GetReleaseContent tiller rpc. -type ContentOption func(*options) - -// ContentReleaseVersion will instruct Tiller to retrieve the content -// of a particular version of a release. -func ContentReleaseVersion(version int32) ContentOption { - return func(opts *options) { - opts.contentReq.Version = version - } -} - -// StatusOption allows setting optional attributes when -// performing a GetReleaseStatus tiller rpc. -type StatusOption func(*options) - -// StatusReleaseVersion will instruct Tiller to retrieve the status -// of a particular version of a release. -func StatusReleaseVersion(version int32) StatusOption { - return func(opts *options) { - opts.statusReq.Version = version - } -} - // DeleteOption allows setting optional attributes when // performing a UninstallRelease tiller rpc. type DeleteOption func(*options) -// VersionOption -- TODO -type VersionOption func(*options) - // UpdateOption allows specifying various settings // configurable by the helm client user for overriding // the defaults used when running the `helm upgrade` command. @@ -406,24 +370,18 @@ type UpdateOption func(*options) // running the `helm rollback` command. type RollbackOption func(*options) -// HistoryOption allows configuring optional request data for -// issuing a GetHistory rpc. -type HistoryOption func(*options) +// ReleaseTestOption allows configuring optional request data for +// issuing a TestRelease rpc. +type ReleaseTestOption func(*options) -// WithMaxHistory sets the max number of releases to return -// in a release history query. -func WithMaxHistory(max int32) HistoryOption { +func Driver(d driver.Driver) Option { return func(opts *options) { - opts.histReq.Max = max + opts.driver = d } } -// NewContext creates a versioned context. -func NewContext() context.Context { - md := metadata.Pairs("x-helm-api-client", version.GetVersion()) - return metadata.NewOutgoingContext(context.TODO(), md) +func ClientSet(cs internalclientset.Interface) Option { + return func(opts *options) { + opts.clientset = cs + } } - -// ReleaseTestOption allows configuring optional request data for -// issuing a TestRelease rpc. -type ReleaseTestOption func(*options) diff --git a/pkg/helm/portforwarder/pod.go b/pkg/helm/portforwarder/pod.go deleted file mode 100644 index 7c2355204..000000000 --- a/pkg/helm/portforwarder/pod.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -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 portforwarder - -import ( - "k8s.io/api/core/v1" -) - -// These functions are adapted from the "kubernetes" repository's file -// -// kubernetes/pkg/api/v1/pod/util.go -// -// where they rely upon the API types specific to that repository. Here we recast them to operate -// upon the type from the "client-go" repository instead. - -// isPodReady returns true if a pod is ready; false otherwise. -func isPodReady(pod *v1.Pod) bool { - return isPodReadyConditionTrue(pod.Status) -} - -// isPodReady retruns true if a pod is ready; false otherwise. -func isPodReadyConditionTrue(status v1.PodStatus) bool { - condition := getPodReadyCondition(status) - return condition != nil && condition.Status == v1.ConditionTrue -} - -// getPodReadyCondition extracts the pod ready condition from the given status and returns that. -// Returns nil if the condition is not present. -func getPodReadyCondition(status v1.PodStatus) *v1.PodCondition { - _, condition := getPodCondition(&status, v1.PodReady) - return condition -} - -// getPodCondition extracts the provided condition from the given status and returns that. -// Returns nil and -1 if the condition is not present, and the index of the located condition. -func getPodCondition(status *v1.PodStatus, conditionType v1.PodConditionType) (int, *v1.PodCondition) { - if status == nil { - return -1, nil - } - for i := range status.Conditions { - if status.Conditions[i].Type == conditionType { - return i, &status.Conditions[i] - } - } - return -1, nil -} diff --git a/pkg/helm/portforwarder/portforwarder.go b/pkg/helm/portforwarder/portforwarder.go deleted file mode 100644 index 878610d5f..000000000 --- a/pkg/helm/portforwarder/portforwarder.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -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 portforwarder - -import ( - "fmt" - - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" - corev1 "k8s.io/client-go/kubernetes/typed/core/v1" - "k8s.io/client-go/rest" - - "k8s.io/helm/pkg/kube" -) - -var ( - tillerPodLabels = labels.Set{"app": "helm", "name": "tiller"} -) - -// New creates a new and initialized tunnel. -func New(namespace string, client kubernetes.Interface, config *rest.Config) (*kube.Tunnel, error) { - podName, err := GetTillerPodName(client.CoreV1(), namespace) - if err != nil { - return nil, err - } - const tillerPort = 44134 - t := kube.NewTunnel(client.CoreV1().RESTClient(), config, namespace, podName, tillerPort) - return t, t.ForwardPort() -} - -// GetTillerPodName fetches the name of tiller pod running in the given namespace. -func GetTillerPodName(client corev1.PodsGetter, namespace string) (string, error) { - selector := tillerPodLabels.AsSelector() - pod, err := getFirstRunningPod(client, namespace, selector) - if err != nil { - return "", err - } - return pod.ObjectMeta.GetName(), nil -} - -func getFirstRunningPod(client corev1.PodsGetter, namespace string, selector labels.Selector) (*v1.Pod, error) { - options := metav1.ListOptions{LabelSelector: selector.String()} - pods, err := client.Pods(namespace).List(options) - if err != nil { - return nil, err - } - if len(pods.Items) < 1 { - return nil, fmt.Errorf("could not find tiller") - } - for _, p := range pods.Items { - if isPodReady(&p) { - return &p, nil - } - } - return nil, fmt.Errorf("could not find a ready tiller pod") -} diff --git a/pkg/helm/portforwarder/portforwarder_test.go b/pkg/helm/portforwarder/portforwarder_test.go deleted file mode 100644 index e4c148991..000000000 --- a/pkg/helm/portforwarder/portforwarder_test.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -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 portforwarder - -import ( - "testing" - - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes/fake" -) - -func mockTillerPod() v1.Pod { - return v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "orca", - Namespace: v1.NamespaceDefault, - Labels: tillerPodLabels, - }, - Status: v1.PodStatus{ - Phase: v1.PodRunning, - Conditions: []v1.PodCondition{ - { - Status: v1.ConditionTrue, - Type: v1.PodReady, - }, - }, - }, - } -} - -func mockTillerPodPending() v1.Pod { - p := mockTillerPod() - p.Name = "blue" - p.Status.Conditions[0].Status = v1.ConditionFalse - return p -} - -func TestGetFirstPod(t *testing.T) { - tests := []struct { - name string - pods []v1.Pod - expected string - err bool - }{ - { - name: "with a ready pod", - pods: []v1.Pod{mockTillerPod()}, - expected: "orca", - }, - { - name: "without a ready pod", - pods: []v1.Pod{mockTillerPodPending()}, - err: true, - }, - { - name: "without a pod", - pods: []v1.Pod{}, - err: true, - }, - } - - for _, tt := range tests { - client := fake.NewSimpleClientset(&v1.PodList{Items: tt.pods}) - name, err := GetTillerPodName(client.Core(), v1.NamespaceDefault) - if (err != nil) != tt.err { - t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err) - } - if name != tt.expected { - t.Errorf("%q. expected %q, got %q", tt.name, tt.expected, name) - } - } -} diff --git a/pkg/kube/tunnel.go b/pkg/kube/tunnel.go deleted file mode 100644 index 08280f25d..000000000 --- a/pkg/kube/tunnel.go +++ /dev/null @@ -1,122 +0,0 @@ -/* -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 kube - -import ( - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "strconv" - - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/portforward" - "k8s.io/client-go/transport/spdy" -) - -// Tunnel describes a ssh-like tunnel to a kubernetes pod -type Tunnel struct { - Local int - Remote int - Namespace string - PodName string - Out io.Writer - stopChan chan struct{} - readyChan chan struct{} - config *rest.Config - client rest.Interface -} - -// NewTunnel creates a new tunnel -func NewTunnel(client rest.Interface, config *rest.Config, namespace, podName string, remote int) *Tunnel { - return &Tunnel{ - config: config, - client: client, - Namespace: namespace, - PodName: podName, - Remote: remote, - stopChan: make(chan struct{}, 1), - readyChan: make(chan struct{}, 1), - Out: ioutil.Discard, - } -} - -// Close disconnects a tunnel connection -func (t *Tunnel) Close() { - close(t.stopChan) -} - -// ForwardPort opens a tunnel to a kubernetes pod -func (t *Tunnel) ForwardPort() error { - // Build a url to the portforward endpoint - // example: http://localhost:8080/api/v1/namespaces/helm/pods/tiller-deploy-9itlq/portforward - u := t.client.Post(). - Resource("pods"). - Namespace(t.Namespace). - Name(t.PodName). - SubResource("portforward").URL() - - transport, upgrader, err := spdy.RoundTripperFor(t.config) - if err != nil { - return err - } - dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", u) - - local, err := getAvailablePort() - if err != nil { - return fmt.Errorf("could not find an available port: %s", err) - } - t.Local = local - - ports := []string{fmt.Sprintf("%d:%d", t.Local, t.Remote)} - - pf, err := portforward.New(dialer, ports, t.stopChan, t.readyChan, t.Out, t.Out) - if err != nil { - return err - } - - errChan := make(chan error) - go func() { - errChan <- pf.ForwardPorts() - }() - - select { - case err = <-errChan: - return fmt.Errorf("forwarding ports: %v", err) - case <-pf.Ready: - return nil - } -} - -func getAvailablePort() (int, error) { - l, err := net.Listen("tcp", ":0") - if err != nil { - return 0, err - } - defer l.Close() - - _, p, err := net.SplitHostPort(l.Addr().String()) - if err != nil { - return 0, err - } - port, err := strconv.Atoi(p) - if err != nil { - return 0, err - } - return port, err -} diff --git a/pkg/kube/tunnel_test.go b/pkg/kube/tunnel_test.go deleted file mode 100644 index 264200ddf..000000000 --- a/pkg/kube/tunnel_test.go +++ /dev/null @@ -1,31 +0,0 @@ -/* -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 kube - -import ( - "testing" -) - -func TestAvailablePort(t *testing.T) { - port, err := getAvailablePort() - if err != nil { - t.Fatal(err) - } - if port < 1 { - t.Fatalf("generated port should be > 1, got %d", port) - } -} diff --git a/pkg/plugin/installer/http_installer.go b/pkg/plugin/installer/http_installer.go index 91d497651..e06b0f776 100644 --- a/pkg/plugin/installer/http_installer.go +++ b/pkg/plugin/installer/http_installer.go @@ -21,14 +21,15 @@ import ( "compress/gzip" "fmt" "io" - "k8s.io/helm/pkg/getter" - "k8s.io/helm/pkg/helm/environment" - "k8s.io/helm/pkg/helm/helmpath" - "k8s.io/helm/pkg/plugin/cache" "os" "path/filepath" "regexp" "strings" + + "k8s.io/helm/pkg/getter" + "k8s.io/helm/pkg/helm/environment" + "k8s.io/helm/pkg/helm/helmpath" + "k8s.io/helm/pkg/plugin/cache" ) // HTTPInstaller installs plugins from an archive served by a web server. diff --git a/pkg/plugin/installer/http_installer_test.go b/pkg/plugin/installer/http_installer_test.go index ca1a71e3e..7756c0091 100644 --- a/pkg/plugin/installer/http_installer_test.go +++ b/pkg/plugin/installer/http_installer_test.go @@ -20,9 +20,10 @@ import ( "encoding/base64" "fmt" "io/ioutil" - "k8s.io/helm/pkg/helm/helmpath" "os" "testing" + + "k8s.io/helm/pkg/helm/helmpath" ) var _ Installer = new(HTTPInstaller) diff --git a/pkg/releasetesting/environment_test.go b/pkg/releasetesting/environment_test.go index 0199b74eb..103928342 100644 --- a/pkg/releasetesting/environment_test.go +++ b/pkg/releasetesting/environment_test.go @@ -129,11 +129,6 @@ func newMockTestingEnvironment() *MockTestingEnvironment { } } -func (mte MockTestingEnvironment) streamRunning(name string) error { return nil } -func (mte MockTestingEnvironment) streamError(info string) error { return nil } -func (mte MockTestingEnvironment) streamFailed(name string) error { return nil } -func (mte MockTestingEnvironment) streamSuccess(name string) error { return nil } -func (mte MockTestingEnvironment) streamUnknown(name, info string) error { return nil } func (mte MockTestingEnvironment) streamMessage(msg string, status release.TestRun_Status) error { mte.Stream.Send(&services.TestReleaseResponse{Msg: msg, Status: status}) return nil diff --git a/pkg/releasetesting/test_suite.go b/pkg/releasetesting/test_suite.go index 2e42400ce..6309c4da5 100644 --- a/pkg/releasetesting/test_suite.go +++ b/pkg/releasetesting/test_suite.go @@ -46,18 +46,15 @@ type test struct { // NewTestSuite takes a release object and returns a TestSuite object with test definitions // extracted from the release -func NewTestSuite(rel *release.Release) (*TestSuite, error) { - testManifests, err := extractTestManifestsFromHooks(rel.Hooks) - if err != nil { - return nil, err - } +func NewTestSuite(rel *release.Release) *TestSuite { + testManifests := extractTestManifestsFromHooks(rel.Hooks) results := []*release.TestRun{} return &TestSuite{ TestManifests: testManifests, Results: results, - }, nil + } } // Run executes tests in a test suite and stores a result within a given environment @@ -152,7 +149,7 @@ func expectedSuccess(hookTypes []string) (bool, error) { return false, fmt.Errorf("No %s or %s hook found", hooks.ReleaseTestSuccess, hooks.ReleaseTestFailure) } -func extractTestManifestsFromHooks(h []*release.Hook) ([]string, error) { +func extractTestManifestsFromHooks(h []*release.Hook) []string { testHooks := hooks.FilterTestHooks(h) tests := []string{} @@ -162,7 +159,7 @@ func extractTestManifestsFromHooks(h []*release.Hook) ([]string, error) { tests = append(tests, t) } } - return tests, nil + return tests } func newTest(testManifest string) (*test, error) { diff --git a/pkg/releasetesting/test_suite_test.go b/pkg/releasetesting/test_suite_test.go index e3ca65702..074af9794 100644 --- a/pkg/releasetesting/test_suite_test.go +++ b/pkg/releasetesting/test_suite_test.go @@ -24,7 +24,6 @@ import ( "github.com/golang/protobuf/ptypes/timestamp" "golang.org/x/net/context" - grpc "google.golang.org/grpc" "google.golang.org/grpc/metadata" "k8s.io/kubernetes/pkg/apis/core" @@ -73,15 +72,6 @@ data: name: value ` -func TestNewTestSuite(t *testing.T) { - rel := releaseStub() - - _, err := NewTestSuite(rel) - if err != nil { - t.Errorf("%s", err) - } -} - func TestRun(t *testing.T) { testManifests := []string{manifestWithTestSuccessHook, manifestWithTestFailureHook} @@ -209,10 +199,7 @@ func TestRunSuccessWithTestFailureHook(t *testing.T) { func TestExtractTestManifestsFromHooks(t *testing.T) { rel := releaseStub() - testManifests, err := extractTestManifestsFromHooks(rel.Hooks) - if err != nil { - t.Errorf("Expected no error, Got: %s", err) - } + testManifests := extractTestManifestsFromHooks(rel.Hooks) if len(testManifests) != 1 { t.Errorf("Expected 1 test manifest, Got: %v", len(testManifests)) @@ -297,7 +284,6 @@ func mockTillerEnvironment() *tillerEnv.Environment { } type mockStream struct { - stream grpc.ServerStream messages []*services.TestReleaseResponse } diff --git a/pkg/tiller/release_content.go b/pkg/tiller/release_content.go index fd783d6b6..f7bd45bf1 100644 --- a/pkg/tiller/release_content.go +++ b/pkg/tiller/release_content.go @@ -17,23 +17,20 @@ limitations under the License. package tiller import ( - ctx "golang.org/x/net/context" - + "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" ) // GetReleaseContent gets all of the stored information for the given release. -func (s *ReleaseServer) GetReleaseContent(c ctx.Context, req *services.GetReleaseContentRequest) (*services.GetReleaseContentResponse, error) { +func (s *ReleaseServer) GetReleaseContent(req *services.GetReleaseContentRequest) (*release.Release, error) { if err := validateReleaseName(req.Name); err != nil { s.Log("releaseContent: Release name is invalid: %s", req.Name) return nil, err } if req.Version <= 0 { - rel, err := s.env.Releases.Last(req.Name) - return &services.GetReleaseContentResponse{Release: rel}, err + return s.env.Releases.Last(req.Name) } - rel, err := s.env.Releases.Get(req.Name, req.Version) - return &services.GetReleaseContentResponse{Release: rel}, err + return s.env.Releases.Get(req.Name, req.Version) } diff --git a/pkg/tiller/release_content_test.go b/pkg/tiller/release_content_test.go index c190c703e..b9b5fa433 100644 --- a/pkg/tiller/release_content_test.go +++ b/pkg/tiller/release_content_test.go @@ -17,26 +17,24 @@ limitations under the License. package tiller import ( - "context" "testing" "k8s.io/helm/pkg/proto/hapi/services" ) func TestGetReleaseContent(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() if err := rs.env.Releases.Create(rel); err != nil { t.Fatalf("Could not store mock release: %s", err) } - res, err := rs.GetReleaseContent(c, &services.GetReleaseContentRequest{Name: rel.Name, Version: 1}) + res, err := rs.GetReleaseContent(&services.GetReleaseContentRequest{Name: rel.Name, Version: 1}) if err != nil { t.Errorf("Error getting release content: %s", err) } - if res.Release.Chart.Metadata.Name != rel.Chart.Metadata.Name { - t.Errorf("Expected %q, got %q", rel.Chart.Metadata.Name, res.Release.Chart.Metadata.Name) + if res.Chart.Metadata.Name != rel.Chart.Metadata.Name { + t.Errorf("Expected %q, got %q", rel.Chart.Metadata.Name, res.Chart.Metadata.Name) } } diff --git a/pkg/tiller/release_history.go b/pkg/tiller/release_history.go index 0dd525978..761a61542 100644 --- a/pkg/tiller/release_history.go +++ b/pkg/tiller/release_history.go @@ -17,14 +17,13 @@ limitations under the License. package tiller import ( - "golang.org/x/net/context" - + "k8s.io/helm/pkg/proto/hapi/release" tpb "k8s.io/helm/pkg/proto/hapi/services" relutil "k8s.io/helm/pkg/releaseutil" ) // GetHistory gets the history for a given release. -func (s *ReleaseServer) GetHistory(ctx context.Context, req *tpb.GetHistoryRequest) (*tpb.GetHistoryResponse, error) { +func (s *ReleaseServer) GetHistory(req *tpb.GetHistoryRequest) ([]*release.Release, error) { if err := validateReleaseName(req.Name); err != nil { s.Log("getHistory: Release name is invalid: %s", req.Name) return nil, err @@ -38,12 +37,12 @@ func (s *ReleaseServer) GetHistory(ctx context.Context, req *tpb.GetHistoryReque relutil.Reverse(h, relutil.SortByRevision) - var resp tpb.GetHistoryResponse + var rels []*release.Release for i := 0; i < min(len(h), int(req.Max)); i++ { - resp.Releases = append(resp.Releases, h[i]) + rels = append(rels, h[i]) } - return &resp, nil + return rels, nil } func min(x, y int) int { diff --git a/pkg/tiller/release_history_test.go b/pkg/tiller/release_history_test.go index a4453dfd7..c43c79785 100644 --- a/pkg/tiller/release_history_test.go +++ b/pkg/tiller/release_history_test.go @@ -20,8 +20,6 @@ import ( "reflect" "testing" - "golang.org/x/net/context" - rpb "k8s.io/helm/pkg/proto/hapi/release" tpb "k8s.io/helm/pkg/proto/hapi/services" ) @@ -39,25 +37,25 @@ func TestGetHistory_WithRevisions(t *testing.T) { tests := []struct { desc string req *tpb.GetHistoryRequest - res *tpb.GetHistoryResponse + res []*rpb.Release }{ { desc: "get release with history and default limit (max=256)", req: &tpb.GetHistoryRequest{Name: "angry-bird", Max: 256}, - res: &tpb.GetHistoryResponse{Releases: []*rpb.Release{ + res: []*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), - }}, + }, }, { desc: "get release with history using result limit (max=2)", req: &tpb.GetHistoryRequest{Name: "angry-bird", Max: 2}, - res: &tpb.GetHistoryResponse{Releases: []*rpb.Release{ + res: []*rpb.Release{ mk("angry-bird", 4, rpb.Status_DEPLOYED), mk("angry-bird", 3, rpb.Status_SUPERSEDED), - }}, + }, }, } @@ -78,7 +76,7 @@ func TestGetHistory_WithRevisions(t *testing.T) { // run tests for _, tt := range tests { - res, err := srv.GetHistory(context.TODO(), tt.req) + res, err := srv.GetHistory(tt.req) if err != nil { t.Fatalf("%s:\nFailed to get History of %q: %s", tt.desc, tt.req.Name, err) } @@ -105,12 +103,12 @@ func TestGetHistory_WithNoRevisions(t *testing.T) { srv.env.Releases.Create(rls) for _, tt := range tests { - res, err := srv.GetHistory(context.TODO(), tt.req) + res, err := srv.GetHistory(tt.req) if err != nil { t.Fatalf("%s:\nFailed to get History of %q: %s", tt.desc, tt.req.Name, err) } - if len(res.Releases) > 1 { - t.Fatalf("%s:\nExpected zero items, got %d", tt.desc, len(res.Releases)) + if len(res) > 1 { + t.Fatalf("%s:\nExpected zero items, got %d", tt.desc, len(res)) } } } diff --git a/pkg/tiller/release_install.go b/pkg/tiller/release_install.go index c7d2b4060..195a61fee 100644 --- a/pkg/tiller/release_install.go +++ b/pkg/tiller/release_install.go @@ -20,8 +20,6 @@ import ( "fmt" "strings" - ctx "golang.org/x/net/context" - "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hooks" "k8s.io/helm/pkg/proto/hapi/release" @@ -31,19 +29,18 @@ import ( ) // InstallRelease installs a release and stores the release record. -func (s *ReleaseServer) InstallRelease(c ctx.Context, req *services.InstallReleaseRequest) (*services.InstallReleaseResponse, error) { +func (s *ReleaseServer) InstallRelease(req *services.InstallReleaseRequest) (*release.Release, error) { s.Log("preparing install for %s", req.Name) rel, err := s.prepareRelease(req) if err != nil { s.Log("failed install prepare step: %s", err) - res := &services.InstallReleaseResponse{Release: rel} // On dry run, append the manifest contents to a failed release. This is // a stop-gap until we can revisit an error backchannel post-2.0. if req.DryRun && strings.HasPrefix(err.Error(), "YAML parse error") { err = fmt.Errorf("%s\n%s", err, rel.Manifest) } - return res, err + return rel, err } s.Log("performing install for %s", req.Name) @@ -132,19 +129,18 @@ func (s *ReleaseServer) prepareRelease(req *services.InstallReleaseRequest) (*re } // performRelease runs a release. -func (s *ReleaseServer) performRelease(r *release.Release, req *services.InstallReleaseRequest) (*services.InstallReleaseResponse, error) { - res := &services.InstallReleaseResponse{Release: r} +func (s *ReleaseServer) performRelease(r *release.Release, req *services.InstallReleaseRequest) (*release.Release, error) { if req.DryRun { s.Log("dry run for %s", r.Name) - res.Release.Info.Description = "Dry run complete" - return res, nil + r.Info.Description = "Dry run complete" + return r, nil } // pre-install hooks if !req.DisableHooks { if err := s.execHook(r.Hooks, r.Name, r.Namespace, hooks.PreInstall, req.Timeout); err != nil { - return res, err + return r, err } } else { s.Log("install hooks disabled for %s", req.Name) @@ -181,7 +177,7 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install r.Info.Description = msg s.recordRelease(old, true) s.recordRelease(r, true) - return res, err + return r, err } default: @@ -194,7 +190,7 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install r.Info.Status.Code = release.Status_FAILED r.Info.Description = msg s.recordRelease(r, true) - return res, fmt.Errorf("release %s failed: %s", r.Name, err) + return r, fmt.Errorf("release %s failed: %s", r.Name, err) } } @@ -206,7 +202,7 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install r.Info.Status.Code = release.Status_FAILED r.Info.Description = msg s.recordRelease(r, true) - return res, err + return r, err } } @@ -221,5 +217,5 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *services.Install // this stored in the future. s.recordRelease(r, true) - return res, nil + return r, nil } diff --git a/pkg/tiller/release_install_test.go b/pkg/tiller/release_install_test.go index 701433a0c..9effc625d 100644 --- a/pkg/tiller/release_install_test.go +++ b/pkg/tiller/release_install_test.go @@ -21,32 +21,29 @@ import ( "strings" "testing" - "golang.org/x/net/context" - "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" "k8s.io/helm/pkg/version" ) func TestInstallRelease(t *testing.T) { - c := context.TODO() rs := rsFixture() req := installRequest() - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err != nil { t.Fatalf("Failed install: %s", err) } - if res.Release.Name == "" { + if res.Name == "" { t.Errorf("Expected release name.") } - if res.Release.Namespace != "spaced" { - t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) + if res.Namespace != "spaced" { + t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Namespace) } - rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) + rel, err := rs.env.Releases.Get(res.Name, res.Version) if err != nil { - t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) + t.Errorf("Expected release for %s (%v).", res.Name, rs.env.Releases) } t.Logf("rel: %v", rel) @@ -65,8 +62,8 @@ func TestInstallRelease(t *testing.T) { t.Errorf("Expected event 0 is pre-delete") } - if len(res.Release.Manifest) == 0 { - t.Errorf("No manifest returned: %v", res.Release) + if len(res.Manifest) == 0 { + t.Errorf("No manifest returned: %v", res) } if len(rel.Manifest) == 0 { @@ -83,26 +80,25 @@ func TestInstallRelease(t *testing.T) { } func TestInstallRelease_WithNotes(t *testing.T) { - c := context.TODO() rs := rsFixture() req := installRequest( withChart(withNotes(notesText)), ) - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err != nil { t.Fatalf("Failed install: %s", err) } - if res.Release.Name == "" { + if res.Name == "" { t.Errorf("Expected release name.") } - if res.Release.Namespace != "spaced" { - t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) + if res.Namespace != "spaced" { + t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Namespace) } - rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) + rel, err := rs.env.Releases.Get(res.Name, res.Version) if err != nil { - t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) + t.Errorf("Expected release for %s (%v).", res.Name, rs.env.Releases) } t.Logf("rel: %v", rel) @@ -125,8 +121,8 @@ func TestInstallRelease_WithNotes(t *testing.T) { t.Errorf("Expected event 0 is pre-delete") } - if len(res.Release.Manifest) == 0 { - t.Errorf("No manifest returned: %v", res.Release) + if len(res.Manifest) == 0 { + t.Errorf("No manifest returned: %v", res) } if len(rel.Manifest) == 0 { @@ -143,26 +139,25 @@ func TestInstallRelease_WithNotes(t *testing.T) { } func TestInstallRelease_WithNotesRendered(t *testing.T) { - c := context.TODO() rs := rsFixture() req := installRequest( withChart(withNotes(notesText + " {{.Release.Name}}")), ) - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err != nil { t.Fatalf("Failed install: %s", err) } - if res.Release.Name == "" { + if res.Name == "" { t.Errorf("Expected release name.") } - if res.Release.Namespace != "spaced" { - t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Release.Namespace) + if res.Namespace != "spaced" { + t.Errorf("Expected release namespace 'spaced', got '%s'.", res.Namespace) } - rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) + rel, err := rs.env.Releases.Get(res.Name, res.Version) if err != nil { - t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) + t.Errorf("Expected release for %s (%v).", res.Name, rs.env.Releases) } t.Logf("rel: %v", rel) @@ -174,7 +169,7 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) { t.Errorf("Unexpected manifest: %v", rel.Hooks[0].Manifest) } - expectedNotes := fmt.Sprintf("%s %s", notesText, res.Release.Name) + expectedNotes := fmt.Sprintf("%s %s", notesText, res.Name) if rel.Info.Status.Notes != expectedNotes { t.Fatalf("Expected '%s', got '%s'", expectedNotes, rel.Info.Status.Notes) } @@ -186,8 +181,8 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) { t.Errorf("Expected event 0 is pre-delete") } - if len(res.Release.Manifest) == 0 { - t.Errorf("No manifest returned: %v", res.Release) + if len(res.Manifest) == 0 { + t.Errorf("No manifest returned: %v", res) } if len(rel.Manifest) == 0 { @@ -205,13 +200,12 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) { func TestInstallRelease_TillerVersion(t *testing.T) { version.Version = "2.2.0" - c := context.TODO() rs := rsFixture() req := installRequest( withChart(withTiller(">=2.2.0")), ) - _, err := rs.InstallRelease(c, req) + _, err := rs.InstallRelease(req) if err != nil { t.Fatalf("Expected valid range. Got %q", err) } @@ -219,13 +213,12 @@ func TestInstallRelease_TillerVersion(t *testing.T) { func TestInstallRelease_WrongTillerVersion(t *testing.T) { version.Version = "2.2.0" - c := context.TODO() rs := rsFixture() req := installRequest( withChart(withTiller("<2.0.0")), ) - _, err := rs.InstallRelease(c, req) + _, err := rs.InstallRelease(req) if err == nil { t.Fatalf("Expected to fail because of wrong version") } @@ -237,24 +230,23 @@ func TestInstallRelease_WrongTillerVersion(t *testing.T) { } func TestInstallRelease_WithChartAndDependencyNotes(t *testing.T) { - c := context.TODO() rs := rsFixture() req := installRequest(withChart( withNotes(notesText), withDependency(withNotes(notesText+" child")), )) - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err != nil { t.Fatalf("Failed install: %s", err) } - if res.Release.Name == "" { + if res.Name == "" { t.Errorf("Expected release name.") } - rel, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) + rel, err := rs.env.Releases.Get(res.Name, res.Version) if err != nil { - t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) + t.Errorf("Expected release for %s (%v).", res.Name, rs.env.Releases) } t.Logf("rel: %v", rel) @@ -269,92 +261,88 @@ func TestInstallRelease_WithChartAndDependencyNotes(t *testing.T) { } func TestInstallRelease_DryRun(t *testing.T) { - c := context.TODO() rs := rsFixture() req := installRequest(withDryRun(), withChart(withSampleTemplates()), ) - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err != nil { t.Errorf("Failed install: %s", err) } - if res.Release.Name == "" { + if res.Name == "" { t.Errorf("Expected release name.") } - if !strings.Contains(res.Release.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { - t.Errorf("unexpected output: %s", res.Release.Manifest) + if !strings.Contains(res.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { + t.Errorf("unexpected output: %s", res.Manifest) } - if !strings.Contains(res.Release.Manifest, "---\n# Source: hello/templates/goodbye\ngoodbye: world") { - t.Errorf("unexpected output: %s", res.Release.Manifest) + if !strings.Contains(res.Manifest, "---\n# Source: hello/templates/goodbye\ngoodbye: world") { + t.Errorf("unexpected output: %s", res.Manifest) } - if !strings.Contains(res.Release.Manifest, "hello: Earth") { - t.Errorf("Should contain partial content. %s", res.Release.Manifest) + if !strings.Contains(res.Manifest, "hello: Earth") { + t.Errorf("Should contain partial content. %s", res.Manifest) } - if strings.Contains(res.Release.Manifest, "hello: {{ template \"_planet\" . }}") { - t.Errorf("Should not contain partial templates itself. %s", res.Release.Manifest) + if strings.Contains(res.Manifest, "hello: {{ template \"_planet\" . }}") { + t.Errorf("Should not contain partial templates itself. %s", res.Manifest) } - if strings.Contains(res.Release.Manifest, "empty") { - t.Errorf("Should not contain template data for an empty file. %s", res.Release.Manifest) + if strings.Contains(res.Manifest, "empty") { + t.Errorf("Should not contain template data for an empty file. %s", res.Manifest) } - if _, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version); err == nil { + if _, err := rs.env.Releases.Get(res.Name, res.Version); err == nil { t.Errorf("Expected no stored release.") } - if l := len(res.Release.Hooks); l != 1 { + if l := len(res.Hooks); l != 1 { t.Fatalf("Expected 1 hook, got %d", l) } - if res.Release.Hooks[0].LastRun != nil { + if res.Hooks[0].LastRun != nil { t.Error("Expected hook to not be marked as run.") } - if res.Release.Info.Description != "Dry run complete" { - t.Errorf("unexpected description: %s", res.Release.Info.Description) + if res.Info.Description != "Dry run complete" { + t.Errorf("unexpected description: %s", res.Info.Description) } } func TestInstallRelease_NoHooks(t *testing.T) { - c := context.TODO() rs := rsFixture() rs.env.Releases.Create(releaseStub()) req := installRequest(withDisabledHooks()) - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err != nil { t.Errorf("Failed install: %s", err) } - if hl := res.Release.Hooks[0].LastRun; hl != nil { + if hl := res.Hooks[0].LastRun; hl != nil { t.Errorf("Expected that no hooks were run. Got %d", hl) } } func TestInstallRelease_FailedHooks(t *testing.T) { - c := context.TODO() rs := rsFixture() rs.env.Releases.Create(releaseStub()) rs.env.KubeClient = newHookFailingKubeClient() req := installRequest() - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err == nil { t.Error("Expected failed install") } - if hl := res.Release.Info.Status.Code; hl != release.Status_FAILED { + if hl := res.Info.Status.Code; hl != release.Status_FAILED { t.Errorf("Expected FAILED release. Got %d", hl) } } func TestInstallRelease_ReuseName(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rel.Info.Status.Code = release.Status_DELETED @@ -364,17 +352,17 @@ func TestInstallRelease_ReuseName(t *testing.T) { withReuseName(), withName(rel.Name), ) - res, err := rs.InstallRelease(c, req) + res, err := rs.InstallRelease(req) if err != nil { t.Fatalf("Failed install: %s", err) } - if res.Release.Name != rel.Name { - t.Errorf("expected %q, got %q", rel.Name, res.Release.Name) + if res.Name != rel.Name { + t.Errorf("expected %q, got %q", rel.Name, res.Name) } getreq := &services.GetReleaseStatusRequest{Name: rel.Name, Version: 0} - getres, err := rs.GetReleaseStatus(c, getreq) + getres, err := rs.GetReleaseStatus(getreq) if err != nil { t.Errorf("Failed to retrieve release: %s", err) } @@ -384,27 +372,25 @@ func TestInstallRelease_ReuseName(t *testing.T) { } func TestInstallRelease_KubeVersion(t *testing.T) { - c := context.TODO() rs := rsFixture() req := installRequest( withChart(withKube(">=0.0.0")), ) - _, err := rs.InstallRelease(c, req) + _, err := rs.InstallRelease(req) if err != nil { t.Fatalf("Expected valid range. Got %q", err) } } func TestInstallRelease_WrongKubeVersion(t *testing.T) { - c := context.TODO() rs := rsFixture() req := installRequest( withChart(withKube(">=5.0.0")), ) - _, err := rs.InstallRelease(c, req) + _, err := rs.InstallRelease(req) if err == nil { t.Fatalf("Expected to fail because of wrong version") } diff --git a/pkg/tiller/release_rollback.go b/pkg/tiller/release_rollback.go index 279022c25..af48561ba 100644 --- a/pkg/tiller/release_rollback.go +++ b/pkg/tiller/release_rollback.go @@ -19,8 +19,6 @@ package tiller import ( "fmt" - ctx "golang.org/x/net/context" - "k8s.io/helm/pkg/hooks" "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" @@ -28,7 +26,7 @@ import ( ) // RollbackRelease rolls back to a previous version of the given release. -func (s *ReleaseServer) RollbackRelease(c ctx.Context, req *services.RollbackReleaseRequest) (*services.RollbackReleaseResponse, error) { +func (s *ReleaseServer) RollbackRelease(req *services.RollbackReleaseRequest) (*release.Release, error) { s.Log("preparing rollback of %s", req.Name) currentRelease, targetRelease, err := s.prepareRollback(req) if err != nil { @@ -111,18 +109,17 @@ func (s *ReleaseServer) prepareRollback(req *services.RollbackReleaseRequest) (* return currentRelease, targetRelease, nil } -func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.Release, req *services.RollbackReleaseRequest) (*services.RollbackReleaseResponse, error) { - res := &services.RollbackReleaseResponse{Release: targetRelease} +func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.Release, req *services.RollbackReleaseRequest) (*release.Release, error) { if req.DryRun { s.Log("dry run for %s", targetRelease.Name) - return res, nil + return targetRelease, nil } // pre-rollback hooks if !req.DisableHooks { if err := s.execHook(targetRelease.Hooks, targetRelease.Name, targetRelease.Namespace, hooks.PreRollback, req.Timeout); err != nil { - return res, err + return targetRelease, err } } else { s.Log("rollback hooks disabled for %s", req.Name) @@ -136,13 +133,13 @@ func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.R targetRelease.Info.Description = msg s.recordRelease(currentRelease, true) s.recordRelease(targetRelease, true) - return res, err + return targetRelease, err } // post-rollback hooks if !req.DisableHooks { if err := s.execHook(targetRelease.Hooks, targetRelease.Name, targetRelease.Namespace, hooks.PostRollback, req.Timeout); err != nil { - return res, err + return targetRelease, err } } @@ -159,5 +156,5 @@ func (s *ReleaseServer) performRollback(currentRelease, targetRelease *release.R targetRelease.Info.Status.Code = release.Status_DEPLOYED - return res, nil + return targetRelease, nil } diff --git a/pkg/tiller/release_rollback_test.go b/pkg/tiller/release_rollback_test.go index c3ed9faaf..f1f8eb5a8 100644 --- a/pkg/tiller/release_rollback_test.go +++ b/pkg/tiller/release_rollback_test.go @@ -20,14 +20,11 @@ import ( "strings" "testing" - "golang.org/x/net/context" - "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" ) func TestRollbackRelease(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -52,30 +49,30 @@ func TestRollbackRelease(t *testing.T) { req := &services.RollbackReleaseRequest{ Name: rel.Name, } - res, err := rs.RollbackRelease(c, req) + res, err := rs.RollbackRelease(req) if err != nil { t.Fatalf("Failed rollback: %s", err) } - if res.Release.Name == "" { + if res.Name == "" { t.Errorf("Expected release name.") } - if res.Release.Name != rel.Name { - t.Errorf("Updated release name does not match previous release name. Expected %s, got %s", rel.Name, res.Release.Name) + if res.Name != rel.Name { + t.Errorf("Updated release name does not match previous release name. Expected %s, got %s", rel.Name, res.Name) } - if res.Release.Namespace != rel.Namespace { - t.Errorf("Expected release namespace '%s', got '%s'.", rel.Namespace, res.Release.Namespace) + if res.Namespace != rel.Namespace { + t.Errorf("Expected release namespace '%s', got '%s'.", rel.Namespace, res.Namespace) } - if res.Release.Version != 3 { - t.Errorf("Expected release version to be %v, got %v", 3, res.Release.Version) + if res.Version != 3 { + t.Errorf("Expected release version to be %v, got %v", 3, res.Version) } - updated, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) + updated, err := rs.env.Releases.Get(res.Name, res.Version) if err != nil { - t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) + t.Errorf("Expected release for %s (%v).", res.Name, rs.env.Releases) } if len(updated.Hooks) != 2 { @@ -90,14 +87,14 @@ func TestRollbackRelease(t *testing.T) { rs.env.Releases.Update(upgradedRel) rs.env.Releases.Create(anotherUpgradedRelease) - res, err = rs.RollbackRelease(c, req) + res, err = rs.RollbackRelease(req) if err != nil { t.Fatalf("Failed rollback: %s", err) } - updated, err = rs.env.Releases.Get(res.Release.Name, res.Release.Version) + updated, err = rs.env.Releases.Get(res.Name, res.Version) if err != nil { - t.Errorf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) + t.Errorf("Expected release for %s (%v).", res.Name, rs.env.Releases) } if len(updated.Hooks) != 1 { @@ -108,8 +105,8 @@ func TestRollbackRelease(t *testing.T) { t.Errorf("Unexpected manifest: %v", updated.Hooks[0].Manifest) } - if res.Release.Version != 4 { - t.Errorf("Expected release version to be %v, got %v", 3, res.Release.Version) + if res.Version != 4 { + t.Errorf("Expected release version to be %v, got %v", 3, res.Version) } if updated.Hooks[0].Events[0] != release.Hook_PRE_ROLLBACK { @@ -120,8 +117,8 @@ func TestRollbackRelease(t *testing.T) { t.Errorf("Expected event 1 to be post rollback") } - if len(res.Release.Manifest) == 0 { - t.Errorf("No manifest returned: %v", res.Release) + if len(res.Manifest) == 0 { + t.Errorf("No manifest returned: %v", res) } if len(updated.Manifest) == 0 { @@ -132,13 +129,12 @@ func TestRollbackRelease(t *testing.T) { t.Errorf("unexpected output: %s", rel.Manifest) } - if res.Release.Info.Description != "Rollback to 2" { - t.Errorf("Expected rollback to 2, got %q", res.Release.Info.Description) + if res.Info.Description != "Rollback to 2" { + t.Errorf("Expected rollback to 2, got %q", res.Info.Description) } } func TestRollbackWithReleaseVersion(t *testing.T) { - c := context.TODO() rs := rsFixture() rs.Log = t.Logf rs.env.Releases.Log = t.Logf @@ -163,7 +159,7 @@ func TestRollbackWithReleaseVersion(t *testing.T) { Version: 1, } - _, err := rs.RollbackRelease(c, req) + _, err := rs.RollbackRelease(req) if err != nil { t.Fatalf("Failed rollback: %s", err) } @@ -186,7 +182,6 @@ func TestRollbackWithReleaseVersion(t *testing.T) { } func TestRollbackReleaseNoHooks(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rel.Hooks = []*release.Hook{ @@ -211,18 +206,17 @@ func TestRollbackReleaseNoHooks(t *testing.T) { DisableHooks: true, } - res, err := rs.RollbackRelease(c, req) + res, err := rs.RollbackRelease(req) if err != nil { t.Fatalf("Failed rollback: %s", err) } - if hl := res.Release.Hooks[0].LastRun; hl != nil { + if hl := res.Hooks[0].LastRun; hl != nil { t.Errorf("Expected that no hooks were run. Got %d", hl) } } func TestRollbackReleaseFailure(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -236,12 +230,12 @@ func TestRollbackReleaseFailure(t *testing.T) { } rs.env.KubeClient = newUpdateFailingKubeClient() - res, err := rs.RollbackRelease(c, req) + res, err := rs.RollbackRelease(req) if err == nil { t.Error("Expected failed rollback") } - if targetStatus := res.Release.Info.Status.Code; targetStatus != release.Status_FAILED { + if targetStatus := res.Info.Status.Code; targetStatus != release.Status_FAILED { t.Errorf("Expected FAILED release. Got %v", targetStatus) } diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index 5d768ef32..7b97b3d77 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -38,6 +38,7 @@ import ( "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" relutil "k8s.io/helm/pkg/releaseutil" + "k8s.io/helm/pkg/storage" "k8s.io/helm/pkg/tiller/environment" "k8s.io/helm/pkg/timeconv" "k8s.io/helm/pkg/version" @@ -97,6 +98,10 @@ func NewReleaseServer(env *environment.Environment, clientset internalclientset. } } +func (s *ReleaseServer) Storage() *storage.Storage { + return s.env.Releases +} + // reuseValues copies values from the current release to a new release if the // new release does not have any values. // diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index 8546e8db8..834729b22 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -428,15 +428,13 @@ func (h *hookFailingKubeClient) WatchUntilReady(ns string, r io.Reader, timeout type mockRunReleaseTestServer struct{} -func (rs mockRunReleaseTestServer) Send(m *services.TestReleaseResponse) error { - return nil -} -func (rs mockRunReleaseTestServer) SetHeader(m metadata.MD) error { return nil } -func (rs mockRunReleaseTestServer) SendHeader(m metadata.MD) error { return nil } -func (rs mockRunReleaseTestServer) SetTrailer(m metadata.MD) {} -func (rs mockRunReleaseTestServer) SendMsg(v interface{}) error { return nil } -func (rs mockRunReleaseTestServer) RecvMsg(v interface{}) error { return nil } -func (rs mockRunReleaseTestServer) Context() context.Context { return context.TODO() } +func (rs mockRunReleaseTestServer) Send(m *services.TestReleaseResponse) error { return nil } +func (rs mockRunReleaseTestServer) SetHeader(m metadata.MD) error { return nil } +func (rs mockRunReleaseTestServer) SendHeader(m metadata.MD) error { return nil } +func (rs mockRunReleaseTestServer) SetTrailer(m metadata.MD) {} +func (rs mockRunReleaseTestServer) SendMsg(v interface{}) error { return nil } +func (rs mockRunReleaseTestServer) RecvMsg(v interface{}) error { return nil } +func (rs mockRunReleaseTestServer) Context() context.Context { return context.TODO() } type mockHooksManifest struct { Metadata struct { diff --git a/pkg/tiller/release_status.go b/pkg/tiller/release_status.go index 8e7c96b4f..e863d8d3d 100644 --- a/pkg/tiller/release_status.go +++ b/pkg/tiller/release_status.go @@ -20,14 +20,12 @@ import ( "errors" "fmt" - ctx "golang.org/x/net/context" - "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" ) // GetReleaseStatus gets the status information for a named release. -func (s *ReleaseServer) GetReleaseStatus(c ctx.Context, req *services.GetReleaseStatusRequest) (*services.GetReleaseStatusResponse, error) { +func (s *ReleaseServer) GetReleaseStatus(req *services.GetReleaseStatusRequest) (*services.GetReleaseStatusResponse, error) { if err := validateReleaseName(req.Name); err != nil { s.Log("getStatus: Release name is invalid: %s", req.Name) return nil, err diff --git a/pkg/tiller/release_status_test.go b/pkg/tiller/release_status_test.go index e992da768..6fbc26bb1 100644 --- a/pkg/tiller/release_status_test.go +++ b/pkg/tiller/release_status_test.go @@ -19,21 +19,18 @@ package tiller import ( "testing" - "golang.org/x/net/context" - "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" ) func TestGetReleaseStatus(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() if err := rs.env.Releases.Create(rel); err != nil { t.Fatalf("Could not store mock release: %s", err) } - res, err := rs.GetReleaseStatus(c, &services.GetReleaseStatusRequest{Name: rel.Name, Version: 1}) + res, err := rs.GetReleaseStatus(&services.GetReleaseStatusRequest{Name: rel.Name, Version: 1}) if err != nil { t.Errorf("Error getting release content: %s", err) } @@ -47,7 +44,6 @@ func TestGetReleaseStatus(t *testing.T) { } func TestGetReleaseStatusDeleted(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rel.Info.Status.Code = release.Status_DELETED @@ -55,7 +51,7 @@ func TestGetReleaseStatusDeleted(t *testing.T) { t.Fatalf("Could not store mock release: %s", err) } - res, err := rs.GetReleaseStatus(c, &services.GetReleaseStatusRequest{Name: rel.Name, Version: 1}) + res, err := rs.GetReleaseStatus(&services.GetReleaseStatusRequest{Name: rel.Name, Version: 1}) if err != nil { t.Fatalf("Error getting release content: %s", err) } diff --git a/pkg/tiller/release_testing.go b/pkg/tiller/release_testing.go index a44b67e6f..5ed5da7bf 100644 --- a/pkg/tiller/release_testing.go +++ b/pkg/tiller/release_testing.go @@ -43,11 +43,7 @@ func (s *ReleaseServer) RunReleaseTest(req *services.TestReleaseRequest, stream Stream: stream, } s.Log("running tests for release %s", rel.Name) - tSuite, err := reltesting.NewTestSuite(rel) - if err != nil { - s.Log("error creating test suite for %s: %s", rel.Name, err) - return err - } + tSuite := reltesting.NewTestSuite(rel) if err := tSuite.Run(testEnv); err != nil { s.Log("error running test suite for %s: %s", rel.Name, err) diff --git a/pkg/tiller/release_uninstall.go b/pkg/tiller/release_uninstall.go index 0d575dc85..98ae0e806 100644 --- a/pkg/tiller/release_uninstall.go +++ b/pkg/tiller/release_uninstall.go @@ -20,8 +20,6 @@ import ( "fmt" "strings" - ctx "golang.org/x/net/context" - "k8s.io/helm/pkg/hooks" "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" @@ -30,7 +28,7 @@ import ( ) // UninstallRelease deletes all of the resources associated with this release, and marks the release DELETED. -func (s *ReleaseServer) UninstallRelease(c ctx.Context, req *services.UninstallReleaseRequest) (*services.UninstallReleaseResponse, error) { +func (s *ReleaseServer) UninstallRelease(req *services.UninstallReleaseRequest) (*services.UninstallReleaseResponse, error) { if err := validateReleaseName(req.Name); err != nil { s.Log("uninstallRelease: Release name is invalid: %s", req.Name) return nil, err diff --git a/pkg/tiller/release_uninstall_test.go b/pkg/tiller/release_uninstall_test.go index 5b05859e9..c3c953019 100644 --- a/pkg/tiller/release_uninstall_test.go +++ b/pkg/tiller/release_uninstall_test.go @@ -20,14 +20,11 @@ import ( "strings" "testing" - "golang.org/x/net/context" - "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/services" ) func TestUninstallRelease(t *testing.T) { - c := context.TODO() rs := rsFixture() rs.env.Releases.Create(releaseStub()) @@ -35,7 +32,7 @@ func TestUninstallRelease(t *testing.T) { Name: "angry-panda", } - res, err := rs.UninstallRelease(c, req) + res, err := rs.UninstallRelease(req) if err != nil { t.Fatalf("Failed uninstall: %s", err) } @@ -62,7 +59,6 @@ func TestUninstallRelease(t *testing.T) { } func TestUninstallPurgeRelease(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -75,7 +71,7 @@ func TestUninstallPurgeRelease(t *testing.T) { Purge: true, } - res, err := rs.UninstallRelease(c, req) + res, err := rs.UninstallRelease(req) if err != nil { t.Fatalf("Failed uninstall: %s", err) } @@ -91,17 +87,16 @@ func TestUninstallPurgeRelease(t *testing.T) { if res.Release.Info.Deleted.Seconds <= 0 { t.Errorf("Expected valid UNIX date, got %d", res.Release.Info.Deleted.Seconds) } - rels, err := rs.GetHistory(context.TODO(), &services.GetHistoryRequest{Name: "angry-panda"}) + rels, err := rs.GetHistory(&services.GetHistoryRequest{Name: "angry-panda"}) if err != nil { t.Fatal(err) } - if len(rels.Releases) != 0 { - t.Errorf("Expected no releases in storage, got %d", len(rels.Releases)) + if len(rels) != 0 { + t.Errorf("Expected no releases in storage, got %d", len(rels)) } } func TestUninstallPurgeDeleteRelease(t *testing.T) { - c := context.TODO() rs := rsFixture() rs.env.Releases.Create(releaseStub()) @@ -109,7 +104,7 @@ func TestUninstallPurgeDeleteRelease(t *testing.T) { Name: "angry-panda", } - _, err := rs.UninstallRelease(c, req) + _, err := rs.UninstallRelease(req) if err != nil { t.Fatalf("Failed uninstall: %s", err) } @@ -119,14 +114,13 @@ func TestUninstallPurgeDeleteRelease(t *testing.T) { Purge: true, } - _, err2 := rs.UninstallRelease(c, req2) + _, err2 := rs.UninstallRelease(req2) if err2 != nil && err2.Error() != "'angry-panda' has no deployed releases" { t.Errorf("Failed uninstall: %s", err2) } } func TestUninstallReleaseWithKeepPolicy(t *testing.T) { - c := context.TODO() rs := rsFixture() name := "angry-bunny" rs.env.Releases.Create(releaseWithKeepStub(name)) @@ -135,7 +129,7 @@ func TestUninstallReleaseWithKeepPolicy(t *testing.T) { Name: name, } - res, err := rs.UninstallRelease(c, req) + res, err := rs.UninstallRelease(req) if err != nil { t.Fatalf("Failed uninstall: %s", err) } @@ -158,7 +152,6 @@ func TestUninstallReleaseWithKeepPolicy(t *testing.T) { } func TestUninstallReleaseNoHooks(t *testing.T) { - c := context.TODO() rs := rsFixture() rs.env.Releases.Create(releaseStub()) @@ -167,7 +160,7 @@ func TestUninstallReleaseNoHooks(t *testing.T) { DisableHooks: true, } - res, err := rs.UninstallRelease(c, req) + res, err := rs.UninstallRelease(req) if err != nil { t.Errorf("Failed uninstall: %s", err) } diff --git a/pkg/tiller/release_update.go b/pkg/tiller/release_update.go index 4f59e9aaa..34c469345 100644 --- a/pkg/tiller/release_update.go +++ b/pkg/tiller/release_update.go @@ -20,8 +20,6 @@ import ( "fmt" "strings" - ctx "golang.org/x/net/context" - "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hooks" "k8s.io/helm/pkg/proto/hapi/release" @@ -30,7 +28,7 @@ import ( ) // UpdateRelease takes an existing release and new information, and upgrades the release. -func (s *ReleaseServer) UpdateRelease(c ctx.Context, req *services.UpdateReleaseRequest) (*services.UpdateReleaseResponse, error) { +func (s *ReleaseServer) UpdateRelease(req *services.UpdateReleaseRequest) (*release.Release, error) { if err := validateReleaseName(req.Name); err != nil { s.Log("updateRelease: Release name is invalid: %s", req.Name) return nil, err @@ -143,7 +141,7 @@ func (s *ReleaseServer) prepareUpdate(req *services.UpdateReleaseRequest) (*rele } // performUpdateForce performs the same action as a `helm delete && helm install --replace`. -func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) (*services.UpdateReleaseResponse, error) { +func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) (*release.Release, error) { // find the last release with the given name oldRelease, err := s.env.Releases.Last(req.Name) if err != nil { @@ -161,7 +159,6 @@ func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) ( Timeout: req.Timeout, Wait: req.Wait, }) - res := &services.UpdateReleaseResponse{Release: newRelease} if err != nil { s.Log("failed update prepare step: %s", err) // On dry run, append the manifest contents to a failed release. This is @@ -169,7 +166,7 @@ func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) ( if req.DryRun && strings.HasPrefix(err.Error(), "YAML parse error") { err = fmt.Errorf("%s\n%s", err, newRelease.Manifest) } - return res, err + return newRelease, err } // From here on out, the release is considered to be in Status_DELETING or Status_DELETED @@ -182,7 +179,7 @@ func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) ( // pre-delete hooks if !req.DisableHooks { if err := s.execHook(oldRelease.Hooks, oldRelease.Name, oldRelease.Namespace, hooks.PreDelete, req.Timeout); err != nil { - return res, err + return newRelease, err } } else { s.Log("hooks disabled for %s", req.Name) @@ -201,20 +198,20 @@ func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) ( s.Log("error: %v", e) es = append(es, e.Error()) } - return res, fmt.Errorf("Upgrade --force successfully deleted the previous release, but encountered %d error(s) and cannot continue: %s", len(es), strings.Join(es, "; ")) + return newRelease, fmt.Errorf("Upgrade --force successfully deleted the previous release, but encountered %d error(s) and cannot continue: %s", len(es), strings.Join(es, "; ")) } // post-delete hooks if !req.DisableHooks { if err := s.execHook(oldRelease.Hooks, oldRelease.Name, oldRelease.Namespace, hooks.PostDelete, req.Timeout); err != nil { - return res, err + return newRelease, err } } // pre-install hooks if !req.DisableHooks { if err := s.execHook(newRelease.Hooks, newRelease.Name, newRelease.Namespace, hooks.PreInstall, req.Timeout); err != nil { - return res, err + return newRelease, err } } @@ -227,7 +224,7 @@ func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) ( newRelease.Info.Status.Code = release.Status_FAILED newRelease.Info.Description = msg s.recordRelease(newRelease, true) - return res, err + return newRelease, err } // post-install hooks @@ -238,7 +235,7 @@ func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) ( newRelease.Info.Status.Code = release.Status_FAILED newRelease.Info.Description = msg s.recordRelease(newRelease, true) - return res, err + return newRelease, err } } @@ -246,22 +243,21 @@ func (s *ReleaseServer) performUpdateForce(req *services.UpdateReleaseRequest) ( newRelease.Info.Description = "Upgrade complete" s.recordRelease(newRelease, true) - return res, nil + return newRelease, nil } -func (s *ReleaseServer) performUpdate(originalRelease, updatedRelease *release.Release, req *services.UpdateReleaseRequest) (*services.UpdateReleaseResponse, error) { - res := &services.UpdateReleaseResponse{Release: updatedRelease} +func (s *ReleaseServer) performUpdate(originalRelease, updatedRelease *release.Release, req *services.UpdateReleaseRequest) (*release.Release, error) { if req.DryRun { s.Log("dry run for %s", updatedRelease.Name) - res.Release.Info.Description = "Dry run complete" - return res, nil + updatedRelease.Info.Description = "Dry run complete" + return updatedRelease, nil } // pre-upgrade hooks if !req.DisableHooks { if err := s.execHook(updatedRelease.Hooks, updatedRelease.Name, updatedRelease.Namespace, hooks.PreUpgrade, req.Timeout); err != nil { - return res, err + return updatedRelease, err } } else { s.Log("update hooks disabled for %s", req.Name) @@ -273,13 +269,13 @@ func (s *ReleaseServer) performUpdate(originalRelease, updatedRelease *release.R updatedRelease.Info.Description = msg s.recordRelease(originalRelease, true) s.recordRelease(updatedRelease, true) - return res, err + return updatedRelease, err } // post-upgrade hooks if !req.DisableHooks { if err := s.execHook(updatedRelease.Hooks, updatedRelease.Name, updatedRelease.Namespace, hooks.PostUpgrade, req.Timeout); err != nil { - return res, err + return updatedRelease, err } } @@ -289,5 +285,5 @@ func (s *ReleaseServer) performUpdate(originalRelease, updatedRelease *release.R updatedRelease.Info.Status.Code = release.Status_DEPLOYED updatedRelease.Info.Description = "Upgrade complete" - return res, nil + return updatedRelease, nil } diff --git a/pkg/tiller/release_update_test.go b/pkg/tiller/release_update_test.go index 84315942c..6d6cb6ef0 100644 --- a/pkg/tiller/release_update_test.go +++ b/pkg/tiller/release_update_test.go @@ -22,7 +22,6 @@ import ( "testing" "github.com/golang/protobuf/proto" - "golang.org/x/net/context" "k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/release" @@ -30,7 +29,6 @@ import ( ) func TestUpdateRelease(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -45,24 +43,24 @@ func TestUpdateRelease(t *testing.T) { }, }, } - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } - if res.Release.Name == "" { + if res.Name == "" { t.Errorf("Expected release name.") } - if res.Release.Name != rel.Name { - t.Errorf("Updated release name does not match previous release name. Expected %s, got %s", rel.Name, res.Release.Name) + if res.Name != rel.Name { + t.Errorf("Updated release name does not match previous release name. Expected %s, got %s", rel.Name, res.Name) } - if res.Release.Namespace != rel.Namespace { - t.Errorf("Expected release namespace '%s', got '%s'.", rel.Namespace, res.Release.Namespace) + if res.Namespace != rel.Namespace { + t.Errorf("Expected release namespace '%s', got '%s'.", rel.Namespace, res.Namespace) } - updated := compareStoredAndReturnedRelease(t, *rs, *res) + updated := compareStoredAndReturnedRelease(t, *rs, res) if len(updated.Hooks) != 1 { t.Fatalf("Expected 1 hook, got %d", len(updated.Hooks)) @@ -83,27 +81,26 @@ func TestUpdateRelease(t *testing.T) { t.Errorf("Expected manifest in %v", res) } - if res.Release.Config == nil { - t.Errorf("Got release without config: %#v", res.Release) - } else if res.Release.Config.Raw != rel.Config.Raw { - t.Errorf("Expected release values %q, got %q", rel.Config.Raw, res.Release.Config.Raw) + if res.Config == nil { + t.Errorf("Got release without config: %#v", res) + } else if res.Config.Raw != rel.Config.Raw { + t.Errorf("Expected release values %q, got %q", rel.Config.Raw, res.Config.Raw) } if !strings.Contains(updated.Manifest, "---\n# Source: hello/templates/hello\nhello: world") { t.Errorf("unexpected output: %s", updated.Manifest) } - if res.Release.Version != 2 { - t.Errorf("Expected release version to be %v, got %v", 2, res.Release.Version) + if res.Version != 2 { + t.Errorf("Expected release version to be %v, got %v", 2, res.Version) } edesc := "Upgrade complete" - if got := res.Release.Info.Description; got != edesc { + if got := res.Info.Description; got != edesc { t.Errorf("Expected description %q, got %q", edesc, got) } } func TestUpdateRelease_ResetValues(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -119,19 +116,18 @@ func TestUpdateRelease_ResetValues(t *testing.T) { }, ResetValues: true, } - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } // This should have been unset. Config: &chart.Config{Raw: `name: value`}, - if res.Release.Config != nil && res.Release.Config.Raw != "" { - t.Errorf("Expected chart config to be empty, got %q", res.Release.Config.Raw) + if res.Config != nil && res.Config.Raw != "" { + t.Errorf("Expected chart config to be empty, got %q", res.Config.Raw) } } // This is a regression test for bug found in issue #3655 func TestUpdateRelease_ComplexReuseValues(t *testing.T) { - c := context.TODO() rs := rsFixture() installReq := &services.InstallReleaseRequest{ @@ -148,12 +144,12 @@ func TestUpdateRelease_ComplexReuseValues(t *testing.T) { } fmt.Println("Running Install release with foo: bar override") - installResp, err := rs.InstallRelease(c, installReq) + installResp, err := rs.InstallRelease(installReq) if err != nil { t.Fatal(err) } - rel := installResp.Release + rel := installResp req := &services.UpdateReleaseRequest{ Name: rel.Name, Chart: &chart.Chart{ @@ -167,17 +163,17 @@ func TestUpdateRelease_ComplexReuseValues(t *testing.T) { } fmt.Println("Running Update release with no overrides and no reuse-values flag") - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } expect := "foo: bar" - if res.Release.Config != nil && res.Release.Config.Raw != expect { - t.Errorf("Expected chart values to be %q, got %q", expect, res.Release.Config.Raw) + if res.Config != nil && res.Config.Raw != expect { + t.Errorf("Expected chart values to be %q, got %q", expect, res.Config.Raw) } - rel = res.Release + rel = res req = &services.UpdateReleaseRequest{ Name: rel.Name, Chart: &chart.Chart{ @@ -193,18 +189,17 @@ func TestUpdateRelease_ComplexReuseValues(t *testing.T) { } fmt.Println("Running Update release with foo2: bar2 override and reuse-values") - res, err = rs.UpdateRelease(c, req) + rel, err = rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } // This should have the newly-passed overrides. expect = "foo: bar\nfoo2: bar2\n" - if res.Release.Config != nil && res.Release.Config.Raw != expect { - t.Errorf("Expected request config to be %q, got %q", expect, res.Release.Config.Raw) + if rel.Config != nil && rel.Config.Raw != expect { + t.Errorf("Expected request config to be %q, got %q", expect, rel.Config.Raw) } - rel = res.Release req = &services.UpdateReleaseRequest{ Name: rel.Name, Chart: &chart.Chart{ @@ -220,18 +215,17 @@ func TestUpdateRelease_ComplexReuseValues(t *testing.T) { } fmt.Println("Running Update release with foo=baz override with reuse-values flag") - res, err = rs.UpdateRelease(c, req) + res, err = rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } expect = "foo: baz\nfoo2: bar2\n" - if res.Release.Config != nil && res.Release.Config.Raw != expect { - t.Errorf("Expected chart values to be %q, got %q", expect, res.Release.Config.Raw) + if res.Config != nil && res.Config.Raw != expect { + t.Errorf("Expected chart values to be %q, got %q", expect, res.Config.Raw) } } func TestUpdateRelease_ReuseValues(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -250,26 +244,25 @@ func TestUpdateRelease_ReuseValues(t *testing.T) { Values: &chart.Config{Raw: "name2: val2"}, ReuseValues: true, } - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } // This should have been overwritten with the old value. expect := "name: value\n" - if res.Release.Chart.Values != nil && res.Release.Chart.Values.Raw != expect { - t.Errorf("Expected chart values to be %q, got %q", expect, res.Release.Chart.Values.Raw) + if res.Chart.Values != nil && res.Chart.Values.Raw != expect { + t.Errorf("Expected chart values to be %q, got %q", expect, res.Chart.Values.Raw) } // This should have the newly-passed overrides and any other computed values. `name: value` comes from release Config via releaseStub() expect = "name: value\nname2: val2\n" - if res.Release.Config != nil && res.Release.Config.Raw != expect { - t.Errorf("Expected request config to be %q, got %q", expect, res.Release.Config.Raw) + if res.Config != nil && res.Config.Raw != expect { + t.Errorf("Expected request config to be %q, got %q", expect, res.Config.Raw) } - compareStoredAndReturnedRelease(t, *rs, *res) + compareStoredAndReturnedRelease(t, *rs, res) } func TestUpdateRelease_ResetReuseValues(t *testing.T) { // This verifies that when both reset and reuse are set, reset wins. - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -286,19 +279,18 @@ func TestUpdateRelease_ResetReuseValues(t *testing.T) { ResetValues: true, ReuseValues: true, } - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } // This should have been unset. Config: &chart.Config{Raw: `name: value`}, - if res.Release.Config != nil && res.Release.Config.Raw != "" { - t.Errorf("Expected chart config to be empty, got %q", res.Release.Config.Raw) + if res.Config != nil && res.Config.Raw != "" { + t.Errorf("Expected chart config to be empty, got %q", res.Config.Raw) } - compareStoredAndReturnedRelease(t, *rs, *res) + compareStoredAndReturnedRelease(t, *rs, res) } func TestUpdateReleaseFailure(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -316,19 +308,19 @@ func TestUpdateReleaseFailure(t *testing.T) { }, } - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err == nil { t.Error("Expected failed update") } - if updatedStatus := res.Release.Info.Status.Code; updatedStatus != release.Status_FAILED { + if updatedStatus := res.Info.Status.Code; updatedStatus != release.Status_FAILED { t.Errorf("Expected FAILED release. Got %d", updatedStatus) } - compareStoredAndReturnedRelease(t, *rs, *res) + compareStoredAndReturnedRelease(t, *rs, res) expectedDescription := "Upgrade \"angry-panda\" failed: Failed update in kube client" - if got := res.Release.Info.Description; got != expectedDescription { + if got := res.Info.Description; got != expectedDescription { t.Errorf("Expected description %q, got %q", expectedDescription, got) } @@ -342,7 +334,6 @@ func TestUpdateReleaseFailure(t *testing.T) { } func TestUpdateReleaseFailure_Force(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := namedReleaseStub("forceful-luke", release.Status_FAILED) rs.env.Releases.Create(rel) @@ -360,19 +351,19 @@ func TestUpdateReleaseFailure_Force(t *testing.T) { Force: true, } - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err != nil { t.Errorf("Expected successful update, got %v", err) } - if updatedStatus := res.Release.Info.Status.Code; updatedStatus != release.Status_DEPLOYED { + if updatedStatus := res.Info.Status.Code; updatedStatus != release.Status_DEPLOYED { t.Errorf("Expected DEPLOYED release. Got %d", updatedStatus) } - compareStoredAndReturnedRelease(t, *rs, *res) + compareStoredAndReturnedRelease(t, *rs, res) expectedDescription := "Upgrade complete" - if got := res.Release.Info.Description; got != expectedDescription { + if got := res.Info.Description; got != expectedDescription { t.Errorf("Expected description %q, got %q", expectedDescription, got) } @@ -386,7 +377,6 @@ func TestUpdateReleaseFailure_Force(t *testing.T) { } func TestUpdateReleaseNoHooks(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -403,19 +393,18 @@ func TestUpdateReleaseNoHooks(t *testing.T) { }, } - res, err := rs.UpdateRelease(c, req) + res, err := rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } - if hl := res.Release.Hooks[0].LastRun; hl != nil { + if hl := res.Hooks[0].LastRun; hl != nil { t.Errorf("Expected that no hooks were run. Got %d", hl) } } func TestUpdateReleaseNoChanges(t *testing.T) { - c := context.TODO() rs := rsFixture() rel := releaseStub() rs.env.Releases.Create(rel) @@ -426,19 +415,19 @@ func TestUpdateReleaseNoChanges(t *testing.T) { Chart: rel.GetChart(), } - _, err := rs.UpdateRelease(c, req) + _, err := rs.UpdateRelease(req) if err != nil { t.Fatalf("Failed updated: %s", err) } } -func compareStoredAndReturnedRelease(t *testing.T, rs ReleaseServer, res services.UpdateReleaseResponse) *release.Release { - storedRelease, err := rs.env.Releases.Get(res.Release.Name, res.Release.Version) +func compareStoredAndReturnedRelease(t *testing.T, rs ReleaseServer, res *release.Release) *release.Release { + storedRelease, err := rs.env.Releases.Get(res.Name, res.Version) if err != nil { - t.Fatalf("Expected release for %s (%v).", res.Release.Name, rs.env.Releases) + t.Fatalf("Expected release for %s (%v).", res.Name, rs.env.Releases) } - if !proto.Equal(storedRelease, res.Release) { + if !proto.Equal(storedRelease, res) { t.Errorf("Stored release doesn't match returned Release") } diff --git a/pkg/tiller/release_version.go b/pkg/tiller/release_version.go deleted file mode 100644 index 66b7137bb..000000000 --- a/pkg/tiller/release_version.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -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 tiller - -import ( - ctx "golang.org/x/net/context" - - "k8s.io/helm/pkg/proto/hapi/services" - "k8s.io/helm/pkg/version" -) - -// GetVersion sends the server version. -func (s *ReleaseServer) GetVersion(c ctx.Context, req *services.GetVersionRequest) (*services.GetVersionResponse, error) { - v := version.GetVersionProto() - return &services.GetVersionResponse{Version: v}, nil -} diff --git a/pkg/tiller/server.go b/pkg/tiller/server.go deleted file mode 100644 index 818cfd47a..000000000 --- a/pkg/tiller/server.go +++ /dev/null @@ -1,96 +0,0 @@ -/* -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 tiller - -import ( - "fmt" - "log" - "strings" - - goprom "github.com/grpc-ecosystem/go-grpc-prometheus" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" - - "k8s.io/helm/pkg/version" -) - -// maxMsgSize use 20MB as the default message size limit. -// grpc library default is 4MB -const maxMsgSize = 1024 * 1024 * 20 - -// DefaultServerOpts returns the set of default grpc ServerOption's that Tiller requires. -func DefaultServerOpts() []grpc.ServerOption { - return []grpc.ServerOption{ - grpc.MaxRecvMsgSize(maxMsgSize), - grpc.MaxSendMsgSize(maxMsgSize), - grpc.UnaryInterceptor(newUnaryInterceptor()), - grpc.StreamInterceptor(newStreamInterceptor()), - } -} - -// NewServer creates a new grpc server. -func NewServer(opts ...grpc.ServerOption) *grpc.Server { - return grpc.NewServer(append(DefaultServerOpts(), opts...)...) -} - -func newUnaryInterceptor() grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { - if err := checkClientVersion(ctx); err != nil { - // whitelist GetVersion() from the version check - if _, m := splitMethod(info.FullMethod); m != "GetVersion" { - log.Println(err) - return nil, err - } - } - return goprom.UnaryServerInterceptor(ctx, req, info, handler) - } -} - -func newStreamInterceptor() grpc.StreamServerInterceptor { - return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - if err := checkClientVersion(ss.Context()); err != nil { - log.Println(err) - return err - } - return goprom.StreamServerInterceptor(srv, ss, info, handler) - } -} - -func splitMethod(fullMethod string) (string, string) { - if frags := strings.Split(fullMethod, "/"); len(frags) == 3 { - return frags[1], frags[2] - } - return "unknown", "unknown" -} - -func versionFromContext(ctx context.Context) string { - if md, ok := metadata.FromIncomingContext(ctx); ok { - if v, ok := md["x-helm-api-client"]; ok && len(v) > 0 { - return v[0] - } - } - return "" -} - -func checkClientVersion(ctx context.Context) error { - clientVersion := versionFromContext(ctx) - if !version.IsCompatible(clientVersion, version.GetVersion()) { - return fmt.Errorf("incompatible versions client[%s] server[%s]", clientVersion, version.GetVersion()) - } - return nil -}