2020-04-06 18:12:43 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
2020-04-29 18:09:58 +02:00
|
|
|
"encoding/json"
|
2020-05-03 08:54:18 +02:00
|
|
|
"github.com/prometheus/alertmanager/template"
|
2020-04-06 18:42:26 +02:00
|
|
|
"github.com/matrix-org/gomatrix"
|
2020-04-06 18:12:43 +02:00
|
|
|
)
|
|
|
|
|
2020-05-03 08:54:18 +02:00
|
|
|
func generateMatrixMessageBody(alert template.Alert) string {
|
|
|
|
return alert.Status + " // " + alert.Annotations["summary"]
|
2020-04-29 18:09:58 +02:00
|
|
|
}
|
|
|
|
|
2020-04-06 18:12:43 +02:00
|
|
|
func main() {
|
|
|
|
// Initialize logger.
|
|
|
|
var logger *log.Logger = log.New(os.Stdout, "", log.Flags())
|
|
|
|
|
|
|
|
// Handle command-line arguments.
|
2020-04-06 18:42:26 +02:00
|
|
|
var homeserver = flag.String("homeserver", "https://matrix.org", "Address of Matrix homeserver")
|
|
|
|
var user = flag.String("user", "", "Full MXID (e.g. @example.domain.tld) of Matrix user")
|
|
|
|
var token = flag.String("token", "", "Access Token of Matrix user")
|
|
|
|
var target = flag.String("target-room", "", "Matrix room to be notified of alerts.")
|
2020-04-06 18:12:43 +02:00
|
|
|
var port = flag.Int("port", 9088, "HTTP port to listen on (incoming alertmanager webhooks)")
|
|
|
|
flag.Parse()
|
|
|
|
|
2020-04-06 18:42:26 +02:00
|
|
|
if *user == "" {
|
|
|
|
logger.Fatal("Matrix user is required. See --help for usage.")
|
|
|
|
}
|
|
|
|
if *token == "" {
|
|
|
|
logger.Fatal("Matrix access token is required. See --help for usage.")
|
|
|
|
}
|
|
|
|
if *target== "" {
|
|
|
|
logger.Fatal("Matrix target room is required. See --help for usage.")
|
|
|
|
}
|
|
|
|
|
2020-04-06 18:12:43 +02:00
|
|
|
// Initialize Matrix client.
|
2020-04-06 18:42:26 +02:00
|
|
|
matrixClient, err := gomatrix.NewClient(*homeserver, *user, *token)
|
|
|
|
if err != nil {
|
|
|
|
logger.Fatalf("Could not log in to Matrix (%v): %v", *homeserver, err)
|
|
|
|
}
|
|
|
|
|
2020-04-29 18:09:58 +02:00
|
|
|
joinedRooms, err := matrixClient.JoinedRooms()
|
2020-04-06 18:42:26 +02:00
|
|
|
if err != nil {
|
2020-04-29 18:09:58 +02:00
|
|
|
logger.Fatalf("Could not fetch joined rooms: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
alreadyJoinedTarget := false
|
|
|
|
for _, roomID := range joinedRooms.JoinedRooms {
|
|
|
|
// FIXME: will only work if target is a roomID, not an alias.
|
|
|
|
if *target == roomID {
|
|
|
|
alreadyJoinedTarget = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !alreadyJoinedTarget {
|
|
|
|
logger.Printf("Trying to join %v...", *target)
|
|
|
|
_, err := matrixClient.JoinRoom(*target, "", nil)
|
|
|
|
if err != nil {
|
|
|
|
logger.Fatalf("Failed to join %v: %v", *target, err)
|
|
|
|
}
|
2020-04-06 18:42:26 +02:00
|
|
|
}
|
2020-04-06 18:12:43 +02:00
|
|
|
|
|
|
|
// Initialize HTTP serve (= listen for incoming requests).
|
|
|
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Fprintf(w, `Hi! I receive prometheus-alertmanager webhooks on /alert and forward them to Matrix.
|
|
|
|
|
|
|
|
You will find more details on: http://git.sr.ht/~fnux/matrix-prometheus-alertmanager`)
|
|
|
|
})
|
|
|
|
|
|
|
|
http.HandleFunc("/alert", func(w http.ResponseWriter, r *http.Request) {
|
2020-04-29 18:09:58 +02:00
|
|
|
if r.Method != http.MethodPost {
|
|
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-05-03 08:54:18 +02:00
|
|
|
payload := template.Data{}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
}
|
2020-04-29 18:09:58 +02:00
|
|
|
|
2020-05-03 08:54:18 +02:00
|
|
|
logger.Printf("Received valid hook from %v", r.RemoteAddr)
|
2020-04-29 18:09:58 +02:00
|
|
|
|
2020-05-03 08:54:18 +02:00
|
|
|
for _, alert := range payload.Alerts {
|
|
|
|
body := generateMatrixMessageBody(alert)
|
|
|
|
logger.Printf("> %v", body)
|
|
|
|
_, err := matrixClient.SendText(*target, body)
|
|
|
|
if err != nil {
|
|
|
|
logger.Fatalf("Could not forward to Matrix: %v", err)
|
|
|
|
}
|
2020-04-29 18:09:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
w.WriteHeader(http.StatusOK)
|
2020-04-06 18:12:43 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
var listenAddr = fmt.Sprintf(":%v", *port)
|
|
|
|
logger.Printf("Listening for HTTP requests (webhooks) on %v", listenAddr)
|
|
|
|
log.Fatal(http.ListenAndServe(listenAddr, nil))
|
|
|
|
}
|