mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
Include mentions in resolved webhook templates (#1118)
This commit is contained in:
parent
ca66581b6e
commit
0a7b93a842
2 changed files with 130 additions and 2 deletions
|
|
@ -339,6 +339,56 @@ func TestSendResolvedWebhookUsesServiceTemplate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSendResolvedWebhookDiscordIncludesMention(t *testing.T) {
|
||||
var gotBody []byte
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
gotBody = body
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
manager := NewNotificationManager("https://pulse.local")
|
||||
defer manager.Stop()
|
||||
manager.webhookClient = server.Client()
|
||||
if err := manager.UpdateAllowedPrivateCIDRs("127.0.0.1/32"); err != nil {
|
||||
t.Fatalf("allowlist: %v", err)
|
||||
}
|
||||
|
||||
alertList := []*alerts.Alert{{
|
||||
ID: "a1",
|
||||
Type: "cpu",
|
||||
Level: alerts.AlertLevelWarning,
|
||||
ResourceID: "vm100",
|
||||
ResourceName: "web-server",
|
||||
Node: "pve1",
|
||||
Message: "CPU usage high",
|
||||
Value: 95,
|
||||
Threshold: 90,
|
||||
StartTime: time.Now().Add(-5 * time.Minute),
|
||||
}}
|
||||
|
||||
webhook := WebhookConfig{
|
||||
Name: "discord-test",
|
||||
URL: server.URL + "/discord",
|
||||
Enabled: true,
|
||||
Service: "discord",
|
||||
Mention: "@everyone",
|
||||
}
|
||||
|
||||
if err := manager.sendResolvedWebhook(webhook, alertList, time.Now()); err != nil {
|
||||
t.Fatalf("sendResolvedWebhook error: %v", err)
|
||||
}
|
||||
|
||||
var payload map[string]interface{}
|
||||
if err := json.Unmarshal(gotBody, &payload); err != nil {
|
||||
t.Fatalf("unmarshal payload: %v", err)
|
||||
}
|
||||
if payload["content"] != "@everyone" {
|
||||
t.Fatalf("expected discord mention in content, got %v", payload["content"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendResolvedWebhookGenericFallback(t *testing.T) {
|
||||
var gotBody []byte
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
@ -422,6 +472,7 @@ func TestSendResolvedWebhookSlackTemplate(t *testing.T) {
|
|||
URL: server.URL + "/slack",
|
||||
Enabled: true,
|
||||
Service: "slack",
|
||||
Mention: "@channel",
|
||||
}
|
||||
|
||||
if err := manager.sendResolvedWebhook(webhook, alertList, time.Now()); err != nil {
|
||||
|
|
@ -439,6 +490,74 @@ func TestSendResolvedWebhookSlackTemplate(t *testing.T) {
|
|||
if !hasBlocks && !hasText {
|
||||
t.Fatalf("expected Slack payload to contain 'blocks' or 'text', got keys: %v", payload)
|
||||
}
|
||||
if payload["text"] != "@channel Resolved: db-server" {
|
||||
t.Fatalf("expected slack mention in text, got %v", payload["text"])
|
||||
}
|
||||
|
||||
blocks, ok := payload["blocks"].([]interface{})
|
||||
if !ok || len(blocks) == 0 {
|
||||
t.Fatalf("expected slack blocks, got %v", payload["blocks"])
|
||||
}
|
||||
firstBlock, ok := blocks[0].(map[string]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("expected first block object, got %T", blocks[0])
|
||||
}
|
||||
text, ok := firstBlock["text"].(map[string]interface{})
|
||||
if !ok || text["text"] != "@channel" {
|
||||
t.Fatalf("expected first slack block to carry mention, got %v", firstBlock["text"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendResolvedWebhookMattermostIncludesMention(t *testing.T) {
|
||||
var gotBody []byte
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
gotBody = body
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
manager := NewNotificationManager("https://pulse.local")
|
||||
defer manager.Stop()
|
||||
manager.webhookClient = server.Client()
|
||||
if err := manager.UpdateAllowedPrivateCIDRs("127.0.0.1/32"); err != nil {
|
||||
t.Fatalf("allowlist: %v", err)
|
||||
}
|
||||
|
||||
alertList := []*alerts.Alert{{
|
||||
ID: "a1",
|
||||
Type: "memory",
|
||||
Level: alerts.AlertLevelCritical,
|
||||
ResourceID: "vm200",
|
||||
ResourceName: "db-server",
|
||||
Node: "pve2",
|
||||
Message: "Memory usage critical",
|
||||
Value: 98,
|
||||
Threshold: 95,
|
||||
StartTime: time.Now().Add(-10 * time.Minute),
|
||||
}}
|
||||
|
||||
webhook := WebhookConfig{
|
||||
Name: "mattermost-test",
|
||||
URL: server.URL + "/mattermost",
|
||||
Enabled: true,
|
||||
Service: "mattermost",
|
||||
Mention: "@channel",
|
||||
}
|
||||
|
||||
if err := manager.sendResolvedWebhook(webhook, alertList, time.Now()); err != nil {
|
||||
t.Fatalf("sendResolvedWebhook error: %v", err)
|
||||
}
|
||||
|
||||
var payload map[string]interface{}
|
||||
if err := json.Unmarshal(gotBody, &payload); err != nil {
|
||||
t.Fatalf("unmarshal payload: %v", err)
|
||||
}
|
||||
|
||||
text, _ := payload["text"].(string)
|
||||
if !strings.HasPrefix(text, "@channel\n\n:white_check_mark: **RESOLVED**") {
|
||||
t.Fatalf("expected mattermost text to start with mention, got %q", text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendResolvedWebhookPagerDutyResolve(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ func GetWebhookTemplates() []WebhookTemplate {
|
|||
}`,
|
||||
ResolvedPayloadTemplate: `{
|
||||
"username": "Pulse Monitoring",
|
||||
{{if .Mention}}"content": "{{.Mention | jsonString}}",{{end}}
|
||||
"embeds": [{
|
||||
"title": "Resolved: {{.ResourceName | jsonString}}",
|
||||
"description": "{{.Message | jsonString}}",
|
||||
|
|
@ -137,8 +138,15 @@ func GetWebhookTemplates() []WebhookTemplate {
|
|||
]
|
||||
}`,
|
||||
ResolvedPayloadTemplate: `{
|
||||
"text": "Resolved: {{.ResourceName | jsonString}}",
|
||||
"text": "{{if .Mention}}{{.Mention | jsonString}} {{end}}Resolved: {{.ResourceName | jsonString}}",
|
||||
"blocks": [
|
||||
{{if .Mention}}{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "{{.Mention | jsonString}}"
|
||||
}
|
||||
},{{end}}
|
||||
{
|
||||
"type": "header",
|
||||
"text": {
|
||||
|
|
@ -217,6 +225,7 @@ func GetWebhookTemplates() []WebhookTemplate {
|
|||
"@context": "http://schema.org/extensions",
|
||||
"themeColor": "2DC72D",
|
||||
"summary": "Resolved: {{.ResourceName | jsonString}}",
|
||||
{{if .Mention}}"text": "{{.Mention | jsonString}}",{{end}}
|
||||
"sections": [{
|
||||
"activityTitle": "Resolved: {{.ResourceName | jsonString}}",
|
||||
"activitySubtitle": "{{.Message | jsonString}}",
|
||||
|
|
@ -478,7 +487,7 @@ View in Pulse: {{.Instance}}`,
|
|||
ResolvedPayloadTemplate: `{
|
||||
"username": "Pulse Monitoring",
|
||||
"icon_url": "https://raw.githubusercontent.com/rcourtman/Pulse/main/frontend-modern/public/android-chrome-192x192.png",
|
||||
"text": ":white_check_mark: **RESOLVED**\n\n**{{.ResourceName | jsonString}}** on **{{.Node | jsonString}}**\n\n{{.Message | jsonString}}\n\n| Detail | Value |\n|:-------|:------|\n| Resource | {{.ResourceName | jsonString}} |\n| Node | {{.Node | jsonString}} |\n| Type | {{.Type | title | jsonString}} |\n| Duration | {{.Duration | jsonString}} |\n| Resolved At | {{.ResolvedAt | jsonString}} |\n| Alert ID | {{.ID | jsonString}} |"
|
||||
"text": "{{if .Mention}}{{.Mention | jsonString}}\n\n{{end}}:white_check_mark: **RESOLVED**\n\n**{{.ResourceName | jsonString}}** on **{{.Node | jsonString}}**\n\n{{.Message | jsonString}}\n\n| Detail | Value |\n|:-------|:------|\n| Resource | {{.ResourceName | jsonString}} |\n| Node | {{.Node | jsonString}} |\n| Type | {{.Type | title | jsonString}} |\n| Duration | {{.Duration | jsonString}} |\n| Resolved At | {{.ResolvedAt | jsonString}} |\n| Alert ID | {{.ID | jsonString}} |"
|
||||
}`,
|
||||
Instructions: "1. In Mattermost, go to Integrations > Incoming Webhooks\n2. Create a new webhook and select the channel\n3. Copy the webhook URL and paste it here\n\nNote: This template uses Markdown formatting which is fully supported by Mattermost.",
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue