Browse Source

add SlackNotifier

tags/v1.3.0
Norwin 7 months ago
parent
commit
e9ddf63dad
5 changed files with 90 additions and 5 deletions
  1. 1
    0
      README.md
  2. 5
    0
      cmd/cmd_root.go
  3. 73
    0
      core/notifier_slack.go
  4. 5
    5
      core/notifier_xmpp.go
  5. 6
    0
      core/notifiers.go

+ 1
- 0
README.md View File

@@ -42,6 +42,7 @@ Run `osem_notify help config` for details and an example configuration.
`transport` | `options`
------------|------------
`email` | `recipients`: list of email addresses
`slack` | -
`xmpp` | `recipients`: list of JIDs

Want more? [add it](#contribute)!

+ 5
- 0
cmd/cmd_root.go View File

@@ -59,6 +59,10 @@ var configHelpCmd = &cobra.Command{
pass: bar
from: hildegunst@example.com

# only needed when sending notifications via Slack
slack:
webhook: https://hooks.slack.com/services/T030YPW07/xxxxxxx/xxxxxxxxxxxxxxxxxxxxxx

# only needed when sending notifications via XMPP
xmpp:
host: jabber.example.com:5222
@@ -72,6 +76,7 @@ var configHelpCmd = &cobra.Command{
transport | options
----------|-------------------------------------
email | recipients: list of email addresses
slack | -
xmpp | recipients: list of JIDs



+ 73
- 0
core/notifier_slack.go View File

@@ -0,0 +1,73 @@
package core

import (
"fmt"
"io/ioutil"
"net/http"

"github.com/dghubble/sling"
"github.com/spf13/viper"
)

var slackClient = sling.New().Client(&http.Client{})

var notificationColors = map[string]string {
CheckOk: "#00ff00",
CheckErr: "#ff0000",
}

// slack Notifier has no configuration
type SlackNotifier struct {
webhook string
}

type SlackMessage struct {
Text string `json:"text"`
Username string `json:"username,omitempty`
Attachments []SlackAttachment `json:"attachments,omitempty"`
}

type SlackAttachment struct {
Text string `json:"text"`
Color string `json:"color,omitempty"`
}

func (n SlackNotifier) New(config TransportConfig) (AbstractNotifier, error) {
// validate transport configuration
// :TransportConfSourceHack
baseUrl := viper.GetString("slack.webhook")
if baseUrl == "" {
return nil, fmt.Errorf("Missing configuration key slack.webhook")
}

return SlackNotifier{
webhook: baseUrl,
}, nil
}

func (n SlackNotifier) Submit(notification Notification) error {
message := &SlackMessage{
Username: "osem_notify box healthcheck",
Text: notification.Subject,
Attachments: []SlackAttachment{ { notification.Body, notificationColors[notification.Status] } },
}

req, err := slackClient.Post(n.webhook).BodyJSON(message).Request()
if err != nil {
return err
}

c := http.Client{}
res, err2 := c.Do(req)
if err2 != nil {
return err2
}

if res.StatusCode > 200 {
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
return fmt.Errorf("slack webhook failed: %s", body)
}

return nil
}

+ 5
- 5
core/notifier_xmpp.go View File

@@ -8,7 +8,7 @@ import (
"github.com/spf13/viper"
)

var client = &xmpp.Client{} // @Hacky
var xmppClient = &xmpp.Client{} // @Hacky

// box config required for the XmppNotifier (TransportConfig.Options)
type XmppNotifier struct {
@@ -27,12 +27,12 @@ func (n XmppNotifier) New(config TransportConfig) (AbstractNotifier, error) {

// establish connection with server once, and share it accross instances
// @Hacky
if client.JID() == "" {
if xmppClient.JID() == "" {
c, err := connectXmpp()
if err != nil {
return nil, err
}
client = c
xmppClient = c
}

// assign configuration to the notifier after ensuring the correct type.
@@ -65,12 +65,12 @@ func (n XmppNotifier) New(config TransportConfig) (AbstractNotifier, error) {
}

func (n XmppNotifier) Submit(notification Notification) error {
if client.JID() == "" {
if xmppClient.JID() == "" {
return fmt.Errorf("xmpp client not correctly initialized!")
}

for _, recipient := range n.Recipients {
_, err := client.Send(xmpp.Chat{
_, err := xmppClient.Send(xmpp.Chat{
Remote: recipient,
Subject: notification.Subject,
Text: fmt.Sprintf("%s\n\n%s", notification.Subject, notification.Body),

+ 6
- 0
core/notifiers.go View File

@@ -10,6 +10,7 @@ import (

var Notifiers = map[string]AbstractNotifier{
"email": EmailNotifier{},
"slack": SlackNotifier{},
"xmpp": XmppNotifier{},
}

@@ -19,6 +20,7 @@ type AbstractNotifier interface {
}

type Notification struct {
Status string // one of CheckOk | CheckErr
Body string
Subject string
}
@@ -137,17 +139,21 @@ func ComposeNotification(box *Box, checks []CheckResult) Notification {
resolved string
resolvedList string
errList string
status string
)
if len(resolvedTexts) != 0 {
resolvedList = fmt.Sprintf("Resolved issue(s):\n\n%s\n\n", strings.Join(resolvedTexts, "\n"))
}
if len(errTexts) != 0 {
errList = fmt.Sprintf("New issue(s):\n\n%s\n\n", strings.Join(errTexts, "\n"))
status = CheckErr
} else {
resolved = "resolved "
status = CheckOk
}

return Notification{
Status: status,
Subject: fmt.Sprintf("Issues %swith your box \"%s\" on opensensemap.org!", resolved, box.Name),
Body: fmt.Sprintf("A check at %s identified the following updates for your box \"%s\":\n\n%s%sYou may visit https://opensensemap.org/explore/%s for more details.\n\n--\nSent automatically by osem_notify (https://github.com/noerw/osem_notify)",
time.Now().Round(time.Minute), box.Name, errList, resolvedList, box.Id),

Loading…
Cancel
Save