diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index d882ec96ed4..bdb5f06b6a6 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -110,6 +110,8 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, } } +// TODO: remove this function and references to it-- errors it prints are +// very unhelpful because file/line number are wrong. func checkErr(err error) { if err != nil { glog.Fatalf("%v", err) diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index d232d8ee8b0..88b72dd6d74 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -32,7 +32,7 @@ func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command { Long: `Display one or many resources. Possible resources include pods (po), replication controllers (rc), services -(se) or minions (mi). +(se), minions (mi), or events (ev). If you specify a Go template, you can use any fields defined for the API version you are connecting to the server with. diff --git a/pkg/kubectl/cmd/resource.go b/pkg/kubectl/cmd/resource.go index b20de67d4ba..a9965a492e9 100644 --- a/pkg/kubectl/cmd/resource.go +++ b/pkg/kubectl/cmd/resource.go @@ -19,10 +19,11 @@ package cmd import ( "fmt" - "github.com/spf13/cobra" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" + + "github.com/spf13/cobra" ) // ResourceFromArgsOrFile expects two arguments or a valid file with a given type, and extracts @@ -35,7 +36,7 @@ func ResourceFromArgsOrFile(cmd *cobra.Command, args []string, filename string, } if len(args) == 2 { - resource := args[0] + resource := kubectl.ExpandResourceShortcut(args[0]) namespace = getKubeNamespace(cmd) name = args[1] if len(name) == 0 || len(resource) == 0 { @@ -70,7 +71,7 @@ func ResourceFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTMapper) usageError(cmd, "Must provide resource and name command line params") } - resource := args[0] + resource := kubectl.ExpandResourceShortcut(args[0]) namespace = getKubeNamespace(cmd) name = args[1] if len(name) == 0 || len(resource) == 0 { @@ -93,7 +94,7 @@ func ResourceOrTypeFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTM usageError(cmd, "Must provide resource or a resource and name as command line params") } - resource := args[0] + resource := kubectl.ExpandResourceShortcut(args[0]) if len(resource) == 0 { usageError(cmd, "Must provide resource or a resource and name as command line params") } diff --git a/pkg/kubectl/kubectl.go b/pkg/kubectl/kubectl.go index 8ad267feff0..13ff22ef094 100644 --- a/pkg/kubectl/kubectl.go +++ b/pkg/kubectl/kubectl.go @@ -146,3 +146,22 @@ func makeImageList(manifest api.ContainerManifest) string { } return strings.Join(images, ",") } + +// ExpandResourceShortcut will return the expanded version of resource +// (something that a pkg/api/meta.RESTMapper can understand), if it is +// indeed a shortcut. Otherwise, will return resource unmodified. +// TODO: Combine with RESTMapper stuff to provide a general solution +// to this problem. +func ExpandResourceShortcut(resource string) string { + shortForms := map[string]string{ + "po": "pods", + "rc": "replicationcontrollers", + "se": "services", + "mi": "minions", + "ev": "events", + } + if expanded, ok := shortForms[resource]; ok { + return expanded + } + return resource +} diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index 8309ef37479..48b573f00f8 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -177,6 +177,7 @@ var replicationControllerColumns = []string{"NAME", "IMAGE(S)", "SELECTOR", "REP var serviceColumns = []string{"NAME", "LABELS", "SELECTOR", "IP", "PORT"} var minionColumns = []string{"NAME"} var statusColumns = []string{"STATUS"} +var eventColumns = []string{"NAME", "KIND", "STATUS", "REASON", "MESSAGE"} // addDefaultHandlers adds print handlers for default Kubernetes types. func (h *HumanReadablePrinter) addDefaultHandlers() { @@ -189,6 +190,8 @@ func (h *HumanReadablePrinter) addDefaultHandlers() { h.Handler(minionColumns, printMinion) h.Handler(minionColumns, printMinionList) h.Handler(statusColumns, printStatus) + h.Handler(eventColumns, printEvent) + h.Handler(eventColumns, printEventList) } func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error { @@ -277,6 +280,27 @@ func printStatus(status *api.Status, w io.Writer) error { return err } +func printEvent(event *api.Event, w io.Writer) error { + _, err := fmt.Fprintf( + w, "%s\t%s\t%s\t%s\t%s\n", + event.InvolvedObject.Name, + event.InvolvedObject.Kind, + event.Status, + event.Reason, + event.Message, + ) + return err +} + +func printEventList(list *api.EventList, w io.Writer) error { + for i := range list.Items { + if err := printEvent(&list.Items[i], w); err != nil { + return err + } + } + return nil +} + // PrintObj prints the obj in a human-friendly format according to the type of the obj. func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error { w := tabwriter.NewWriter(output, 20, 5, 3, ' ', 0)