Skip to content

Commit

Permalink
Make kubectl commands return errors and centralize exit handling
Browse files Browse the repository at this point in the history
  • Loading branch information
j3ffml committed Mar 10, 2015
1 parent 7b72d95 commit cd7d78b
Show file tree
Hide file tree
Showing 20 changed files with 856 additions and 625 deletions.
14 changes: 10 additions & 4 deletions pkg/kubectl/cmd/clusterinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand All @@ -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
}
11 changes: 3 additions & 8 deletions pkg/kubectl/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
}
Expand Down
91 changes: 52 additions & 39 deletions pkg/kubectl/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
},
}
cmd.Flags().VarP(&filenames, "filename", "f", "Filename, directory, or URL to file to use to create the resource")
return cmd
}

cmdNamespace, err := f.DefaultNamespace(cmd)
cmdutil.CheckErr(err)
func RunCreate(f *Factory, out io.Writer, cmd *cobra.Command, filenames util.StringList) error {
schema, err := f.Validator(cmd)
if err != nil {
return 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())
cmdNamespace, err := f.DefaultNamespace(cmd)
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
})
cmdutil.CheckErr(err)
if count == 0 {
cmdutil.CheckErr(fmt.Errorf("no objects passed to create"))
}
},
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
}
cmd.Flags().VarP(&flags.Filenames, "filename", "f", "Filename, directory, or URL to file to use to create the resource")
return cmd

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
}
71 changes: 41 additions & 30 deletions pkg/kubectl/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -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] | (<resource> [(<id> | -l <label> | --all)]",
Short: "Delete a resource by filename, stdin, or resource and ID.",
Long: delete_long,
Example: delete_example,
Run: func(cmd *cobra.Command, args []string) {
cmdNamespace, err := f.DefaultNamespace(cmd)
err := RunDelete(f, out, cmd, args, filenames)
cmdutil.CheckErr(err)
mapper, typer := f.Object(cmd)
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(flags.Filenames...).
SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
SelectAllParam(cmdutil.GetFlagBool(cmd, "all")).
ResourceTypeOrNameArgs(false, args...).
Flatten().
Do()
cmdutil.CheckErr(r.Err())

found := 0
err = r.IgnoreErrors(errors.IsNotFound).Visit(func(r *resource.Info) error {
found++
if err := resource.NewHelper(r.Client, r.Mapping).Delete(r.Namespace, r.Name); err != nil {
return err
}
fmt.Fprintf(out, "%s\n", r.Name)
return nil
})
cmdutil.CheckErr(err)
if found == 0 {
fmt.Fprintf(cmd.Out(), "No resources found\n")
}
},
}
cmd.Flags().VarP(&flags.Filenames, "filename", "f", "Filename, directory, or URL to a file containing the resource to delete")
cmd.Flags().VarP(&filenames, "filename", "f", "Filename, directory, or URL to a file containing the resource to delete")
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources")
return cmd
}

func RunDelete(f *Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error {
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).DefaultNamespace().
FilenameParam(filenames...).
SelectorParam(cmdutil.GetFlagString(cmd, "selector")).
SelectAllParam(cmdutil.GetFlagBool(cmd, "all")).
ResourceTypeOrNameArgs(false, args...).
Flatten().
Do()
err = r.Err()
if err != nil {
return err
}

found := 0
err = r.IgnoreErrors(errors.IsNotFound).Visit(func(r *resource.Info) error {
found++
if err := resource.NewHelper(r.Client, r.Mapping).Delete(r.Namespace, r.Name); err != nil {
return err
}
fmt.Fprintf(out, "%s\n", r.Name)
return nil
})
if err != nil {
return err
}
if found == 0 {
fmt.Fprintf(cmd.Out(), "No resources found\n")
}
return nil
}
37 changes: 26 additions & 11 deletions pkg/kubectl/cmd/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,35 @@ func (f *Factory) NewCmdDescribe(out io.Writer) *cobra.Command {
This command joins many API calls together to form a detailed description of a
given resource.`,
Run: func(cmd *cobra.Command, args []string) {
cmdNamespace, err := f.DefaultNamespace(cmd)
err := RunDescribe(f, out, cmd, args)
util.CheckErr(err)
},
}
return cmd
}

mapper, _ := f.Object(cmd)
// TODO: use resource.Builder instead
mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
func RunDescribe(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
cmdNamespace, err := f.DefaultNamespace(cmd)
if err != nil {
return err
}

describer, err := f.Describer(cmd, mapping)
util.CheckErr(err)
mapper, _ := f.Object(cmd)
// TODO: use resource.Builder instead
mapping, namespace, name, err := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
if err != nil {
return err
}

s, err := describer.Describe(namespace, name)
util.CheckErr(err)
fmt.Fprintf(out, "%s\n", s)
},
describer, err := f.Describer(cmd, mapping)
if err != nil {
return err
}
return cmd

s, err := describer.Describe(namespace, name)
if err != nil {
return err
}
fmt.Fprintf(out, "%s\n", s)
return nil
}
Loading

0 comments on commit cd7d78b

Please sign in to comment.