in cli/scorecard/score.go [175:289]
func writeResults(config *ScoringConfig, dest io.Writer, outputFormat string, outputMetadataFields []string) error {
switch outputFormat {
case "json":
var richViolations []*RichViolation
for _, category := range config.categories {
for _, cv := range category.constraints {
for _, v := range cv.Violations {
v.Category = category.Name
if len(outputMetadataFields) > 0 {
newMetadata := make(map[string]interface{})
oldMetadata := v.Metadata.GetStructValue().Fields["details"].GetStructValue()
for _, field := range outputMetadataFields {
newMetadata[field], _ = interfaceViaJSON(oldMetadata.Fields[field])
}
err := protoViaJSON(newMetadata, v.Metadata)
if err != nil {
return err
}
}
richViolations = append(richViolations, v)
Log.Debug("violation metadata", "metadata", v.GetMetadata())
}
}
}
byteContent, err := json.MarshalIndent(richViolations, "", " ")
if err != nil {
return err
}
_, err = io.WriteString(dest, string(byteContent)+"\n")
if err != nil {
return err
}
return nil
case "csv":
w := csv.NewWriter(dest)
header := []string{"Category", "Constraint", "Resource", "Message", "Parent"}
header = append(header, outputMetadataFields...)
err := w.Write(header)
if err != nil {
return err
}
w.Flush()
for _, category := range config.categories {
for _, cv := range category.constraints {
for _, v := range cv.Violations {
parent := ""
if len(v.asset.Ancestors) > 0 {
parent = v.asset.Ancestors[0]
}
record := []string{category.Name, getConstraintShortName(v.Constraint), v.Resource, v.Message, parent}
for _, field := range outputMetadataFields {
metadata := v.Metadata.GetStructValue().Fields["details"].GetStructValue().Fields[field]
value, _ := stringViaJSON(metadata)
record = append(record, value)
}
err := w.Write(record)
if err != nil {
return err
}
w.Flush()
Log.Debug("Violation metadata", "metadata", v.GetMetadata())
}
}
}
return nil
case "txt":
_, err := io.WriteString(dest, fmt.Sprintf("\n\n%v total issues found\n", config.CountViolations()))
if err != nil {
return err
}
for _, category := range config.categories {
_, err = io.WriteString(dest, fmt.Sprintf("\n\n%v: %v issues found\n", category.Name, category.Count()))
if err != nil {
return err
}
_, err = io.WriteString(dest, "----------\n")
if err != nil {
return err
}
for _, cv := range category.constraints {
_, err = io.WriteString(dest, fmt.Sprintf("%v: %v issues\n", getConstraintShortName(cv.constraint), cv.Count()))
if err != nil {
return err
}
for _, v := range cv.Violations {
_, err = io.WriteString(dest, fmt.Sprintf("- %v\n", v.Message))
if err != nil {
return err
}
for _, field := range outputMetadataFields {
metadata := v.Metadata.GetStructValue().Fields["details"].GetStructValue().Fields[field]
value, _ := stringViaJSON(metadata)
if value != "" {
_, err = io.WriteString(dest, fmt.Sprintf(" %v: %v\n", field, value))
if err != nil {
return err
}
}
}
_, err = io.WriteString(dest, "\n")
if err != nil {
return err
}
Log.Debug("Violation metadata", "metadata", v.GetMetadata())
}
}
}
return nil
}
return fmt.Errorf("unsupported output format %v", outputFormat)
}