diff --git a/config.yaml b/config.yaml index 71489b33d..36b2ff641 100644 --- a/config.yaml +++ b/config.yaml @@ -131,7 +131,8 @@ communications: enabled: false channel: 'SLACK_CHANNEL' token: 'SLACK_API_TOKEN' - + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) + # Settings for Mattermost mattermost: enabled: false @@ -139,7 +140,8 @@ communications: token: 'MATTERMOST_TOKEN' # Personal Access token generated by BotKube user team: 'MATTERMOST_TEAM' # Mattermost Team to configure with BotKube channel: 'MATTERMOST_CHANNEL' # Mattermost Channel for receiving BotKube alerts - + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) + # Settings for ELS elasticsearch: enabled: false diff --git a/deploy-all-in-one-tls.yaml b/deploy-all-in-one-tls.yaml index 7b14081cc..78fba8602 100644 --- a/deploy-all-in-one-tls.yaml +++ b/deploy-all-in-one-tls.yaml @@ -148,7 +148,8 @@ data: enabled: false channel: 'SLACK_CHANNEL' token: 'SLACK_API_TOKEN' - + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) + # Settings for Mattermost mattermost: enabled: false @@ -156,7 +157,8 @@ data: token: 'MATTERMOST_TOKEN' # Personal Access token generated by BotKube user team: 'MATTERMOST_TEAM' # Mattermost Team to configure with BotKube channel: 'MATTERMOST_CHANNEL' # Mattermost Channel for receiving BotKube alerts - + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) + # Settings for ELS elasticsearch: enable: false diff --git a/deploy-all-in-one.yaml b/deploy-all-in-one.yaml index 067263441..c43507bfa 100644 --- a/deploy-all-in-one.yaml +++ b/deploy-all-in-one.yaml @@ -142,7 +142,8 @@ data: enabled: false channel: 'SLACK_CHANNEL' token: 'SLACK_API_TOKEN' - + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) + # Settings for Mattermost mattermost: enabled: false @@ -150,7 +151,8 @@ data: token: 'MATTERMOST_TOKEN' # Personal Access token generated by BotKube user team: 'MATTERMOST_TEAM' # Mattermost Team to configure with BotKube channel: 'MATTERMOST_CHANNEL' # Mattermost Channel for receiving BotKube alerts - + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) + # Settings for ELS elasticsearch: enable: false diff --git a/helm/botkube/values.yaml b/helm/botkube/values.yaml index 40467876f..e9e65d850 100644 --- a/helm/botkube/values.yaml +++ b/helm/botkube/values.yaml @@ -152,6 +152,7 @@ config: enabled: false channel: 'SLACK_CHANNEL' # Slack channel name without '#' prefix where you have added BotKube and want to receive notifications in token: 'SLACK_API_TOKEN' + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) # Settings for Mattermost mattermost: @@ -161,7 +162,8 @@ config: token: 'MATTERMOST_TOKEN' # Personal Access token generated by BotKube user team: 'MATTERMOST_TEAM' # Mattermost Team to configure with BotKube channel: 'MATTERMOST_CHANNEL' # Mattermost Channel for receiving BotKube alerts - + notiftype: short # Change notification type short/long you want to receive. notiftype is optional and Default notification type is short (if not specified) + # Settings for ELS elasticsearch: enabled: false diff --git a/pkg/config/config.go b/pkg/config/config.go index 6d2cd27e0..eca4494f0 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -24,6 +24,10 @@ const ( WarningEvent EventType = "warning" // AllEvent to watch all events AllEvent EventType = "all" + // ShortNotify is the Default NotifType + ShortNotify NotifType = "short" + // LongNotify for short events notification + LongNotify NotifType = "long" ) // EventType to watch @@ -35,6 +39,9 @@ var ConfigFileName = "config.yaml" // Notify flag to toggle event notification var Notify = true +// NotifType to change notification type +type NotifType string + // Config structure of configuration yaml file type Config struct { Resources []Resource @@ -59,9 +66,10 @@ type Communications struct { // Slack configuration to authentication and send notifications type Slack struct { - Enabled bool - Channel string - Token string `yaml:",omitempty"` + Enabled bool + Channel string + NotifType NotifType `yaml:",omitempty"` + Token string `yaml:",omitempty"` } // ElasticSearch config auth settings @@ -83,11 +91,12 @@ type Index struct { // Mattermost configuration to authentication and send notifications type Mattermost struct { - Enabled bool - URL string - Token string - Team string - Channel string + Enabled bool + URL string + Token string + Team string + Channel string + NotifType NotifType `yaml:",omitempty"` } // Settings for multicluster support diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 74a47d718..44aa1daa1 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -218,6 +218,12 @@ func sendEvent(obj interface{}, c *config.Config, kind string, eventType config. return } + // check if Recommendations are disabled + if !c.Recommendations { + event.Recommendations = nil + log.Logger.Debug("Skipping Recommendations in Event Notifications") + } + var notifier notify.Notifier // Send notification to communication channel if c.Communications.Slack.Enabled { diff --git a/pkg/events/events.go b/pkg/events/events.go index 0c6048a9e..b379a5d0b 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -183,3 +183,53 @@ func New(object interface{}, eventType config.EventType, kind string) Event { return event } + +// Message returns event message in brief format. +// included as a part of event package to use across handlers. +func (event *Event) Message() (msg string) { + message := "" + if len(event.Messages) > 0 { + for _, m := range event.Messages { + message = message + m + } + } + if len(event.Recommendations) > 0 { + recommend := "" + for _, m := range event.Recommendations { + recommend = recommend + m + } + message = message + fmt.Sprintf("\nRecommendations: %s", recommend) + } + + switch event.Type { + case config.CreateEvent, config.DeleteEvent, config.UpdateEvent: + msg = fmt.Sprintf( + "%s `%s` in of cluster `%s`, namespace `%s` has been %s:\n```%s```", + event.Kind, + event.Name, + event.Cluster, + event.Namespace, + event.Type+"d", + message, + ) + case config.ErrorEvent: + msg = fmt.Sprintf( + "Error Occurred in %s: `%s` of cluster `%s`, namespace `%s`:\n```%s``` ", + event.Kind, + event.Name, + event.Cluster, + event.Namespace, + message, + ) + case config.WarningEvent: + msg = fmt.Sprintf( + "Warning %s: `%s` of cluster `%s`, namespace `%s`:\n```%s``` ", + event.Kind, + event.Name, + event.Cluster, + event.Namespace, + message, + ) + } + return msg +} diff --git a/pkg/notify/mattermost.go b/pkg/notify/mattermost.go index 0652dfa0a..58e030fc2 100644 --- a/pkg/notify/mattermost.go +++ b/pkg/notify/mattermost.go @@ -16,6 +16,7 @@ type Mattermost struct { Client *model.Client4 Channel string ClusterName string + NotifType config.NotifType } // NewMattermost returns new Mattermost object @@ -44,6 +45,7 @@ func NewMattermost(c *config.Config) (Notifier, error) { Client: client, Channel: botChannel.Id, ClusterName: c.Settings.ClusterName, + NotifType: c.Communications.Mattermost.NotifType, }, nil } @@ -51,69 +53,87 @@ func NewMattermost(c *config.Config) (Notifier, error) { func (m *Mattermost) SendEvent(event events.Event) error { log.Logger.Info(fmt.Sprintf(">> Sending to Mattermost: %+v", event)) - fields := []*model.SlackAttachmentField{ - { - Title: "Kind", - Value: event.Kind, - Short: true, - }, - { - Title: "Name", - Value: event.Name, - Short: true, - }, - } + var fields []*model.SlackAttachmentField + + switch m.NotifType { + case config.LongNotify: + fields = []*model.SlackAttachmentField{ + { + Title: "Kind", + Value: event.Kind, + Short: true, + }, + { + Title: "Name", + Value: event.Name, + Short: true, + }, + } - if event.Namespace != "" { - fields = append(fields, &model.SlackAttachmentField{ - Title: "Namespace", - Value: event.Namespace, - Short: true, - }) - } + if event.Namespace != "" { + fields = append(fields, &model.SlackAttachmentField{ + Title: "Namespace", + Value: event.Namespace, + Short: true, + }) + } - if event.Reason != "" { - fields = append(fields, &model.SlackAttachmentField{ - Title: "Reason", - Value: event.Reason, - Short: true, - }) - } + if event.Reason != "" { + fields = append(fields, &model.SlackAttachmentField{ + Title: "Reason", + Value: event.Reason, + Short: true, + }) + } - if len(event.Messages) > 0 { - message := "" - for _, m := range event.Messages { - message = message + m + if len(event.Messages) > 0 { + message := "" + for _, m := range event.Messages { + message = message + m + } + fields = append(fields, &model.SlackAttachmentField{ + Title: "Message", + Value: message, + }) } - fields = append(fields, &model.SlackAttachmentField{ - Title: "Message", - Value: message, - }) - } - if event.Action != "" { - fields = append(fields, &model.SlackAttachmentField{ - Title: "Action", - Value: event.Action, - }) - } + if event.Action != "" { + fields = append(fields, &model.SlackAttachmentField{ + Title: "Action", + Value: event.Action, + }) + } - if len(event.Recommendations) > 0 { - rec := "" - for _, r := range event.Recommendations { - rec = rec + r + if len(event.Recommendations) > 0 { + rec := "" + for _, r := range event.Recommendations { + rec = rec + r + } + fields = append(fields, &model.SlackAttachmentField{ + Title: "Recommendations", + Value: rec, + }) } + + // Add clustername in the message fields = append(fields, &model.SlackAttachmentField{ - Title: "Recommendations", - Value: rec, + Title: "Cluster", + Value: m.ClusterName, }) - } - // Add clustername in the message - fields = append(fields, &model.SlackAttachmentField{ - Title: "Cluster", - Value: m.ClusterName, - }) + case config.ShortNotify: + fallthrough + + default: + // set missing cluster name to event object + event.Cluster = m.ClusterName + fields = []*model.SlackAttachmentField{ + { + Title: fmt.Sprintf("%s", event.Kind+" "+string(event.Type)), + Value: event.Message(), + }, + } + } attachment := []*model.SlackAttachment{{ Fields: fields, diff --git a/pkg/notify/slack.go b/pkg/notify/slack.go index d6084e6eb..2c8316618 100644 --- a/pkg/notify/slack.go +++ b/pkg/notify/slack.go @@ -18,6 +18,7 @@ type Slack struct { Token string Channel string ClusterName string + NotifType config.NotifType } // NewSlack returns new Slack object @@ -34,6 +35,7 @@ func NewSlack(c *config.Config) Notifier { Token: c.Communications.Slack.Token, Channel: c.Communications.Slack.Channel, ClusterName: c.Settings.ClusterName, + NotifType: c.Communications.Slack.NotifType, } } @@ -45,79 +47,100 @@ func (s *Slack) SendEvent(event events.Event) error { params := slack.PostMessageParameters{ AsUser: true, } - attachment := slack.Attachment{ - Fields: []slack.AttachmentField{ - { - Title: "Kind", - Value: event.Kind, - Short: true, - }, - { - Title: "Name", - Value: event.Name, - Short: true, + var attachment slack.Attachment + + switch s.NotifType { + case config.LongNotify: + attachment = slack.Attachment{ + Fields: []slack.AttachmentField{ + { + Title: "Kind", + Value: event.Kind, + Short: true, + }, + { + + Title: "Name", + Value: event.Name, + Short: true, + }, }, - }, - Footer: "BotKube", - } + Footer: "BotKube", + } + if event.Namespace != "" { + attachment.Fields = append(attachment.Fields, slack.AttachmentField{ + Title: "Namespace", + Value: event.Namespace, + Short: true, + }) + } - // Add timestamp - ts := json.Number(strconv.FormatInt(event.TimeStamp.Unix(), 10)) - if ts > "0" { - attachment.Ts = ts - } + if event.Reason != "" { + attachment.Fields = append(attachment.Fields, slack.AttachmentField{ + Title: "Reason", + Value: event.Reason, + Short: true, + }) + } - if event.Namespace != "" { - attachment.Fields = append(attachment.Fields, slack.AttachmentField{ - Title: "Namespace", - Value: event.Namespace, - Short: true, - }) - } + if len(event.Messages) > 0 { + message := "" + for _, m := range event.Messages { + message = message + m + } + attachment.Fields = append(attachment.Fields, slack.AttachmentField{ + Title: "Message", + Value: message, + }) + } - if event.Reason != "" { - attachment.Fields = append(attachment.Fields, slack.AttachmentField{ - Title: "Reason", - Value: event.Reason, - Short: true, - }) - } + if event.Action != "" { + attachment.Fields = append(attachment.Fields, slack.AttachmentField{ + Title: "Action", + Value: event.Action, + }) + } - if len(event.Messages) > 0 { - message := "" - for _, m := range event.Messages { - message = message + m + if len(event.Recommendations) > 0 { + rec := "" + for _, r := range event.Recommendations { + rec = rec + r + } + attachment.Fields = append(attachment.Fields, slack.AttachmentField{ + Title: "Recommendations", + Value: rec, + }) } - attachment.Fields = append(attachment.Fields, slack.AttachmentField{ - Title: "Message", - Value: message, - }) - } - if event.Action != "" { + // Add clustername in the message attachment.Fields = append(attachment.Fields, slack.AttachmentField{ - Title: "Action", - Value: event.Action, + Title: "Cluster", + Value: s.ClusterName, }) - } - if len(event.Recommendations) > 0 { - rec := "" - for _, r := range event.Recommendations { - rec = rec + r + case config.ShortNotify: + fallthrough + + default: + // set missing cluster name to event object + event.Cluster = s.ClusterName + attachment = slack.Attachment{ + Fields: []slack.AttachmentField{ + { + Title: fmt.Sprintf("%s", event.Kind+" "+string(event.Type)), + Value: event.Message(), + }, + }, + Footer: "BotKube", } - attachment.Fields = append(attachment.Fields, slack.AttachmentField{ - Title: "Recommendations", - Value: rec, - }) } - // Add clustername in the message - attachment.Fields = append(attachment.Fields, slack.AttachmentField{ - Title: "Cluster", - Value: s.ClusterName, - }) + // Add timestamp + ts := json.Number(strconv.FormatInt(event.TimeStamp.Unix(), 10)) + if ts > "0" { + attachment.Ts = ts + } attachment.Color = attachmentColor[event.Level] params.Attachments = []slack.Attachment{attachment}