diff --git a/cmd/status/cmdstatus.go b/cmd/status/cmdstatus.go index 28f87d5d..83b138be 100644 --- a/cmd/status/cmdstatus.go +++ b/cmd/status/cmdstatus.go @@ -13,6 +13,7 @@ import ( cmdutil "k8s.io/kubectl/pkg/cmd/util" "sigs.k8s.io/cli-utils/cmd/flagutils" "sigs.k8s.io/cli-utils/cmd/status/printers" + "sigs.k8s.io/cli-utils/cmd/status/printers/printer" "sigs.k8s.io/cli-utils/pkg/apply/poller" "sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/inventory" @@ -22,6 +23,7 @@ import ( "sigs.k8s.io/cli-utils/pkg/kstatus/polling/event" "sigs.k8s.io/cli-utils/pkg/kstatus/status" "sigs.k8s.io/cli-utils/pkg/manifestreader" + "sigs.k8s.io/cli-utils/pkg/object" ) func GetRunner(factory cmdutil.Factory, invFactory inventory.ClientFactory, loader manifestreader.ManifestLoader) *Runner { @@ -109,6 +111,18 @@ func (r *Runner) runE(cmd *cobra.Command, args []string) error { return nil } + // initialize maps in printData + printData := printer.PrintData{ + InvNameMap: make(map[object.ObjMetadata]string), + StatusSet: make(map[string]bool), + } + for _, obj := range identifiers { + // add to the map for future reference + printData.InvNameMap[obj] = inv.Name() + // append to identifiers + printData.Identifiers = append(printData.Identifiers, obj) + } + statusPoller, err := r.pollerFactoryFunc(r.factory) if err != nil { return err @@ -120,7 +134,7 @@ func (r *Runner) runE(cmd *cobra.Command, args []string) error { In: cmd.InOrStdin(), Out: cmd.OutOrStdout(), ErrOut: cmd.ErrOrStderr(), - }) + }, &printData) if err != nil { return fmt.Errorf("error creating printer: %w", err) } diff --git a/cmd/status/cmdstatus_test.go b/cmd/status/cmdstatus_test.go index a1375296..47702b8b 100644 --- a/cmd/status/cmdstatus_test.go +++ b/cmd/status/cmdstatus_test.go @@ -99,8 +99,8 @@ func TestCommand(t *testing.T) { }, }, expectedOutput: ` -deployment.apps/foo is InProgress: inProgress -statefulset.apps/bar is Current: current +foo/deployment.apps/default/foo is InProgress: inProgress +foo/statefulset.apps/default/bar is Current: current `, }, "wait for all current": { @@ -146,10 +146,10 @@ statefulset.apps/bar is Current: current }, }, expectedOutput: ` -deployment.apps/foo is InProgress: inProgress -statefulset.apps/bar is InProgress: inProgress -statefulset.apps/bar is Current: current -deployment.apps/foo is Current: current +foo/deployment.apps/default/foo is InProgress: inProgress +foo/statefulset.apps/default/bar is InProgress: inProgress +foo/statefulset.apps/default/bar is Current: current +foo/deployment.apps/default/foo is Current: current `, }, "wait for all deleted": { @@ -179,8 +179,8 @@ deployment.apps/foo is Current: current }, }, expectedOutput: ` -statefulset.apps/bar is NotFound: notFound -deployment.apps/foo is NotFound: notFound +foo/statefulset.apps/default/bar is NotFound: notFound +foo/deployment.apps/default/foo is NotFound: notFound `, }, "forever with timeout": { @@ -211,8 +211,8 @@ deployment.apps/foo is NotFound: notFound }, }, expectedOutput: ` -statefulset.apps/bar is InProgress: inProgress -deployment.apps/foo is InProgress: inProgress +foo/statefulset.apps/default/bar is InProgress: inProgress +foo/deployment.apps/default/foo is InProgress: inProgress `, }, } diff --git a/cmd/status/printers/event/printer.go b/cmd/status/printers/event/printer.go index c500911d..6cc57dd1 100644 --- a/cmd/status/printers/event/printer.go +++ b/cmd/status/printers/event/printer.go @@ -7,23 +7,31 @@ import ( "fmt" "strings" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/cli-runtime/pkg/genericclioptions" + "sigs.k8s.io/cli-utils/cmd/status/printers/printer" + "sigs.k8s.io/cli-utils/pkg/apply/event" + "sigs.k8s.io/cli-utils/pkg/common" "sigs.k8s.io/cli-utils/pkg/kstatus/polling/collector" pollevent "sigs.k8s.io/cli-utils/pkg/kstatus/polling/event" "sigs.k8s.io/cli-utils/pkg/object" + "sigs.k8s.io/cli-utils/pkg/print/list" + "sigs.k8s.io/cli-utils/pkg/printers/events" ) // Printer implements the Printer interface and outputs the resource // status information as a list of events as they happen. type Printer struct { + Formatter list.Formatter IOStreams genericclioptions.IOStreams + Data *printer.PrintData } // NewPrinter returns a new instance of the eventPrinter. -func NewPrinter(ioStreams genericclioptions.IOStreams) *Printer { +func NewPrinter(ioStreams genericclioptions.IOStreams, printData *printer.PrintData) *Printer { return &Printer{ + Formatter: events.NewFormatter(ioStreams, common.DryRunNone), IOStreams: ioStreams, + Data: printData, } } @@ -40,7 +48,10 @@ func (ep *Printer) Print(ch <-chan pollevent.Event, identifiers object.ObjMetada // stopping the poller at the correct time. done := coll.ListenWithObserver(ch, collector.ObserverFunc( func(statusCollector *collector.ResourceStatusCollector, e pollevent.Event) { - ep.printStatusEvent(e) + err := ep.printStatusEvent(e) + if err != nil { + panic(err) + } cancelFunc(statusCollector, e) }), ) @@ -52,25 +63,27 @@ func (ep *Printer) Print(ch <-chan pollevent.Event, identifiers object.ObjMetada return err } -func (ep *Printer) printStatusEvent(se pollevent.Event) { +func (ep *Printer) printStatusEvent(se pollevent.Event) error { switch se.Type { case pollevent.ResourceUpdateEvent: id := se.Resource.Identifier - printResourceStatus(id, se, ep.IOStreams) + var invName string + var ok bool + if invName, ok = ep.Data.InvNameMap[id]; !ok { + return fmt.Errorf("%s: resource not found", id) + } + // filter out status that are not assigned + statusString := se.Resource.Status.String() + if _, ok := ep.Data.StatusSet[strings.ToLower(statusString)]; len(ep.Data.StatusSet) != 0 && !ok { + return nil + } + _, err := fmt.Fprintf(ep.IOStreams.Out, "%s/%s/%s/%s is %s: %s\n", invName, + strings.ToLower(id.GroupKind.String()), id.Namespace, id.Name, statusString, se.Resource.Message) + return err case pollevent.ErrorEvent: - id := se.Resource.Identifier - gk := id.GroupKind - fmt.Fprintf(ep.IOStreams.Out, "%s error: %s\n", resourceIDToString(gk, id.Name), - se.Error.Error()) + return ep.Formatter.FormatErrorEvent(event.ErrorEvent{ + Err: se.Error, + }) } -} - -// resourceIDToString returns the string representation of a GroupKind and a resource name. -func resourceIDToString(gk schema.GroupKind, name string) string { - return fmt.Sprintf("%s/%s", strings.ToLower(gk.String()), name) -} - -func printResourceStatus(id object.ObjMetadata, se pollevent.Event, ioStreams genericclioptions.IOStreams) { - fmt.Fprintf(ioStreams.Out, "%s is %s: %s\n", resourceIDToString(id.GroupKind, id.Name), - se.Resource.Status.String(), se.Resource.Message) + return nil } diff --git a/cmd/status/printers/printer/printer.go b/cmd/status/printers/printer/printer.go index 33a22ee5..b89a4bc3 100644 --- a/cmd/status/printers/printer/printer.go +++ b/cmd/status/printers/printer/printer.go @@ -9,6 +9,13 @@ import ( "sigs.k8s.io/cli-utils/pkg/object" ) +// PrintData records data required for printing +type PrintData struct { + Identifiers object.ObjMetadataSet + InvNameMap map[object.ObjMetadata]string + StatusSet map[string]bool +} + // Printer defines an interface for outputting information about status of // resources. Different implementations allow output formats tailored to // different use cases. diff --git a/cmd/status/printers/printers.go b/cmd/status/printers/printers.go index 5c638246..2751dc75 100644 --- a/cmd/status/printers/printers.go +++ b/cmd/status/printers/printers.go @@ -4,20 +4,19 @@ package printers import ( + "k8s.io/cli-runtime/pkg/genericclioptions" "sigs.k8s.io/cli-utils/cmd/status/printers/event" "sigs.k8s.io/cli-utils/cmd/status/printers/printer" "sigs.k8s.io/cli-utils/cmd/status/printers/table" - - "k8s.io/cli-runtime/pkg/genericclioptions" ) // CreatePrinter return an implementation of the Printer interface. The // actual implementation is based on the printerType requested. -func CreatePrinter(printerType string, ioStreams genericclioptions.IOStreams) (printer.Printer, error) { +func CreatePrinter(printerType string, ioStreams genericclioptions.IOStreams, printData *printer.PrintData) (printer.Printer, error) { switch printerType { case "table": return table.NewPrinter(ioStreams), nil default: - return event.NewPrinter(ioStreams), nil + return event.NewPrinter(ioStreams, printData), nil } }