Browse Source

Initial Prometheus alertmanager webhook

tags/v0.4.4
Russ Garrett 4 years ago
parent
commit
573057a305
No account linked to committer's email address

+ 7
- 0
README.md View File

@@ -91,6 +91,13 @@ GitHub can be configured to deliver webhooks to irccat on an organisation level
91 91
 with the `default_channel` setting, significantly reduces configuration effort compared to
92 92
 GitHub's old integrations system.
93 93
 
94
+### Prometheus Alertmanager Webhook
95
+```json
96
+"prometheus": "#channel"
97
+```
98
+
99
+Receives [Prometheus Alertmanager webhooks](https://prometheus.io/docs/alerting/configuration/#webhook_config) at `/prometheus`. They will be sent to the channel defined in `http.listeners.prometheus`. Note that this endpoint is unauthenticated.
100
+
94 101
 ## IRC → Shell
95 102
 You can use irccat to execute commands from IRC:
96 103
 

+ 4
- 0
go.mod View File

@@ -6,7 +6,11 @@ require (
6 6
 	github.com/deckarep/golang-set v1.7.1
7 7
 	github.com/fsnotify/fsnotify v1.4.7
8 8
 	github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8
9
+	github.com/spf13/pflag v1.0.5 // indirect
9 10
 	github.com/spf13/viper v1.5.0
11
+	github.com/stretchr/testify v1.3.0 // indirect
10 12
 	github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb
13
+	golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e // indirect
11 14
 	gopkg.in/go-playground/webhooks.v5 v5.13.0
15
+	gopkg.in/yaml.v2 v2.2.7 // indirect
12 16
 )

+ 13
- 0
go.sum View File

@@ -14,6 +14,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
14 14
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
15 15
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
16 16
 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
17
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
17 18
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
18 19
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
19 20
 github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
@@ -48,6 +49,7 @@ github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVE
48 49
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
49 50
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
50 51
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
52
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
51 53
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
52 54
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
53 55
 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@@ -77,6 +79,7 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
77 79
 github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
78 80
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
79 81
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
82
+github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
80 83
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
81 84
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
82 85
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -88,11 +91,16 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9
88 91
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
89 92
 github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
90 93
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
94
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
95
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
91 96
 github.com/spf13/viper v1.5.0 h1:GpsTwfsQ27oS/Aha/6d1oD7tpKIqWnOA6tgOX9HHkt4=
92 97
 github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4=
98
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
93 99
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
94 100
 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
95 101
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
102
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
103
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
96 104
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
97 105
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
98 106
 github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb h1:EavwSqheIJl3nb91HhkL73DwnT2Fk8W3yM7T7TuLZvA=
@@ -106,6 +114,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
106 114
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
107 115
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
108 116
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
117
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
109 118
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
110 119
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
111 120
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -124,6 +133,8 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
124 133
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
125 134
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
126 135
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
136
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
137
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
127 138
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
128 139
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
129 140
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
@@ -148,4 +159,6 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
148 159
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
149 160
 gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
150 161
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
162
+gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
163
+gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
151 164
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 5
- 0
httplistener/httplistener.go View File

@@ -40,6 +40,11 @@ func New(irc *irc.Connection) (*HTTPListener, error) {
40 40
 		mux.HandleFunc("/github", hl.githubHandler)
41 41
 	}
42 42
 
43
+	if viper.IsSet("http.listeners.prometheus") {
44
+		log.Infof("Listening for Prometheus Alertmanager webhooks at /prometheus")
45
+		mux.HandleFunc("/prometheus", hl.prometheusHandler)
46
+	}
47
+
43 48
 	hl.http.Handler = mux
44 49
 	if viper.GetBool("http.tls") {
45 50
 		go hl.http.ListenAndServeTLS(viper.GetString("http.tls_cert"), viper.GetString("http.tls_key"))

+ 53
- 0
httplistener/prometheus.go View File

@@ -0,0 +1,53 @@
1
+package httplistener
2
+
3
+import (
4
+	"bytes"
5
+	"encoding/json"
6
+	"github.com/spf13/viper"
7
+	"net/http"
8
+)
9
+
10
+type HookMessage struct {
11
+	Version           string            `json:"version"`
12
+	GroupKey          string            `json:"groupKey"`
13
+	Status            string            `json:"status"`
14
+	Receiver          string            `json:"receiver"`
15
+	GroupLabels       map[string]string `json:"groupLabels"`
16
+	CommonLabels      map[string]string `json:"commonLabels"`
17
+	CommonAnnotations map[string]string `json:"commonAnnotations"`
18
+	ExternalURL       string            `json:"externalURL"`
19
+	Alerts            []Alert           `json:"alerts"`
20
+}
21
+
22
+type Alert struct {
23
+	Status       string            `json:"status"`
24
+	Labels       map[string]string `json:"labels"`
25
+	Annotations  map[string]string `json:"annotations"`
26
+	StartsAt     string            `json:"startsAt,omitempty"`
27
+	EndsAt       string            `json:"endsAt,omitempty"`
28
+	GeneratorURL string            `json:"generatorURL"`
29
+}
30
+
31
+func (hl *HTTPListener) prometheusHandler(w http.ResponseWriter, request *http.Request) {
32
+	if request.Method != "POST" {
33
+		http.NotFound(w, request)
34
+		return
35
+	}
36
+
37
+	var message HookMessage
38
+	buf := new(bytes.Buffer)
39
+	buf.ReadFrom(request.Body)
40
+	json.Unmarshal(buf.Bytes(), &message)
41
+	log.Infof("%s [%s] Prometheus alert", request.RemoteAddr, viper.GetString("http.listeners.prometheus"))
42
+
43
+	msgs, err := hl.renderTemplate("prometheus.alert", message)
44
+	if err != nil {
45
+		log.Errorf("Unable to render template: %s", err)
46
+		return
47
+	}
48
+
49
+	channel := viper.GetString("http.listeners.prometheus")
50
+	for _, msg := range msgs {
51
+		hl.irc.Privmsg(channel, msg)
52
+	}
53
+}

+ 2
- 0
httplistener/templates.go View File

@@ -18,6 +18,8 @@ var defaultTemplates = map[string]string{
18 18
 	"github.issue":        "[{{b .Repository.Name}}] {{g .Sender.Login}} {{.Action}} issue #{{.Issue.Number}}: {{.Issue.Title}} {{.Issue.HTMLURL}}",
19 19
 	"github.issuecomment": "[{{b .Repository.Name}}] {{g .Comment.User.Login}} commented on issue #{{.Issue.Number}}: {{trunc .Comment.Body 150}} {{.Comment.HTMLURL}}",
20 20
 	"github.pullrequest":  "[{{b .Repository.Name}}] {{g .Sender.Login}} {{if .PullRequest.Merged}}merged{{else}}{{.Action}}{{end}} pull request #{{.PullRequest.Number}} (\x0303{{.PullRequest.Base.Ref}}…{{.PullRequest.Head.Ref}}\x0f): {{.PullRequest.Title}} {{.PullRequest.HTMLURL}}",
21
+	"prometheus.alert": `{{range .Alerts}}[{{b "Prometheus"}}] {{if (eq .Status "firing")}}{{b "alerting"}}{{else}}{{h "resolved"}}{{end}}: {{.Annotations.summary}}
22
+{{end}}`,
21 23
 }
22 24
 
23 25
 func refName(ref string) string {

+ 26
- 0
webhook_test_data/prometheus/alert.json View File

@@ -0,0 +1,26 @@
1
+{
2
+  "version": "4",
3
+  "groupKey": "group",
4
+  "status": "firing",
5
+  "receiver": "irccat",
6
+  "groupLabels": {},
7
+  "commonLabels": {},
8
+  "commonAnnotations": {},
9
+  "externalURL": "http://alertmanager:9093",
10
+  "alerts": [
11
+    {
12
+      "status": "firing",
13
+      "labels": {
14
+	"alertname": "Test Alert",
15
+	"instance": "test.example.com",
16
+	"job": "jobname"
17
+      },
18
+      "annotations": {
19
+	"summary": "Alert summary"
20
+      },
21
+      "startsAt": "2019-11-10T23:20:50.52Z",
22
+      "endsAt": "2019-11-10T23:20:50.52Z",
23
+      "generatorURL": "http://prometheus:9090/graph?"
24
+    }
25
+  ]
26
+}

+ 26
- 0
webhook_test_data/prometheus/resolved.json View File

@@ -0,0 +1,26 @@
1
+{
2
+  "version": "4",
3
+  "groupKey": "group",
4
+  "status": "firing",
5
+  "receiver": "irccat",
6
+  "groupLabels": {},
7
+  "commonLabels": {},
8
+  "commonAnnotations": {},
9
+  "externalURL": "http://alertmanager:9093",
10
+  "alerts": [
11
+    {
12
+      "status": "firing",
13
+      "labels": {
14
+	"alertname": "Test Alert",
15
+	"instance": "test.example.com",
16
+	"job": "jobname"
17
+      },
18
+      "annotations": {
19
+	"summary": "Alert summary"
20
+      },
21
+      "startsAt": "2019-11-10T23:20:50.52Z",
22
+      "endsAt": "2019-11-10T23:20:50.52Z",
23
+      "generatorURL": "http://prometheus:9090/graph?"
24
+    }
25
+  ]
26
+}

Loading…
Cancel
Save