go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/cli/reporter/reporter.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package reporter
     5  
     6  import (
     7  	"bytes"
     8  	"errors"
     9  	"io"
    10  	"sort"
    11  	"strings"
    12  
    13  	"go.mondoo.com/cnquery/logger"
    14  	"sigs.k8s.io/yaml"
    15  
    16  	"go.mondoo.com/cnquery/cli/printer"
    17  	"go.mondoo.com/cnquery/cli/theme/colors"
    18  	"go.mondoo.com/cnquery/explorer"
    19  	"go.mondoo.com/cnquery/shared"
    20  )
    21  
    22  type Format byte
    23  
    24  const (
    25  	Compact Format = iota + 1
    26  	Summary
    27  	Full
    28  	YAML
    29  	JSON
    30  	JUnit
    31  	CSV
    32  )
    33  
    34  // Formats that are supported by the reporter
    35  var Formats = map[string]Format{
    36  	"compact": Compact,
    37  	"summary": Summary,
    38  	"full":    Full,
    39  	"":        Compact,
    40  	"yaml":    YAML,
    41  	"yml":     YAML,
    42  	"json":    JSON,
    43  	"csv":     CSV,
    44  }
    45  
    46  func AllFormats() string {
    47  	var res []string
    48  	for k := range Formats {
    49  		if k != "" && // default if nothing is provided, ignore
    50  			k != "yml" { // don't show both yaml and yml
    51  			res = append(res, k)
    52  		}
    53  	}
    54  
    55  	// ensure the order is always the same
    56  	sort.Strings(res)
    57  	return strings.Join(res, ", ")
    58  }
    59  
    60  type Reporter struct {
    61  	Format      Format
    62  	Printer     *printer.Printer
    63  	Colors      *colors.Theme
    64  	IsIncognito bool
    65  	IsVerbose   bool
    66  }
    67  
    68  func New(typ string) (*Reporter, error) {
    69  	format, ok := Formats[strings.ToLower(typ)]
    70  	if !ok {
    71  		return nil, errors.New("unknown output format '" + typ + "'. Available: " + AllFormats())
    72  	}
    73  
    74  	return &Reporter{
    75  		Format:  format,
    76  		Printer: &printer.DefaultPrinter,
    77  		Colors:  &colors.DefaultColorTheme,
    78  	}, nil
    79  }
    80  
    81  func (r *Reporter) Print(data *explorer.ReportCollection, out io.Writer) error {
    82  	logger.DebugDumpYAML("report_collection", data)
    83  	switch r.Format {
    84  	case Compact:
    85  		rr := &cliReporter{
    86  			Reporter:  r,
    87  			isCompact: true,
    88  			out:       out,
    89  			data:      data,
    90  		}
    91  		return rr.print()
    92  	case Summary:
    93  		rr := &cliReporter{
    94  			Reporter:  r,
    95  			isCompact: true,
    96  			isSummary: true,
    97  			out:       out,
    98  			data:      data,
    99  		}
   100  		return rr.print()
   101  	case Full:
   102  		rr := &cliReporter{
   103  			Reporter:  r,
   104  			isCompact: false,
   105  			out:       out,
   106  			data:      data,
   107  		}
   108  		return rr.print()
   109  	case JSON:
   110  		w := shared.IOWriter{Writer: out}
   111  		return ReportCollectionToJSON(data, &w)
   112  	case CSV:
   113  		w := shared.IOWriter{Writer: out}
   114  		return ReportCollectionToCSV(data, &w)
   115  	case YAML:
   116  		raw := bytes.Buffer{}
   117  		writer := shared.IOWriter{Writer: &raw}
   118  		err := ReportCollectionToJSON(data, &writer)
   119  		if err != nil {
   120  			return err
   121  		}
   122  
   123  		json, err := yaml.JSONToYAML(raw.Bytes())
   124  		if err != nil {
   125  			return err
   126  		}
   127  		_, err = out.Write(json)
   128  		return err
   129  	default:
   130  		return errors.New("unknown reporter type, don't recognize this Format")
   131  	}
   132  }