M README.md => README.md +9 -4
@@ 16,10 16,11 @@ You can specify the configuration file location with the `--config` flag. By def
the configuration file will be read from `/etc/ntfy-alertmanager/config`. The format
of this file is [scfg].
-ntfy-alertmanager has support for setting ntfy [priority] and [tags]. Define a
-decreasing order of labels in the config file and map those labels to tags or priority.
+ntfy-alertmanager has support for setting ntfy [priority], [tags], [icon] and [action buttons]
+(which can be used to create an Alertmanager silence).
+Define a decreasing order of labels in the config file and map those labels to tags, priority or an icon.
-- For priority the first found value will be chosen.
+- For priority and icon the first found value will be chosen. An icon for "resolved" alerts will take precedence.
- Tags are added together.
Example:
@@ 45,6 46,7 @@ labels {
severity "critical" {
priority 5
tags "rotating_light"
+ icon "https://foo.com/critical.png"
}
severity "info" {
@@ 56,9 58,10 @@ labels {
}
}
-# Set tags for resolved alerts
+# Settings for resolved alerts
resolved {
tags "resolved,partying_face"
+ icon "https://foo.com/resolved.png"
}
ntfy {
@@ 118,6 121,8 @@ Report bugs on the [issue tracker].
[scfg]: https://git.sr.ht/~emersion/scfg
[priority]: https://ntfy.sh/docs/publish/#message-priority
[tags]: https://ntfy.sh/docs/publish/#tags-emojis
+[icon]: https://docs.ntfy.sh/publish/#icons
+[action buttons]: https://docs.ntfy.sh/publish/#action-buttons
[issue tracker]: https://todo.xenrox.net/~xenrox/ntfy-alertmanager
[docker image]: https://hub.docker.com/r/xenrox/ntfy-alertmanager
[docker-compose file]: https://git.xenrox.net/~xenrox/ntfy-alertmanager/tree/master/item/docker/docker-compose.yml
M config.go => config.go +16 -0
@@ 43,6 43,7 @@ type labels struct {
type labelConfig struct {
Priority string
Tags []string
+ Icon string
}
type cacheConfig struct {
@@ 59,6 60,7 @@ type alertmanagerConfig struct {
type resolvedConfig struct {
Tags []string
+ Icon string
}
func readConfig(path string) (*config, error) {
@@ 169,6 171,13 @@ func readConfig(path string) (*config, error) {
labelConfig.Tags = strings.Split(tags, ",")
}
+ d = labelDir.Children.Get("icon")
+ if d != nil {
+ if err := d.ParseParams(&labelConfig.Icon); err != nil {
+ return nil, err
+ }
+ }
+
labels[fmt.Sprintf("%s:%s", labelName, name)] = *labelConfig
}
}
@@ 288,6 297,13 @@ func readConfig(path string) (*config, error) {
config.resolved.Tags = strings.Split(tags, ",")
}
+
+ d = resolvedDir.Children.Get("icon")
+ if d != nil {
+ if err := d.ParseParams(&config.resolved.Icon); err != nil {
+ return nil, err
+ }
+ }
}
return config, nil
M config_test.go => config_test.go +4 -1
@@ 30,6 30,7 @@ labels {
severity "critical" {
priority 5
tags "rotating_light"
+ icon "https://foo.com/critical.png"
}
severity "info" {
@@ 43,6 44,7 @@ labels {
resolved {
tags "resolved,partying_face"
+ icon "https://foo.com/resolved.png"
}
ntfy {
@@ 85,7 87,7 @@ cache {
ntfy: ntfyConfig{Topic: "https://ntfy.sh/alertmanager-alerts", User: "user", Password: "pass"},
labels: labels{Order: []string{"severity", "instance"},
Label: map[string]labelConfig{
- "severity:critical": {Priority: "5", Tags: []string{"rotating_light"}},
+ "severity:critical": {Priority: "5", Tags: []string{"rotating_light"}, Icon: "https://foo.com/critical.png"},
"severity:info": {Priority: "1"},
"instance:example.com": {Tags: []string{"computer", "example"}},
},
@@ 99,6 101,7 @@ cache {
},
resolved: resolvedConfig{
Tags: []string{"resolved", "partying_face"},
+ Icon: "https://foo.com/resolved.png",
},
}
M main.go => main.go +15 -0
@@ 49,6 49,7 @@ type notification struct {
body string
priority string
tags string
+ icon string
silenceBody string
fingerprint fingerprint
status string
@@ 90,6 91,7 @@ func (rcv *receiver) singleAlertNotifications(p *payload) []*notification {
var tags []string
if alert.Status == "resolved" {
tags = append(tags, rcv.cfg.resolved.Tags...)
+ n.icon = rcv.cfg.resolved.Icon
}
for _, labelName := range rcv.cfg.labels.Order {
@@ 107,6 109,10 @@ func (rcv *receiver) singleAlertNotifications(p *payload) []*notification {
n.priority = labelConfig.Priority
}
+ if n.icon == "" {
+ n.icon = labelConfig.Icon
+ }
+
for _, val := range labelConfig.Tags {
if !sliceContains(tags, val) {
tags = append(tags, val)
@@ 181,6 187,7 @@ func (rcv *receiver) multiAlertNotification(p *payload) *notification {
var tags []string
if p.Status == "resolved" {
tags = append(tags, rcv.cfg.resolved.Tags...)
+ n.icon = rcv.cfg.resolved.Icon
}
for _, labelName := range rcv.cfg.labels.Order {
@@ 198,6 205,10 @@ func (rcv *receiver) multiAlertNotification(p *payload) *notification {
priority = labelConfig.Priority
}
+ if n.icon == "" {
+ n.icon = labelConfig.Icon
+ }
+
for _, val := range labelConfig.Tags {
if !sliceContains(tags, val) {
tags = append(tags, val)
@@ 245,6 256,10 @@ func (rcv *receiver) publish(n *notification) error {
req.Header.Set("X-Priority", n.priority)
}
+ if n.icon != "" {
+ req.Header.Set("X-Icon", n.icon)
+ }
+
if n.tags != "" {
req.Header.Set("X-Tags", n.tags)
}