Browse Source

add SlackNotifier

tags/v1.3.0
Norwin Roosen 5 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.
42 42
 `transport` | `options`
43 43
 ------------|------------
44 44
 `email`     | `recipients`: list of email addresses
45
+`slack`     | -
45 46
 `xmpp`      | `recipients`: list of JIDs
46 47
 
47 48
 Want more? [add it](#contribute)!

+ 5
- 0
cmd/cmd_root.go View File

@@ -59,6 +59,10 @@ var configHelpCmd = &cobra.Command{
59 59
     pass: bar
60 60
     from: hildegunst@example.com
61 61
 
62
+  # only needed when sending notifications via Slack
63
+  slack:
64
+    webhook: https://hooks.slack.com/services/T030YPW07/xxxxxxx/xxxxxxxxxxxxxxxxxxxxxx
65
+
62 66
   # only needed when sending notifications via XMPP
63 67
   xmpp:
64 68
     host: jabber.example.com:5222
@@ -72,6 +76,7 @@ var configHelpCmd = &cobra.Command{
72 76
   transport | options
73 77
   ----------|-------------------------------------
74 78
   email     | recipients: list of email addresses
79
+  slack     | -
75 80
   xmpp      | recipients: list of JIDs
76 81
 
77 82
 

+ 73
- 0
core/notifier_slack.go View File

@@ -0,0 +1,73 @@
1
+package core
2
+
3
+import (
4
+	"fmt"
5
+	"io/ioutil"
6
+	"net/http"
7
+
8
+	"github.com/dghubble/sling"
9
+	"github.com/spf13/viper"
10
+)
11
+
12
+var slackClient = sling.New().Client(&http.Client{})
13
+
14
+var notificationColors = map[string]string {
15
+	CheckOk: "#00ff00",
16
+	CheckErr: "#ff0000",
17
+}
18
+
19
+// slack Notifier has no configuration
20
+type SlackNotifier struct {
21
+	webhook string
22
+}
23
+
24
+type SlackMessage struct {
25
+	Text        string            `json:"text"`
26
+	Username    string            `json:"username,omitempty`
27
+	Attachments []SlackAttachment `json:"attachments,omitempty"`
28
+}
29
+
30
+type SlackAttachment struct {
31
+	Text  string `json:"text"`
32
+	Color string `json:"color,omitempty"`
33
+}
34
+
35
+func (n SlackNotifier) New(config TransportConfig) (AbstractNotifier, error) {
36
+	// validate transport configuration
37
+	// :TransportConfSourceHack
38
+	baseUrl := viper.GetString("slack.webhook")
39
+	if baseUrl == "" {
40
+		return nil, fmt.Errorf("Missing configuration key slack.webhook")
41
+	}
42
+
43
+	return SlackNotifier{
44
+		webhook: baseUrl,
45
+	}, nil
46
+}
47
+
48
+func (n SlackNotifier) Submit(notification Notification) error {
49
+	message := &SlackMessage{
50
+		Username: "osem_notify box healthcheck",
51
+		Text:        notification.Subject,
52
+		Attachments: []SlackAttachment{ { notification.Body, notificationColors[notification.Status] } },
53
+	}
54
+
55
+	req, err := slackClient.Post(n.webhook).BodyJSON(message).Request()
56
+	if err != nil {
57
+		return err
58
+	}
59
+
60
+	c := http.Client{}
61
+	res, err2 := c.Do(req)
62
+	if err2 != nil {
63
+		return err2
64
+	}
65
+
66
+	if res.StatusCode > 200 {
67
+		defer res.Body.Close()
68
+		body, _ := ioutil.ReadAll(res.Body)
69
+		return fmt.Errorf("slack webhook failed: %s", body)
70
+	}
71
+
72
+	return nil
73
+}

+ 5
- 5
core/notifier_xmpp.go View File

@@ -8,7 +8,7 @@ import (
8 8
 	"github.com/spf13/viper"
9 9
 )
10 10
 
11
-var client = &xmpp.Client{} // @Hacky
11
+var xmppClient = &xmpp.Client{} // @Hacky
12 12
 
13 13
 // box config required for the XmppNotifier (TransportConfig.Options)
14 14
 type XmppNotifier struct {
@@ -27,12 +27,12 @@ func (n XmppNotifier) New(config TransportConfig) (AbstractNotifier, error) {
27 27
 
28 28
 	// establish connection with server once, and share it accross instances
29 29
 	// @Hacky
30
-	if client.JID() == "" {
30
+	if xmppClient.JID() == "" {
31 31
 		c, err := connectXmpp()
32 32
 		if err != nil {
33 33
 			return nil, err
34 34
 		}
35
-		client = c
35
+		xmppClient = c
36 36
 	}
37 37
 
38 38
 	// assign configuration to the notifier after ensuring the correct type.
@@ -65,12 +65,12 @@ func (n XmppNotifier) New(config TransportConfig) (AbstractNotifier, error) {
65 65
 }
66 66
 
67 67
 func (n XmppNotifier) Submit(notification Notification) error {
68
-	if client.JID() == "" {
68
+	if xmppClient.JID() == "" {
69 69
 		return fmt.Errorf("xmpp client not correctly initialized!")
70 70
 	}
71 71
 
72 72
 	for _, recipient := range n.Recipients {
73
-		_, err := client.Send(xmpp.Chat{
73
+		_, err := xmppClient.Send(xmpp.Chat{
74 74
 			Remote:  recipient,
75 75
 			Subject: notification.Subject,
76 76
 			Text:    fmt.Sprintf("%s\n\n%s", notification.Subject, notification.Body),

+ 6
- 0
core/notifiers.go View File

@@ -10,6 +10,7 @@ import (
10 10
 
11 11
 var Notifiers = map[string]AbstractNotifier{
12 12
 	"email": EmailNotifier{},
13
+	"slack": SlackNotifier{},
13 14
 	"xmpp":  XmppNotifier{},
14 15
 }
15 16
 
@@ -19,6 +20,7 @@ type AbstractNotifier interface {
19 20
 }
20 21
 
21 22
 type Notification struct {
23
+	Status  string // one of CheckOk | CheckErr
22 24
 	Body    string
23 25
 	Subject string
24 26
 }
@@ -137,17 +139,21 @@ func ComposeNotification(box *Box, checks []CheckResult) Notification {
137 139
 		resolved     string
138 140
 		resolvedList string
139 141
 		errList      string
142
+		status string
140 143
 	)
141 144
 	if len(resolvedTexts) != 0 {
142 145
 		resolvedList = fmt.Sprintf("Resolved issue(s):\n\n%s\n\n", strings.Join(resolvedTexts, "\n"))
143 146
 	}
144 147
 	if len(errTexts) != 0 {
145 148
 		errList = fmt.Sprintf("New issue(s):\n\n%s\n\n", strings.Join(errTexts, "\n"))
149
+		status = CheckErr
146 150
 	} else {
147 151
 		resolved = "resolved "
152
+		status = CheckOk
148 153
 	}
149 154
 
150 155
 	return Notification{
156
+		Status: status,
151 157
 		Subject: fmt.Sprintf("Issues %swith your box \"%s\" on opensensemap.org!", resolved, box.Name),
152 158
 		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)",
153 159
 			time.Now().Round(time.Minute), box.Name, errList, resolvedList, box.Id),

Loading…
Cancel
Save