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  }