Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
sc.APIURL = c.Global.SlackAPIURL
}
}
for _, tc := range rcv.TeamsConfigs {
if tc.APIURL == "" {
if c.Global.TeamsAPIURL == "" {
return fmt.Errorf("no global Teams API URL set")
}
tc.APIURL = c.Global.TeamsAPIURL
}
}
for _, hc := range rcv.HipchatConfigs {
if hc.APIURL == "" {
if c.Global.HipchatURL == "" {
Expand Down Expand Up @@ -320,6 +328,7 @@ type GlobalConfig struct {
SMTPAuthIdentity string `yaml:"smtp_auth_identity,omitempty" json:"smtp_auth_identity,omitempty"`
SMTPRequireTLS bool `yaml:"smtp_require_tls,omitempty" json:"smtp_require_tls,omitempty"`
SlackAPIURL Secret `yaml:"slack_api_url,omitempty" json:"slack_api_url,omitempty"`
TeamsAPIURL Secret `yaml:"teams_api_url,omitempty" json:"teams_api_url,omitempty"`
PagerdutyURL string `yaml:"pagerduty_url,omitempty" json:"pagerduty_url,omitempty"`
HipchatURL string `yaml:"hipchat_url,omitempty" json:"hipchat_url,omitempty"`
HipchatAuthToken Secret `yaml:"hipchat_auth_token,omitempty" json:"hipchat_auth_token,omitempty"`
Expand Down Expand Up @@ -457,6 +466,7 @@ type Receiver struct {
PagerdutyConfigs []*PagerdutyConfig `yaml:"pagerduty_configs,omitempty" json:"pagerduty_configs,omitempty"`
HipchatConfigs []*HipchatConfig `yaml:"hipchat_configs,omitempty" json:"hipchat_configs,omitempty"`
SlackConfigs []*SlackConfig `yaml:"slack_configs,omitempty" json:"slack_configs,omitempty"`
TeamsConfigs []*TeamsConfig `yaml:"teams_configs,omitempty" json:"teams_configs,omitempty"`
WebhookConfigs []*WebhookConfig `yaml:"webhook_configs,omitempty" json:"webhook_configs,omitempty"`
OpsGenieConfigs []*OpsGenieConfig `yaml:"opsgenie_configs,omitempty" json:"opsgenie_configs,omitempty"`
PushoverConfigs []*PushoverConfig `yaml:"pushover_configs,omitempty" json:"pushover_configs,omitempty"`
Expand Down
44 changes: 44 additions & 0 deletions config/notifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ var (
Fallback: `{{ template "slack.default.fallback" . }}`,
}

// DefaultTeamsConfig defines default values for Microsoft Teams configurations.
DefaultTeamsConfig = TeamsConfig{
NotifierConfig: NotifierConfig{
VSendResolved: false,
},
Context: `{{ template "teams.default.context" . }}`,
Type: `{{ template "teams.default.type" . }}`,
Title: `{{ template "teams.default.title" . }}`,
Text: `{{ template "teams.default.text" . }}`,
URI: `{{ template "teams.default.uri" . }}`,
URIText: `{{ template "teams.default.uritext" . }}`,
URIOS: `{{ template "teams.default.urios" . }}`,
ThemeColor: `{{ template "teams.default.themecolor" . }}`,
}

// DefaultHipchatConfig defines default values for Hipchat configurations.
DefaultHipchatConfig = HipchatConfig{
NotifierConfig: NotifierConfig{
Expand Down Expand Up @@ -236,6 +251,35 @@ func (c *SlackConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
return checkOverflow(c.XXX, "slack config")
}

// TeamsConfig configures notifications via Microsoft Teams.
type TeamsConfig struct {
NotifierConfig `yaml:",inline" json:",inline"`

APIURL Secret `yaml:"api_url,omitempty" json:"api_url,omitempty"`

Context string `yaml:"context,omitempty" json:"context,omitempty"`
Type string `yaml:"type,omitempty" json:"type,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"`
Text string `yaml:"text,omitempty" json:"text,omitempty"`
URI string `yaml:"uri,omitempty" json:"uri,omitempty"`
URIText string `yaml:"uritext,omitempty" json:"uritext,omitempty"`
URIOS string `yaml:"urios,omitempty" json:"urios,omitempty"`
ThemeColor string `yaml:"themecolor,omitempty" json:"themecolor,omitempty"`

// Catches all undefined fields and must be empty after parsing.
XXX map[string]interface{} `yaml:",inline" json:"-"`
}

// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *TeamsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
*c = DefaultTeamsConfig
type plain TeamsConfig
if err := unmarshal((*plain)(c)); err != nil {
return err
}
return checkOverflow(c.XXX, "teams config")
}

// HipchatConfig configures notifications via Hipchat.
type HipchatConfig struct {
NotifierConfig `yaml:",inline" json:",inline"`
Expand Down
96 changes: 95 additions & 1 deletion notify/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ import (
"golang.org/x/net/context"
"golang.org/x/net/context/ctxhttp"

"net/textproto"

"github.com/prometheus/alertmanager/config"
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/alertmanager/types"
"net/textproto"
)

type notifierConfig interface {
Expand Down Expand Up @@ -120,6 +121,10 @@ func BuildReceiverIntegrations(nc *config.Receiver, tmpl *template.Template) []I
n := NewSlack(c, tmpl)
add("slack", i, n, c)
}
for i, c := range nc.TeamsConfigs {
n := NewTeams(c, tmpl)
add("teams", i, n, c)
}
for i, c := range nc.HipchatConfigs {
n := NewHipchat(c, tmpl)
add("hipchat", i, n, c)
Expand Down Expand Up @@ -607,6 +612,95 @@ func (n *Slack) retry(statusCode int) (bool, error) {
return false, nil
}

// Teams implements a Notifier for Microsoft Teams notifications.
type Teams struct {
conf *config.TeamsConfig
tmpl *template.Template
}

// NewTeams returns a new Microsoft Teams notification handler.
func NewTeams(conf *config.TeamsConfig, tmpl *template.Template) *Teams {
return &Teams{
conf: conf,
tmpl: tmpl,
}
}

type teamsReq struct {
Context string `json:"@context,omitempty"`
Type string `json:"@type,omitempty"`
Title string `json:"title,omitempty"`
Text string `json:"text"`
ThemeColor string `json:"themeColor,omitempty"`
PotentialAction []potentialAction `json:"potentialAction,omitempty"`
}

type potentialAction interface{}

type teamsOpenURI struct {
Type string `json:"@type"`
Name string `json:"name"`
Target []teamOpenURITarget `json:"targets"`
}

type teamOpenURITarget struct {
OS string `json:"os"`
URI string `json:"uri"`
}

// Notify implements the Notifier interface.
func (n *Teams) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
var err error
var (
data = n.tmpl.Data(receiverName(ctx), groupLabels(ctx), as...)
tmplText = tmplText(n.tmpl, data, &err)
)

openURI := &teamsOpenURI{
Type: "OpenUri",
Name: tmplText(n.conf.URIText),
Target: []teamOpenURITarget{
{
OS: tmplText(n.conf.URIOS),
URI: tmplText(n.conf.URI),
},
},
}

req := &teamsReq{
Context: tmplText(n.conf.Context),
Type: tmplText(n.conf.Type),
Title: tmplText(n.conf.Title),
Text: tmplText(n.conf.Text),
ThemeColor: tmplText(n.conf.ThemeColor),
PotentialAction: []potentialAction{openURI},
}
if err != nil {
return false, err
}

var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(req); err != nil {
return false, err
}

resp, err := ctxhttp.Post(ctx, http.DefaultClient, string(n.conf.APIURL), contentTypeJSON, &buf)
if err != nil {
return true, err
}
resp.Body.Close()

return n.retry(resp.StatusCode)
}

func (n *Teams) retry(statusCode int) (bool, error) {
if statusCode/100 != 2 {
return (statusCode/100 == 5), fmt.Errorf("unexpected status code %v", statusCode)
}

return false, nil
}

// Hipchat implements a Notifier for Hipchat notifications.
type Hipchat struct {
conf *config.HipchatConfig
Expand Down
9 changes: 9 additions & 0 deletions template/default.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@
{{ define "slack.default.iconurl" }}{{ end }}
{{ define "slack.default.text" }}{{ end }}

{{ define "teams.default.context" }}http://schema.org/extensions{{ end }}
{{ define "teams.default.type" }}MessageCard{{ end }}
{{ define "teams.default.title" }}{{ end }}
{{ define "teams.default.text" }}{{ template "__subject" . }}{{ end }}
{{ define "teams.default.uri" }}{{ template "__alertmanagerURL" . }}{{ end }}
{{ define "teams.default.uritext" }}View Alert{{ end }}
{{ define "teams.default.urios" }}default{{ end }}
{{ define "teams.default.themecolor" }}{{ if gt (len .Alerts.Firing) 0 }}F35225{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}81BB05{{ end }}{{ end }}


{{ define "hipchat.default.from" }}{{ template "__alertmanager" . }}{{ end }}
{{ define "hipchat.default.message" }}{{ template "__subject" . }}{{ end }}
Expand Down
Loading