From 4138f37f9a6d48975f744bcc01df9c30fd24a430 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Sun, 25 Nov 2018 11:40:35 +0200 Subject: [PATCH] Add Slack notifier component --- pkg/notifier/slack.go | 102 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 pkg/notifier/slack.go diff --git a/pkg/notifier/slack.go b/pkg/notifier/slack.go new file mode 100644 index 00000000..389c6b18 --- /dev/null +++ b/pkg/notifier/slack.go @@ -0,0 +1,102 @@ +package notifier + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/http" + "net/url" +) + +// Slack holds the hook URL +type Slack struct { + URL string + Username string + Channel string + IconEmoji string +} + +// SlackPayload holds the channel and attachments +type SlackPayload struct { + Channel string `json:"channel"` + Username string `json:"username"` + IconUrl string `json:"icon_url"` + IconEmoji string `json:"icon_emoji"` + Text string `json:"text,omitempty"` + Attachments []SlackAttachment `json:"attachments,omitempty"` +} + +// SlackAttachment holds the markdown message body +type SlackAttachment struct { + Color string `json:"color"` + AuthorName string `json:"author_name"` + Text string `json:"text"` + MrkdwnIn []string `json:"mrkdwn_in"` +} + +// NewSlack validates the Slack URL and returns a Slack object +func NewSlack(hookURL string, username string, channel string) (*Slack, error) { + _, err := url.ParseRequestURI(hookURL) + if err != nil { + return nil, fmt.Errorf("invalid Slack hook URL %s", hookURL) + } + + if username == "" { + return nil, errors.New("empty Slack username") + } + + if channel == "" { + return nil, errors.New("empty Slack channel") + } + + return &Slack{ + Channel: channel, + URL: hookURL, + Username: username, + IconEmoji: ":rocket:", + }, nil +} + +// Post Slack message +func (s *Slack) Post(workload string, namespace string, message string, warn bool) error { + payload := SlackPayload{ + Channel: s.Channel, + Username: s.Username, + } + + color := "good" + if warn { + color = "danger" + } + + a := SlackAttachment{ + Color: color, + AuthorName: fmt.Sprintf("%s.%s", workload, namespace), + Text: message, + MrkdwnIn: []string{"text"}, + } + + payload.Attachments = []SlackAttachment{a} + + data, err := json.Marshal(payload) + if err != nil { + return fmt.Errorf("marshalling slack payload failed %v", err) + } + + b := bytes.NewBuffer(data) + + if res, err := http.Post(s.URL, "application/json", b); err != nil { + return fmt.Errorf("sending data to slack failed %v", err) + } else { + defer res.Body.Close() + statusCode := res.StatusCode + if statusCode != 200 { + body, _ := ioutil.ReadAll(res.Body) + return fmt.Errorf("sending data to slack failed %v", string(body)) + } + } + + return nil +}