From f4483532f52ed264cf1b1ea9e6ce194190c8ea91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorben=20G=C3=BCnther?= Date: Wed, 6 Nov 2024 14:01:01 +0100 Subject: [PATCH] Add support for displaying the alert's GeneratorURL --- README.md | 20 ++++++++++---------- config.scfg | 6 +++++- config/config.go | 22 +++++++++++++++------- config/config_test.go | 10 ++++++---- main.go | 26 +++++++++++++++++++++----- 5 files changed, 57 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index bb87365..8136574 100644 --- a/README.md +++ b/README.md @@ -19,23 +19,23 @@ of this file is [scfg] and there is an [example configuration file] in this repo Furthermore you can take a look at [my deployment]. ntfy-alertmanager has support for setting ntfy [priority], [tags], [icon], [action buttons] -(which can be used to create an Alertmanager silence), [email notifications] and [phone calls]. +(which can be used to e.g. create an Alertmanager silence or open the alert's Prometheus URL), [email notifications] and [phone calls]. Define a decreasing order of labels in the config file and map those labels to tags, priority, an icon or an email address. -- For priority and icon the first found value will be chosen. Settings for "resolved" alerts will take precedence. -- Tags are added together. +- For priority and icon the first found value will be chosen. Settings for "resolved" alerts will take precedence. +- Tags are added together. ### Alertmanager config ```yaml receivers: - - name: "ntfy" - webhook_configs: - - url: "http://127.0.0.1:8080" - http_config: - basic_auth: - username: "webhookUser" - password: "webhookPass" + - name: "ntfy" + webhook_configs: + - url: "http://127.0.0.1:8080" + http_config: + basic_auth: + username: "webhookUser" + password: "webhookPass" ``` ## Contributing diff --git a/config.scfg b/config.scfg index 8076443..b8114bc 100644 --- a/config.scfg +++ b/config.scfg @@ -87,8 +87,12 @@ ntfy { # Default: "" email-address foo@example.com # Call the specified number for all alerts. Use `yes` to pick the first of your verified numbers. - Default: "" + # Default: "" call +123456789 + # Add a button that will open the alert's generator/Prometheus URL with the following label. + # This only works for the "single" alert-mode. + # Default: "" + generator-url-label source } alertmanager { diff --git a/config/config.go b/config/config.go index 1273bd7..20a4e11 100644 --- a/config/config.go +++ b/config/config.go @@ -37,13 +37,14 @@ type Config struct { } type ntfyConfig struct { - Topic string - User string - Password string - AccessToken string - CertFingerprint string - EmailAddress string - Call string + Topic string + User string + Password string + AccessToken string + CertFingerprint string + EmailAddress string + Call string + GeneratorURLLabel string } type labels struct { @@ -272,6 +273,13 @@ func parseBlock(block scfg.Block, config *Config) error { return err } } + + d = ntfyDir.Children.Get("generator-url-label") + if d != nil { + if err := d.ParseParams(&config.Ntfy.GeneratorURLLabel); err != nil { + return err + } + } } cacheDir := block.Get("cache") diff --git a/config/config_test.go b/config/config_test.go index 010dc09..d72ca40 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -50,6 +50,7 @@ ntfy { certificate-fingerprint 13:6D:2B:88:9C:57:36:D0:81:B4:B2:9C:79:09:27:62:92:CF:B8:6A:6B:D3:AD:46:35:CB:70:17:EB:99:6E:28:08:2A:B8:C6:79:4B:F6:2E:81:79:41:98:1D:53:C8:07:B3:5C:24:5F:B1:8E:B6:FB:66:B5:DD:B4:D0:5C:29:91 user user password pass + generator-url-label source } alertmanager { @@ -76,10 +77,11 @@ cache { User: "webhookUser", Password: "webhookPass", Ntfy: ntfyConfig{ - Topic: "https://ntfy.sh/alertmanager-alerts", - User: "user", - Password: "pass", - CertFingerprint: "136d2b889c5736d081b4b29c7909276292cfb86a6bd3ad4635cb7017eb996e28082ab8c6794bf62e817941981d53c807b35c245fb18eb6fb66b5ddb4d05c2991", + Topic: "https://ntfy.sh/alertmanager-alerts", + User: "user", + Password: "pass", + CertFingerprint: "136d2b889c5736d081b4b29c7909276292cfb86a6bd3ad4635cb7017eb996e28082ab8c6794bf62e817941981d53c807b35c245fb18eb6fb66b5ddb4d05c2991", + GeneratorURLLabel: "source", }, Labels: labels{Order: []string{"severity", "instance"}, Label: map[string]labelConfig{ diff --git a/main.go b/main.go index 33d0bcf..5145c18 100644 --- a/main.go +++ b/main.go @@ -50,10 +50,11 @@ type payload struct { } type alert struct { - Status string `json:"status"` - Labels map[string]string `json:"labels"` - Annotations map[string]string `json:"annotations"` - Fingerprint string `json:"fingerprint"` + Status string `json:"status"` + Labels map[string]string `json:"labels"` + Annotations map[string]string `json:"annotations"` + GeneratorURL string `json:"generatorURL"` + Fingerprint string `json:"fingerprint"` } type notification struct { @@ -67,6 +68,7 @@ type notification struct { silenceBody string fingerprint string status string + generatorURL string } type ntfyError struct { @@ -91,6 +93,7 @@ func (br *bridge) singleAlertNotifications(p *payload) []*notification { n := new(notification) n.fingerprint = alert.Fingerprint n.status = alert.Status + n.generatorURL = alert.GeneratorURL // create title n.title = fmt.Sprintf("[%s]", strings.ToUpper(alert.Status)) @@ -295,6 +298,8 @@ func (br *bridge) publish(n *notification) error { return err } + var actions []string + // ntfy authentication if br.cfg.Ntfy.Password != "" && br.cfg.Ntfy.User != "" { req.SetBasicAuth(br.cfg.Ntfy.User, br.cfg.Ntfy.Password) @@ -333,9 +338,20 @@ func (br *bridge) publish(n *notification) error { authString = fmt.Sprintf(", headers.Authorization=Basic %s", auth) } - req.Header.Set("Actions", fmt.Sprintf("http, Silence, %s, method=POST, body=%s%s", url, n.silenceBody, authString)) + actions = append(actions, fmt.Sprintf("http, Silence, %s, method=POST, body=%s%s", url, n.silenceBody, authString)) } + if br.cfg.Ntfy.GeneratorURLLabel != "" && n.generatorURL != "" { + actions = append(actions, fmt.Sprintf("view, %s, %s", br.cfg.Ntfy.GeneratorURLLabel, n.generatorURL)) + } + + nActions := len(actions) + if nActions > 3 { + // TODO: Limit actions to three + br.logger.Warn(fmt.Sprintf("Publish: Too many actions (%d), ntfy only supports up to three.", nActions)) + } + req.Header.Set("Actions", strings.Join(actions, ";")) + configFingerprint := br.cfg.Ntfy.CertFingerprint if configFingerprint != "" { tlsCfg := &tls.Config{}