forked from mcuadros/ofelia
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathslack.go
113 lines (94 loc) · 2.76 KB
/
slack.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package middlewares
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"github.com/mcuadros/ofelia/core"
)
var (
slackUsername = "Ofelia"
slackAvatarURL = "https://raw.githubusercontent.com/mcuadros/ofelia/master/static/avatar.png"
slackPayloadVar = "payload"
)
// SlackConfig configuration for the Slack middleware
type SlackConfig struct {
SlackWebhook string `gcfg:"slack-webhook" mapstructure:"slack-webhook"`
SlackOnlyOnError bool `gcfg:"slack-only-on-error" mapstructure:"slack-only-on-error"`
}
// NewSlack returns a Slack middleware if the given configuration is not empty
func NewSlack(c *SlackConfig) core.Middleware {
var m core.Middleware
if !IsEmpty(c) {
m = &Slack{*c}
}
return m
}
// Slack middleware calls to a Slack input-hook after every execution of a job
type Slack struct {
SlackConfig
}
// ContinueOnStop return allways true, we want alloways report the final status
func (m *Slack) ContinueOnStop() bool {
return true
}
// Run sends a message to the slack channel, its close stop the exection to
// collect the metrics
func (m *Slack) Run(ctx *core.Context) error {
err := ctx.Next()
ctx.Stop(err)
if ctx.Execution.Failed || !m.SlackOnlyOnError {
m.pushMessage(ctx)
}
return err
}
func (m *Slack) pushMessage(ctx *core.Context) {
values := make(url.Values, 0)
content, _ := json.Marshal(m.buildMessage(ctx))
values.Add(slackPayloadVar, string(content))
r, err := http.PostForm(m.SlackWebhook, values)
if err != nil {
ctx.Logger.Errorf("Slack error calling %q error: %q", m.SlackWebhook, err)
} else if r.StatusCode != 200 {
ctx.Logger.Errorf("Slack error non-200 status code calling %q", m.SlackWebhook)
}
}
func (m *Slack) buildMessage(ctx *core.Context) *slackMessage {
msg := &slackMessage{
Username: slackUsername,
IconURL: slackAvatarURL,
}
msg.Text = fmt.Sprintf(
"Job *%q* finished in *%s*, command `%s`",
ctx.Job.GetName(), ctx.Execution.Duration, ctx.Job.GetCommand(),
)
if ctx.Execution.Failed {
msg.Attachments = append(msg.Attachments, slackAttachment{
Title: "Execution failed",
Text: ctx.Execution.Error.Error(),
Color: "#F35A00",
})
} else if ctx.Execution.Skipped {
msg.Attachments = append(msg.Attachments, slackAttachment{
Title: "Execution skipped",
Color: "#FFA500",
})
} else {
msg.Attachments = append(msg.Attachments, slackAttachment{
Title: "Execution successful",
Color: "#7CD197",
})
}
return msg
}
type slackMessage struct {
Text string `json:"text"`
Username string `json:"username"`
Attachments []slackAttachment `json:"attachments"`
IconURL string `json:"icon_url"`
}
type slackAttachment struct {
Color string `json:"color,omitempty"`
Title string `json:"title,omitempty"`
Text string `json:"text"`
}