-
Notifications
You must be signed in to change notification settings - Fork 100
/
writer.go
141 lines (125 loc) · 3.17 KB
/
writer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package report
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"html"
"io"
"io/ioutil"
"os"
"strings"
"text/template"
"time"
"github.com/controlplaneio/kubesec/v2/pkg/ruler"
)
// Heavily based on aquasecurity/trivy's reporter
// Now returns the current time
var Now = time.Now
type reports ruler.Reports
// WriteReports writes the result to output, format as passed in argument
func WriteReports(format string, output io.Writer, reports reports, outputTemplate string) error {
var writer Writer
switch format {
case "json":
writer = &JSONWriter{Output: output}
case "template":
var err error
if len(outputTemplate) == 0 {
return errors.New("template is unset, please specify with --template")
}
if writer, err = NewTemplateWriter(output, outputTemplate); err != nil {
return err
}
default:
return errors.New("Unrecognized format specified")
}
if err := writer.Write(reports); err != nil {
return err
}
return nil
}
// Writer defines the result write operation
type Writer interface {
Write(reports) error
}
// JSONWriter implements result Writer
type JSONWriter struct {
Output io.Writer
}
// PrettyJSON will indent JSON to be pretty
func PrettyJSON(jsonBytes []byte) ([]byte, error) {
var out bytes.Buffer
err := json.Indent(&out, jsonBytes, "", " ")
if err != nil {
return jsonBytes, err
}
return out.Bytes(), nil
}
// Write writes the reports in JSON format
func (jw JSONWriter) Write(reports reports) error {
output, err := json.Marshal(reports)
if err != nil {
return err
}
formattedOutput, err := PrettyJSON(output)
if err != nil {
return err
}
if _, err = fmt.Fprint(jw.Output, string(formattedOutput)); err != nil {
return err
}
return nil
}
// TemplateWriter write result in custom format defined by user's template
type TemplateWriter struct {
Output io.Writer
Template *template.Template
}
// NewTemplateWriter is the factory method to return TemplateWriter object
func NewTemplateWriter(output io.Writer, outputTemplate string) (*TemplateWriter, error) {
// if outputTemplate is a file read it and use that
if _, err := os.Stat(outputTemplate); err == nil {
buf, err := ioutil.ReadFile(outputTemplate)
if err != nil {
return nil, err
}
outputTemplate = string(buf)
}
tmpl, err := template.New("output template").Funcs(template.FuncMap{
"endWithPeriod": func(input string) string {
if !strings.HasSuffix(input, ".") {
input += "."
}
return input
},
"toLower": func(input string) string {
return strings.ToLower(input)
},
"escapeString": func(input string) string {
return html.EscapeString(input)
},
"getCurrentTime": func() string {
return Now().UTC().Format(time.RFC3339Nano)
},
"joinSlices": func(slices ...[]ruler.RuleRef) []ruler.RuleRef {
var resultSlice []ruler.RuleRef
for _, slice := range slices {
resultSlice = append(resultSlice, slice...)
}
return resultSlice
},
}).Parse(outputTemplate)
if err != nil {
return nil, err
}
return &TemplateWriter{Output: output, Template: tmpl}, nil
}
// Write writes result
func (tw TemplateWriter) Write(reports reports) error {
err := tw.Template.Execute(tw.Output, reports)
if err != nil {
return err
}
return nil
}