Implement MS Teams notifier

This commit is contained in:
stefanprodan
2019-07-06 17:14:21 +03:00
parent 61d0216c21
commit 8ca9cf24bb
3 changed files with 107 additions and 15 deletions
+11 -15
View File
@@ -54,10 +54,10 @@ func init() {
flag.DurationVar(&controlLoopInterval, "control-loop-interval", 10*time.Second, "Kubernetes API sync interval.")
flag.StringVar(&logLevel, "log-level", "debug", "Log level can be: debug, info, warning, error.")
flag.StringVar(&port, "port", "8080", "Port to listen on.")
flag.StringVar(&msteamsURL, "msteams-url", "", "MS Teams incoming webhook URL.")
flag.StringVar(&slackURL, "slack-url", "", "Slack hook URL.")
flag.StringVar(&slackUser, "slack-user", "flagger", "Slack user name.")
flag.StringVar(&slackChannel, "slack-channel", "", "Slack channel.")
flag.StringVar(&msteamsURL, "msteams-url", "", "MS Teams incoming webhook URL.")
flag.IntVar(&threadiness, "threadiness", 2, "Worker concurrency.")
flag.BoolVar(&zapReplaceGlobals, "zap-replace-globals", false, "Whether to change the logging level of the global zap logger.")
flag.StringVar(&zapEncoding, "zap-encoding", "json", "Zap logger encoding.")
@@ -160,25 +160,21 @@ func main() {
logger.Errorf("Metrics server %s unreachable %v", metricsServer, err)
}
var notifierClient notifier.Interface
if slackURL != "" {
f := notifier.NewFactory(slackURL, slackUser, slackChannel)
var err error
notifierClient, err = f.Notifier()
if err != nil {
logger.Errorf("Notifier %v", err)
} else {
logger.Infof("Slack notifications enabled for channel %s", slackChannel)
}
}
// setup Slack or MS Teams notifications
notifierURL := slackURL
if msteamsURL != "" {
f := notifier.NewFactory(slackURL, slackUser, slackChannel)
notifierURL = msteamsURL
}
notifierFactory := notifier.NewFactory(notifierURL, slackUser, slackChannel)
var notifierClient notifier.Interface
if notifierURL != "" {
var err error
notifierClient, err = f.Notifier()
notifierClient, err = notifierFactory.Notifier()
if err != nil {
logger.Errorf("Notifier %v", err)
} else {
logger.Infof("Slack notifications enabled for channel %s", slackChannel)
logger.Infof("Notifications enabled for %s", notifierURL[0:30])
}
}
+2
View File
@@ -22,6 +22,8 @@ func (f Factory) Notifier() (Interface, error) {
switch {
case strings.Contains(f.URL, "slack.com"):
return NewSlack(f.URL, f.Username, f.Channel)
case strings.Contains(f.URL, "office.com"):
return NewMSTeams(f.URL)
}
return nil, nil
+94
View File
@@ -0,0 +1,94 @@
package notifier
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
// MS Teams holds the incoming webhook URL
type MSTeams struct {
URL string
}
// MSTeamsPayload holds the message card data
type MSTeamsPayload struct {
Type string `json:"@type"`
Context string `json:"@context"`
ThemeColor string `json:"themeColor"`
Summary string `json:"summary"`
Sections []MSTeamsSection `json:"sections"`
}
// MSTeamsSection holds the canary analysis result
type MSTeamsSection struct {
ActivityTitle string `json:"activityTitle"`
ActivitySubtitle string `json:"activitySubtitle"`
Facts []MSTeamsField `json:"facts"`
}
type MSTeamsField struct {
Name string `json:"name"`
Value string `json:"value"`
}
// NewMSTeams validates the MS Teams URL and returns a MSTeams object
func NewMSTeams(hookURL string) (*MSTeams, error) {
_, err := url.ParseRequestURI(hookURL)
if err != nil {
return nil, fmt.Errorf("invalid MS Teams webhook URL %s", hookURL)
}
return &MSTeams{
URL: hookURL,
}, nil
}
// Post MS Teams message
func (s *MSTeams) Post(workload string, namespace string, message string, fields []Field, warn bool) error {
facts := make([]MSTeamsField, len(fields))
for _, f := range fields {
facts = append(facts, MSTeamsField{f.Name, f.Value})
}
payload := MSTeamsPayload{
Type: "MessageCard",
Context: "http://schema.org/extensions",
ThemeColor: "0076D7",
Summary: fmt.Sprintf("%s.%s", workload, namespace),
Sections: []MSTeamsSection{
{
ActivityTitle: message,
ActivitySubtitle: fmt.Sprintf("%s.%s", workload, namespace),
Facts: facts,
},
},
}
if warn {
payload.ThemeColor = "FF0000"
}
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 MS Teams 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 MS Teams failed %v", string(body))
}
}
return nil
}