adding test containers
Some checks failed
Check scripts syntax / check-scripts-syntax (push) Successful in 3s
Test automated-nfs-backup / test-automated-nfs-backup (push) Successful in 4s
Haven Notify Build and Deploy / Build Haven Notify Image (pull_request) Has been cancelled
Haven Notify Build and Deploy / Build Haven Notify Image (PR) (pull_request) Has been cancelled
Haven Notify Build and Deploy / Deploy Haven Notify (internal) (pull_request) Has been cancelled
Haven Notify Build and Deploy / Test Haven Notify (pull_request) Has been cancelled
Some checks failed
Check scripts syntax / check-scripts-syntax (push) Successful in 3s
Test automated-nfs-backup / test-automated-nfs-backup (push) Successful in 4s
Haven Notify Build and Deploy / Build Haven Notify Image (pull_request) Has been cancelled
Haven Notify Build and Deploy / Build Haven Notify Image (PR) (pull_request) Has been cancelled
Haven Notify Build and Deploy / Deploy Haven Notify (internal) (pull_request) Has been cancelled
Haven Notify Build and Deploy / Test Haven Notify (pull_request) Has been cancelled
This commit is contained in:
135
haven-notify/templates.go
Normal file
135
haven-notify/templates.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"strconv"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
//go:embed template/*.tmpl
|
||||
var templatesFS embed.FS
|
||||
|
||||
type templateRenderer struct {
|
||||
templates map[string]*template.Template
|
||||
}
|
||||
|
||||
type templateExtra struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type backupTemplateData struct {
|
||||
Title string
|
||||
Asset string
|
||||
BackupSizeInMB float64
|
||||
Extra []templateExtra
|
||||
}
|
||||
|
||||
type updateTemplateData struct {
|
||||
Host string
|
||||
Asset string
|
||||
Time float64
|
||||
}
|
||||
|
||||
type errorTemplateData struct {
|
||||
Caller string
|
||||
Message string
|
||||
Critical bool
|
||||
Extra []templateExtra
|
||||
}
|
||||
|
||||
func newTemplateRenderer() (*templateRenderer, error) {
|
||||
return newTemplateRendererFromFS(templatesFS)
|
||||
}
|
||||
|
||||
func newTemplateRendererFromFS(templateFS fs.FS) (*templateRenderer, error) {
|
||||
functions := template.FuncMap{
|
||||
"formatSize": formatSize,
|
||||
"formatSeconds": formatSeconds,
|
||||
"json": jsonLiteral,
|
||||
}
|
||||
templates := make(map[string]*template.Template, 3)
|
||||
for _, name := range []string{"backup", "update", "error"} {
|
||||
contents, err := fs.ReadFile(templateFS, "template/"+name+".tmpl")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsed, err := template.New(name).Funcs(functions).Parse(string(contents))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templates[name] = parsed
|
||||
}
|
||||
return &templateRenderer{templates: templates}, nil
|
||||
}
|
||||
|
||||
func (r *templateRenderer) renderBackup(request backupRequest) (discordPayload, error) {
|
||||
return r.render("backup", backupTemplateData{
|
||||
Title: *request.Title,
|
||||
Asset: *request.Asset,
|
||||
BackupSizeInMB: *request.BackupSizeInMB,
|
||||
Extra: templateExtras(request.Extra),
|
||||
})
|
||||
}
|
||||
|
||||
func (r *templateRenderer) renderUpdate(request updateRequest) (discordPayload, error) {
|
||||
return r.render("update", updateTemplateData{
|
||||
Host: *request.Host,
|
||||
Asset: *request.Asset,
|
||||
Time: *request.Time,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *templateRenderer) renderError(request errorRequest) (discordPayload, error) {
|
||||
return r.render("error", errorTemplateData{
|
||||
Caller: *request.Caller,
|
||||
Message: *request.Message,
|
||||
Critical: *request.Critical,
|
||||
Extra: templateExtras(request.Extra),
|
||||
})
|
||||
}
|
||||
|
||||
func (r *templateRenderer) render(name string, data any) (discordPayload, error) {
|
||||
parsed, ok := r.templates[name]
|
||||
if !ok {
|
||||
return discordPayload{}, fmt.Errorf("unknown template %q", name)
|
||||
}
|
||||
var rendered bytes.Buffer
|
||||
if err := parsed.Execute(&rendered, data); err != nil {
|
||||
return discordPayload{}, err
|
||||
}
|
||||
var payload discordPayload
|
||||
if err := json.Unmarshal(rendered.Bytes(), &payload); err != nil {
|
||||
return discordPayload{}, fmt.Errorf("template produced invalid JSON: %w", err)
|
||||
}
|
||||
normalizeDiscordPayload(&payload)
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
func templateExtras(extra extraRequests) []templateExtra {
|
||||
result := make([]templateExtra, 0, len(extra))
|
||||
for _, field := range extra {
|
||||
result = append(result, templateExtra{Name: *field.Name, Value: *field.Value})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func jsonLiteral(value any) (string, error) {
|
||||
encoded, err := json.Marshal(value)
|
||||
return string(encoded), err
|
||||
}
|
||||
|
||||
func formatSize(size float64) string {
|
||||
if size >= 1024 {
|
||||
return fmt.Sprintf("%.2f GiB", size/1024)
|
||||
}
|
||||
return fmt.Sprintf("%.2f MiB", size)
|
||||
}
|
||||
|
||||
func formatSeconds(seconds float64) string {
|
||||
return strconv.FormatFloat(seconds, 'f', -1, 64) + " seconds"
|
||||
}
|
||||
Reference in New Issue
Block a user