mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-04 02:57:27 +09:00
75 lines
1.6 KiB
Go
75 lines
1.6 KiB
Go
package template
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
tmpl "text/template"
|
|
|
|
sprig "github.com/go-task/slim-sprig/v3"
|
|
)
|
|
|
|
func Template[T any](obj *T, templateContext map[string]any) (*T, error) {
|
|
b, err := json.Marshal(obj)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var unstructured any
|
|
err = json.Unmarshal(b, &unstructured)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
templateFunc := func(in string) string {
|
|
out, err := template(in, templateContext)
|
|
if err != nil {
|
|
return in
|
|
}
|
|
return out
|
|
}
|
|
unstructured = mapAtStrings(unstructured, templateFunc)
|
|
b, err = json.Marshal(unstructured)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out T
|
|
err = json.Unmarshal(b, &out)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|
|
|
|
func mapAtStrings(v any, f func(string) string) any {
|
|
switch x := v.(type) {
|
|
case map[string]any:
|
|
for k, val := range x {
|
|
x[k] = mapAtStrings(val, f)
|
|
}
|
|
return x
|
|
case []any:
|
|
for i, val := range x {
|
|
x[i] = mapAtStrings(val, f)
|
|
}
|
|
return x
|
|
case string:
|
|
return f(x)
|
|
default:
|
|
return v
|
|
}
|
|
}
|
|
|
|
func template(in string, templateContext map[string]any) (string, error) {
|
|
// FuncMap from slim-sprig is text-template-only (no HTML escaping, which
|
|
// is what we want for Pod spec strings) and excludes network/OS/crypto
|
|
// helpers - the subset matches what strategy authors actually reach for
|
|
// (default, required, quote, printf wrappers, dict/list/index helpers).
|
|
tpl, err := tmpl.New("this").Funcs(sprig.FuncMap()).Parse(in)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var buf bytes.Buffer
|
|
if err := tpl.Execute(&buf, templateContext); err != nil {
|
|
return "", err
|
|
}
|
|
return buf.String(), nil
|
|
}
|