...

Source file src/sigs.k8s.io/cli-utils/pkg/print/list/base.go

Documentation: sigs.k8s.io/cli-utils/pkg/print/list

     1  // Copyright 2020 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package list
     5  
     6  import (
     7  	"sigs.k8s.io/cli-utils/pkg/apply/event"
     8  	"sigs.k8s.io/cli-utils/pkg/common"
     9  	"sigs.k8s.io/cli-utils/pkg/object"
    10  	printcommon "sigs.k8s.io/cli-utils/pkg/print/common"
    11  	"sigs.k8s.io/cli-utils/pkg/print/stats"
    12  )
    13  
    14  type Formatter interface {
    15  	FormatValidationEvent(ve event.ValidationEvent) error
    16  	FormatApplyEvent(ae event.ApplyEvent) error
    17  	FormatStatusEvent(se event.StatusEvent) error
    18  	FormatPruneEvent(pe event.PruneEvent) error
    19  	FormatDeleteEvent(de event.DeleteEvent) error
    20  	FormatWaitEvent(we event.WaitEvent) error
    21  	FormatErrorEvent(ee event.ErrorEvent) error
    22  	FormatActionGroupEvent(
    23  		age event.ActionGroupEvent,
    24  		ags []event.ActionGroup,
    25  		s stats.Stats,
    26  		c Collector,
    27  	) error
    28  	FormatSummary(s stats.Stats) error
    29  }
    30  
    31  type FormatterFactory func(previewStrategy common.DryRunStrategy) Formatter
    32  
    33  type BaseListPrinter struct {
    34  	FormatterFactory FormatterFactory
    35  }
    36  
    37  type Collector interface {
    38  	LatestStatus() map[object.ObjMetadata]event.StatusEvent
    39  }
    40  
    41  type StatusCollector struct {
    42  	latestStatus map[object.ObjMetadata]event.StatusEvent
    43  }
    44  
    45  func (sc *StatusCollector) updateStatus(id object.ObjMetadata, se event.StatusEvent) {
    46  	sc.latestStatus[id] = se
    47  }
    48  
    49  func (sc *StatusCollector) LatestStatus() map[object.ObjMetadata]event.StatusEvent {
    50  	return sc.latestStatus
    51  }
    52  
    53  // Print outputs the events from the provided channel in a simple
    54  // format on StdOut. As we support other printer implementations
    55  // this should probably be an interface.
    56  // This function will block until the channel is closed.
    57  //
    58  //nolint:gocyclo
    59  func (b *BaseListPrinter) Print(ch <-chan event.Event, previewStrategy common.DryRunStrategy, printStatus bool) error {
    60  	var actionGroups []event.ActionGroup
    61  	var statsCollector stats.Stats
    62  	statusCollector := &StatusCollector{
    63  		latestStatus: make(map[object.ObjMetadata]event.StatusEvent),
    64  	}
    65  	formatter := b.FormatterFactory(previewStrategy)
    66  	for e := range ch {
    67  		statsCollector.Handle(e)
    68  		switch e.Type {
    69  		case event.InitType:
    70  			actionGroups = e.InitEvent.ActionGroups
    71  		case event.ErrorType:
    72  			_ = formatter.FormatErrorEvent(e.ErrorEvent)
    73  			return e.ErrorEvent.Err
    74  		case event.ValidationType:
    75  			if err := formatter.FormatValidationEvent(e.ValidationEvent); err != nil {
    76  				return err
    77  			}
    78  		case event.ApplyType:
    79  			if err := formatter.FormatApplyEvent(e.ApplyEvent); err != nil {
    80  				return err
    81  			}
    82  		case event.StatusType:
    83  			statusCollector.updateStatus(e.StatusEvent.Identifier, e.StatusEvent)
    84  			if printStatus {
    85  				if err := formatter.FormatStatusEvent(e.StatusEvent); err != nil {
    86  					return err
    87  				}
    88  			}
    89  		case event.PruneType:
    90  			if err := formatter.FormatPruneEvent(e.PruneEvent); err != nil {
    91  				return err
    92  			}
    93  		case event.DeleteType:
    94  			if err := formatter.FormatDeleteEvent(e.DeleteEvent); err != nil {
    95  				return err
    96  			}
    97  		case event.WaitType:
    98  			if err := formatter.FormatWaitEvent(e.WaitEvent); err != nil {
    99  				return err
   100  			}
   101  		case event.ActionGroupType:
   102  			if err := formatter.FormatActionGroupEvent(
   103  				e.ActionGroupEvent,
   104  				actionGroups,
   105  				statsCollector,
   106  				statusCollector,
   107  			); err != nil {
   108  				return err
   109  			}
   110  		}
   111  	}
   112  
   113  	if err := formatter.FormatSummary(statsCollector); err != nil {
   114  		return err
   115  	}
   116  	return printcommon.ResultErrorFromStats(statsCollector)
   117  }
   118  
   119  // IsLastActionGroup returns true if the passed ActionGroupEvent is the
   120  // last of its type in the slice of ActionGroup; false otherwise. For example,
   121  // this function will determine if an ApplyAction is the last ApplyAction in
   122  // the initialized task queue. This functionality is current used to determine
   123  // when to print stats.
   124  func IsLastActionGroup(age event.ActionGroupEvent, ags []event.ActionGroup) bool {
   125  	var found bool
   126  	var action event.ResourceAction
   127  	for _, ag := range ags {
   128  		if found && (action == ag.Action) {
   129  			return false
   130  		}
   131  		if age.GroupName == ag.Name {
   132  			found = true
   133  			action = age.Action
   134  		}
   135  	}
   136  	return true
   137  }
   138  

View as plain text