mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
Implement MS Teams notifier
This commit is contained in:
+11
-15
@@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user