github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/server/template.go (about) 1 package server 2 3 import ( 4 "context" 5 "io" 6 "io/ioutil" 7 "net/http" 8 "net/url" 9 "path" 10 template_text "text/template" 11 "time" 12 13 "github.com/pkg/errors" 14 "github.com/prometheus/common/model" 15 "github.com/prometheus/prometheus/template" 16 17 "github.com/grafana/loki/clients/pkg/promtail/server/ui" 18 ) 19 20 // templateOptions is a set of options to render a template. 21 type templateOptions struct { 22 ExternalURL *url.URL 23 Name, PageTitle, BuildVersion string 24 Data interface{} 25 TemplateFuncs template_text.FuncMap 26 } 27 28 // tmplFuncs create a default template function for a given template options 29 func (opts templateOptions) tmplFuncs() template_text.FuncMap { 30 return template_text.FuncMap{ 31 "since": func(t time.Time) time.Duration { 32 return time.Since(t) / time.Millisecond * time.Millisecond 33 }, 34 "pathPrefix": func() string { return opts.ExternalURL.Path }, 35 "pageTitle": func() string { return opts.PageTitle }, 36 "buildVersion": func() string { return opts.BuildVersion }, 37 } 38 } 39 40 // executeTemplate execute a template and write result to the http.ResponseWriter 41 func executeTemplate(ctx context.Context, w http.ResponseWriter, tmplOpts templateOptions) { 42 text, err := getTemplate(tmplOpts.Name) 43 if err != nil { 44 http.Error(w, err.Error(), http.StatusInternalServerError) 45 } 46 47 tmpl := template.NewTemplateExpander( 48 ctx, 49 text, 50 tmplOpts.Name, 51 tmplOpts.Data, 52 model.Now(), 53 nil, 54 tmplOpts.ExternalURL, 55 nil, 56 ) 57 58 tmpl.Funcs(tmplOpts.tmplFuncs()) 59 tmpl.Funcs(tmplOpts.TemplateFuncs) 60 61 result, err := tmpl.ExpandHTML(nil) 62 if err != nil { 63 http.Error(w, err.Error(), http.StatusInternalServerError) 64 return 65 } 66 _, _ = io.WriteString(w, result) 67 } 68 69 func getTemplate(name string) (string, error) { 70 var tmpl string 71 72 appendf := func(name string) error { 73 f, err := ui.Assets.Open(path.Join("/templates", name)) 74 if err != nil { 75 return err 76 } 77 defer func() { 78 _ = f.Close() 79 }() 80 b, err := ioutil.ReadAll(f) 81 if err != nil { 82 return err 83 } 84 tmpl += string(b) 85 return nil 86 } 87 88 err := appendf("_base.html") 89 if err != nil { 90 return "", errors.Wrap(err, "error reading base template") 91 } 92 err = appendf(name) 93 if err != nil { 94 return "", errors.Wrapf(err, "error reading page template %s", name) 95 } 96 97 return tmpl, nil 98 }