Merge pull request #18004 from jiangyaoguo/print-absolute-time-when-watch-event

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2015-12-08 22:58:12 -08:00
commit 637a33924c
8 changed files with 205 additions and 173 deletions

View File

@ -167,7 +167,7 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
Describer: func(*meta.RESTMapping) (kubectl.Describer, error) { Describer: func(*meta.RESTMapping) (kubectl.Describer, error) {
return t.Describer, t.Err return t.Describer, t.Err
}, },
Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, columnLabels []string) (kubectl.ResourcePrinter, error) { Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error) {
return t.Printer, t.Err return t.Printer, t.Err
}, },
Validator: func(validate bool, cacheDir string) (validation.Schema, error) { Validator: func(validate bool, cacheDir string) (validation.Schema, error) {
@ -224,7 +224,7 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
Describer: func(*meta.RESTMapping) (kubectl.Describer, error) { Describer: func(*meta.RESTMapping) (kubectl.Describer, error) {
return t.Describer, t.Err return t.Describer, t.Err
}, },
Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, columnLabels []string) (kubectl.ResourcePrinter, error) { Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error) {
return t.Printer, t.Err return t.Printer, t.Err
}, },
Validator: func(validate bool, cacheDir string) (validation.Schema, error) { Validator: func(validate bool, cacheDir string) (validation.Schema, error) {
@ -299,7 +299,7 @@ func stringBody(body string) io.ReadCloser {
func ExamplePrintReplicationControllerWithNamespace() { func ExamplePrintReplicationControllerWithNamespace() {
f, tf, codec := NewAPIFactory() f, tf, codec := NewAPIFactory()
tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, []string{}) tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, false, []string{})
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
Codec: codec, Codec: codec,
Client: nil, Client: nil,
@ -341,7 +341,7 @@ func ExamplePrintReplicationControllerWithNamespace() {
func ExamplePrintPodWithWideFormat() { func ExamplePrintPodWithWideFormat() {
f, tf, codec := NewAPIFactory() f, tf, codec := NewAPIFactory()
tf.Printer = kubectl.NewHumanReadablePrinter(false, false, true, false, []string{}) tf.Printer = kubectl.NewHumanReadablePrinter(false, false, true, false, false, []string{})
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
Codec: codec, Codec: codec,
Client: nil, Client: nil,
@ -468,7 +468,7 @@ func newAllPhasePodList() *api.PodList {
func ExamplePrintPodHideTerminated() { func ExamplePrintPodHideTerminated() {
f, tf, codec := NewAPIFactory() f, tf, codec := NewAPIFactory()
tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, false, []string{}) tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, false, false, []string{})
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
Codec: codec, Codec: codec,
Client: nil, Client: nil,
@ -488,7 +488,7 @@ func ExamplePrintPodHideTerminated() {
func ExamplePrintPodShowAll() { func ExamplePrintPodShowAll() {
f, tf, codec := NewAPIFactory() f, tf, codec := NewAPIFactory()
tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, true, []string{}) tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, true, false, []string{})
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
Codec: codec, Codec: codec,
Client: nil, Client: nil,
@ -510,7 +510,7 @@ func ExamplePrintPodShowAll() {
func ExamplePrintServiceWithNamespacesAndLabels() { func ExamplePrintServiceWithNamespacesAndLabels() {
f, tf, codec := NewAPIFactory() f, tf, codec := NewAPIFactory()
tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, []string{"l1"}) tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, false, []string{"l1"})
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{
Codec: codec, Codec: codec,
Client: nil, Client: nil,

View File

@ -71,7 +71,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
// retrieve a list of handled resources from printer as valid args // retrieve a list of handled resources from printer as valid args
validArgs := []string{} validArgs := []string{}
p, err := f.Printer(nil, false, false, false, false, []string{}) p, err := f.Printer(nil, false, false, false, false, false, []string{})
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
if p != nil { if p != nil {
validArgs = p.HandledResources() validArgs = p.HandledResources()

View File

@ -78,7 +78,7 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
// retrieve a list of handled resources from printer as valid args // retrieve a list of handled resources from printer as valid args
validArgs := []string{} validArgs := []string{}
p, err := f.Printer(nil, false, false, false, false, []string{}) p, err := f.Printer(nil, false, false, false, false, false, []string{})
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
if p != nil { if p != nil {
validArgs = p.HandledResources() validArgs = p.HandledResources()

View File

@ -71,7 +71,7 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
// retrieve a list of handled resources from printer as valid args // retrieve a list of handled resources from printer as valid args
validArgs := []string{} validArgs := []string{}
p, err := f.Printer(nil, false, false, false, false, []string{}) p, err := f.Printer(nil, false, false, false, false, false, []string{})
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
if p != nil { if p != nil {
validArgs = p.HandledResources() validArgs = p.HandledResources()

View File

@ -73,7 +73,7 @@ type Factory struct {
// Returns a Describer for displaying the specified RESTMapping type or an error. // Returns a Describer for displaying the specified RESTMapping type or an error.
Describer func(mapping *meta.RESTMapping) (kubectl.Describer, error) Describer func(mapping *meta.RESTMapping) (kubectl.Describer, error)
// Returns a Printer for formatting objects of the given type or an error. // Returns a Printer for formatting objects of the given type or an error.
Printer func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, columnLabels []string) (kubectl.ResourcePrinter, error) Printer func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error)
// Returns a Scaler for changing the size of the specified RESTMapping type or an error // Returns a Scaler for changing the size of the specified RESTMapping type or an error
Scaler func(mapping *meta.RESTMapping) (kubectl.Scaler, error) Scaler func(mapping *meta.RESTMapping) (kubectl.Scaler, error)
// Returns a Reaper for gracefully shutting down resources. // Returns a Reaper for gracefully shutting down resources.
@ -180,8 +180,8 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
} }
return nil, fmt.Errorf("no description has been implemented for %q", mapping.Kind) return nil, fmt.Errorf("no description has been implemented for %q", mapping.Kind)
}, },
Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, columnLabels []string) (kubectl.ResourcePrinter, error) { Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error) {
return kubectl.NewHumanReadablePrinter(noHeaders, withNamespace, wide, showAll, columnLabels), nil return kubectl.NewHumanReadablePrinter(noHeaders, withNamespace, wide, showAll, absoluteTimestamps, columnLabels), nil
}, },
PodSelectorForObject: func(object runtime.Object) (string, error) { PodSelectorForObject: func(object runtime.Object) (string, error) {
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection) // TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
@ -611,7 +611,7 @@ func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMappin
if err != nil { if err != nil {
columnLabel = []string{} columnLabel = []string{}
} }
printer, err = f.Printer(mapping, GetFlagBool(cmd, "no-headers"), withNamespace, GetWideFlag(cmd), GetFlagBool(cmd, "show-all"), columnLabel) printer, err = f.Printer(mapping, GetFlagBool(cmd, "no-headers"), withNamespace, GetWideFlag(cmd), GetFlagBool(cmd, "show-all"), isWatch(cmd), columnLabel)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -214,6 +214,19 @@ func UsageError(cmd *cobra.Command, format string, args ...interface{}) error {
return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath()) return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath())
} }
// Whether this cmd need watching objects.
func isWatch(cmd *cobra.Command) bool {
if w, err := cmd.Flags().GetBool("watch"); w && err == nil {
return true
}
if wo, err := cmd.Flags().GetBool("watch-only"); wo && err == nil {
return true
}
return false
}
func getFlag(cmd *cobra.Command, flag string) *pflag.Flag { func getFlag(cmd *cobra.Command, flag string) *pflag.Flag {
f := cmd.Flags().Lookup(flag) f := cmd.Flags().Lookup(flag)
if f == nil { if f == nil {

View File

@ -300,29 +300,37 @@ type handlerEntry struct {
printFunc reflect.Value printFunc reflect.Value
} }
type printOptions struct {
noHeaders bool
withNamespace bool
wide bool
showAll bool
absoluteTimestamps bool
columnLabels []string
}
// HumanReadablePrinter is an implementation of ResourcePrinter which attempts to provide // HumanReadablePrinter is an implementation of ResourcePrinter which attempts to provide
// more elegant output. It is not threadsafe, but you may call PrintObj repeatedly; headers // more elegant output. It is not threadsafe, but you may call PrintObj repeatedly; headers
// will only be printed if the object type changes. This makes it useful for printing items // will only be printed if the object type changes. This makes it useful for printing items
// received from watches. // received from watches.
type HumanReadablePrinter struct { type HumanReadablePrinter struct {
handlerMap map[reflect.Type]*handlerEntry handlerMap map[reflect.Type]*handlerEntry
noHeaders bool options printOptions
withNamespace bool
wide bool
showAll bool
columnLabels []string
lastType reflect.Type lastType reflect.Type
} }
// NewHumanReadablePrinter creates a HumanReadablePrinter. // NewHumanReadablePrinter creates a HumanReadablePrinter.
func NewHumanReadablePrinter(noHeaders, withNamespace bool, wide bool, showAll bool, columnLabels []string) *HumanReadablePrinter { func NewHumanReadablePrinter(noHeaders, withNamespace bool, wide bool, showAll bool, absoluteTimestamps bool, columnLabels []string) *HumanReadablePrinter {
printer := &HumanReadablePrinter{ printer := &HumanReadablePrinter{
handlerMap: make(map[reflect.Type]*handlerEntry), handlerMap: make(map[reflect.Type]*handlerEntry),
options: printOptions{
noHeaders: noHeaders, noHeaders: noHeaders,
withNamespace: withNamespace, withNamespace: withNamespace,
wide: wide, wide: wide,
showAll: showAll, showAll: showAll,
absoluteTimestamps: absoluteTimestamps,
columnLabels: columnLabels, columnLabels: columnLabels,
},
} }
printer.addDefaultHandlers() printer.addDefaultHandlers()
return printer return printer
@ -347,22 +355,22 @@ func (h *HumanReadablePrinter) Handler(columns []string, printFunc interface{})
// validatePrintHandlerFunc validates print handler signature. // validatePrintHandlerFunc validates print handler signature.
// printFunc is the function that will be called to print an object. // printFunc is the function that will be called to print an object.
// It must be of the following type: // It must be of the following type:
// func printFunc(object ObjectType, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error // func printFunc(object ObjectType, w io.Writer, options PrintOptions) error
// where ObjectType is the type of the object that will be printed. // where ObjectType is the type of the object that will be printed.
func (h *HumanReadablePrinter) validatePrintHandlerFunc(printFunc reflect.Value) error { func (h *HumanReadablePrinter) validatePrintHandlerFunc(printFunc reflect.Value) error {
if printFunc.Kind() != reflect.Func { if printFunc.Kind() != reflect.Func {
return fmt.Errorf("invalid print handler. %#v is not a function", printFunc) return fmt.Errorf("invalid print handler. %#v is not a function", printFunc)
} }
funcType := printFunc.Type() funcType := printFunc.Type()
if funcType.NumIn() != 6 || funcType.NumOut() != 1 { if funcType.NumIn() != 3 || funcType.NumOut() != 1 {
return fmt.Errorf("invalid print handler." + return fmt.Errorf("invalid print handler." +
"Must accept 6 parameters and return 1 value.") "Must accept 3 parameters and return 1 value.")
} }
if funcType.In(1) != reflect.TypeOf((*io.Writer)(nil)).Elem() || if funcType.In(1) != reflect.TypeOf((*io.Writer)(nil)).Elem() ||
funcType.In(5) != reflect.TypeOf((*[]string)(nil)).Elem() || funcType.In(2) != reflect.TypeOf((*printOptions)(nil)).Elem() ||
funcType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() { funcType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() {
return fmt.Errorf("invalid print handler. The expected signature is: "+ return fmt.Errorf("invalid print handler. The expected signature is: "+
"func handler(obj %v, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error", funcType.In(0)) "func handler(obj %v, w io.Writer, options printOptions) error", funcType.In(0))
} }
return nil return nil
} }
@ -528,11 +536,11 @@ func translateTimestamp(timestamp unversioned.Time) string {
return shortHumanDuration(time.Now().Sub(timestamp.Time)) return shortHumanDuration(time.Now().Sub(timestamp.Time))
} }
func printPod(pod *api.Pod, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPod(pod *api.Pod, w io.Writer, options printOptions) error {
return printPodBase(pod, w, withNamespace, wide, showAll, true, columnLabels) return printPodBase(pod, w, true, options)
} }
func printPodBase(pod *api.Pod, w io.Writer, withNamespace bool, wide bool, showAll bool, showIfTerminating bool, columnLabels []string) error { func printPodBase(pod *api.Pod, w io.Writer, showIfTerminating bool, options printOptions) error {
name := pod.Name name := pod.Name
namespace := pod.Namespace namespace := pod.Namespace
@ -542,7 +550,7 @@ func printPodBase(pod *api.Pod, w io.Writer, withNamespace bool, wide bool, show
reason := string(pod.Status.Phase) reason := string(pod.Status.Phase)
// if not printing all pods, skip terminated pods (default) // if not printing all pods, skip terminated pods (default)
if !showIfTerminating && !showAll && (reason == string(api.PodSucceeded) || reason == string(api.PodFailed)) { if !showIfTerminating && !options.showAll && (reason == string(api.PodSucceeded) || reason == string(api.PodFailed)) {
return nil return nil
} }
if pod.Status.Reason != "" { if pod.Status.Reason != "" {
@ -571,7 +579,7 @@ func printPodBase(pod *api.Pod, w io.Writer, withNamespace bool, wide bool, show
reason = "Terminating" reason = "Terminating"
} }
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -587,7 +595,7 @@ func printPodBase(pod *api.Pod, w io.Writer, withNamespace bool, wide bool, show
return err return err
} }
if wide { if options.wide {
nodeName := pod.Spec.NodeName nodeName := pod.Spec.NodeName
if _, err := fmt.Fprintf(w, "\t%s", if _, err := fmt.Fprintf(w, "\t%s",
nodeName, nodeName,
@ -596,20 +604,20 @@ func printPodBase(pod *api.Pod, w io.Writer, withNamespace bool, wide bool, show
} }
} }
_, err := fmt.Fprint(w, appendLabels(pod.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(pod.Labels, options.columnLabels))
return err return err
} }
func printPodList(podList *api.PodList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPodList(podList *api.PodList, w io.Writer, options printOptions) error {
for _, pod := range podList.Items { for _, pod := range podList.Items {
if err := printPodBase(&pod, w, withNamespace, wide, showAll, false, columnLabels); err != nil { if err := printPodBase(&pod, w, false, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printPodTemplate(pod *api.PodTemplate, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPodTemplate(pod *api.PodTemplate, w io.Writer, options printOptions) error {
name := pod.Name name := pod.Name
namespace := pod.Namespace namespace := pod.Namespace
@ -619,7 +627,7 @@ func printPodTemplate(pod *api.PodTemplate, w io.Writer, withNamespace bool, wid
firstContainer, containers = containers[0], containers[1:] firstContainer, containers = containers[0], containers[1:]
} }
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -632,13 +640,13 @@ func printPodTemplate(pod *api.PodTemplate, w io.Writer, withNamespace bool, wid
); err != nil { ); err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabels(pod.Labels, columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabels(pod.Labels, options.columnLabels)); err != nil {
return err return err
} }
// Lay out all the other containers on separate lines. // Lay out all the other containers on separate lines.
extraLinePrefix := "\t" extraLinePrefix := "\t"
if withNamespace { if options.withNamespace {
extraLinePrefix = "\t\t" extraLinePrefix = "\t\t"
} }
for _, container := range containers { for _, container := range containers {
@ -646,23 +654,23 @@ func printPodTemplate(pod *api.PodTemplate, w io.Writer, withNamespace bool, wid
if err != nil { if err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabelTabs(options.columnLabels)); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printPodTemplateList(podList *api.PodTemplateList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPodTemplateList(podList *api.PodTemplateList, w io.Writer, options printOptions) error {
for _, pod := range podList.Items { for _, pod := range podList.Items {
if err := printPodTemplate(&pod, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printPodTemplate(&pod, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printReplicationController(controller *api.ReplicationController, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printReplicationController(controller *api.ReplicationController, w io.Writer, options printOptions) error {
name := controller.Name name := controller.Name
namespace := controller.Namespace namespace := controller.Namespace
containers := controller.Spec.Template.Spec.Containers containers := controller.Spec.Template.Spec.Containers
@ -671,7 +679,7 @@ func printReplicationController(controller *api.ReplicationController, w io.Writ
firstContainer, containers = containers[0], containers[1:] firstContainer, containers = containers[0], containers[1:]
} }
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -686,13 +694,13 @@ func printReplicationController(controller *api.ReplicationController, w io.Writ
); err != nil { ); err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabels(controller.Labels, columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabels(controller.Labels, options.columnLabels)); err != nil {
return err return err
} }
// Lay out all the other containers on separate lines. // Lay out all the other containers on separate lines.
extraLinePrefix := "\t" extraLinePrefix := "\t"
if withNamespace { if options.withNamespace {
extraLinePrefix = "\t\t" extraLinePrefix = "\t\t"
} }
for _, container := range containers { for _, container := range containers {
@ -700,23 +708,23 @@ func printReplicationController(controller *api.ReplicationController, w io.Writ
if err != nil { if err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabelTabs(options.columnLabels)); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printReplicationControllerList(list *api.ReplicationControllerList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printReplicationControllerList(list *api.ReplicationControllerList, w io.Writer, options printOptions) error {
for _, controller := range list.Items { for _, controller := range list.Items {
if err := printReplicationController(&controller, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printReplicationController(&controller, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printJob(job *extensions.Job, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printJob(job *extensions.Job, w io.Writer, options printOptions) error {
name := job.Name name := job.Name
namespace := job.Namespace namespace := job.Namespace
containers := job.Spec.Template.Spec.Containers containers := job.Spec.Template.Spec.Containers
@ -724,7 +732,7 @@ func printJob(job *extensions.Job, w io.Writer, withNamespace bool, wide bool, s
if len(containers) > 0 { if len(containers) > 0 {
firstContainer, containers = containers[0], containers[1:] firstContainer, containers = containers[0], containers[1:]
} }
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -740,13 +748,13 @@ func printJob(job *extensions.Job, w io.Writer, withNamespace bool, wide bool, s
if err != nil { if err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabels(job.Labels, columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabels(job.Labels, options.columnLabels)); err != nil {
return err return err
} }
// Lay out all the other containers on separate lines. // Lay out all the other containers on separate lines.
extraLinePrefix := "\t" extraLinePrefix := "\t"
if withNamespace { if options.withNamespace {
extraLinePrefix = "\t\t" extraLinePrefix = "\t\t"
} }
for _, container := range containers { for _, container := range containers {
@ -754,16 +762,16 @@ func printJob(job *extensions.Job, w io.Writer, withNamespace bool, wide bool, s
if err != nil { if err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabelTabs(options.columnLabels)); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printJobList(list *extensions.JobList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printJobList(list *extensions.JobList, w io.Writer, options printOptions) error {
for _, job := range list.Items { for _, job := range list.Items {
if err := printJob(&job, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printJob(&job, w, options); err != nil {
return err return err
} }
} }
@ -814,14 +822,14 @@ func makePortString(ports []api.ServicePort) string {
return strings.Join(pieces, ",") return strings.Join(pieces, ",")
} }
func printService(svc *api.Service, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printService(svc *api.Service, w io.Writer, options printOptions) error {
name := svc.Name name := svc.Name
namespace := svc.Namespace namespace := svc.Namespace
internalIP := svc.Spec.ClusterIP internalIP := svc.Spec.ClusterIP
externalIP := getServiceExternalIP(svc) externalIP := getServiceExternalIP(svc)
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -836,15 +844,15 @@ func printService(svc *api.Service, w io.Writer, withNamespace bool, wide bool,
); err != nil { ); err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabels(svc.Labels, columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabels(svc.Labels, options.columnLabels)); err != nil {
return err return err
} }
return nil return nil
} }
func printServiceList(list *api.ServiceList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printServiceList(list *api.ServiceList, w io.Writer, options printOptions) error {
for _, svc := range list.Items { for _, svc := range list.Items {
if err := printService(&svc, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printService(&svc, w, options); err != nil {
return err return err
} }
} }
@ -859,12 +867,12 @@ func backendStringer(backend *extensions.IngressBackend) string {
return fmt.Sprintf("%v:%v", backend.ServiceName, backend.ServicePort.String()) return fmt.Sprintf("%v:%v", backend.ServiceName, backend.ServicePort.String())
} }
func printIngress(ingress *extensions.Ingress, w io.Writer, withNamespace, wide bool, showAll bool, columnLabels []string) error { func printIngress(ingress *extensions.Ingress, w io.Writer, options printOptions) error {
name := ingress.Name name := ingress.Name
namespace := ingress.Namespace namespace := ingress.Namespace
hostRules := ingress.Spec.Rules hostRules := ingress.Spec.Rules
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -880,7 +888,7 @@ func printIngress(ingress *extensions.Ingress, w io.Writer, withNamespace, wide
// Lay out all the rules on separate lines. // Lay out all the rules on separate lines.
extraLinePrefix := "" extraLinePrefix := ""
if withNamespace { if options.withNamespace {
extraLinePrefix = "\t" extraLinePrefix = "\t"
} }
for _, rules := range hostRules { for _, rules := range hostRules {
@ -891,7 +899,7 @@ func printIngress(ingress *extensions.Ingress, w io.Writer, withNamespace, wide
if err != nil { if err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabelTabs(options.columnLabels)); err != nil {
return err return err
} }
for _, rule := range rules.HTTP.Paths { for _, rule := range rules.HTTP.Paths {
@ -899,7 +907,7 @@ func printIngress(ingress *extensions.Ingress, w io.Writer, withNamespace, wide
if err != nil { if err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabelTabs(options.columnLabels)); err != nil {
return err return err
} }
} }
@ -907,16 +915,16 @@ func printIngress(ingress *extensions.Ingress, w io.Writer, withNamespace, wide
return nil return nil
} }
func printIngressList(ingressList *extensions.IngressList, w io.Writer, withNamespace, wide bool, showAll bool, columnLabels []string) error { func printIngressList(ingressList *extensions.IngressList, w io.Writer, options printOptions) error {
for _, ingress := range ingressList.Items { for _, ingress := range ingressList.Items {
if err := printIngress(&ingress, w, withNamespace, wide, true, columnLabels); err != nil { if err := printIngress(&ingress, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, options printOptions) error {
name := ds.Name name := ds.Name
namespace := ds.Namespace namespace := ds.Namespace
@ -926,7 +934,7 @@ func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, withNamespace bool, w
firstContainer, containers = containers[0], containers[1:] firstContainer, containers = containers[0], containers[1:]
} }
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -945,13 +953,13 @@ func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, withNamespace bool, w
); err != nil { ); err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabels(ds.Labels, columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabels(ds.Labels, options.columnLabels)); err != nil {
return err return err
} }
// Lay out all the other containers on separate lines. // Lay out all the other containers on separate lines.
extraLinePrefix := "\t" extraLinePrefix := "\t"
if withNamespace { if options.withNamespace {
extraLinePrefix = "\t\t" extraLinePrefix = "\t\t"
} }
for _, container := range containers { for _, container := range containers {
@ -959,27 +967,27 @@ func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, withNamespace bool, w
if err != nil { if err != nil {
return err return err
} }
if _, err := fmt.Fprint(w, appendLabelTabs(columnLabels)); err != nil { if _, err := fmt.Fprint(w, appendLabelTabs(options.columnLabels)); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printDaemonSetList(list *extensions.DaemonSetList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printDaemonSetList(list *extensions.DaemonSetList, w io.Writer, options printOptions) error {
for _, ds := range list.Items { for _, ds := range list.Items {
if err := printDaemonSet(&ds, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printDaemonSet(&ds, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printEndpoints(endpoints *api.Endpoints, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printEndpoints(endpoints *api.Endpoints, w io.Writer, options printOptions) error {
name := endpoints.Name name := endpoints.Name
namespace := endpoints.Namespace namespace := endpoints.Namespace
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -987,45 +995,45 @@ func printEndpoints(endpoints *api.Endpoints, w io.Writer, withNamespace bool, w
if _, err := fmt.Fprintf(w, "%s\t%s\t%s", name, formatEndpoints(endpoints, nil), translateTimestamp(endpoints.CreationTimestamp)); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%s", name, formatEndpoints(endpoints, nil), translateTimestamp(endpoints.CreationTimestamp)); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(endpoints.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(endpoints.Labels, options.columnLabels))
return err return err
} }
func printEndpointsList(list *api.EndpointsList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printEndpointsList(list *api.EndpointsList, w io.Writer, options printOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printEndpoints(&item, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printEndpoints(&item, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printNamespace(item *api.Namespace, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printNamespace(item *api.Namespace, w io.Writer, options printOptions) error {
if withNamespace { if options.withNamespace {
return fmt.Errorf("namespace is not namespaced") return fmt.Errorf("namespace is not namespaced")
} }
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", item.Name, labels.FormatLabels(item.Labels), item.Status.Phase, translateTimestamp(item.CreationTimestamp)); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", item.Name, labels.FormatLabels(item.Labels), item.Status.Phase, translateTimestamp(item.CreationTimestamp)); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(item.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(item.Labels, options.columnLabels))
return err return err
} }
func printNamespaceList(list *api.NamespaceList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printNamespaceList(list *api.NamespaceList, w io.Writer, options printOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printNamespace(&item, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printNamespace(&item, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printSecret(item *api.Secret, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printSecret(item *api.Secret, w io.Writer, options printOptions) error {
name := item.Name name := item.Name
namespace := item.Namespace namespace := item.Namespace
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -1033,13 +1041,13 @@ func printSecret(item *api.Secret, w io.Writer, withNamespace bool, wide bool, s
if _, err := fmt.Fprintf(w, "%s\t%s\t%v\t%s", name, item.Type, len(item.Data), translateTimestamp(item.CreationTimestamp)); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%v\t%s", name, item.Type, len(item.Data), translateTimestamp(item.CreationTimestamp)); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(item.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(item.Labels, options.columnLabels))
return err return err
} }
func printSecretList(list *api.SecretList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printSecretList(list *api.SecretList, w io.Writer, options printOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printSecret(&item, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printSecret(&item, w, options); err != nil {
return err return err
} }
} }
@ -1047,11 +1055,11 @@ func printSecretList(list *api.SecretList, w io.Writer, withNamespace bool, wide
return nil return nil
} }
func printServiceAccount(item *api.ServiceAccount, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printServiceAccount(item *api.ServiceAccount, w io.Writer, options printOptions) error {
name := item.Name name := item.Name
namespace := item.Namespace namespace := item.Namespace
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -1059,13 +1067,13 @@ func printServiceAccount(item *api.ServiceAccount, w io.Writer, withNamespace bo
if _, err := fmt.Fprintf(w, "%s\t%d\t%s", name, len(item.Secrets), translateTimestamp(item.CreationTimestamp)); err != nil { if _, err := fmt.Fprintf(w, "%s\t%d\t%s", name, len(item.Secrets), translateTimestamp(item.CreationTimestamp)); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(item.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(item.Labels, options.columnLabels))
return err return err
} }
func printServiceAccountList(list *api.ServiceAccountList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printServiceAccountList(list *api.ServiceAccountList, w io.Writer, options printOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printServiceAccount(&item, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printServiceAccount(&item, w, options); err != nil {
return err return err
} }
} }
@ -1073,8 +1081,8 @@ func printServiceAccountList(list *api.ServiceAccountList, w io.Writer, withName
return nil return nil
} }
func printNode(node *api.Node, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printNode(node *api.Node, w io.Writer, options printOptions) error {
if withNamespace { if options.withNamespace {
return fmt.Errorf("node is not namespaced") return fmt.Errorf("node is not namespaced")
} }
conditionMap := make(map[api.NodeConditionType]*api.NodeCondition) conditionMap := make(map[api.NodeConditionType]*api.NodeCondition)
@ -1103,21 +1111,21 @@ func printNode(node *api.Node, w io.Writer, withNamespace bool, wide bool, showA
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", node.Name, labels.FormatLabels(node.Labels), strings.Join(status, ","), translateTimestamp(node.CreationTimestamp)); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", node.Name, labels.FormatLabels(node.Labels), strings.Join(status, ","), translateTimestamp(node.CreationTimestamp)); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(node.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(node.Labels, options.columnLabels))
return err return err
} }
func printNodeList(list *api.NodeList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printNodeList(list *api.NodeList, w io.Writer, options printOptions) error {
for _, node := range list.Items { for _, node := range list.Items {
if err := printNode(&node, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printNode(&node, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, options printOptions) error {
if withNamespace { if options.withNamespace {
return fmt.Errorf("persistentVolume is not namespaced") return fmt.Errorf("persistentVolume is not namespaced")
} }
name := pv.Name name := pv.Name
@ -1145,24 +1153,24 @@ func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, withNamespace
); err != nil { ); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(pv.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(pv.Labels, options.columnLabels))
return err return err
} }
func printPersistentVolumeList(list *api.PersistentVolumeList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPersistentVolumeList(list *api.PersistentVolumeList, w io.Writer, options printOptions) error {
for _, pv := range list.Items { for _, pv := range list.Items {
if err := printPersistentVolume(&pv, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printPersistentVolume(&pv, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, options printOptions) error {
name := pvc.Name name := pvc.Name
namespace := pvc.Namespace namespace := pvc.Namespace
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -1182,30 +1190,41 @@ func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, wit
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s", name, labels, phase, pvc.Spec.VolumeName, capacity, accessModes, translateTimestamp(pvc.CreationTimestamp)); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s", name, labels, phase, pvc.Spec.VolumeName, capacity, accessModes, translateTimestamp(pvc.CreationTimestamp)); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(pvc.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(pvc.Labels, options.columnLabels))
return err return err
} }
func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, w io.Writer, options printOptions) error {
for _, psd := range list.Items { for _, psd := range list.Items {
if err := printPersistentVolumeClaim(&psd, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printPersistentVolumeClaim(&psd, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printEvent(event *api.Event, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printEvent(event *api.Event, w io.Writer, options printOptions) error {
namespace := event.Namespace namespace := event.Namespace
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
} }
// While watching event, we should print absolute time.
var FirstTimestamp, LastTimestamp string
if options.absoluteTimestamps {
FirstTimestamp = event.FirstTimestamp.String()
LastTimestamp = event.LastTimestamp.String()
} else {
FirstTimestamp = translateTimestamp(event.FirstTimestamp)
LastTimestamp = translateTimestamp(event.LastTimestamp)
}
if _, err := fmt.Fprintf( if _, err := fmt.Fprintf(
w, "%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s", w, "%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
translateTimestamp(event.FirstTimestamp), FirstTimestamp,
translateTimestamp(event.LastTimestamp), LastTimestamp,
event.Count, event.Count,
event.InvolvedObject.Name, event.InvolvedObject.Name,
event.InvolvedObject.Kind, event.InvolvedObject.Kind,
@ -1217,26 +1236,26 @@ func printEvent(event *api.Event, w io.Writer, withNamespace bool, wide bool, sh
); err != nil { ); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(event.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(event.Labels, options.columnLabels))
return err return err
} }
// Sorts and prints the EventList in a human-friendly format. // Sorts and prints the EventList in a human-friendly format.
func printEventList(list *api.EventList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printEventList(list *api.EventList, w io.Writer, options printOptions) error {
sort.Sort(SortableEvents(list.Items)) sort.Sort(SortableEvents(list.Items))
for i := range list.Items { for i := range list.Items {
if err := printEvent(&list.Items[i], w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printEvent(&list.Items[i], w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printLimitRange(limitRange *api.LimitRange, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printLimitRange(limitRange *api.LimitRange, w io.Writer, options printOptions) error {
name := limitRange.Name name := limitRange.Name
namespace := limitRange.Namespace namespace := limitRange.Namespace
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -1249,25 +1268,25 @@ func printLimitRange(limitRange *api.LimitRange, w io.Writer, withNamespace bool
); err != nil { ); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(limitRange.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(limitRange.Labels, options.columnLabels))
return err return err
} }
// Prints the LimitRangeList in a human-friendly format. // Prints the LimitRangeList in a human-friendly format.
func printLimitRangeList(list *api.LimitRangeList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printLimitRangeList(list *api.LimitRangeList, w io.Writer, options printOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printLimitRange(&list.Items[i], w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printLimitRange(&list.Items[i], w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printResourceQuota(resourceQuota *api.ResourceQuota, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printResourceQuota(resourceQuota *api.ResourceQuota, w io.Writer, options printOptions) error {
name := resourceQuota.Name name := resourceQuota.Name
namespace := resourceQuota.Namespace namespace := resourceQuota.Namespace
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -1280,22 +1299,22 @@ func printResourceQuota(resourceQuota *api.ResourceQuota, w io.Writer, withNames
); err != nil { ); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(resourceQuota.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(resourceQuota.Labels, options.columnLabels))
return err return err
} }
// Prints the ResourceQuotaList in a human-friendly format. // Prints the ResourceQuotaList in a human-friendly format.
func printResourceQuotaList(list *api.ResourceQuotaList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printResourceQuotaList(list *api.ResourceQuotaList, w io.Writer, options printOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printResourceQuota(&list.Items[i], w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printResourceQuota(&list.Items[i], w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printComponentStatus(item *api.ComponentStatus, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printComponentStatus(item *api.ComponentStatus, w io.Writer, options printOptions) error {
if withNamespace { if options.withNamespace {
return fmt.Errorf("componentStatus is not namespaced") return fmt.Errorf("componentStatus is not namespaced")
} }
status := "Unknown" status := "Unknown"
@ -1317,13 +1336,13 @@ func printComponentStatus(item *api.ComponentStatus, w io.Writer, withNamespace
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", item.Name, status, message, error); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", item.Name, status, message, error); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(item.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(item.Labels, options.columnLabels))
return err return err
} }
func printComponentStatusList(list *api.ComponentStatusList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printComponentStatusList(list *api.ComponentStatusList, w io.Writer, options printOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printComponentStatus(&item, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printComponentStatus(&item, w, options); err != nil {
return err return err
} }
} }
@ -1331,7 +1350,7 @@ func printComponentStatusList(list *api.ComponentStatusList, w io.Writer, withNa
return nil return nil
} }
func printThirdPartyResource(rsrc *extensions.ThirdPartyResource, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printThirdPartyResource(rsrc *extensions.ThirdPartyResource, w io.Writer, options printOptions) error {
versions := make([]string, len(rsrc.Versions)) versions := make([]string, len(rsrc.Versions))
for ix := range rsrc.Versions { for ix := range rsrc.Versions {
version := &rsrc.Versions[ix] version := &rsrc.Versions[ix]
@ -1344,9 +1363,9 @@ func printThirdPartyResource(rsrc *extensions.ThirdPartyResource, w io.Writer, w
return nil return nil
} }
func printThirdPartyResourceList(list *extensions.ThirdPartyResourceList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printThirdPartyResourceList(list *extensions.ThirdPartyResourceList, w io.Writer, options printOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printThirdPartyResource(&item, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printThirdPartyResource(&item, w, options); err != nil {
return err return err
} }
} }
@ -1354,8 +1373,8 @@ func printThirdPartyResourceList(list *extensions.ThirdPartyResourceList, w io.W
return nil return nil
} }
func printDeployment(deployment *extensions.Deployment, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printDeployment(deployment *extensions.Deployment, w io.Writer, options printOptions) error {
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", deployment.Namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", deployment.Namespace); err != nil {
return err return err
} }
@ -1366,20 +1385,20 @@ func printDeployment(deployment *extensions.Deployment, w io.Writer, withNamespa
if _, err := fmt.Fprintf(w, "%s\t%s\t%s", deployment.Name, updatedReplicas, age); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%s", deployment.Name, updatedReplicas, age); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(deployment.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(deployment.Labels, options.columnLabels))
return err return err
} }
func printDeploymentList(list *extensions.DeploymentList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printDeploymentList(list *extensions.DeploymentList, w io.Writer, options printOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printDeployment(&item, w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printDeployment(&item, w, options); err != nil {
return err return err
} }
} }
return nil return nil
} }
func printHorizontalPodAutoscaler(hpa *extensions.HorizontalPodAutoscaler, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printHorizontalPodAutoscaler(hpa *extensions.HorizontalPodAutoscaler, w io.Writer, options printOptions) error {
namespace := hpa.Namespace namespace := hpa.Namespace
name := hpa.Name name := hpa.Name
reference := fmt.Sprintf("%s/%s/%s", reference := fmt.Sprintf("%s/%s/%s",
@ -1399,7 +1418,7 @@ func printHorizontalPodAutoscaler(hpa *extensions.HorizontalPodAutoscaler, w io.
minPods = fmt.Sprintf("%d", *hpa.Spec.MinReplicas) minPods = fmt.Sprintf("%d", *hpa.Spec.MinReplicas)
} }
maxPods := hpa.Spec.MaxReplicas maxPods := hpa.Spec.MaxReplicas
if withNamespace { if options.withNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
return err return err
} }
@ -1416,13 +1435,13 @@ func printHorizontalPodAutoscaler(hpa *extensions.HorizontalPodAutoscaler, w io.
); err != nil { ); err != nil {
return err return err
} }
_, err := fmt.Fprint(w, appendLabels(hpa.Labels, columnLabels)) _, err := fmt.Fprint(w, appendLabels(hpa.Labels, options.columnLabels))
return err return err
} }
func printHorizontalPodAutoscalerList(list *extensions.HorizontalPodAutoscalerList, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func printHorizontalPodAutoscalerList(list *extensions.HorizontalPodAutoscalerList, w io.Writer, options printOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printHorizontalPodAutoscaler(&list.Items[i], w, withNamespace, wide, showAll, columnLabels); err != nil { if err := printHorizontalPodAutoscaler(&list.Items[i], w, options); err != nil {
return err return err
} }
} }
@ -1495,16 +1514,16 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
} }
t := reflect.TypeOf(obj) t := reflect.TypeOf(obj)
if handler := h.handlerMap[t]; handler != nil { if handler := h.handlerMap[t]; handler != nil {
if !h.noHeaders && t != h.lastType { if !h.options.noHeaders && t != h.lastType {
headers := append(handler.columns, formatWideHeaders(h.wide, t)...) headers := append(handler.columns, formatWideHeaders(h.options.wide, t)...)
headers = append(headers, formatLabelHeaders(h.columnLabels)...) headers = append(headers, formatLabelHeaders(h.options.columnLabels)...)
if h.withNamespace { if h.options.withNamespace {
headers = append(withNamespacePrefixColumns, headers...) headers = append(withNamespacePrefixColumns, headers...)
} }
h.printHeader(headers, w) h.printHeader(headers, w)
h.lastType = t h.lastType = t
} }
args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(w), reflect.ValueOf(h.withNamespace), reflect.ValueOf(h.wide), reflect.ValueOf(h.showAll), reflect.ValueOf(h.columnLabels)} args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(w), reflect.ValueOf(h.options)}
resultValue := handler.printFunc.Call(args)[0] resultValue := handler.printFunc.Call(args)[0]
if resultValue.IsNil() { if resultValue.IsNil() {
return nil return nil

View File

@ -213,18 +213,18 @@ func TestJSONPrinter(t *testing.T) {
testPrinter(t, &JSONPrinter{}, json.Unmarshal) testPrinter(t, &JSONPrinter{}, json.Unmarshal)
} }
func PrintCustomType(obj *TestPrintType, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func PrintCustomType(obj *TestPrintType, w io.Writer, options printOptions) error {
_, err := fmt.Fprintf(w, "%s", obj.Data) _, err := fmt.Fprintf(w, "%s", obj.Data)
return err return err
} }
func ErrorPrintHandler(obj *TestPrintType, w io.Writer, withNamespace bool, wide bool, showAll bool, columnLabels []string) error { func ErrorPrintHandler(obj *TestPrintType, w io.Writer, options printOptions) error {
return fmt.Errorf("ErrorPrintHandler error") return fmt.Errorf("ErrorPrintHandler error")
} }
func TestCustomTypePrinting(t *testing.T) { func TestCustomTypePrinting(t *testing.T) {
columns := []string{"Data"} columns := []string{"Data"}
printer := NewHumanReadablePrinter(false, false, false, false, []string{}) printer := NewHumanReadablePrinter(false, false, false, false, false, []string{})
printer.Handler(columns, PrintCustomType) printer.Handler(columns, PrintCustomType)
obj := TestPrintType{"test object"} obj := TestPrintType{"test object"}
@ -241,7 +241,7 @@ func TestCustomTypePrinting(t *testing.T) {
func TestPrintHandlerError(t *testing.T) { func TestPrintHandlerError(t *testing.T) {
columns := []string{"Data"} columns := []string{"Data"}
printer := NewHumanReadablePrinter(false, false, false, false, []string{}) printer := NewHumanReadablePrinter(false, false, false, false, false, []string{})
printer.Handler(columns, ErrorPrintHandler) printer.Handler(columns, ErrorPrintHandler)
obj := TestPrintType{"test object"} obj := TestPrintType{"test object"}
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
@ -252,7 +252,7 @@ func TestPrintHandlerError(t *testing.T) {
} }
func TestUnknownTypePrinting(t *testing.T) { func TestUnknownTypePrinting(t *testing.T) {
printer := NewHumanReadablePrinter(false, false, false, false, []string{}) printer := NewHumanReadablePrinter(false, false, false, false, false, []string{})
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
err := printer.PrintObj(&TestUnknownType{}, buffer) err := printer.PrintObj(&TestUnknownType{}, buffer)
if err == nil { if err == nil {
@ -456,8 +456,8 @@ func TestPrinters(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
printers := map[string]ResourcePrinter{ printers := map[string]ResourcePrinter{
"humanReadable": NewHumanReadablePrinter(true, false, false, false, []string{}), "humanReadable": NewHumanReadablePrinter(true, false, false, false, false, []string{}),
"humanReadableHeaders": NewHumanReadablePrinter(false, false, false, false, []string{}), "humanReadableHeaders": NewHumanReadablePrinter(false, false, false, false, false, []string{}),
"json": &JSONPrinter{}, "json": &JSONPrinter{},
"yaml": &YAMLPrinter{}, "yaml": &YAMLPrinter{},
"template": templatePrinter, "template": templatePrinter,
@ -497,7 +497,7 @@ func TestPrinters(t *testing.T) {
func TestPrintEventsResultSorted(t *testing.T) { func TestPrintEventsResultSorted(t *testing.T) {
// Arrange // Arrange
printer := NewHumanReadablePrinter(false /* noHeaders */, false, false, false, []string{}) printer := NewHumanReadablePrinter(false /* noHeaders */, false, false, false, false, []string{})
obj := api.EventList{ obj := api.EventList{
Items: []api.Event{ Items: []api.Event{
@ -541,7 +541,7 @@ func TestPrintEventsResultSorted(t *testing.T) {
} }
func TestPrintNodeStatus(t *testing.T) { func TestPrintNodeStatus(t *testing.T) {
printer := NewHumanReadablePrinter(false, false, false, false, []string{}) printer := NewHumanReadablePrinter(false, false, false, false, false, []string{})
table := []struct { table := []struct {
node api.Node node api.Node
status string status string
@ -752,7 +752,7 @@ func TestPrintHumanReadableService(t *testing.T) {
for _, svc := range tests { for _, svc := range tests {
buff := bytes.Buffer{} buff := bytes.Buffer{}
printService(&svc, &buff, false, false, false, []string{}) printService(&svc, &buff, printOptions{false, false, false, false, false, []string{}})
output := string(buff.Bytes()) output := string(buff.Bytes())
ip := svc.Spec.ClusterIP ip := svc.Spec.ClusterIP
if !strings.Contains(output, ip) { if !strings.Contains(output, ip) {
@ -934,7 +934,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) {
for _, test := range table { for _, test := range table {
if test.isNamespaced { if test.isNamespaced {
// Expect output to include namespace when requested. // Expect output to include namespace when requested.
printer := NewHumanReadablePrinter(false, true, false, false, []string{}) printer := NewHumanReadablePrinter(false, true, false, false, false, []string{})
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
err := printer.PrintObj(test.obj, buffer) err := printer.PrintObj(test.obj, buffer)
if err != nil { if err != nil {
@ -946,7 +946,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) {
} }
} else { } else {
// Expect error when trying to get all namespaces for un-namespaced object. // Expect error when trying to get all namespaces for un-namespaced object.
printer := NewHumanReadablePrinter(false, true, false, false, []string{}) printer := NewHumanReadablePrinter(false, true, false, false, false, []string{})
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
err := printer.PrintObj(test.obj, buffer) err := printer.PrintObj(test.obj, buffer)
if err == nil { if err == nil {
@ -1041,7 +1041,7 @@ func TestPrintPod(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printPod(&test.pod, buf, false, false, true, []string{}) printPod(&test.pod, buf, printOptions{false, false, false, true, false, []string{}})
// We ignore time // We ignore time
if !strings.HasPrefix(buf.String(), test.expect) { if !strings.HasPrefix(buf.String(), test.expect) {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
@ -1134,7 +1134,7 @@ func TestPrintNonTerminatedPod(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printPod(&test.pod, buf, false, false, false, []string{}) printPod(&test.pod, buf, printOptions{false, false, false, false, false, []string{}})
// We ignore time // We ignore time
if !strings.HasPrefix(buf.String(), test.expect) { if !strings.HasPrefix(buf.String(), test.expect) {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
@ -1194,7 +1194,7 @@ func TestPrintPodWithLabels(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printPod(&test.pod, buf, false, false, false, test.labelColumns) printPod(&test.pod, buf, printOptions{false, false, false, false, false, test.labelColumns})
// We ignore time // We ignore time
if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) { if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) {
t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String()) t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String())
@ -1255,7 +1255,7 @@ func TestPrintDeployment(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printDeployment(&test.deployment, buf, false, false, true, []string{}) printDeployment(&test.deployment, buf, printOptions{false, false, false, true, false, []string{}})
if buf.String() != test.expect { if buf.String() != test.expect {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
} }