-
Notifications
You must be signed in to change notification settings - Fork 6
/
render.go
120 lines (107 loc) · 3.59 KB
/
render.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
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Gardener contributors
//
// SPDX-License-Identifier: Apache-2.0
package report
import (
"embed"
"fmt"
"html/template"
"io"
"time"
"gopkg.in/yaml.v3"
"github.com/gardener/diki/pkg/rule"
)
const (
tmplReportName = "report"
tmplReportPath = "templates/html/report.html"
tmplMergedReportName = "merged_report"
tmplMergedReportPath = "templates/html/merged_report.html"
tmplDifferenceReportName = "difference_report"
tmplDifferenceReportPath = "templates/html/difference_report.html"
tmplStylesPath = "templates/html/_styles.tpl"
)
var (
//go:embed templates/html/*
files embed.FS
)
// HTMLRenderer renders Diki reports in html format.
type HTMLRenderer struct {
templates map[string]*template.Template
}
// NewHTMLRenderer creates a HTMLRenderer.
func NewHTMLRenderer() (*HTMLRenderer, error) {
convTimeFunc := func(time time.Time) string {
return time.Format("01-02-2006")
}
add := func(a, b int) int {
return a + b
}
keyExists := func(m map[string]string, k string) bool {
_, ok := m[k]
return ok
}
yamlFormat := func(m map[string]any) string {
yaml, err := yaml.Marshal(m)
if err != nil {
return err.Error()
}
return string(yaml)
}
templates := make(map[string]*template.Template)
parsedReport, err := template.New(tmplReportName+".html").Funcs(template.FuncMap{
"getStatuses": rule.Statuses,
"icon": rule.GetStatusIcon,
"time": convTimeFunc,
"yamlFormat": yamlFormat,
"rulesetSummaryText": rulesetSummaryText,
"rulesWithStatus": rulesWithStatus,
"sortedMapKeys": sortedKeys[string],
}).ParseFS(files, tmplReportPath, tmplStylesPath)
if err != nil {
return nil, err
}
templates[tmplReportName] = parsedReport
parsedMergedReport, err := template.New(tmplMergedReportName+".html").Funcs(template.FuncMap{
"getStatuses": rule.Statuses,
"icon": rule.GetStatusIcon,
"time": convTimeFunc,
"yamlFormat": yamlFormat,
"mergedMetadataTexts": metadataTextForMergedProvider,
"mergedRulesetSummaryText": mergedRulesetSummaryText,
"mergedRulesWithStatus": mergedRulesWithStatus,
"sortedMapKeys": sortedKeys[string],
}).ParseFS(files, tmplMergedReportPath, tmplStylesPath)
if err != nil {
return nil, err
}
templates[tmplMergedReportName] = parsedMergedReport
parsedDifferenceReport, err := template.New(tmplDifferenceReportName+".html").Funcs(template.FuncMap{
"add": add,
"icon": rule.GetStatusIcon,
"rulesetDiffAddedSummaryText": rulesetDiffAddedSummaryText,
"rulesetDiffRemovedSummaryText": rulesetDiffRemovedSummaryText,
"keyExists": keyExists,
"getAttrString": getProviderDiffIDText,
"sortedMapKeys": sortedKeys[string],
}).ParseFS(files, tmplDifferenceReportPath, tmplStylesPath)
if err != nil {
return nil, err
}
templates[tmplDifferenceReportName] = parsedDifferenceReport
return &HTMLRenderer{
templates: templates,
}, nil
}
// Render writes a Diki report in html format into the passed writer.
func (r *HTMLRenderer) Render(w io.Writer, report any) error {
switch rep := report.(type) {
case *Report:
return r.templates[tmplReportName].Execute(w, rep)
case *MergedReport:
return r.templates[tmplMergedReportName].Execute(w, rep)
case *DifferenceReportsWrapper:
return r.templates[tmplDifferenceReportName].Execute(w, rep)
default:
return fmt.Errorf("unsupported report type: %T", report)
}
}