Create and use custom template package
This commit is contained in:
parent
41821faf92
commit
3a2db95a8e
29
main.go
29
main.go
|
@ -17,13 +17,11 @@ import (
|
|||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
txttemplate "text/template"
|
||||
|
||||
"github.com/prometheus/common/log"
|
||||
"github.com/prometheus/common/route"
|
||||
|
@ -32,6 +30,7 @@ import (
|
|||
"github.com/prometheus/alertmanager/config"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/provider"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
|
||||
|
@ -50,6 +49,8 @@ func main() {
|
|||
}
|
||||
defer db.Close()
|
||||
|
||||
tmpl := &template.Template{}
|
||||
|
||||
alerts, err := provider.NewSQLAlerts(db)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -115,7 +116,7 @@ func main() {
|
|||
for _, ec := range nc.EmailConfigs {
|
||||
all = append(all, ¬ify.LogNotifier{
|
||||
Log: log.With("notifier", "email"),
|
||||
Notifier: notify.NewEmail(ec),
|
||||
Notifier: notify.NewEmail(ec, tmpl),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -145,14 +146,13 @@ func main() {
|
|||
}
|
||||
|
||||
routedNotifier.Lock()
|
||||
log.Debugf("set notifiers for routes %#v", res)
|
||||
routedNotifier.Notifiers = res
|
||||
routedNotifier.Unlock()
|
||||
}
|
||||
|
||||
disp := NewDispatcher(alerts, notifier)
|
||||
|
||||
if err := reloadConfig(*configFile, disp, types.ReloadFunc(build), inhibitor); err != nil {
|
||||
if err := reloadConfig(*configFile, disp, types.ReloadFunc(build), inhibitor, tmpl); err != nil {
|
||||
log.Fatalf("Couldn't load configuration (-config.file=%s): %v", *configFile, err)
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ func main() {
|
|||
|
||||
go func() {
|
||||
for range hup {
|
||||
if err := reloadConfig(*configFile, disp, types.ReloadFunc(build), inhibitor); err != nil {
|
||||
if err := reloadConfig(*configFile, disp, types.ReloadFunc(build), inhibitor, tmpl); err != nil {
|
||||
log.Errorf("Couldn't load configuration (-config.file=%s): %v", *configFile, err)
|
||||
}
|
||||
}
|
||||
|
@ -194,23 +194,6 @@ func reloadConfig(filename string, rls ...types.Reloadable) error {
|
|||
return err
|
||||
}
|
||||
|
||||
t := template.New("")
|
||||
for _, tpath := range conf.Templates {
|
||||
t, err = t.ParseGlob(tpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
tt := txttemplate.New("")
|
||||
for _, tpath := range conf.Templates {
|
||||
tt, err = tt.ParseGlob(tpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
notify.SetTemplate(t, tt)
|
||||
|
||||
for _, rl := range rls {
|
||||
rl.ApplyConfig(conf)
|
||||
}
|
||||
|
|
|
@ -5,13 +5,11 @@ import (
|
|||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/smtp"
|
||||
"os"
|
||||
"strings"
|
||||
txttemplate "text/template"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/common/log"
|
||||
|
@ -20,6 +18,7 @@ import (
|
|||
"golang.org/x/net/context/ctxhttp"
|
||||
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
)
|
||||
|
||||
|
@ -68,10 +67,11 @@ func (w *Webhook) Notify(ctx context.Context, alerts ...*types.Alert) error {
|
|||
|
||||
type Email struct {
|
||||
conf *config.EmailConfig
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
func NewEmail(ec *config.EmailConfig) *Email {
|
||||
return &Email{conf: ec}
|
||||
func NewEmail(c *config.EmailConfig, t *template.Template) *Email {
|
||||
return &Email{conf: c, tmpl: t}
|
||||
}
|
||||
|
||||
func (n *Email) auth(mechs string) (smtp.Auth, *tls.Config, error) {
|
||||
|
@ -161,16 +161,17 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) error {
|
|||
Date: time.Now().Format(time.RFC1123Z),
|
||||
}
|
||||
|
||||
if err := txttmpl.ExecuteTemplate(wc, n.conf.Templates.Header, &data); err != nil {
|
||||
if err := n.tmpl.ExecuteText(wc, n.conf.Templates.Header, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(fabxc): do a multipart write that considers the plain template.
|
||||
return tmpl.ExecuteTemplate(wc, n.conf.Templates.HTML, &data)
|
||||
return n.tmpl.ExecuteHTML(wc, n.conf.Templates.HTML, &data)
|
||||
}
|
||||
|
||||
type Slack struct {
|
||||
conf *config.SlackConfig
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
// slackReq is the request for sending a slack notification.
|
||||
|
@ -209,21 +210,25 @@ func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) error {
|
|||
color = n.conf.ColorFiring
|
||||
}
|
||||
|
||||
var title, link, pretext, text, fallback bytes.Buffer
|
||||
|
||||
if err := tmpl.ExecuteTemplate(&title, n.conf.Templates.Title, alerts); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tmpl.ExecuteTemplate(&text, n.conf.Templates.Text, alerts); err != nil {
|
||||
return err
|
||||
var err error
|
||||
tmpl := func(name string) (s string) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s, err = n.tmpl.ExecuteHTMLString(name, struct {
|
||||
Alerts model.Alerts
|
||||
}{
|
||||
Alerts: alerts,
|
||||
})
|
||||
return s
|
||||
}
|
||||
|
||||
attachment := &slackAttachment{
|
||||
Title: title.String(),
|
||||
TitleLink: link.String(),
|
||||
Pretext: pretext.String(),
|
||||
Text: text.String(),
|
||||
Fallback: fallback.String(),
|
||||
Title: tmpl(n.conf.Templates.Title),
|
||||
TitleLink: tmpl(n.conf.Templates.TitleLink),
|
||||
Pretext: tmpl(n.conf.Templates.Pretext),
|
||||
Text: tmpl(n.conf.Templates.Text),
|
||||
Fallback: tmpl(n.conf.Templates.Fallback),
|
||||
|
||||
Fields: []slackAttachmentField{{
|
||||
Title: "Status",
|
||||
|
@ -233,6 +238,10 @@ func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) error {
|
|||
Color: color,
|
||||
MrkdwnIn: []string{"fallback", "pretext"},
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := &slackReq{
|
||||
Channel: n.conf.Channel,
|
||||
Attachments: []slackAttachment{*attachment},
|
||||
|
@ -256,11 +265,3 @@ func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
var tmpl *template.Template
|
||||
var txttmpl *txttemplate.Template
|
||||
|
||||
func SetTemplate(t *template.Template, tt *txttemplate.Template) {
|
||||
tmpl = t
|
||||
txttmpl = tt
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package template
|
||||
|
||||
import (
|
||||
text_tmpl "html/template"
|
||||
html_tmpl "text/template"
|
||||
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
)
|
||||
|
||||
type Template struct {
|
||||
text *text_tmpl.Template
|
||||
html *html_tmpl.Template
|
||||
}
|
||||
|
||||
type FuncMap map[string]interface{}
|
||||
|
||||
var DefaultFuncs = FuncMap{
|
||||
"upper": strings.ToUpper,
|
||||
"lower": strings.ToLower,
|
||||
}
|
||||
|
||||
func (t *Template) funcs(fm FuncMap) *Template {
|
||||
t.text.Funcs(text_tmpl.FuncMap(fm))
|
||||
t.html.Funcs(html_tmpl.FuncMap(fm))
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Template) ExecuteTextString(name string, data interface{}) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
err := t.ExecuteText(&buf, name, data)
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func (t *Template) ExecuteText(w io.Writer, name string, data interface{}) error {
|
||||
return t.text.ExecuteTemplate(w, name, data)
|
||||
}
|
||||
|
||||
func (t *Template) ExecuteHTMLString(name string, data interface{}) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
err := t.ExecuteHTML(&buf, name, data)
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func (t *Template) ExecuteHTML(w io.Writer, name string, data interface{}) error {
|
||||
return t.html.ExecuteTemplate(w, name, data)
|
||||
}
|
||||
|
||||
func (t *Template) ApplyConfig(conf *config.Config) {
|
||||
var (
|
||||
tt = text_tmpl.New("")
|
||||
ht = html_tmpl.New("")
|
||||
)
|
||||
|
||||
for _, tf := range conf.Templates {
|
||||
tt = text_tmpl.Must(tt.ParseGlob(tf))
|
||||
ht = html_tmpl.Must(ht.ParseGlob(tf))
|
||||
}
|
||||
|
||||
t.text = tt
|
||||
t.html = ht
|
||||
|
||||
t.funcs(DefaultFuncs)
|
||||
}
|
Loading…
Reference in New Issue