github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/control/controldisplay/table.go (about) 1 package controldisplay 2 3 import ( 4 "strings" 5 6 "github.com/spf13/viper" 7 "github.com/turbot/steampipe/pkg/constants" 8 "github.com/turbot/steampipe/pkg/control/controlexecute" 9 ) 10 11 type TableRenderer struct { 12 resultTree *controlexecute.ExecutionTree 13 14 // screen width 15 width int 16 maxFailedControls int 17 maxTotalControls int 18 } 19 20 func NewTableRenderer(resultTree *controlexecute.ExecutionTree) *TableRenderer { 21 return &TableRenderer{ 22 resultTree: resultTree, 23 maxFailedControls: resultTree.Root.Summary.Status.FailedCount(), 24 maxTotalControls: resultTree.Root.Summary.Status.TotalCount(), 25 } 26 } 27 28 // MinimumWidth is the width we require 29 // It is determined by the left indent, title, severity, counter and counter graph 30 func (r TableRenderer) MinimumWidth() int { 31 minimumWidthRequired := r.maxIndent() + minimumGroupTitleWidth + severityMaxLen + minimumCounterWidth + counterGraphSegments 32 return minimumWidthRequired 33 } 34 35 func (r TableRenderer) maxIndent() int { 36 depth := r.groupDepth(r.resultTree.Root, 0) 37 // each indent level is "| " or "+ " (2 characters) 38 return (depth * 2) 39 } 40 41 func (r TableRenderer) groupDepth(g *controlexecute.ResultGroup, myDepth int) int { 42 if len(g.Groups) == 0 { 43 return 0 44 } 45 maxDepth := 0 46 for _, subGroup := range g.Groups { 47 branchDepth := r.groupDepth(subGroup, myDepth+1) 48 if branchDepth > maxDepth { 49 maxDepth = branchDepth 50 } 51 } 52 return myDepth + maxDepth 53 } 54 55 func (r TableRenderer) Render(width int) string { 56 r.width = width 57 58 // the buffer to put the output data in 59 builder := strings.Builder{} 60 61 builder.WriteString(r.renderResult()) 62 builder.WriteString("\n") 63 builder.WriteString(r.renderSummary()) 64 65 return builder.String() 66 } 67 68 func (r TableRenderer) renderSummary() string { 69 // no need to render the summary when the dry-run flag is set 70 if viper.GetBool(constants.ArgDryRun) { 71 return "" 72 } 73 return NewSummaryRenderer(r.resultTree, r.width).Render() 74 } 75 76 func (r TableRenderer) renderResult() string { 77 return NewGroupRenderer(r.resultTree.Root, nil, r.maxFailedControls, r.maxTotalControls, r.resultTree, r.width).Render() 78 }