From cd7d78b6969a9ccd9fc370e5c8d79b7ae9114095 Mon Sep 17 00:00:00 2001 From: Jeff Lowdermilk Date: Mon, 9 Mar 2015 15:08:16 -0700 Subject: [PATCH] Make kubectl commands return errors and centralize exit handling --- pkg/kubectl/cmd/clusterinfo.go | 14 ++- pkg/kubectl/cmd/cmd.go | 11 +- pkg/kubectl/cmd/create.go | 93 ++++++++++------- pkg/kubectl/cmd/delete.go | 71 +++++++------ pkg/kubectl/cmd/describe.go | 39 ++++--- pkg/kubectl/cmd/exec.go | 172 ++++++++++++++++--------------- pkg/kubectl/cmd/expose.go | 124 ++++++++++++---------- pkg/kubectl/cmd/get.go | 57 ++++++---- pkg/kubectl/cmd/label.go | 90 ++++++++++------ pkg/kubectl/cmd/log.go | 104 ++++++++++--------- pkg/kubectl/cmd/namespace.go | 7 +- pkg/kubectl/cmd/portforward.go | 110 +++++++++++--------- pkg/kubectl/cmd/proxy.go | 47 +++++---- pkg/kubectl/cmd/resize.go | 65 +++++++----- pkg/kubectl/cmd/rollingupdate.go | 157 ++++++++++++++++------------ pkg/kubectl/cmd/run.go | 92 ++++++++++------- pkg/kubectl/cmd/update.go | 144 +++++++++++++++----------- pkg/kubectl/cmd/util/helpers.go | 46 ++++----- pkg/kubectl/cmd/util/resource.go | 52 ++++++---- pkg/kubectl/cmd/version.go | 24 +++-- 20 files changed, 875 insertions(+), 644 deletions(-) diff --git a/pkg/kubectl/cmd/clusterinfo.go b/pkg/kubectl/cmd/clusterinfo.go index 62b6692147d..5e02e289df2 100644 --- a/pkg/kubectl/cmd/clusterinfo.go +++ b/pkg/kubectl/cmd/clusterinfo.go @@ -34,20 +34,25 @@ func (f *Factory) NewCmdClusterInfo(out io.Writer) *cobra.Command { Short: "Display cluster info", Long: "Display addresses of the master and services with label kubernetes.io/cluster-service=true", Run: func(cmd *cobra.Command, args []string) { - RunClusterInfo(f, out, cmd) + err := RunClusterInfo(f, out, cmd) + util.CheckErr(err) }, } return cmd } -func RunClusterInfo(factory *Factory, out io.Writer, cmd *cobra.Command) { +func RunClusterInfo(factory *Factory, out io.Writer, cmd *cobra.Command) error { client, err := factory.ClientConfig(cmd) - util.CheckErr(err) + if err != nil { + return err + } fmt.Fprintf(out, "Kubernetes master is running at %v\n", client.Host) mapper, typer := factory.Object(cmd) cmdNamespace, err := factory.DefaultNamespace(cmd) - util.CheckErr(err) + if err != nil { + return err + } // TODO: use generalized labels once they are implemented (#341) b := resource.NewBuilder(mapper, typer, factory.ClientMapperForCommand(cmd)). @@ -68,6 +73,7 @@ func RunClusterInfo(factory *Factory, out io.Writer, cmd *cobra.Command) { } return nil }) + return nil // TODO: consider printing more information about cluster } diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index fca23010ffb..9da593ec759 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -34,7 +34,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" - "github.com/golang/glog" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -253,7 +252,9 @@ func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMappin } if ok { clientConfig, err := f.ClientConfig(cmd) - cmdutil.CheckErr(err) + if err != nil { + return nil, err + } defaultVersion := clientConfig.Version version := cmdutil.OutputVersion(cmd, defaultVersion) @@ -329,12 +330,6 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig { return clientConfig } -func usageError(cmd *cobra.Command, format string, args ...interface{}) { - glog.Errorf(format, args...) - glog.Errorf("See '%s -h' for help.", cmd.CommandPath()) - os.Exit(1) -} - func runHelp(cmd *cobra.Command, args []string) { cmd.Help() } diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index e3d90967919..c006d067780 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -39,54 +39,67 @@ $ cat pod.json | kubectl create -f -` ) func (f *Factory) NewCmdCreate(out io.Writer) *cobra.Command { - flags := &struct { - Filenames util.StringList - }{} + var filenames util.StringList cmd := &cobra.Command{ Use: "create -f filename", Short: "Create a resource by filename or stdin", Long: create_long, Example: create_example, Run: func(cmd *cobra.Command, args []string) { - schema, err := f.Validator(cmd) + err := RunCreate(f, out, cmd, filenames) cmdutil.CheckErr(err) - - cmdNamespace, err := f.DefaultNamespace(cmd) - cmdutil.CheckErr(err) - - mapper, typer := f.Object(cmd) - r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). - ContinueOnError(). - NamespaceParam(cmdNamespace).RequireNamespace(). - FilenameParam(flags.Filenames...). - Flatten(). - Do() - cmdutil.CheckErr(r.Err()) - - count := 0 - err = r.Visit(func(info *resource.Info) error { - data, err := info.Mapping.Codec.Encode(info.Object) - if err != nil { - return err - } - if err := schema.ValidateBytes(data); err != nil { - return err - } - obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, data) - if err != nil { - return err - } - count++ - info.Refresh(obj, true) - fmt.Fprintf(out, "%s\n", info.Name) - return nil - }) - cmdutil.CheckErr(err) - if count == 0 { - cmdutil.CheckErr(fmt.Errorf("no objects passed to create")) - } }, } - cmd.Flags().VarP(&flags.Filenames, "filename", "f", "Filename, directory, or URL to file to use to create the resource") + cmd.Flags().VarP(&filenames, "filename", "f", "Filename, directory, or URL to file to use to create the resource") return cmd } + +func RunCreate(f *Factory, out io.Writer, cmd *cobra.Command, filenames util.StringList) error { + schema, err := f.Validator(cmd) + if err != nil { + return err + } + + cmdNamespace, err := f.DefaultNamespace(cmd) + if err != nil { + return err + } + + mapper, typer := f.Object(cmd) + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). + ContinueOnError(). + NamespaceParam(cmdNamespace).RequireNamespace(). + FilenameParam(filenames...). + Flatten(). + Do() + err = r.Err() + if err != nil { + return err + } + + count := 0 + err = r.Visit(func(info *resource.Info) error { + data, err := info.Mapping.Codec.Encode(info.Object) + if err != nil { + return err + } + if err := schema.ValidateBytes(data); err != nil { + return err + } + obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, data) + if err != nil { + return err + } + count++ + info.Refresh(obj, true) + fmt.Fprintf(out, "%s\n", info.Name) + return nil + }) + if err != nil { + return err + } + if count == 0 { + return fmt.Errorf("no objects passed to create") + } + return nil +} diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 1ed5331db09..dcc9307a5b1 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -56,46 +56,57 @@ $ kubectl delete pods --all` ) func (f *Factory) NewCmdDelete(out io.Writer) *cobra.Command { - flags := &struct { - Filenames util.StringList - }{} + var filenames util.StringList cmd := &cobra.Command{ Use: "delete ([-f filename] | ( [( | -l