mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Make kubectl commands return errors and centralize exit handling
This commit is contained in:
		@@ -34,20 +34,25 @@ func (f *Factory) NewCmdClusterInfo(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Short: "Display cluster info",
 | 
							Short: "Display cluster info",
 | 
				
			||||||
		Long:  "Display addresses of the master and services with label kubernetes.io/cluster-service=true",
 | 
							Long:  "Display addresses of the master and services with label kubernetes.io/cluster-service=true",
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			RunClusterInfo(f, out, cmd)
 | 
								err := RunClusterInfo(f, out, cmd)
 | 
				
			||||||
 | 
								util.CheckErr(err)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cmd
 | 
						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)
 | 
						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)
 | 
						fmt.Fprintf(out, "Kubernetes master is running at %v\n", client.Host)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mapper, typer := factory.Object(cmd)
 | 
						mapper, typer := factory.Object(cmd)
 | 
				
			||||||
	cmdNamespace, err := factory.DefaultNamespace(cmd)
 | 
						cmdNamespace, err := factory.DefaultNamespace(cmd)
 | 
				
			||||||
	util.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: use generalized labels once they are implemented (#341)
 | 
						// TODO: use generalized labels once they are implemented (#341)
 | 
				
			||||||
	b := resource.NewBuilder(mapper, typer, factory.ClientMapperForCommand(cmd)).
 | 
						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
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: consider printing more information about cluster
 | 
						// TODO: consider printing more information about cluster
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,6 @@ import (
 | 
				
			|||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/golang/glog"
 | 
					 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
	"github.com/spf13/pflag"
 | 
						"github.com/spf13/pflag"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -253,7 +252,9 @@ func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMappin
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if ok {
 | 
						if ok {
 | 
				
			||||||
		clientConfig, err := f.ClientConfig(cmd)
 | 
							clientConfig, err := f.ClientConfig(cmd)
 | 
				
			||||||
		cmdutil.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		defaultVersion := clientConfig.Version
 | 
							defaultVersion := clientConfig.Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		version := cmdutil.OutputVersion(cmd, defaultVersion)
 | 
							version := cmdutil.OutputVersion(cmd, defaultVersion)
 | 
				
			||||||
@@ -329,12 +330,6 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
 | 
				
			|||||||
	return 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) {
 | 
					func runHelp(cmd *cobra.Command, args []string) {
 | 
				
			||||||
	cmd.Help()
 | 
						cmd.Help()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,54 +39,67 @@ $ cat pod.json | kubectl create -f -`
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *Factory) NewCmdCreate(out io.Writer) *cobra.Command {
 | 
					func (f *Factory) NewCmdCreate(out io.Writer) *cobra.Command {
 | 
				
			||||||
	flags := &struct {
 | 
						var filenames util.StringList
 | 
				
			||||||
		Filenames util.StringList
 | 
					 | 
				
			||||||
	}{}
 | 
					 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "create -f filename",
 | 
							Use:     "create -f filename",
 | 
				
			||||||
		Short:   "Create a resource by filename or stdin",
 | 
							Short:   "Create a resource by filename or stdin",
 | 
				
			||||||
		Long:    create_long,
 | 
							Long:    create_long,
 | 
				
			||||||
		Example: create_example,
 | 
							Example: create_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			schema, err := f.Validator(cmd)
 | 
								err := RunCreate(f, out, cmd, filenames)
 | 
				
			||||||
			cmdutil.CheckErr(err)
 | 
								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
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,46 +56,57 @@ $ kubectl delete pods --all`
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *Factory) NewCmdDelete(out io.Writer) *cobra.Command {
 | 
					func (f *Factory) NewCmdDelete(out io.Writer) *cobra.Command {
 | 
				
			||||||
	flags := &struct {
 | 
						var filenames util.StringList
 | 
				
			||||||
		Filenames util.StringList
 | 
					 | 
				
			||||||
	}{}
 | 
					 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "delete ([-f filename] | (<resource> [(<id> | -l <label> | --all)]",
 | 
							Use:     "delete ([-f filename] | (<resource> [(<id> | -l <label> | --all)]",
 | 
				
			||||||
		Short:   "Delete a resource by filename, stdin, or resource and ID.",
 | 
							Short:   "Delete a resource by filename, stdin, or resource and ID.",
 | 
				
			||||||
		Long:    delete_long,
 | 
							Long:    delete_long,
 | 
				
			||||||
		Example: delete_example,
 | 
							Example: delete_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
								err := RunDelete(f, out, cmd, args, filenames)
 | 
				
			||||||
			cmdutil.CheckErr(err)
 | 
								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().StringP("selector", "l", "", "Selector (label query) to filter on")
 | 
				
			||||||
	cmd.Flags().Bool("all", false, "[-all] to select all the specified resources")
 | 
						cmd.Flags().Bool("all", false, "[-all] to select all the specified resources")
 | 
				
			||||||
	return cmd
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					This command joins many API calls together to form a detailed description of a
 | 
				
			||||||
given resource.`,
 | 
					given resource.`,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
								err := RunDescribe(f, out, cmd, args)
 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			mapper, _ := f.Object(cmd)
 | 
					 | 
				
			||||||
			// TODO: use resource.Builder instead
 | 
					 | 
				
			||||||
			mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			describer, err := f.Describer(cmd, mapping)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			s, err := describer.Describe(namespace, name)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			fmt.Fprintf(out, "%s\n", s)
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunDescribe(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						describer, err := f.Describer(cmd, mapping)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s, err := describer.Describe(namespace, name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Fprintf(out, "%s\n", s)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,97 +39,105 @@ $ kubectl exec -p 123456-7890 -c ruby-container -i -t -- bash -il`
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *Factory) NewCmdExec(cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
 | 
					func (f *Factory) NewCmdExec(cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
 | 
				
			||||||
	flags := &struct {
 | 
					 | 
				
			||||||
		pod       string
 | 
					 | 
				
			||||||
		container string
 | 
					 | 
				
			||||||
		stdin     bool
 | 
					 | 
				
			||||||
		tty       bool
 | 
					 | 
				
			||||||
	}{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "exec -p <pod> -c <container> -- <command> [<args...>]",
 | 
							Use:     "exec -p <pod> -c <container> -- <command> [<args...>]",
 | 
				
			||||||
		Short:   "Execute a command in a container.",
 | 
							Short:   "Execute a command in a container.",
 | 
				
			||||||
		Long:    "Execute a command in a container.",
 | 
							Long:    "Execute a command in a container.",
 | 
				
			||||||
		Example: exec_example,
 | 
							Example: exec_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if len(flags.pod) == 0 {
 | 
								err := RunExec(f, cmdIn, cmdOut, cmdErr, cmd, args)
 | 
				
			||||||
				usageError(cmd, "<pod> is required for exec")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if len(args) < 1 {
 | 
					 | 
				
			||||||
				usageError(cmd, "<command> is required for exec")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			namespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			client, err := f.Client(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			pod, err := client.Pods(namespace).Get(flags.pod)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if pod.Status.Phase != api.PodRunning {
 | 
					 | 
				
			||||||
				glog.Fatalf("Unable to execute command because pod is not running. Current status=%v", pod.Status.Phase)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if len(flags.container) == 0 {
 | 
					 | 
				
			||||||
				flags.container = pod.Spec.Containers[0].Name
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var stdin io.Reader
 | 
					 | 
				
			||||||
			if util.GetFlagBool(cmd, "stdin") {
 | 
					 | 
				
			||||||
				stdin = cmdIn
 | 
					 | 
				
			||||||
				if flags.tty {
 | 
					 | 
				
			||||||
					if file, ok := cmdIn.(*os.File); ok {
 | 
					 | 
				
			||||||
						inFd := file.Fd()
 | 
					 | 
				
			||||||
						if term.IsTerminal(inFd) {
 | 
					 | 
				
			||||||
							oldState, err := term.SetRawTerminal(inFd)
 | 
					 | 
				
			||||||
							if err != nil {
 | 
					 | 
				
			||||||
								glog.Fatal(err)
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
							// this handles a clean exit, where the command finished
 | 
					 | 
				
			||||||
							defer term.RestoreTerminal(inFd, oldState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							// SIGINT is handled by term.SetRawTerminal (it runs a goroutine that listens
 | 
					 | 
				
			||||||
							// for SIGINT and restores the terminal before exiting)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							// this handles SIGTERM
 | 
					 | 
				
			||||||
							sigChan := make(chan os.Signal, 1)
 | 
					 | 
				
			||||||
							signal.Notify(sigChan, syscall.SIGTERM)
 | 
					 | 
				
			||||||
							go func() {
 | 
					 | 
				
			||||||
								<-sigChan
 | 
					 | 
				
			||||||
								term.RestoreTerminal(inFd, oldState)
 | 
					 | 
				
			||||||
								os.Exit(0)
 | 
					 | 
				
			||||||
							}()
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							glog.Warning("Stdin is not a terminal")
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						flags.tty = false
 | 
					 | 
				
			||||||
						glog.Warning("Unable to use a TTY")
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			config, err := f.ClientConfig(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			req := client.RESTClient.Get().
 | 
					 | 
				
			||||||
				Prefix("proxy").
 | 
					 | 
				
			||||||
				Resource("minions").
 | 
					 | 
				
			||||||
				Name(pod.Status.Host).
 | 
					 | 
				
			||||||
				Suffix("exec", namespace, flags.pod, flags.container)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			e := remotecommand.New(req, config, args, stdin, cmdOut, cmdErr, flags.tty)
 | 
					 | 
				
			||||||
			err = e.Execute()
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.Flags().StringVarP(&flags.pod, "pod", "p", "", "Pod name")
 | 
						cmd.Flags().StringP("pod", "p", "", "Pod name")
 | 
				
			||||||
	// TODO support UID
 | 
						// TODO support UID
 | 
				
			||||||
	cmd.Flags().StringVarP(&flags.container, "container", "c", "", "Container name")
 | 
						cmd.Flags().StringP("container", "c", "", "Container name")
 | 
				
			||||||
	cmd.Flags().BoolVarP(&flags.stdin, "stdin", "i", false, "Pass stdin to the container")
 | 
						cmd.Flags().BoolP("stdin", "i", false, "Pass stdin to the container")
 | 
				
			||||||
	cmd.Flags().BoolVarP(&flags.tty, "tty", "t", false, "Stdin is a TTY")
 | 
						cmd.Flags().BoolP("tty", "t", false, "Stdin is a TTY")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunExec(f *Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						podName := util.GetFlagString(cmd, "pod")
 | 
				
			||||||
 | 
						if len(podName) == 0 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "<pod> is required for exec")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(args) < 1 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "<command> is required for exec")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						namespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client, err := f.Client(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pod, err := client.Pods(namespace).Get(podName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if pod.Status.Phase != api.PodRunning {
 | 
				
			||||||
 | 
							glog.Fatalf("Unable to execute command because pod is not running. Current status=%v", pod.Status.Phase)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						containerName := util.GetFlagString(cmd, "container")
 | 
				
			||||||
 | 
						if len(containerName) == 0 {
 | 
				
			||||||
 | 
							containerName = pod.Spec.Containers[0].Name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var stdin io.Reader
 | 
				
			||||||
 | 
						tty := util.GetFlagBool(cmd, "tty")
 | 
				
			||||||
 | 
						if util.GetFlagBool(cmd, "stdin") {
 | 
				
			||||||
 | 
							stdin = cmdIn
 | 
				
			||||||
 | 
							if tty {
 | 
				
			||||||
 | 
								if file, ok := cmdIn.(*os.File); ok {
 | 
				
			||||||
 | 
									inFd := file.Fd()
 | 
				
			||||||
 | 
									if term.IsTerminal(inFd) {
 | 
				
			||||||
 | 
										oldState, err := term.SetRawTerminal(inFd)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											glog.Fatal(err)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										// this handles a clean exit, where the command finished
 | 
				
			||||||
 | 
										defer term.RestoreTerminal(inFd, oldState)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// SIGINT is handled by term.SetRawTerminal (it runs a goroutine that listens
 | 
				
			||||||
 | 
										// for SIGINT and restores the terminal before exiting)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// this handles SIGTERM
 | 
				
			||||||
 | 
										sigChan := make(chan os.Signal, 1)
 | 
				
			||||||
 | 
										signal.Notify(sigChan, syscall.SIGTERM)
 | 
				
			||||||
 | 
										go func() {
 | 
				
			||||||
 | 
											<-sigChan
 | 
				
			||||||
 | 
											term.RestoreTerminal(inFd, oldState)
 | 
				
			||||||
 | 
											os.Exit(0)
 | 
				
			||||||
 | 
										}()
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										glog.Warning("Stdin is not a terminal")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									tty = false
 | 
				
			||||||
 | 
									glog.Warning("Unable to use a TTY")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config, err := f.ClientConfig(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req := client.RESTClient.Get().
 | 
				
			||||||
 | 
							Prefix("proxy").
 | 
				
			||||||
 | 
							Resource("minions").
 | 
				
			||||||
 | 
							Name(pod.Status.Host).
 | 
				
			||||||
 | 
							Suffix("exec", namespace, podName, containerName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e := remotecommand.New(req, config, args, stdin, cmdOut, cmdErr, tty)
 | 
				
			||||||
 | 
						return e.Execute()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,59 +46,7 @@ func (f *Factory) NewCmdExposeService(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Long:    expose_long,
 | 
							Long:    expose_long,
 | 
				
			||||||
		Example: expose_example,
 | 
							Example: expose_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if len(args) != 1 {
 | 
								err := RunExpose(f, out, cmd, args)
 | 
				
			||||||
				usageError(cmd, "<name> is required for expose")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			namespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			client, err := f.Client(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			generatorName := util.GetFlagString(cmd, "generator")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			generator, found := kubectl.Generators[generatorName]
 | 
					 | 
				
			||||||
			if !found {
 | 
					 | 
				
			||||||
				usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if util.GetFlagInt(cmd, "port") < 1 {
 | 
					 | 
				
			||||||
				usageError(cmd, "--port is required and must be a positive integer.")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			names := generator.ParamNames()
 | 
					 | 
				
			||||||
			params := kubectl.MakeParams(cmd, names)
 | 
					 | 
				
			||||||
			if len(util.GetFlagString(cmd, "service-name")) == 0 {
 | 
					 | 
				
			||||||
				params["name"] = args[0]
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				params["name"] = util.GetFlagString(cmd, "service-name")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if _, found := params["selector"]; !found {
 | 
					 | 
				
			||||||
				rc, err := client.ReplicationControllers(namespace).Get(args[0])
 | 
					 | 
				
			||||||
				util.CheckErr(err)
 | 
					 | 
				
			||||||
				params["selector"] = kubectl.MakeLabels(rc.Spec.Selector)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if util.GetFlagBool(cmd, "create-external-load-balancer") {
 | 
					 | 
				
			||||||
				params["create-external-load-balancer"] = "true"
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			err = kubectl.ValidateParams(names, params)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			service, err := generator.Generate(params)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			inline := util.GetFlagString(cmd, "overrides")
 | 
					 | 
				
			||||||
			if len(inline) > 0 {
 | 
					 | 
				
			||||||
				service, err = util.Merge(service, inline, "Service")
 | 
					 | 
				
			||||||
				util.CheckErr(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// TODO: extract this flag to a central location, when such a location exists.
 | 
					 | 
				
			||||||
			if !util.GetFlagBool(cmd, "dry-run") {
 | 
					 | 
				
			||||||
				service, err = client.Services(namespace).Create(service.(*api.Service))
 | 
					 | 
				
			||||||
				util.CheckErr(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			err = f.PrintObject(cmd, service, out)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -115,3 +63,73 @@ func (f *Factory) NewCmdExposeService(out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().String("service-name", "", "The name for the newly created service.")
 | 
						cmd.Flags().String("service-name", "", "The name for the newly created service.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunExpose(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						if len(args) != 1 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "<name> is required for expose")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						namespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := f.Client(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						generatorName := util.GetFlagString(cmd, "generator")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						generator, found := kubectl.Generators[generatorName]
 | 
				
			||||||
 | 
						if !found {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if util.GetFlagInt(cmd, "port") < 1 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "--port is required and must be a positive integer.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						names := generator.ParamNames()
 | 
				
			||||||
 | 
						params := kubectl.MakeParams(cmd, names)
 | 
				
			||||||
 | 
						if len(util.GetFlagString(cmd, "service-name")) == 0 {
 | 
				
			||||||
 | 
							params["name"] = args[0]
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							params["name"] = util.GetFlagString(cmd, "service-name")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, found := params["selector"]; !found {
 | 
				
			||||||
 | 
							rc, err := client.ReplicationControllers(namespace).Get(args[0])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							params["selector"] = kubectl.MakeLabels(rc.Spec.Selector)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if util.GetFlagBool(cmd, "create-external-load-balancer") {
 | 
				
			||||||
 | 
							params["create-external-load-balancer"] = "true"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = kubectl.ValidateParams(names, params)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						service, err := generator.Generate(params)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline := util.GetFlagString(cmd, "overrides")
 | 
				
			||||||
 | 
						if len(inline) > 0 {
 | 
				
			||||||
 | 
							service, err = util.Merge(service, inline, "Service")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: extract this flag to a central location, when such a location exists.
 | 
				
			||||||
 | 
						if !util.GetFlagBool(cmd, "dry-run") {
 | 
				
			||||||
 | 
							service, err = client.Services(namespace).Create(service.(*api.Service))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return f.PrintObject(cmd, service, out)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,7 +63,8 @@ func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Long:    get_long,
 | 
							Long:    get_long,
 | 
				
			||||||
		Example: get_example,
 | 
							Example: get_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			RunGet(f, out, cmd, args)
 | 
								err := RunGet(f, out, cmd, args)
 | 
				
			||||||
 | 
								util.CheckErr(err)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	util.AddPrinterFlags(cmd)
 | 
						util.AddPrinterFlags(cmd)
 | 
				
			||||||
@@ -75,13 +76,14 @@ func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// RunGet implements the generic Get command
 | 
					// RunGet implements the generic Get command
 | 
				
			||||||
// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
 | 
					// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
 | 
				
			||||||
// TODO: return an error instead of using glog.Fatal and checkErr
 | 
					func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
 | 
					 | 
				
			||||||
	selector := util.GetFlagString(cmd, "selector")
 | 
						selector := util.GetFlagString(cmd, "selector")
 | 
				
			||||||
	mapper, typer := f.Object(cmd)
 | 
						mapper, typer := f.Object(cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
						cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
	util.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// handle watch separately since we cannot watch multiple resource types
 | 
						// handle watch separately since we cannot watch multiple resource types
 | 
				
			||||||
	isWatch, isWatchOnly := util.GetFlagBool(cmd, "watch"), util.GetFlagBool(cmd, "watch-only")
 | 
						isWatch, isWatchOnly := util.GetFlagBool(cmd, "watch"), util.GetFlagBool(cmd, "watch-only")
 | 
				
			||||||
@@ -92,35 +94,47 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
 | 
				
			|||||||
			ResourceTypeOrNameArgs(true, args...).
 | 
								ResourceTypeOrNameArgs(true, args...).
 | 
				
			||||||
			SingleResourceType().
 | 
								SingleResourceType().
 | 
				
			||||||
			Do()
 | 
								Do()
 | 
				
			||||||
		util.CheckErr(r.Err())
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mapping, err := r.ResourceMapping()
 | 
							mapping, err := r.ResourceMapping()
 | 
				
			||||||
		util.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		printer, err := f.PrinterForMapping(cmd, mapping)
 | 
							printer, err := f.PrinterForMapping(cmd, mapping)
 | 
				
			||||||
		util.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		obj, err := r.Object()
 | 
							obj, err := r.Object()
 | 
				
			||||||
		util.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rv, err := mapping.MetadataAccessor.ResourceVersion(obj)
 | 
							rv, err := mapping.MetadataAccessor.ResourceVersion(obj)
 | 
				
			||||||
		util.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// print the current object
 | 
							// print the current object
 | 
				
			||||||
		if !isWatchOnly {
 | 
							if !isWatchOnly {
 | 
				
			||||||
			if err := printer.PrintObj(obj, out); err != nil {
 | 
								if err := printer.PrintObj(obj, out); err != nil {
 | 
				
			||||||
				util.CheckErr(fmt.Errorf("unable to output the provided object: %v", err))
 | 
									return fmt.Errorf("unable to output the provided object: %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// print watched changes
 | 
							// print watched changes
 | 
				
			||||||
		w, err := r.Watch(rv)
 | 
							w, err := r.Watch(rv)
 | 
				
			||||||
		util.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		kubectl.WatchLoop(w, func(e watch.Event) error {
 | 
							kubectl.WatchLoop(w, func(e watch.Event) error {
 | 
				
			||||||
			return printer.PrintObj(e.Object, out)
 | 
								return printer.PrintObj(e.Object, out)
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		return
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
 | 
						b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)).
 | 
				
			||||||
@@ -129,11 +143,15 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
 | 
				
			|||||||
		ResourceTypeOrNameArgs(true, args...).
 | 
							ResourceTypeOrNameArgs(true, args...).
 | 
				
			||||||
		Latest()
 | 
							Latest()
 | 
				
			||||||
	printer, generic, err := util.PrinterForCommand(cmd)
 | 
						printer, generic, err := util.PrinterForCommand(cmd)
 | 
				
			||||||
	util.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if generic {
 | 
						if generic {
 | 
				
			||||||
		clientConfig, err := f.ClientConfig(cmd)
 | 
							clientConfig, err := f.ClientConfig(cmd)
 | 
				
			||||||
		util.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		defaultVersion := clientConfig.Version
 | 
							defaultVersion := clientConfig.Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// the outermost object will be converted to the output-version
 | 
							// the outermost object will be converted to the output-version
 | 
				
			||||||
@@ -141,7 +159,9 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		r := b.Flatten().Do()
 | 
							r := b.Flatten().Do()
 | 
				
			||||||
		obj, err := r.Object()
 | 
							obj, err := r.Object()
 | 
				
			||||||
		util.CheckErr(err)
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// try conversion to all the possible versions
 | 
							// try conversion to all the possible versions
 | 
				
			||||||
		// TODO: simplify by adding a ResourceBuilder mode
 | 
							// TODO: simplify by adding a ResourceBuilder mode
 | 
				
			||||||
@@ -157,18 +177,15 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) {
 | 
				
			|||||||
		// builder on initialization
 | 
							// builder on initialization
 | 
				
			||||||
		printer := kubectl.NewVersionedPrinter(printer, api.Scheme, versions...)
 | 
							printer := kubectl.NewVersionedPrinter(printer, api.Scheme, versions...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = printer.PrintObj(obj, out)
 | 
							return printer.PrintObj(obj, out)
 | 
				
			||||||
		util.CheckErr(err)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// use the default printer for each object
 | 
						// use the default printer for each object
 | 
				
			||||||
	err = b.Do().Visit(func(r *resource.Info) error {
 | 
						return b.Do().Visit(func(r *resource.Info) error {
 | 
				
			||||||
		printer, err := f.PrinterForMapping(cmd, r.Mapping)
 | 
							printer, err := f.PrinterForMapping(cmd, r.Mapping)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return printer.PrintObj(r.Object, out)
 | 
							return printer.PrintObj(r.Object, out)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	util.CheckErr(err)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,38 +55,8 @@ func (f *Factory) NewCmdLabel(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Long:    label_long,
 | 
							Long:    label_long,
 | 
				
			||||||
		Example: label_example,
 | 
							Example: label_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if len(args) < 2 {
 | 
								err := RunLabel(f, out, cmd, args)
 | 
				
			||||||
				usageError(cmd, "<resource> <name> is required")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if len(args) < 3 {
 | 
					 | 
				
			||||||
				usageError(cmd, "at least one label update is required.")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			res := args[:2]
 | 
					 | 
				
			||||||
			cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			mapper, _ := f.Object(cmd)
 | 
					 | 
				
			||||||
			// TODO: use resource.Builder instead
 | 
					 | 
				
			||||||
			mapping, namespace, name := util.ResourceFromArgs(cmd, res, mapper, cmdNamespace)
 | 
					 | 
				
			||||||
			client, err := f.RESTClient(cmd, mapping)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			labels, remove, err := parseLabels(args[2:])
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			overwrite := util.GetFlagBool(cmd, "overwrite")
 | 
					 | 
				
			||||||
			resourceVersion := util.GetFlagString(cmd, "resource-version")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			obj, err := updateObject(client, mapping, namespace, name, func(obj runtime.Object) runtime.Object {
 | 
					 | 
				
			||||||
				outObj, err := labelFunc(obj, overwrite, resourceVersion, labels, remove)
 | 
					 | 
				
			||||||
				util.CheckErr(err)
 | 
					 | 
				
			||||||
				return outObj
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			printer, err := f.PrinterForMapping(cmd, mapping)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			printer.PrintObj(obj, out)
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	util.AddPrinterFlags(cmd)
 | 
						util.AddPrinterFlags(cmd)
 | 
				
			||||||
@@ -95,7 +65,7 @@ func (f *Factory) NewCmdLabel(out io.Writer) *cobra.Command {
 | 
				
			|||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func updateObject(client resource.RESTClient, mapping *meta.RESTMapping, namespace, name string, updateFn func(runtime.Object) runtime.Object) (runtime.Object, error) {
 | 
					func updateObject(client resource.RESTClient, mapping *meta.RESTMapping, namespace, name string, updateFn func(runtime.Object) (runtime.Object, error)) (runtime.Object, error) {
 | 
				
			||||||
	helper := resource.NewHelper(client, mapping)
 | 
						helper := resource.NewHelper(client, mapping)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	obj, err := helper.Get(namespace, name)
 | 
						obj, err := helper.Get(namespace, name)
 | 
				
			||||||
@@ -103,7 +73,10 @@ func updateObject(client resource.RESTClient, mapping *meta.RESTMapping, namespa
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	obj = updateFn(obj)
 | 
						obj, err = updateFn(obj)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data, err := helper.Codec.Encode(obj)
 | 
						data, err := helper.Codec.Encode(obj)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -177,3 +150,54 @@ func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, label
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return obj, nil
 | 
						return obj, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunLabel(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						if len(args) < 2 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "<resource> <name> is required")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(args) < 3 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "at least one label update is required.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := args[:2]
 | 
				
			||||||
 | 
						cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mapper, _ := f.Object(cmd)
 | 
				
			||||||
 | 
						// TODO: use resource.Builder instead
 | 
				
			||||||
 | 
						mapping, namespace, name, err := util.ResourceFromArgs(cmd, res, mapper, cmdNamespace)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := f.RESTClient(cmd, mapping)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						labels, remove, err := parseLabels(args[2:])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						overwrite := util.GetFlagBool(cmd, "overwrite")
 | 
				
			||||||
 | 
						resourceVersion := util.GetFlagString(cmd, "resource-version")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj, err := updateObject(client, mapping, namespace, name, func(obj runtime.Object) (runtime.Object, error) {
 | 
				
			||||||
 | 
							outObj, err := labelFunc(obj, overwrite, resourceVersion, labels, remove)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return outObj, nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printer, err := f.PrinterForMapping(cmd, mapping)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printer.PrintObj(obj, out)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,6 @@ package cmd
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
@@ -65,56 +64,7 @@ func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Long:    "Print the logs for a container in a pod. If the pod has only one container, the container name is optional.",
 | 
							Long:    "Print the logs for a container in a pod. If the pod has only one container, the container name is optional.",
 | 
				
			||||||
		Example: log_example,
 | 
							Example: log_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if len(args) == 0 {
 | 
								err := RunLog(f, out, cmd, args)
 | 
				
			||||||
				usageError(cmd, "<pod> is required for log")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if len(args) > 2 {
 | 
					 | 
				
			||||||
				usageError(cmd, "log <pod> [<container>]")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			namespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			client, err := f.Client(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			podID := args[0]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			pod, err := client.Pods(namespace).Get(podID)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var container string
 | 
					 | 
				
			||||||
			if len(args) == 1 {
 | 
					 | 
				
			||||||
				if len(pod.Spec.Containers) != 1 {
 | 
					 | 
				
			||||||
					if !util.GetFlagBool(cmd, "interactive") {
 | 
					 | 
				
			||||||
						usageError(cmd, "<container> is required for pods with multiple containers")
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						container = selectContainer(pod, os.Stdin, out)
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					// Get logs for the only container in the pod
 | 
					 | 
				
			||||||
					container = pod.Spec.Containers[0].Name
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				container = args[1]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			follow := false
 | 
					 | 
				
			||||||
			if util.GetFlagBool(cmd, "follow") {
 | 
					 | 
				
			||||||
				follow = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			readCloser, err := client.RESTClient.Get().
 | 
					 | 
				
			||||||
				Prefix("proxy").
 | 
					 | 
				
			||||||
				Resource("minions").
 | 
					 | 
				
			||||||
				Name(pod.Status.Host).
 | 
					 | 
				
			||||||
				Suffix("containerLogs", namespace, podID, container).
 | 
					 | 
				
			||||||
				Param("follow", strconv.FormatBool(follow)).
 | 
					 | 
				
			||||||
				Stream()
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			defer readCloser.Close()
 | 
					 | 
				
			||||||
			_, err = io.Copy(out, readCloser)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -122,3 +72,55 @@ func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().Bool("interactive", true, "If true, prompt the user for input when required. Default true.")
 | 
						cmd.Flags().Bool("interactive", true, "If true, prompt the user for input when required. Default true.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunLog(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						if len(args) == 0 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "<pod> is required for log")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(args) > 2 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "log <pod> [<container>]")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						namespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := f.Client(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						podID := args[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pod, err := client.Pods(namespace).Get(podID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var container string
 | 
				
			||||||
 | 
						if len(args) == 1 {
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							container = args[1]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						follow := false
 | 
				
			||||||
 | 
						if util.GetFlagBool(cmd, "follow") {
 | 
				
			||||||
 | 
							follow = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						readCloser, err := client.RESTClient.Get().
 | 
				
			||||||
 | 
							Prefix("proxy").
 | 
				
			||||||
 | 
							Resource("minions").
 | 
				
			||||||
 | 
							Name(pod.Status.Host).
 | 
				
			||||||
 | 
							Suffix("containerLogs", namespace, podID, container).
 | 
				
			||||||
 | 
							Param("follow", strconv.FormatBool(follow)).
 | 
				
			||||||
 | 
							Stream()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer readCloser.Close()
 | 
				
			||||||
 | 
						_, err = io.Copy(out, readCloser)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,10 @@ limitations under the License.
 | 
				
			|||||||
package cmd
 | 
					package cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,8 +34,7 @@ func NewCmdNamespace(out io.Writer) *cobra.Command {
 | 
				
			|||||||
namespace has been superceded by the context.namespace field of .kubeconfig files.  See 'kubectl config set-context --help' for more details.
 | 
					namespace has been superceded by the context.namespace field of .kubeconfig files.  See 'kubectl config set-context --help' for more details.
 | 
				
			||||||
`,
 | 
					`,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			glog.Errorln("namespace has been superceded by the context.namespace field of .kubeconfig files.  See 'kubectl config set-context --help' for more details.")
 | 
								util.CheckErr(fmt.Errorf("namespace has been superceded by the context.namespace field of .kubeconfig files.  See 'kubectl config set-context --help' for more details."))
 | 
				
			||||||
			os.Exit(1)
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,65 +42,75 @@ $ kubectl port-forward -p mypod 0:5000
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *Factory) NewCmdPortForward() *cobra.Command {
 | 
					func (f *Factory) NewCmdPortForward() *cobra.Command {
 | 
				
			||||||
	flags := &struct {
 | 
					 | 
				
			||||||
		pod       string
 | 
					 | 
				
			||||||
		container string
 | 
					 | 
				
			||||||
	}{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "port-forward -p <pod> [<local port>:]<remote port> [<port>...]",
 | 
							Use:     "port-forward -p <pod> [<local port>:]<remote port> [<port>...]",
 | 
				
			||||||
		Short:   "Forward 1 or more local ports to a pod.",
 | 
							Short:   "Forward 1 or more local ports to a pod.",
 | 
				
			||||||
		Long:    "Forward 1 or more local ports to a pod.",
 | 
							Long:    "Forward 1 or more local ports to a pod.",
 | 
				
			||||||
		Example: portforward_example,
 | 
							Example: portforward_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if len(flags.pod) == 0 {
 | 
								err := RunPortForward(f, cmd, args)
 | 
				
			||||||
				usageError(cmd, "<pod> is required for exec")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if len(args) < 1 {
 | 
					 | 
				
			||||||
				usageError(cmd, "at least 1 <port> is required for port-forward")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			namespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			client, err := f.Client(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			pod, err := client.Pods(namespace).Get(flags.pod)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if pod.Status.Phase != api.PodRunning {
 | 
					 | 
				
			||||||
				glog.Fatalf("Unable to execute command because pod is not running. Current status=%v", pod.Status.Phase)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			config, err := f.ClientConfig(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			signals := make(chan os.Signal, 1)
 | 
					 | 
				
			||||||
			signal.Notify(signals, os.Interrupt)
 | 
					 | 
				
			||||||
			defer signal.Stop(signals)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			stopCh := make(chan struct{}, 1)
 | 
					 | 
				
			||||||
			go func() {
 | 
					 | 
				
			||||||
				<-signals
 | 
					 | 
				
			||||||
				close(stopCh)
 | 
					 | 
				
			||||||
			}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			req := client.RESTClient.Get().
 | 
					 | 
				
			||||||
				Prefix("proxy").
 | 
					 | 
				
			||||||
				Resource("minions").
 | 
					 | 
				
			||||||
				Name(pod.Status.Host).
 | 
					 | 
				
			||||||
				Suffix("portForward", namespace, flags.pod)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			pf, err := portforward.New(req, config, args, stopCh)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			err = pf.ForwardPorts()
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.Flags().StringVarP(&flags.pod, "pod", "p", "", "Pod name")
 | 
						cmd.Flags().StringP("pod", "p", "", "Pod name")
 | 
				
			||||||
	// TODO support UID
 | 
						// TODO support UID
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunPortForward(f *Factory, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						podName := util.GetFlagString(cmd, "pod")
 | 
				
			||||||
 | 
						if len(podName) == 0 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "<pod> is required for exec")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(args) < 1 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "at least 1 <port> is required for port-forward")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						namespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client, err := f.Client(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pod, err := client.Pods(namespace).Get(podName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if pod.Status.Phase != api.PodRunning {
 | 
				
			||||||
 | 
							glog.Fatalf("Unable to execute command because pod is not running. Current status=%v", pod.Status.Phase)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config, err := f.ClientConfig(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signals := make(chan os.Signal, 1)
 | 
				
			||||||
 | 
						signal.Notify(signals, os.Interrupt)
 | 
				
			||||||
 | 
						defer signal.Stop(signals)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stopCh := make(chan struct{}, 1)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							<-signals
 | 
				
			||||||
 | 
							close(stopCh)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req := client.RESTClient.Get().
 | 
				
			||||||
 | 
							Prefix("proxy").
 | 
				
			||||||
 | 
							Resource("minions").
 | 
				
			||||||
 | 
							Name(pod.Status.Host).
 | 
				
			||||||
 | 
							Suffix("portForward", namespace, podName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pf, err := portforward.New(req, config, args, stopCh)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pf.ForwardPorts()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package cmd
 | 
					package cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,25 +33,8 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Short: "Run a proxy to the Kubernetes API server",
 | 
							Short: "Run a proxy to the Kubernetes API server",
 | 
				
			||||||
		Long:  `Run a proxy to the Kubernetes API server.`,
 | 
							Long:  `Run a proxy to the Kubernetes API server.`,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			port := util.GetFlagInt(cmd, "port")
 | 
								err := RunProxy(f, out, cmd)
 | 
				
			||||||
			glog.Infof("Starting to serve on localhost:%d", port)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			clientConfig, err := f.ClientConfig(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			staticPrefix := util.GetFlagString(cmd, "www-prefix")
 | 
					 | 
				
			||||||
			if !strings.HasSuffix(staticPrefix, "/") {
 | 
					 | 
				
			||||||
				staticPrefix += "/"
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			apiProxyPrefix := util.GetFlagString(cmd, "api-prefix")
 | 
					 | 
				
			||||||
			if !strings.HasSuffix(apiProxyPrefix, "/") {
 | 
					 | 
				
			||||||
				apiProxyPrefix += "/"
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			server, err := kubectl.NewProxyServer(util.GetFlagString(cmd, "www"), apiProxyPrefix, staticPrefix, clientConfig)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			glog.Fatal(server.Serve(port))
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the specified prefix.")
 | 
						cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the specified prefix.")
 | 
				
			||||||
@@ -59,3 +43,30 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().IntP("port", "p", 8001, "The port on which to run the proxy.")
 | 
						cmd.Flags().IntP("port", "p", 8001, "The port on which to run the proxy.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunProxy(f *Factory, out io.Writer, cmd *cobra.Command) error {
 | 
				
			||||||
 | 
						port := util.GetFlagInt(cmd, "port")
 | 
				
			||||||
 | 
						fmt.Fprintf(out, "Starting to serve on localhost:%d", port)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clientConfig, err := f.ClientConfig(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						staticPrefix := util.GetFlagString(cmd, "www-prefix")
 | 
				
			||||||
 | 
						if !strings.HasSuffix(staticPrefix, "/") {
 | 
				
			||||||
 | 
							staticPrefix += "/"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						apiProxyPrefix := util.GetFlagString(cmd, "api-prefix")
 | 
				
			||||||
 | 
						if !strings.HasSuffix(apiProxyPrefix, "/") {
 | 
				
			||||||
 | 
							apiProxyPrefix += "/"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						server, err := kubectl.NewProxyServer(util.GetFlagString(cmd, "www"), apiProxyPrefix, staticPrefix, clientConfig)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glog.Fatal(server.Serve(port))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,32 +52,8 @@ func (f *Factory) NewCmdResize(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Long:    resize_long,
 | 
							Long:    resize_long,
 | 
				
			||||||
		Example: resize_example,
 | 
							Example: resize_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			count := util.GetFlagInt(cmd, "replicas")
 | 
								err := RunResize(f, out, cmd, args)
 | 
				
			||||||
			if len(args) != 2 || count < 0 {
 | 
					 | 
				
			||||||
				usageError(cmd, "--replicas=<count> <resource> <id>")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			mapper, _ := f.Object(cmd)
 | 
					 | 
				
			||||||
			// TODO: use resource.Builder instead
 | 
					 | 
				
			||||||
			mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			resizer, err := f.Resizer(cmd, mapping)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			resourceVersion := util.GetFlagString(cmd, "resource-version")
 | 
					 | 
				
			||||||
			currentSize := util.GetFlagInt(cmd, "current-replicas")
 | 
					 | 
				
			||||||
			precondition := &kubectl.ResizePrecondition{currentSize, resourceVersion}
 | 
					 | 
				
			||||||
			cond := kubectl.ResizeCondition(resizer, precondition, namespace, name, uint(count))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			msg := "resized"
 | 
					 | 
				
			||||||
			if err = wait.Poll(retryFrequency, retryTimeout, cond); err != nil {
 | 
					 | 
				
			||||||
				msg = fmt.Sprintf("Failed to resize controller in spite of retrying for %s", retryTimeout)
 | 
					 | 
				
			||||||
				util.CheckErr(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			fmt.Fprintf(out, "%s\n", msg)
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.Flags().String("resource-version", "", "Precondition for resource version. Requires that the current resource version match this value in order to resize.")
 | 
						cmd.Flags().String("resource-version", "", "Precondition for resource version. Requires that the current resource version match this value in order to resize.")
 | 
				
			||||||
@@ -85,3 +61,42 @@ func (f *Factory) NewCmdResize(out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().Int("replicas", -1, "The new desired number of replicas. Required.")
 | 
						cmd.Flags().Int("replicas", -1, "The new desired number of replicas. Required.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunResize(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						count := util.GetFlagInt(cmd, "replicas")
 | 
				
			||||||
 | 
						if len(args) != 2 || count < 0 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "--replicas=<count> <resource> <id>")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resizer, err := f.Resizer(cmd, mapping)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resourceVersion := util.GetFlagString(cmd, "resource-version")
 | 
				
			||||||
 | 
						currentSize := util.GetFlagInt(cmd, "current-replicas")
 | 
				
			||||||
 | 
						precondition := &kubectl.ResizePrecondition{currentSize, resourceVersion}
 | 
				
			||||||
 | 
						cond := kubectl.ResizeCondition(resizer, precondition, namespace, name, uint(count))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg := "resized"
 | 
				
			||||||
 | 
						if err = wait.Poll(retryFrequency, retryTimeout, cond); err != nil {
 | 
				
			||||||
 | 
							msg = fmt.Sprintf("Failed to resize controller in spite of retrying for %s", retryTimeout)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Fprintf(out, "%s\n", msg)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,73 +49,8 @@ func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Long:    rollingupdate_long,
 | 
							Long:    rollingupdate_long,
 | 
				
			||||||
		Example: rollingupdate_example,
 | 
							Example: rollingupdate_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			filename := util.GetFlagString(cmd, "filename")
 | 
								err := RunRollingUpdate(f, out, cmd, args)
 | 
				
			||||||
			if len(filename) == 0 {
 | 
					 | 
				
			||||||
				usageError(cmd, "Must specify filename for new controller")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			period := util.GetFlagDuration(cmd, "update-period")
 | 
					 | 
				
			||||||
			interval := util.GetFlagDuration(cmd, "poll-interval")
 | 
					 | 
				
			||||||
			timeout := util.GetFlagDuration(cmd, "timeout")
 | 
					 | 
				
			||||||
			if len(args) != 1 {
 | 
					 | 
				
			||||||
				usageError(cmd, "Must specify the controller to update")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			oldName := args[0]
 | 
					 | 
				
			||||||
			schema, err := f.Validator(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			clientConfig, err := f.ClientConfig(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			cmdApiVersion := clientConfig.Version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			mapper, typer := f.Object(cmd)
 | 
					 | 
				
			||||||
			// TODO: use resource.Builder instead
 | 
					 | 
				
			||||||
			mapping, namespace, newName, data := util.ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion)
 | 
					 | 
				
			||||||
			if mapping.Kind != "ReplicationController" {
 | 
					 | 
				
			||||||
				usageError(cmd, "%s does not specify a valid ReplicationController", filename)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if oldName == newName {
 | 
					 | 
				
			||||||
				usageError(cmd, "%s cannot have the same name as the existing ReplicationController %s",
 | 
					 | 
				
			||||||
					filename, oldName)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			// TODO: use resource.Builder instead
 | 
					 | 
				
			||||||
			err = util.CompareNamespace(cmdNamespace, namespace)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			client, err := f.Client(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			obj, err := mapping.Codec.Decode(data)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
			newRc := obj.(*api.ReplicationController)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			updater := kubectl.NewRollingUpdater(cmdNamespace, client)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// fetch rc
 | 
					 | 
				
			||||||
			oldRc, err := client.ReplicationControllers(cmdNamespace).Get(oldName)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			var hasLabel bool
 | 
					 | 
				
			||||||
			for key, oldValue := range oldRc.Spec.Selector {
 | 
					 | 
				
			||||||
				if newValue, ok := newRc.Spec.Selector[key]; ok && newValue != oldValue {
 | 
					 | 
				
			||||||
					hasLabel = true
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if !hasLabel {
 | 
					 | 
				
			||||||
				usageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s",
 | 
					 | 
				
			||||||
					filename, oldName)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// TODO: handle resizes during rolling update
 | 
					 | 
				
			||||||
			if newRc.Spec.Replicas == 0 {
 | 
					 | 
				
			||||||
				newRc.Spec.Replicas = oldRc.Spec.Replicas
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			err = updater.Update(out, oldRc, newRc, period, interval, timeout)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			fmt.Fprintf(out, "%s\n", newName)
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.Flags().String("update-period", updatePeriod, `Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`)
 | 
						cmd.Flags().String("update-period", updatePeriod, `Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`)
 | 
				
			||||||
@@ -124,3 +59,93 @@ func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().StringP("filename", "f", "", "Filename or URL to file to use to create the new controller.")
 | 
						cmd.Flags().StringP("filename", "f", "", "Filename or URL to file to use to create the new controller.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunRollingUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						filename := util.GetFlagString(cmd, "filename")
 | 
				
			||||||
 | 
						if len(filename) == 0 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "Must specify filename for new controller")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						period := util.GetFlagDuration(cmd, "update-period")
 | 
				
			||||||
 | 
						interval := util.GetFlagDuration(cmd, "poll-interval")
 | 
				
			||||||
 | 
						timeout := util.GetFlagDuration(cmd, "timeout")
 | 
				
			||||||
 | 
						if len(args) != 1 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "Must specify the controller to update")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						oldName := args[0]
 | 
				
			||||||
 | 
						schema, err := f.Validator(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clientConfig, err := f.ClientConfig(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmdApiVersion := clientConfig.Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mapper, typer := f.Object(cmd)
 | 
				
			||||||
 | 
						// TODO: use resource.Builder instead
 | 
				
			||||||
 | 
						mapping, namespace, newName, data, err := util.ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if mapping.Kind != "ReplicationController" {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "%s does not specify a valid ReplicationController", filename)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if oldName == newName {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "%s cannot have the same name as the existing ReplicationController %s",
 | 
				
			||||||
 | 
								filename, oldName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: use resource.Builder instead
 | 
				
			||||||
 | 
						err = util.CompareNamespace(cmdNamespace, namespace)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client, err := f.Client(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj, err := mapping.Codec.Decode(data)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newRc := obj.(*api.ReplicationController)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updater := kubectl.NewRollingUpdater(cmdNamespace, client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// fetch rc
 | 
				
			||||||
 | 
						oldRc, err := client.ReplicationControllers(cmdNamespace).Get(oldName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var hasLabel bool
 | 
				
			||||||
 | 
						for key, oldValue := range oldRc.Spec.Selector {
 | 
				
			||||||
 | 
							if newValue, ok := newRc.Spec.Selector[key]; ok && newValue != oldValue {
 | 
				
			||||||
 | 
								hasLabel = true
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !hasLabel {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s",
 | 
				
			||||||
 | 
								filename, oldName)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: handle resizes during rolling update
 | 
				
			||||||
 | 
						if newRc.Spec.Replicas == 0 {
 | 
				
			||||||
 | 
							newRc.Spec.Replicas = oldRc.Spec.Replicas
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = updater.Update(out, oldRc, newRc, period, interval, timeout)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Fprintf(out, "%s\n", newName)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,44 +49,7 @@ func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Long:    run_long,
 | 
							Long:    run_long,
 | 
				
			||||||
		Example: run_example,
 | 
							Example: run_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if len(args) != 1 {
 | 
								err := RunRunContainer(f, out, cmd, args)
 | 
				
			||||||
				usageError(cmd, "<name> is required for run-container")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			namespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			client, err := f.Client(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			generatorName := util.GetFlagString(cmd, "generator")
 | 
					 | 
				
			||||||
			generator, found := kubectl.Generators[generatorName]
 | 
					 | 
				
			||||||
			if !found {
 | 
					 | 
				
			||||||
				usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			names := generator.ParamNames()
 | 
					 | 
				
			||||||
			params := kubectl.MakeParams(cmd, names)
 | 
					 | 
				
			||||||
			params["name"] = args[0]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			err = kubectl.ValidateParams(names, params)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			controller, err := generator.Generate(params)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			inline := util.GetFlagString(cmd, "overrides")
 | 
					 | 
				
			||||||
			if len(inline) > 0 {
 | 
					 | 
				
			||||||
				controller, err = util.Merge(controller, inline, "ReplicationController")
 | 
					 | 
				
			||||||
				util.CheckErr(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// TODO: extract this flag to a central location, when such a location exists.
 | 
					 | 
				
			||||||
			if !util.GetFlagBool(cmd, "dry-run") {
 | 
					 | 
				
			||||||
				controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
 | 
					 | 
				
			||||||
				util.CheckErr(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			err = f.PrintObject(cmd, controller, out)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -100,3 +63,56 @@ func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s) created by this call to run-container.")
 | 
						cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s) created by this call to run-container.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunRunContainer(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
 | 
						if len(args) != 1 {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, "<name> is required for run-container")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						namespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client, err := f.Client(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						generatorName := util.GetFlagString(cmd, "generator")
 | 
				
			||||||
 | 
						generator, found := kubectl.Generators[generatorName]
 | 
				
			||||||
 | 
						if !found {
 | 
				
			||||||
 | 
							return util.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						names := generator.ParamNames()
 | 
				
			||||||
 | 
						params := kubectl.MakeParams(cmd, names)
 | 
				
			||||||
 | 
						params["name"] = args[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = kubectl.ValidateParams(names, params)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						controller, err := generator.Generate(params)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inline := util.GetFlagString(cmd, "overrides")
 | 
				
			||||||
 | 
						if len(inline) > 0 {
 | 
				
			||||||
 | 
							controller, err = util.Merge(controller, inline, "ReplicationController")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: extract this flag to a central location, when such a location exists.
 | 
				
			||||||
 | 
						if !util.GetFlagBool(cmd, "dry-run") {
 | 
				
			||||||
 | 
							controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return f.PrintObject(cmd, controller, out)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,91 +41,115 @@ $ kubectl update pods my-pod --patch='{ "apiVersion": "v1beta1", "desiredState":
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *Factory) NewCmdUpdate(out io.Writer) *cobra.Command {
 | 
					func (f *Factory) NewCmdUpdate(out io.Writer) *cobra.Command {
 | 
				
			||||||
	flags := &struct {
 | 
						var filenames util.StringList
 | 
				
			||||||
		Filenames util.StringList
 | 
					 | 
				
			||||||
	}{}
 | 
					 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "update -f filename",
 | 
							Use:     "update -f filename",
 | 
				
			||||||
		Short:   "Update a resource by filename or stdin.",
 | 
							Short:   "Update a resource by filename or stdin.",
 | 
				
			||||||
		Long:    update_long,
 | 
							Long:    update_long,
 | 
				
			||||||
		Example: update_example,
 | 
							Example: update_example,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			schema, err := f.Validator(cmd)
 | 
								err := RunUpdate(f, out, cmd, args, filenames)
 | 
				
			||||||
			cmdutil.CheckErr(err)
 | 
								cmdutil.CheckErr(err)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
					 | 
				
			||||||
			cmdutil.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			patch := cmdutil.GetFlagString(cmd, "patch")
 | 
					 | 
				
			||||||
			if len(flags.Filenames) == 0 && len(patch) == 0 {
 | 
					 | 
				
			||||||
				usageError(cmd, "Must specify --filename or --patch to update")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if len(flags.Filenames) != 0 && len(patch) != 0 {
 | 
					 | 
				
			||||||
				usageError(cmd, "Can not specify both --filename and --patch")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// TODO: Make patching work with -f, updating with patched JSON input files
 | 
					 | 
				
			||||||
			if len(flags.Filenames) == 0 {
 | 
					 | 
				
			||||||
				name := updateWithPatch(cmd, args, f, patch)
 | 
					 | 
				
			||||||
				fmt.Fprintf(out, "%s\n", name)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			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())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			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).Update(info.Namespace, info.Name, true, data)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				info.Refresh(obj, true)
 | 
					 | 
				
			||||||
				fmt.Fprintf(out, "%s\n", info.Name)
 | 
					 | 
				
			||||||
				return nil
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
			cmdutil.CheckErr(err)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.Flags().VarP(&flags.Filenames, "filename", "f", "Filename, directory, or URL to file to use to update the resource.")
 | 
						cmd.Flags().VarP(&filenames, "filename", "f", "Filename, directory, or URL to file to use to update the resource.")
 | 
				
			||||||
	cmd.Flags().String("patch", "", "A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.")
 | 
						cmd.Flags().String("patch", "", "A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string) string {
 | 
					func RunUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error {
 | 
				
			||||||
 | 
						schema, err := f.Validator(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
						cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
	cmdutil.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						patch := cmdutil.GetFlagString(cmd, "patch")
 | 
				
			||||||
 | 
						if len(filenames) == 0 && len(patch) == 0 {
 | 
				
			||||||
 | 
							return cmdutil.UsageError(cmd, "Must specify --filename or --patch to update")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(filenames) != 0 && len(patch) != 0 {
 | 
				
			||||||
 | 
							return cmdutil.UsageError(cmd, "Can not specify both --filename and --patch")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: Make patching work with -f, updating with patched JSON input files
 | 
				
			||||||
 | 
						if len(filenames) == 0 {
 | 
				
			||||||
 | 
							name, err := updateWithPatch(cmd, args, f, patch)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "%s\n", name)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 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).Update(info.Namespace, info.Name, true, data)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							info.Refresh(obj, true)
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "%s\n", info.Name)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string) (string, error) {
 | 
				
			||||||
 | 
						cmdNamespace, err := f.DefaultNamespace(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mapper, _ := f.Object(cmd)
 | 
						mapper, _ := f.Object(cmd)
 | 
				
			||||||
	// TODO: use resource.Builder instead
 | 
						// TODO: use resource.Builder instead
 | 
				
			||||||
	mapping, namespace, name := cmdutil.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
 | 
						mapping, namespace, name, err := cmdutil.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	client, err := f.RESTClient(cmd, mapping)
 | 
						client, err := f.RESTClient(cmd, mapping)
 | 
				
			||||||
	cmdutil.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	helper := resource.NewHelper(client, mapping)
 | 
						helper := resource.NewHelper(client, mapping)
 | 
				
			||||||
	obj, err := helper.Get(namespace, name)
 | 
						obj, err := helper.Get(namespace, name)
 | 
				
			||||||
	cmdutil.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	patchedObj, err := cmdutil.Merge(obj, patch, mapping.Kind)
 | 
						patchedObj, err := cmdutil.Merge(obj, patch, mapping.Kind)
 | 
				
			||||||
	cmdutil.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data, err := helper.Codec.Encode(patchedObj)
 | 
						data, err := helper.Codec.Encode(patchedObj)
 | 
				
			||||||
	cmdutil.CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = helper.Update(namespace, name, true, data)
 | 
						_, err = helper.Update(namespace, name, true, data)
 | 
				
			||||||
	cmdutil.CheckErr(err)
 | 
						return name, err
 | 
				
			||||||
	return name
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,10 +31,11 @@ import (
 | 
				
			|||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/evanphx/json-patch"
 | 
						"github.com/evanphx/json-patch"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
						"github.com/spf13/pflag"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func CheckErr(err error) {
 | 
					func CheckErr(err error) {
 | 
				
			||||||
@@ -52,25 +53,26 @@ func CheckErr(err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func usageError(cmd *cobra.Command, format string, args ...interface{}) {
 | 
					func UsageError(cmd *cobra.Command, format string, args ...interface{}) error {
 | 
				
			||||||
	glog.Errorf(format, args...)
 | 
						msg := fmt.Sprintf(format, args...)
 | 
				
			||||||
	glog.Errorf("See '%s -h' for help.", cmd.CommandPath())
 | 
						return fmt.Errorf("%s\nsee '%s -h' for help.", msg, cmd.CommandPath())
 | 
				
			||||||
	os.Exit(1)
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getFlag(cmd *cobra.Command, flag string) *pflag.Flag {
 | 
				
			||||||
 | 
						f := cmd.Flags().Lookup(flag)
 | 
				
			||||||
 | 
						if f == nil {
 | 
				
			||||||
 | 
							glog.Fatalf("flag accessed but not defined for command %s: %s", cmd.Name(), flag)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return f
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetFlagString(cmd *cobra.Command, flag string) string {
 | 
					func GetFlagString(cmd *cobra.Command, flag string) string {
 | 
				
			||||||
	f := cmd.Flags().Lookup(flag)
 | 
						f := getFlag(cmd, flag)
 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		glog.Fatalf("Flag accessed but not defined for command %s: %s", cmd.Name(), flag)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.Value.String()
 | 
						return f.Value.String()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetFlagBool(cmd *cobra.Command, flag string) bool {
 | 
					func GetFlagBool(cmd *cobra.Command, flag string) bool {
 | 
				
			||||||
	f := cmd.Flags().Lookup(flag)
 | 
						f := getFlag(cmd, flag)
 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		glog.Fatalf("Flag accessed but not defined for command %s: %s", cmd.Name(), flag)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	result, err := strconv.ParseBool(f.Value.String())
 | 
						result, err := strconv.ParseBool(f.Value.String())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		glog.Fatalf("Invalid value for a boolean flag: %s", f.Value.String())
 | 
							glog.Fatalf("Invalid value for a boolean flag: %s", f.Value.String())
 | 
				
			||||||
@@ -80,24 +82,22 @@ func GetFlagBool(cmd *cobra.Command, flag string) bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Assumes the flag has a default value.
 | 
					// Assumes the flag has a default value.
 | 
				
			||||||
func GetFlagInt(cmd *cobra.Command, flag string) int {
 | 
					func GetFlagInt(cmd *cobra.Command, flag string) int {
 | 
				
			||||||
	f := cmd.Flags().Lookup(flag)
 | 
						f := getFlag(cmd, flag)
 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		glog.Fatalf("Flag accessed but not defined for command %s: %s", cmd.Name(), flag)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	v, err := strconv.Atoi(f.Value.String())
 | 
						v, err := strconv.Atoi(f.Value.String())
 | 
				
			||||||
	// This is likely not a sufficiently friendly error message, but cobra
 | 
						// This is likely not a sufficiently friendly error message, but cobra
 | 
				
			||||||
	// should prevent non-integer values from reaching here.
 | 
						// should prevent non-integer values from reaching here.
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							glog.Fatalf("unable to convert flag value to int: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return v
 | 
						return v
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetFlagDuration(cmd *cobra.Command, flag string) time.Duration {
 | 
					func GetFlagDuration(cmd *cobra.Command, flag string) time.Duration {
 | 
				
			||||||
	f := cmd.Flags().Lookup(flag)
 | 
						f := getFlag(cmd, flag)
 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		glog.Fatalf("Flag accessed but not defined for command %s: %s", cmd.Name(), flag)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	v, err := time.ParseDuration(f.Value.String())
 | 
						v, err := time.ParseDuration(f.Value.String())
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							glog.Fatalf("unable to convert flag value to Duration: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return v
 | 
						return v
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,26 +27,29 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ResourceFromArgs expects two arguments with a given type, and extracts the fields necessary
 | 
					// ResourceFromArgs expects two arguments with a given type, and extracts the fields necessary
 | 
				
			||||||
// to uniquely locate a resource. Displays a usageError if that contract is not satisfied, or
 | 
					// to uniquely locate a resource. Displays a UsageError if that contract is not satisfied, or
 | 
				
			||||||
// a generic error if any other problems occur.
 | 
					// a generic error if any other problems occur.
 | 
				
			||||||
// DEPRECATED: Use resource.Builder
 | 
					// DEPRECATED: Use resource.Builder
 | 
				
			||||||
func ResourceFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTMapper, cmdNamespace string) (mapping *meta.RESTMapping, namespace, name string) {
 | 
					func ResourceFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTMapper, cmdNamespace string) (mapping *meta.RESTMapping, namespace, name string, err error) {
 | 
				
			||||||
	if len(args) != 2 {
 | 
						if len(args) != 2 {
 | 
				
			||||||
		usageError(cmd, "Must provide resource and name command line params")
 | 
							err = UsageError(cmd, "Must provide resource and name command line params")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resource := args[0]
 | 
						resource := args[0]
 | 
				
			||||||
	namespace = cmdNamespace
 | 
						namespace = cmdNamespace
 | 
				
			||||||
	name = args[1]
 | 
						name = args[1]
 | 
				
			||||||
	if len(name) == 0 || len(resource) == 0 {
 | 
						if len(name) == 0 || len(resource) == 0 {
 | 
				
			||||||
		usageError(cmd, "Must provide resource and name command line params")
 | 
							err = UsageError(cmd, "Must provide resource and name command line params")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	version, kind, err := mapper.VersionAndKindForResource(resource)
 | 
						version, kind, err := mapper.VersionAndKindForResource(resource)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mapping, err = mapper.RESTMapping(kind, version)
 | 
						mapping, err = mapper.RESTMapping(kind, version)
 | 
				
			||||||
	CheckErr(err)
 | 
					 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -54,41 +57,52 @@ func ResourceFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTMapper,
 | 
				
			|||||||
// resolve to a known type an error is returned. The returned mapping can be used to determine
 | 
					// resolve to a known type an error is returned. The returned mapping can be used to determine
 | 
				
			||||||
// the correct REST endpoint to modify this resource with.
 | 
					// the correct REST endpoint to modify this resource with.
 | 
				
			||||||
// DEPRECATED: Use resource.Builder
 | 
					// DEPRECATED: Use resource.Builder
 | 
				
			||||||
func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper, schema validation.Schema, cmdVersion string) (mapping *meta.RESTMapping, namespace, name string, data []byte) {
 | 
					func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper, schema validation.Schema, cmdVersion string) (mapping *meta.RESTMapping, namespace, name string, data []byte, err error) {
 | 
				
			||||||
	configData, err := ReadConfigData(filename)
 | 
						data, err = ReadConfigData(filename)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
	data = configData
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	objVersion, kind, err := typer.DataVersionAndKind(data)
 | 
						objVersion, kind, err := typer.DataVersionAndKind(data)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: allow unversioned objects?
 | 
						// TODO: allow unversioned objects?
 | 
				
			||||||
	if len(objVersion) == 0 {
 | 
						if len(objVersion) == 0 {
 | 
				
			||||||
		CheckErr(fmt.Errorf("the resource in the provided file has no apiVersion defined"))
 | 
							err = fmt.Errorf("the resource in the provided file has no apiVersion defined")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = schema.ValidateBytes(data)
 | 
						err = schema.ValidateBytes(data)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// decode using the version stored with the object (allows codec to vary across versions)
 | 
						// decode using the version stored with the object (allows codec to vary across versions)
 | 
				
			||||||
	mapping, err = mapper.RESTMapping(kind, objVersion)
 | 
						mapping, err = mapper.RESTMapping(kind, objVersion)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	obj, err := mapping.Codec.Decode(data)
 | 
						obj, err := mapping.Codec.Decode(data)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	meta := mapping.MetadataAccessor
 | 
						meta := mapping.MetadataAccessor
 | 
				
			||||||
	namespace, err = meta.Namespace(obj)
 | 
						namespace, err = meta.Namespace(obj)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	name, err = meta.Name(obj)
 | 
						name, err = meta.Name(obj)
 | 
				
			||||||
	CheckErr(err)
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// if the preferred API version differs, get a different mapper
 | 
						// if the preferred API version differs, get a different mapper
 | 
				
			||||||
	if cmdVersion != objVersion {
 | 
						if cmdVersion != objVersion {
 | 
				
			||||||
		mapping, err = mapper.RESTMapping(kind, cmdVersion)
 | 
							mapping, err = mapper.RESTMapping(kind, cmdVersion)
 | 
				
			||||||
		CheckErr(err)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,17 +30,25 @@ func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
 | 
				
			|||||||
		Use:   "version",
 | 
							Use:   "version",
 | 
				
			||||||
		Short: "Print the client and server version information.",
 | 
							Short: "Print the client and server version information.",
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			if util.GetFlagBool(cmd, "client") {
 | 
								err := RunVersion(f, out, cmd)
 | 
				
			||||||
				kubectl.GetClientVersion(out)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			client, err := f.Client(cmd)
 | 
					 | 
				
			||||||
			util.CheckErr(err)
 | 
								util.CheckErr(err)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			kubectl.GetVersion(out, client)
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
 | 
						cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
 | 
				
			||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunVersion(f *Factory, out io.Writer, cmd *cobra.Command) error {
 | 
				
			||||||
 | 
						if util.GetFlagBool(cmd, "client") {
 | 
				
			||||||
 | 
							kubectl.GetClientVersion(out)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client, err := f.Client(cmd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kubectl.GetVersion(out, client)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user