mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Update the types of recipient supported by the Slack notifier (#22205)
* Alerting: Update types of supported Slack recipients * Document Slack recipient requirements
This commit is contained in:
parent
f1989f1bfc
commit
019834ae12
@ -85,7 +85,7 @@ Setting | Description
|
||||
---------- | -----------
|
||||
Url | Slack incoming webhook URL.
|
||||
Username | Set the username for the bot's message.
|
||||
Recipient | Allows you to override the Slack recipient.
|
||||
Recipient | Allows you to override the Slack recipient. You must either provide a channel Slack ID, a user Slack ID, a username reference (@<user>, all lowercase, no whitespace), or a channel reference (#<channel>, all lowercase, no whitespace).
|
||||
Icon emoji | Provide an emoji to use as the icon for the bot's message. Ex :smile:
|
||||
Icon URL | Provide a URL to an image to use as the icon for the bot's message.
|
||||
Mention Users | Optionally mention one or more users in the Slack notification sent by Grafana. You have to refer to users, comma-separated, via their corresponding Slack IDs (which you can find by clicking the overflow button on each user's Slack profile).
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -38,7 +39,7 @@ func init() {
|
||||
data-placement="right">
|
||||
</input>
|
||||
<info-popover mode="right-absolute">
|
||||
Override default channel or user, use #channel-name or @username
|
||||
Override default channel or user, use #channel-name, @username (has to be all lowercase, no whitespace), or user/channel Slack ID
|
||||
</info-popover>
|
||||
</div>
|
||||
<div class="gf-form max-width-30">
|
||||
@ -118,14 +119,15 @@ func init() {
|
||||
data-placement="right">
|
||||
</input>
|
||||
<info-popover mode="right-absolute">
|
||||
Provide a bot token to use the Slack file.upload API (starts with "xoxb"). Specify #channel-name or @username in Recipient for this to work
|
||||
Provide a bot token to use the Slack file.upload API (starts with "xoxb"). Specify Recipient for this to work
|
||||
</info-popover>
|
||||
</div>
|
||||
`,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
var reRecipient *regexp.Regexp = regexp.MustCompile("^((@[a-z0-9][a-zA-Z0-9._-]*)|(#[^ .A-Z]{1,79})|([a-zA-Z0-9]+))$")
|
||||
|
||||
// NewSlackNotifier is the constructor for the Slack notifier
|
||||
func NewSlackNotifier(model *models.AlertNotification) (alerting.Notifier, error) {
|
||||
url := model.Settings.Get("url").MustString()
|
||||
@ -133,7 +135,10 @@ func NewSlackNotifier(model *models.AlertNotification) (alerting.Notifier, error
|
||||
return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
|
||||
}
|
||||
|
||||
recipient := model.Settings.Get("recipient").MustString()
|
||||
recipient := strings.TrimSpace(model.Settings.Get("recipient").MustString())
|
||||
if recipient != "" && !reRecipient.MatchString(recipient) {
|
||||
return nil, alerting.ValidationError{Reason: fmt.Sprintf("Recipient on invalid format: %q", recipient)}
|
||||
}
|
||||
username := model.Settings.Get("username").MustString()
|
||||
iconEmoji := model.Settings.Get("icon_emoji").MustString()
|
||||
iconURL := model.Settings.Get("icon_url").MustString()
|
||||
@ -144,7 +149,9 @@ func NewSlackNotifier(model *models.AlertNotification) (alerting.Notifier, error
|
||||
uploadImage := model.Settings.Get("uploadImage").MustBool(true)
|
||||
|
||||
if mentionChannel != "" && mentionChannel != "here" && mentionChannel != "channel" {
|
||||
return nil, fmt.Errorf(fmt.Sprintf("invalid value for mentionChannel: %q", mentionChannel))
|
||||
return nil, alerting.ValidationError{
|
||||
Reason: fmt.Sprintf("Invalid value for mentionChannel: %q", mentionChannel),
|
||||
}
|
||||
}
|
||||
mentionUsers := []string{}
|
||||
for _, u := range strings.Split(mentionUsersStr, ",") {
|
||||
|
@ -15,15 +15,16 @@ func TestSlackNotifier(t *testing.T) {
|
||||
Convey("empty settings should return error", func() {
|
||||
json := `{ }`
|
||||
|
||||
settingsJSON, _ := simplejson.NewJson([]byte(json))
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
So(err, ShouldBeNil)
|
||||
model := &models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "slack",
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewSlackNotifier(model)
|
||||
So(err, ShouldNotBeNil)
|
||||
_, err = NewSlackNotifier(model)
|
||||
So(err, ShouldBeError, "Alert validation error: Could not find url property in settings")
|
||||
})
|
||||
|
||||
//nolint:goconst
|
||||
@ -71,7 +72,8 @@ func TestSlackNotifier(t *testing.T) {
|
||||
"token": "xoxb-XXXXXXXX-XXXXXXXX-XXXXXXXXXX"
|
||||
}`
|
||||
|
||||
settingsJSON, _ := simplejson.NewJson([]byte(json))
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
So(err, ShouldBeNil)
|
||||
model := &models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "slack",
|
||||
@ -94,6 +96,88 @@ func TestSlackNotifier(t *testing.T) {
|
||||
So(slackNotifier.MentionChannel, ShouldEqual, "here")
|
||||
So(slackNotifier.Token, ShouldEqual, "xoxb-XXXXXXXX-XXXXXXXX-XXXXXXXXXX")
|
||||
})
|
||||
|
||||
Convey("with channel recipient with spaces should return an error", func() {
|
||||
json := `
|
||||
{
|
||||
"url": "http://google.com",
|
||||
"recipient": "#open tsdb"
|
||||
}`
|
||||
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
So(err, ShouldBeNil)
|
||||
model := &models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "slack",
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err = NewSlackNotifier(model)
|
||||
|
||||
So(err, ShouldBeError, "Alert validation error: Recipient on invalid format: \"#open tsdb\"")
|
||||
})
|
||||
|
||||
Convey("with user recipient with spaces should return an error", func() {
|
||||
json := `
|
||||
{
|
||||
"url": "http://google.com",
|
||||
"recipient": "@user name"
|
||||
}`
|
||||
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
So(err, ShouldBeNil)
|
||||
model := &models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "slack",
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err = NewSlackNotifier(model)
|
||||
|
||||
So(err, ShouldBeError, "Alert validation error: Recipient on invalid format: \"@user name\"")
|
||||
})
|
||||
|
||||
Convey("with user recipient with uppercase letters should return an error", func() {
|
||||
json := `
|
||||
{
|
||||
"url": "http://google.com",
|
||||
"recipient": "@User"
|
||||
}`
|
||||
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
So(err, ShouldBeNil)
|
||||
model := &models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "slack",
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err = NewSlackNotifier(model)
|
||||
|
||||
So(err, ShouldBeError, "Alert validation error: Recipient on invalid format: \"@User\"")
|
||||
})
|
||||
|
||||
Convey("with Slack ID for recipient should work", func() {
|
||||
json := `
|
||||
{
|
||||
"url": "http://google.com",
|
||||
"recipient": "1ABCDE"
|
||||
}`
|
||||
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
So(err, ShouldBeNil)
|
||||
model := &models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "slack",
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSlackNotifier(model)
|
||||
So(err, ShouldBeNil)
|
||||
slackNotifier := not.(*SlackNotifier)
|
||||
|
||||
So(slackNotifier.Recipient, ShouldEqual, "1ABCDE")
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user