NGAlert: Fix templating and remove unwanted default templates (#33918)
Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com>
This commit is contained in:
@@ -260,8 +260,6 @@ func (am *Alertmanager) SyncAndApplyConfigFromDatabase() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultTemplate = "templates/default.tmpl"
|
|
||||||
|
|
||||||
// applyConfig applies a new configuration by re-initializing all components using the configuration provided.
|
// applyConfig applies a new configuration by re-initializing all components using the configuration provided.
|
||||||
// It is not safe to call concurrently.
|
// It is not safe to call concurrently.
|
||||||
func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) error {
|
func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) error {
|
||||||
@@ -279,6 +277,12 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig
|
|||||||
if md5.Sum(am.config) != md5.Sum(rawConfig) {
|
if md5.Sum(am.config) != md5.Sum(rawConfig) {
|
||||||
configChanged = true
|
configChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cfg.TemplateFiles == nil {
|
||||||
|
cfg.TemplateFiles = map[string]string{}
|
||||||
|
}
|
||||||
|
cfg.TemplateFiles["__default__.tmpl"] = channels.DefaultTemplateString
|
||||||
|
|
||||||
// next, we need to make sure we persist the templates to disk.
|
// next, we need to make sure we persist the templates to disk.
|
||||||
paths, templatesChanged, err := PersistTemplates(cfg, am.WorkingDirPath())
|
paths, templatesChanged, err := PersistTemplates(cfg, am.WorkingDirPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -291,8 +295,6 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
paths = append([]string{defaultTemplate}, paths...)
|
|
||||||
|
|
||||||
// With the templates persisted, create the template list using the paths.
|
// With the templates persisted, create the template list using the paths.
|
||||||
tmpl, err := template.FromGlobs(paths...)
|
tmpl, err := template.FromGlobs(paths...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package channels
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/prometheus/alertmanager/template"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
const DefaultTemplateString = `
|
||||||
|
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
|
||||||
|
|
||||||
|
{{ define "__text_alert_list" }}{{ range . }}Labels:
|
||||||
|
{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||||
|
{{ end }}Annotations:
|
||||||
|
{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||||
|
{{ end }}Source: {{ .GeneratorURL }}
|
||||||
|
{{ end }}{{ end }}
|
||||||
|
|
||||||
|
{{ define "default.title" }}{{ template "__subject" . }}{{ end }}
|
||||||
|
|
||||||
|
{{ define "default.message" }}{{ if gt (len .Alerts.Firing) 0 }}
|
||||||
|
**Firing**
|
||||||
|
{{ template "__text_alert_list" .Alerts.Firing }}
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
{{ if gt (len .Alerts.Resolved) 0 }}
|
||||||
|
**Resolved**
|
||||||
|
{{ template "__text_alert_list" .Alerts.Resolved }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
`
|
||||||
|
|
||||||
|
func templateForTests(t *testing.T) *template.Template {
|
||||||
|
f, err := ioutil.TempFile("/tmp", "template")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
require.NoError(t, os.RemoveAll(f.Name()))
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = f.WriteString(DefaultTemplateString)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tmpl, err := template.FromGlobs(f.Name())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return tmpl
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prometheus/alertmanager/notify"
|
"github.com/prometheus/alertmanager/notify"
|
||||||
"github.com/prometheus/alertmanager/template"
|
|
||||||
"github.com/prometheus/alertmanager/types"
|
"github.com/prometheus/alertmanager/types"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -20,8 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestDingdingNotifier(t *testing.T) {
|
func TestDingdingNotifier(t *testing.T) {
|
||||||
tmpl, err := template.FromGlobs("templates/default.tmpl")
|
tmpl := templateForTests(t)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
externalURL, err := url.Parse("http://localhost")
|
externalURL, err := url.Parse("http://localhost")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ func NewPagerdutyNotifier(model *models.AlertNotification, t *template.Template)
|
|||||||
NotifierBase: old_notifiers.NewNotifierBase(model),
|
NotifierBase: old_notifiers.NewNotifierBase(model),
|
||||||
Key: key,
|
Key: key,
|
||||||
CustomDetails: map[string]string{
|
CustomDetails: map[string]string{
|
||||||
"firing": `{{ template "pagerduty.default.instances" .Alerts.Firing }}`,
|
"firing": `{{ template "__text_alert_list" .Alerts.Firing }}`,
|
||||||
"resolved": `{{ template "pagerduty.default.instances" .Alerts.Resolved }}`,
|
"resolved": `{{ template "__text_alert_list" .Alerts.Resolved }}`,
|
||||||
"num_firing": `{{ .Alerts.Firing | len }}`,
|
"num_firing": `{{ .Alerts.Firing | len }}`,
|
||||||
"num_resolved": `{{ .Alerts.Resolved | len }}`,
|
"num_resolved": `{{ .Alerts.Resolved | len }}`,
|
||||||
},
|
},
|
||||||
@@ -67,7 +67,7 @@ func NewPagerdutyNotifier(model *models.AlertNotification, t *template.Template)
|
|||||||
Class: model.Settings.Get("class").MustString("default"),
|
Class: model.Settings.Get("class").MustString("default"),
|
||||||
Component: model.Settings.Get("component").MustString("Grafana"),
|
Component: model.Settings.Get("component").MustString("Grafana"),
|
||||||
Group: model.Settings.Get("group").MustString("default"),
|
Group: model.Settings.Get("group").MustString("default"),
|
||||||
Summary: model.Settings.Get("summary").MustString(`{{ template "pagerduty.default.description" .}}`),
|
Summary: model.Settings.Get("summary").MustString(`{{ template "default.title" . }}`),
|
||||||
tmpl: t,
|
tmpl: t,
|
||||||
log: log.New("alerting.notifier." + model.Name),
|
log: log.New("alerting.notifier." + model.Name),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prometheus/alertmanager/notify"
|
"github.com/prometheus/alertmanager/notify"
|
||||||
"github.com/prometheus/alertmanager/template"
|
|
||||||
"github.com/prometheus/alertmanager/types"
|
"github.com/prometheus/alertmanager/types"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -21,8 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestPagerdutyNotifier(t *testing.T) {
|
func TestPagerdutyNotifier(t *testing.T) {
|
||||||
tmpl, err := template.FromGlobs("templates/default.tmpl")
|
tmpl := templateForTests(t)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
externalURL, err := url.Parse("http://localhost")
|
externalURL, err := url.Parse("http://localhost")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -121,8 +121,8 @@ func NewSlackNotifier(model *models.AlertNotification, t *template.Template) (*S
|
|||||||
IconEmoji: model.Settings.Get("icon_emoji").MustString(),
|
IconEmoji: model.Settings.Get("icon_emoji").MustString(),
|
||||||
IconURL: model.Settings.Get("icon_url").MustString(),
|
IconURL: model.Settings.Get("icon_url").MustString(),
|
||||||
Token: token,
|
Token: token,
|
||||||
Text: model.Settings.Get("text").MustString(`{{ template "slack.default.text" . }}`),
|
Text: model.Settings.Get("text").MustString(`{{ template "default.message" . }}`),
|
||||||
Title: model.Settings.Get("title").MustString(`{{ template "slack.default.title" . }}`),
|
Title: model.Settings.Get("title").MustString(`{{ template "default.title" . }}`),
|
||||||
log: log.New("alerting.notifier.slack"),
|
log: log.New("alerting.notifier.slack"),
|
||||||
tmpl: t,
|
tmpl: t,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prometheus/alertmanager/notify"
|
"github.com/prometheus/alertmanager/notify"
|
||||||
"github.com/prometheus/alertmanager/template"
|
|
||||||
"github.com/prometheus/alertmanager/types"
|
"github.com/prometheus/alertmanager/types"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -22,8 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestSlackNotifier(t *testing.T) {
|
func TestSlackNotifier(t *testing.T) {
|
||||||
tmpl, err := template.FromGlobs("templates/default.tmpl")
|
tmpl := templateForTests(t)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
externalURL, err := url.Parse("http://localhost")
|
externalURL, err := url.Parse("http://localhost")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -60,7 +58,7 @@ func TestSlackNotifier(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Title: "[FIRING:1] (val1)",
|
Title: "[FIRING:1] (val1)",
|
||||||
TitleLink: "http:/localhost/alerting/list",
|
TitleLink: "http:/localhost/alerting/list",
|
||||||
Text: "",
|
Text: "\n**Firing**\nLabels:\n - alertname = alert1\n - lbl1 = val1\nAnnotations:\n - ann1 = annv1\nSource: \n\n\n\n\n",
|
||||||
Fallback: "[FIRING:1] (val1)",
|
Fallback: "[FIRING:1] (val1)",
|
||||||
Fields: nil,
|
Fields: nil,
|
||||||
Footer: "Grafana v",
|
Footer: "Grafana v",
|
||||||
@@ -96,7 +94,7 @@ func TestSlackNotifier(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Title: "[FIRING:1] (val1)",
|
Title: "[FIRING:1] (val1)",
|
||||||
TitleLink: "http:/localhost/alerting/list",
|
TitleLink: "http:/localhost/alerting/list",
|
||||||
Text: "",
|
Text: "\n**Firing**\nLabels:\n - alertname = alert1\n - lbl1 = val1\nAnnotations:\n - ann1 = annv1\nSource: \n\n\n\n\n",
|
||||||
Fallback: "[FIRING:1] (val1)",
|
Fallback: "[FIRING:1] (val1)",
|
||||||
Fields: nil,
|
Fields: nil,
|
||||||
Footer: "Grafana v",
|
Footer: "Grafana v",
|
||||||
@@ -139,7 +137,7 @@ func TestSlackNotifier(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Title: "2 firing, 0 resolved",
|
Title: "2 firing, 0 resolved",
|
||||||
TitleLink: "http:/localhost/alerting/list",
|
TitleLink: "http:/localhost/alerting/list",
|
||||||
Text: "",
|
Text: "\n**Firing**\nLabels:\n - alertname = alert1\n - lbl1 = val1\nAnnotations:\n - ann1 = annv1\nSource: \nLabels:\n - alertname = alert1\n - lbl1 = val2\nAnnotations:\n - ann1 = annv2\nSource: \n\n\n\n\n",
|
||||||
Fallback: "2 firing, 0 resolved",
|
Fallback: "2 firing, 0 resolved",
|
||||||
Fields: nil,
|
Fields: nil,
|
||||||
Footer: "Grafana v",
|
Footer: "Grafana v",
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prometheus/alertmanager/notify"
|
"github.com/prometheus/alertmanager/notify"
|
||||||
"github.com/prometheus/alertmanager/template"
|
|
||||||
"github.com/prometheus/alertmanager/types"
|
"github.com/prometheus/alertmanager/types"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -20,8 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestTeamsNotifier(t *testing.T) {
|
func TestTeamsNotifier(t *testing.T) {
|
||||||
tmpl, err := template.FromGlobs("templates/default.tmpl")
|
tmpl := templateForTests(t)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
externalURL, err := url.Parse("http://localhost")
|
externalURL, err := url.Parse("http://localhost")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prometheus/alertmanager/notify"
|
"github.com/prometheus/alertmanager/notify"
|
||||||
"github.com/prometheus/alertmanager/template"
|
|
||||||
"github.com/prometheus/alertmanager/types"
|
"github.com/prometheus/alertmanager/types"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -18,8 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestTelegramNotifier(t *testing.T) {
|
func TestTelegramNotifier(t *testing.T) {
|
||||||
tmpl, err := template.FromGlobs("templates/default.tmpl")
|
tmpl := templateForTests(t)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
externalURL, err := url.Parse("http://localhost")
|
externalURL, err := url.Parse("http://localhost")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -1,230 +0,0 @@
|
|||||||
{{ define "__alertmanager" }}Alertmanager{{ end }}
|
|
||||||
{{ define "__alertmanagerURL" }}{{ .ExternalURL }}/#/alerts?receiver={{ .Receiver | urlquery }}{{ end }}
|
|
||||||
|
|
||||||
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
|
|
||||||
{{ define "__description" }}{{ end }}
|
|
||||||
|
|
||||||
{{ define "__text_alert_list" }}{{ range . }}Labels:
|
|
||||||
{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
|
||||||
{{ end }}Annotations:
|
|
||||||
{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
|
||||||
{{ end }}Source: {{ .GeneratorURL }}
|
|
||||||
{{ end }}{{ end }}
|
|
||||||
|
|
||||||
{{ define "default.title" }}{{ template "__subject" . }}{{ end }}
|
|
||||||
{{ define "default.message" }}{{ if gt (len .Alerts.Firing) 0 }}
|
|
||||||
**Firing**
|
|
||||||
{{ template "__text_alert_list" .Alerts.Firing }}
|
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
{{ if gt (len .Alerts.Resolved) 0 }}
|
|
||||||
**Resolved**
|
|
||||||
{{ template "__text_alert_list" .Alerts.Resolved }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ define "slack.default.title" }}{{ template "default.title" . }}{{ end }}
|
|
||||||
{{ define "slack.default.username" }}{{ template "__alertmanager" . }}{{ end }}
|
|
||||||
{{ define "slack.default.fallback" }}{{ template "slack.default.title" . }} | {{ template "slack.default.titlelink" . }}{{ end }}
|
|
||||||
{{ define "slack.default.callbackid" }}{{ end }}
|
|
||||||
{{ define "slack.default.pretext" }}{{ end }}
|
|
||||||
{{ define "slack.default.titlelink" }}{{ template "__alertmanagerURL" . }}{{ end }}
|
|
||||||
{{ define "slack.default.iconemoji" }}{{ end }}
|
|
||||||
{{ define "slack.default.iconurl" }}{{ end }}
|
|
||||||
{{ define "slack.default.text" }}{{ end }}
|
|
||||||
{{ define "slack.default.footer" }}{{ end }}
|
|
||||||
|
|
||||||
|
|
||||||
{{ define "pagerduty.default.description" }}{{ template "default.title" . }}{{ end }}
|
|
||||||
{{ define "pagerduty.default.client" }}{{ template "__alertmanager" . }}{{ end }}
|
|
||||||
{{ define "pagerduty.default.clientURL" }}{{ template "__alertmanagerURL" . }}{{ end }}
|
|
||||||
{{ define "pagerduty.default.instances" }}{{ template "__text_alert_list" . }}{{ end }}
|
|
||||||
|
|
||||||
|
|
||||||
{{ define "opsgenie.default.message" }}{{ template "__subject" . }}{{ end }}
|
|
||||||
{{ define "opsgenie.default.description" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }}
|
|
||||||
{{ if gt (len .Alerts.Firing) 0 -}}
|
|
||||||
Alerts Firing:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Firing }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if gt (len .Alerts.Resolved) 0 -}}
|
|
||||||
Alerts Resolved:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Resolved }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{ define "opsgenie.default.source" }}{{ template "__alertmanagerURL" . }}{{ end }}
|
|
||||||
|
|
||||||
|
|
||||||
{{ define "wechat.default.message" }}{{ template "__subject" . }}
|
|
||||||
{{ .CommonAnnotations.SortedPairs.Values | join " " }}
|
|
||||||
{{ if gt (len .Alerts.Firing) 0 -}}
|
|
||||||
Alerts Firing:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Firing }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if gt (len .Alerts.Resolved) 0 -}}
|
|
||||||
Alerts Resolved:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Resolved }}
|
|
||||||
{{- end }}
|
|
||||||
AlertmanagerUrl:
|
|
||||||
{{ template "__alertmanagerURL" . }}
|
|
||||||
{{- end }}
|
|
||||||
{{ define "wechat.default.to_user" }}{{ end }}
|
|
||||||
{{ define "wechat.default.to_party" }}{{ end }}
|
|
||||||
{{ define "wechat.default.to_tag" }}{{ end }}
|
|
||||||
{{ define "wechat.default.agent_id" }}{{ end }}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{{ define "victorops.default.state_message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }}
|
|
||||||
{{ if gt (len .Alerts.Firing) 0 -}}
|
|
||||||
Alerts Firing:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Firing }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if gt (len .Alerts.Resolved) 0 -}}
|
|
||||||
Alerts Resolved:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Resolved }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{ define "victorops.default.entity_display_name" }}{{ template "__subject" . }}{{ end }}
|
|
||||||
{{ define "victorops.default.monitoring_tool" }}{{ template "__alertmanager" . }}{{ end }}
|
|
||||||
|
|
||||||
{{ define "email.default.subject" }}{{ template "__subject" . }}{{ end }}
|
|
||||||
{{ define "email.default.html" }}
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<!--
|
|
||||||
Style and HTML derived from https://github.com/mailgun/transactional-email-templates
|
|
||||||
|
|
||||||
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Mailgun
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
-->
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<head style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<meta name="viewport" content="width=device-width" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
<title style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{ template "__subject" . }}</title>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body itemscope="" itemtype="http://schema.org/EmailMessage" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 1.6em; width: 100% !important; background-color: #f6f6f6; margin: 0; padding: 0;" bgcolor="#f6f6f6">
|
|
||||||
|
|
||||||
<table style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6">
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top"></td>
|
|
||||||
<td width="600" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; display: block !important; max-width: 600px !important; clear: both !important; width: 100% !important; margin: 0 auto; padding: 0;" valign="top">
|
|
||||||
<div style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; max-width: 600px; display: block; margin: 0 auto; padding: 0;">
|
|
||||||
<table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; background-color: #fff; margin: 0; border: 1px solid #e9e9e9;" bgcolor="#fff">
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; color: #fff; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; background-color: #E6522C; margin: 0; padding: 20px;" align="center" bgcolor="#E6522C" valign="top">
|
|
||||||
{{ .Alerts | len }} alert{{ if gt (len .Alerts) 1 }}s{{ end }} for {{ range .GroupLabels.SortedPairs }}
|
|
||||||
{{ .Name }}={{ .Value }}
|
|
||||||
{{ end }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 10px;" valign="top">
|
|
||||||
<table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
|
||||||
<a href="{{ template "__alertmanagerURL" . }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #FFF; text-decoration: none; line-height: 2em; font-weight: bold; text-align: center; cursor: pointer; display: inline-block; border-radius: 5px; text-transform: capitalize; background-color: #348eda; margin: 0; border-color: #348eda; border-style: solid; border-width: 10px 20px;">View in {{ template "__alertmanager" . }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ if gt (len .Alerts.Firing) 0 }}
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
|
||||||
<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">[{{ .Alerts.Firing | len }}] Firing</strong>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
{{ range .Alerts.Firing }}
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
|
||||||
<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Labels</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
{{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
|
|
||||||
{{ if gt (len .Annotations) 0 }}<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Annotations</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
|
|
||||||
{{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
|
|
||||||
<a href="{{ .GeneratorURL }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #348eda; text-decoration: underline; margin: 0;">Source</a><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ if gt (len .Alerts.Resolved) 0 }}
|
|
||||||
{{ if gt (len .Alerts.Firing) 0 }}
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
|
||||||
<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
<hr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
|
||||||
<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">[{{ .Alerts.Resolved | len }}] Resolved</strong>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
{{ range .Alerts.Resolved }}
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
|
||||||
<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Labels</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
{{ range .Labels.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
|
|
||||||
{{ if gt (len .Annotations) 0 }}<strong style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">Annotations</strong><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
|
|
||||||
{{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}<br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />{{ end }}
|
|
||||||
<a href="{{ .GeneratorURL }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; color: #348eda; text-decoration: underline; margin: 0;">Source</a><br style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;">
|
|
||||||
<table width="100%" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<tr style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; text-align: center; color: #999; margin: 0; padding: 0 0 20px;" align="center" valign="top"><a href="{{ .ExternalURL }}" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">Sent by {{ template "__alertmanager" . }}</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div></div>
|
|
||||||
</td>
|
|
||||||
<td style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top"></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ define "pushover.default.title" }}{{ template "__subject" . }}{{ end }}
|
|
||||||
{{ define "pushover.default.message" }}{{ .CommonAnnotations.SortedPairs.Values | join " " }}
|
|
||||||
{{ if gt (len .Alerts.Firing) 0 }}
|
|
||||||
Alerts Firing:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Firing }}
|
|
||||||
{{ end }}
|
|
||||||
{{ if gt (len .Alerts.Resolved) 0 }}
|
|
||||||
Alerts Resolved:
|
|
||||||
{{ template "__text_alert_list" .Alerts.Resolved }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
{{ define "pushover.default.url" }}{{ template "__alertmanagerURL" . }}{{ end }}
|
|
||||||
@@ -19,8 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestWebhookNotifier(t *testing.T) {
|
func TestWebhookNotifier(t *testing.T) {
|
||||||
tmpl, err := template.FromGlobs("templates/default.tmpl")
|
tmpl := templateForTests(t)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
externalURL, err := url.Parse("http://localhost")
|
externalURL, err := url.Parse("http://localhost")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
Reference in New Issue
Block a user