[Request] Add Slack actions to notifications (#1355)

* Added slack actions to notifications

Signed-off-by: Alex Lardschneider <alex.lardschneider@gmail.com>
This commit is contained in:
Alex Lardschneider 2018-05-14 17:26:11 +02:00 committed by stuart nelson
parent 292256ca7f
commit 1f9a7b6182
2 changed files with 62 additions and 18 deletions

View File

@ -220,6 +220,34 @@ func (c *PagerdutyConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
return nil return nil
} }
// SlackAction configures a single Slack action that is sent with each notification.
// Each action must contain a type, text, and url.
// See https://api.slack.com/docs/message-attachments#action_fields for more information.
type SlackAction struct {
Type string `yaml:"type,omitempty" json:"type,omitempty"`
Text string `yaml:"text,omitempty" json:"text,omitempty"`
URL string `yaml:"url,omitempty" json:"url,omitempty"`
Style string `yaml:"style,omitempty" json:"style,omitempty"`
}
// UnmarshalYAML implements the yaml.Unmarshaler interface for SlackAction.
func (c *SlackAction) UnmarshalYAML(unmarshal func(interface{}) error) error {
type plain SlackAction
if err := unmarshal((*plain)(c)); err != nil {
return err
}
if c.Type == "" {
return fmt.Errorf("missing type in Slack action configuration")
}
if c.Text == "" {
return fmt.Errorf("missing value in Slack text configuration")
}
if c.URL == "" {
return fmt.Errorf("missing value in Slack url configuration")
}
return nil
}
// SlackField configures a single Slack field that is sent with each notification. // SlackField configures a single Slack field that is sent with each notification.
// Each field must contain a title, value, and optionally, a boolean value to indicate if the field // Each field must contain a title, value, and optionally, a boolean value to indicate if the field
// is short enough to be displayed next to other fields designated as short. // is short enough to be displayed next to other fields designated as short.
@ -258,17 +286,18 @@ type SlackConfig struct {
Username string `yaml:"username,omitempty" json:"username,omitempty"` Username string `yaml:"username,omitempty" json:"username,omitempty"`
Color string `yaml:"color,omitempty" json:"color,omitempty"` Color string `yaml:"color,omitempty" json:"color,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"` Title string `yaml:"title,omitempty" json:"title,omitempty"`
TitleLink string `yaml:"title_link,omitempty" json:"title_link,omitempty"` TitleLink string `yaml:"title_link,omitempty" json:"title_link,omitempty"`
Pretext string `yaml:"pretext,omitempty" json:"pretext,omitempty"` Pretext string `yaml:"pretext,omitempty" json:"pretext,omitempty"`
Text string `yaml:"text,omitempty" json:"text,omitempty"` Text string `yaml:"text,omitempty" json:"text,omitempty"`
Fields []*SlackField `yaml:"fields,omitempty" json:"fields,omitempty"` Fields []*SlackField `yaml:"fields,omitempty" json:"fields,omitempty"`
ShortFields bool `yaml:"short_fields,omitempty" json:"short_fields,omitempty"` ShortFields bool `yaml:"short_fields,omitempty" json:"short_fields,omitempty"`
Footer string `yaml:"footer,omitempty" json:"footer,omitempty"` Footer string `yaml:"footer,omitempty" json:"footer,omitempty"`
Fallback string `yaml:"fallback,omitempty" json:"fallback,omitempty"` Fallback string `yaml:"fallback,omitempty" json:"fallback,omitempty"`
IconEmoji string `yaml:"icon_emoji,omitempty" json:"icon_emoji,omitempty"` IconEmoji string `yaml:"icon_emoji,omitempty" json:"icon_emoji,omitempty"`
IconURL string `yaml:"icon_url,omitempty" json:"icon_url,omitempty"` IconURL string `yaml:"icon_url,omitempty" json:"icon_url,omitempty"`
LinkNames bool `yaml:"link_names,omitempty" json:"link_names,omitempty"` LinkNames bool `yaml:"link_names,omitempty" json:"link_names,omitempty"`
Actions []*SlackAction `yaml:"actions,omitempty" json:"actions,omitempty"`
} }
// UnmarshalYAML implements the yaml.Unmarshaler interface. // UnmarshalYAML implements the yaml.Unmarshaler interface.

View File

@ -638,13 +638,14 @@ type slackReq struct {
// slackAttachment is used to display a richly-formatted message block. // slackAttachment is used to display a richly-formatted message block.
type slackAttachment struct { type slackAttachment struct {
Title string `json:"title,omitempty"` Title string `json:"title,omitempty"`
TitleLink string `json:"title_link,omitempty"` TitleLink string `json:"title_link,omitempty"`
Pretext string `json:"pretext,omitempty"` Pretext string `json:"pretext,omitempty"`
Text string `json:"text"` Text string `json:"text"`
Fallback string `json:"fallback"` Fallback string `json:"fallback"`
Fields []config.SlackField `json:"fields,omitempty"` Fields []config.SlackField `json:"fields,omitempty"`
Footer string `json:"footer"` Actions []config.SlackAction `json:"actions,omitempty"`
Footer string `json:"footer"`
Color string `json:"color,omitempty"` Color string `json:"color,omitempty"`
MrkdwnIn []string `json:"mrkdwn_in,omitempty"` MrkdwnIn []string `json:"mrkdwn_in,omitempty"`
@ -691,6 +692,20 @@ func (n *Slack) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
attachment.Fields = fields attachment.Fields = fields
} }
var numActions = len(n.conf.Actions)
if numActions > 0 {
var actions = make([]config.SlackAction, numActions)
for index, action := range n.conf.Actions {
actions[index] = config.SlackAction{
Type: tmplText(action.Type),
Text: tmplText(action.Text),
URL: tmplText(action.URL),
Style: tmplText(action.Style),
}
}
attachment.Actions = actions
}
req := &slackReq{ req := &slackReq{
Channel: tmplText(n.conf.Channel), Channel: tmplText(n.conf.Channel),
Username: tmplText(n.conf.Username), Username: tmplText(n.conf.Username),