102 lines
2.4 KiB
Go
102 lines
2.4 KiB
Go
// render.go — Go-based IEC 62443-3-3 SL2 compliance report renderer.
|
|
//
|
|
// Loads a JSON report produced by ansible-test and renders it through
|
|
// an external Go template file (report.gohtml by default).
|
|
//
|
|
// Usage:
|
|
// go run render.go <report.json> [template.gohtml]
|
|
//
|
|
// The template receives the full JSON document as an untyped map.
|
|
// Registered template functions:
|
|
// passIcon — maps passed value to ✅/❌/🔍/❓
|
|
// severityIcon — maps severity string to 🔴/🟠/🟡/🟢/⚪
|
|
// title — capitalizes first letter of each word
|
|
// divf — float64 division (a/b*100) for percentages
|
|
// add, sub — integer arithmetic
|
|
//
|
|
// Dependencies:
|
|
// golang.org/x/text v0.14.0 (for cases.Title)
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"text/template"
|
|
|
|
"golang.org/x/text/cases"
|
|
"golang.org/x/text/language"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
fmt.Fprintf(os.Stderr, "Usage: gomplate-report <report.json> [template.gohtml]\n")
|
|
os.Exit(1)
|
|
}
|
|
|
|
jsonPath := os.Args[1]
|
|
tmplPath := "reports/report.gohtml"
|
|
if len(os.Args) >= 3 {
|
|
tmplPath = os.Args[2]
|
|
}
|
|
|
|
data, err := os.ReadFile(jsonPath)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error reading JSON: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
var report map[string]any
|
|
if err := json.Unmarshal(data, &report); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error parsing JSON: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
funcMap := template.FuncMap{
|
|
"passIcon": func(v any) string {
|
|
b, ok := v.(bool)
|
|
if !ok {
|
|
return "❓ MANUAL"
|
|
}
|
|
if b {
|
|
return "✅ PASS"
|
|
}
|
|
return "❌ FAIL"
|
|
},
|
|
"severityIcon": func(s string) string {
|
|
switch s {
|
|
case "critical":
|
|
return "🔴"
|
|
case "high":
|
|
return "🟠"
|
|
case "medium":
|
|
return "🟡"
|
|
case "low":
|
|
return "🟢"
|
|
}
|
|
return "⚪"
|
|
},
|
|
"title": cases.Title(language.English).String,
|
|
"divf": func(a, b int) float64 {
|
|
if b == 0 {
|
|
return 0
|
|
}
|
|
return float64(a) / float64(b) * 100.0
|
|
},
|
|
"add": func(a, b int) int { return a + b },
|
|
"sub": func(a, b int) int { return a - b },
|
|
}
|
|
|
|
tmpl, err := template.New("report.gohtml").Funcs(funcMap).ParseFiles(tmplPath)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error parsing template: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if err := tmpl.ExecuteTemplate(os.Stdout, "report.gohtml", report); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error rendering: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|