github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/terraform/executor/statistics.go (about)

     1  package executor
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"sort"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/aquasecurity/defsec/pkg/scan"
    12  	"github.com/olekukonko/tablewriter"
    13  )
    14  
    15  type StatisticsItem struct {
    16  	RuleID          string   `json:"rule_id"`
    17  	RuleDescription string   `json:"rule_description"`
    18  	Links           []string `json:"links"`
    19  	Count           int      `json:"count"`
    20  }
    21  
    22  type Statistics []StatisticsItem
    23  
    24  type StatisticsResult struct {
    25  	Result Statistics `json:"results"`
    26  }
    27  
    28  func SortStatistics(statistics Statistics) Statistics {
    29  	sort.Slice(statistics, func(i, j int) bool {
    30  		return statistics[i].Count > statistics[j].Count
    31  	})
    32  	return statistics
    33  }
    34  
    35  func (statistics Statistics) PrintStatisticsTable(format string, w io.Writer) error {
    36  	// lovely is the default so we keep it like that
    37  	if format != "lovely" && format != "markdown" && format != "json" {
    38  		return fmt.Errorf("you must specify only lovely, markdown or json format with --run-statistics")
    39  	}
    40  
    41  	sorted := SortStatistics(statistics)
    42  
    43  	if format == "json" {
    44  		result := StatisticsResult{Result: sorted}
    45  		val, err := json.MarshalIndent(result, "", "    ")
    46  		if err != nil {
    47  			return err
    48  		}
    49  
    50  		_, _ = fmt.Fprintln(w, string(val))
    51  
    52  		return nil
    53  	}
    54  
    55  	table := tablewriter.NewWriter(w)
    56  	table.SetHeader([]string{"Rule ID", "Description", "Link", "Count"})
    57  	table.SetRowLine(true)
    58  
    59  	if format == "markdown" {
    60  		table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false})
    61  		table.SetCenterSeparator("|")
    62  	}
    63  
    64  	for _, item := range sorted {
    65  		table.Append([]string{item.RuleID,
    66  			item.RuleDescription,
    67  			strings.Join(item.Links, "\n"),
    68  			strconv.Itoa(item.Count)})
    69  	}
    70  
    71  	table.Render()
    72  
    73  	return nil
    74  }
    75  
    76  func AddStatisticsCount(statistics Statistics, result scan.Result) Statistics {
    77  	for i, statistic := range statistics {
    78  		if statistic.RuleID == result.Rule().LongID() {
    79  			statistics[i].Count += 1
    80  			return statistics
    81  		}
    82  	}
    83  	statistics = append(statistics, StatisticsItem{
    84  		RuleID:          result.Rule().LongID(),
    85  		RuleDescription: result.Rule().Summary,
    86  		Links:           result.Rule().Links,
    87  		Count:           1,
    88  	})
    89  
    90  	return statistics
    91  }