From ca62fdaedd39488ef9d17152917ab8b3daeac082 Mon Sep 17 00:00:00 2001 From: Prasad Ghangal Date: Sat, 7 Sep 2019 17:41:52 +0530 Subject: [PATCH] Make notification messages more readable Signed-off-by: Prasad Ghangal --- pkg/events/events.go | 37 +++++++++++++++--------------- pkg/notify/mattermost.go | 13 +++++++---- pkg/notify/slack.go | 1 + test/e2e/filters/filters.go | 18 +++++++-------- test/e2e/notifier/create/create.go | 12 +++++----- 5 files changed, 42 insertions(+), 39 deletions(-) diff --git a/pkg/events/events.go b/pkg/events/events.go index 87ad7f014..8b1c215ee 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -33,6 +33,7 @@ const ( // Event to store required information from k8s objects type Event struct { Code string + Title string Kind string Name string Namespace string @@ -96,10 +97,10 @@ func New(object interface{}, eventType config.EventType, kind string) Event { if kind != "events" { switch eventType { case config.ErrorEvent, config.InfoEvent: - event.Messages = []string{fmt.Sprintf("Resource %s\n", eventType.String())} + event.Title = fmt.Sprintf("Resource %s", eventType.String()) default: // Events like create, update, delete comes with an extra 'd' at the end - event.Messages = []string{fmt.Sprintf("Resource %sd\n", eventType.String())} + event.Title = fmt.Sprintf("Resource %sd", eventType.String()) } } @@ -190,64 +191,62 @@ func (event *Event) Message() (msg string) { switch event.Kind { case "Namespace", "Node", "PersistentVolume", "ClusterRole", "ClusterRoleBinding": msg = fmt.Sprintf( - "%s `%s` in of cluster `%s` has been %s:\n```%s```", + "%s *%s/%s* has been %s in *%s* cluster", event.Kind, + event.Namespace, event.Name, - event.Cluster, event.Type+"d", - message, + event.Cluster, ) default: msg = fmt.Sprintf( - "%s `%s` in of cluster `%s`, namespace `%s` has been %s:\n```%s```", + "%s *%s/%s* has been %s in *%s* cluster", event.Kind, - event.Name, - event.Cluster, event.Namespace, + event.Name, event.Type+"d", - message, + event.Cluster, ) } case config.ErrorEvent: switch event.Kind { case "Namespace", "Node", "PersistentVolume", "ClusterRole", "ClusterRoleBinding": msg = fmt.Sprintf( - "Error Occurred in %s: `%s` of cluster `%s`:\n```%s``` ", + "Error Occurred in %s: *%s* in *%s* cluster", event.Kind, event.Name, event.Cluster, - message, ) default: msg = fmt.Sprintf( - "Error Occurred in %s: `%s` of cluster `%s`, namespace `%s`:\n```%s``` ", + "Error Occurred in %s: *%s* in *%s* cluster", event.Kind, event.Name, event.Cluster, - event.Namespace, - message, ) } case config.WarningEvent: switch event.Kind { case "Namespace", "Node", "PersistentVolume", "ClusterRole", "ClusterRoleBinding": msg = fmt.Sprintf( - "Warning %s: `%s` of cluster `%s`:\n```%s``` ", + "Warning %s: *%s* in *%s* cluster", event.Kind, event.Name, event.Cluster, - message, ) default: msg = fmt.Sprintf( - "Warning %s: `%s` of cluster `%s`, namespace `%s`:\n```%s``` ", + "Warning %s: *%s* in *%s* cluster", event.Kind, event.Name, event.Cluster, - event.Namespace, - message, ) } } + + // Add message in the attachment if there is any + if len(message) > 0 { + msg += fmt.Sprintf("\n```%s```", message) + } return msg } diff --git a/pkg/notify/mattermost.go b/pkg/notify/mattermost.go index b1f468d1d..c42b960ce 100644 --- a/pkg/notify/mattermost.go +++ b/pkg/notify/mattermost.go @@ -146,11 +146,14 @@ func (m *Mattermost) SendEvent(event events.Event) error { } } - attachment := []*model.SlackAttachment{{ - Fields: fields, - Footer: "BotKube", - Timestamp: json.Number(strconv.FormatInt(event.TimeStamp.Unix(), 10)), - }} + attachment := []*model.SlackAttachment{ + { + Pretext: fmt.Sprintf("*%s*", event.Title), + Fields: fields, + Footer: "BotKube", + Timestamp: json.Number(strconv.FormatInt(event.TimeStamp.Unix(), 10)), + }, + } post := &model.Post{} post.Props = map[string]interface{}{ diff --git a/pkg/notify/slack.go b/pkg/notify/slack.go index 2f9618e16..6f5255f49 100644 --- a/pkg/notify/slack.go +++ b/pkg/notify/slack.go @@ -43,6 +43,7 @@ func FormatSlackMessage(event events.Event, notifyType config.NotifType, cluster switch notifyType { case config.LongNotify: attachment = slack.Attachment{ + Pretext: fmt.Sprintf("*%s*", event.Title), Fields: []slack.AttachmentField{ { Title: "Kind", diff --git a/test/e2e/filters/filters.go b/test/e2e/filters/filters.go index 3f92b868a..07577b061 100644 --- a/test/e2e/filters/filters.go +++ b/test/e2e/filters/filters.go @@ -28,12 +28,12 @@ func (c *context) testFilters(t *testing.T) { Namespace: "test", Specs: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "nginx-pod", Labels: map[string]string{"env": "test"}}, Spec: v1.PodSpec{Containers: []v1.Container{{Name: "nginx", Image: "nginx:latest"}}}}, ExpectedSlackMessage: utils.SlackMessage{ - Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod `nginx-pod` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- :latest tag used in image 'nginx:latest' of Container 'nginx' should be avoided.\n```", Short: false}}, Footer: "BotKube"}}, + Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod *test/nginx-pod* has been created in *test-cluster-1* cluster\n```Recommendations:\n- :latest tag used in image 'nginx:latest' of Container 'nginx' should be avoided.\n```", Short: false}}, Footer: "BotKube"}}, }, ExpectedWebhookPayload: utils.WebhookPayload{ EventMeta: notify.EventMeta{Kind: "Pod", Name: "nginx-pod", Namespace: "test", Cluster: "test-cluster-1"}, - EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: "", Messages: []string{"Resource created\n"}}, - Summary: "Pod `nginx-pod` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- :latest tag used in image 'nginx:latest' of Container 'nginx' should be avoided.\n```", + EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: ""}, + Summary: "Pod *test/nginx-pod* has been created in *test-cluster-1* cluster\n```Recommendations:\n- :latest tag used in image 'nginx:latest' of Container 'nginx' should be avoided.\n```", }, }, @@ -42,12 +42,12 @@ func (c *context) testFilters(t *testing.T) { Namespace: "test", Specs: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod-wo-label"}}, ExpectedSlackMessage: utils.SlackMessage{ - Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod `pod-wo-label` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- pod 'pod-wo-label' creation without labels should be avoided.\n```", Short: false}}, Footer: "BotKube"}}, + Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod *test/pod-wo-label* has been created in *test-cluster-1* cluster\n```Recommendations:\n- pod 'pod-wo-label' creation without labels should be avoided.\n```", Short: false}}, Footer: "BotKube"}}, }, ExpectedWebhookPayload: utils.WebhookPayload{ EventMeta: notify.EventMeta{Kind: "Pod", Name: "pod-wo-label", Namespace: "test", Cluster: "test-cluster-1"}, - EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: "", Messages: []string{"Resource created\n"}}, - Summary: "Pod `pod-wo-label` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- pod 'pod-wo-label' creation without labels should be avoided.\n```", + EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: ""}, + Summary: "Pod *test/pod-wo-label* has been created in *test-cluster-1* cluster\n```Recommendations:\n- pod 'pod-wo-label' creation without labels should be avoided.\n```", }, }, @@ -56,12 +56,12 @@ func (c *context) testFilters(t *testing.T) { Namespace: "test", Specs: &extV1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{Name: "ingress-with-service"}, Spec: extV1beta1.IngressSpec{Rules: []extV1beta1.IngressRule{{IngressRuleValue: extV1beta1.IngressRuleValue{HTTP: &extV1beta1.HTTPIngressRuleValue{Paths: []extV1beta1.HTTPIngressPath{{Path: "testpath", Backend: extV1beta1.IngressBackend{ServiceName: "test-service", ServicePort: intstr.FromInt(80)}}}}}}}}}, ExpectedSlackMessage: utils.SlackMessage{ - Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Ingress create", Value: "Ingress `ingress-with-service` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nWarnings:\n- Service 'test-service' used in ingress 'ingress-with-service' config does not exist or port '80' not exposed\n```", Short: false}}, Footer: "BotKube"}}, + Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Ingress create", Value: "Ingress *test/ingress-with-service* has been created in *test-cluster-1* cluster\n```Warnings:\n- Service 'test-service' used in ingress 'ingress-with-service' config does not exist or port '80' not exposed\n```", Short: false}}, Footer: "BotKube"}}, }, ExpectedWebhookPayload: utils.WebhookPayload{ EventMeta: notify.EventMeta{Kind: "Ingress", Name: "ingress-with-service", Namespace: "test", Cluster: "test-cluster-1"}, - EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: "", Messages: []string{"Resource created\n"}}, - Summary: "Ingress `ingress-with-service` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nWarnings:\n- Service 'test-service' used in ingress 'ingress-with-service' config does not exist or port '80' not exposed\n```", + EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: ""}, + Summary: "Ingress *test/ingress-with-service* has been created in *test-cluster-1* cluster\n```Warnings:\n- Service 'test-service' used in ingress 'ingress-with-service' config does not exist or port '80' not exposed\n```", }, }, } diff --git a/test/e2e/notifier/create/create.go b/test/e2e/notifier/create/create.go index 134800b6b..ae9e4b3af 100644 --- a/test/e2e/notifier/create/create.go +++ b/test/e2e/notifier/create/create.go @@ -28,12 +28,12 @@ func (c *context) testCreateResource(t *testing.T) { Namespace: "test", Specs: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test-pod"}}, ExpectedSlackMessage: testutils.SlackMessage{ - Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod `test-pod` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- pod 'test-pod' creation without labels should be avoided.\n```", Short: false}}, Footer: "BotKube"}}, + Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Pod create", Value: "Pod *test/test-pod* has been created in *test-cluster-1* cluster\n```Recommendations:\n- pod 'test-pod' creation without labels should be avoided.\n```", Short: false}}, Footer: "BotKube"}}, }, ExpectedWebhookPayload: testutils.WebhookPayload{ EventMeta: notify.EventMeta{Kind: "Pod", Name: "test-pod", Namespace: "test", Cluster: "test-cluster-1"}, - EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: "", Messages: []string{"Resource created\n"}}, - Summary: "Pod `test-pod` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\nRecommendations:\n- pod 'test-pod' creation without labels should be avoided.\n```", + EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: ""}, + Summary: "Pod *test/test-pod* has been created in *test-cluster-1* cluster\n```Recommendations:\n- pod 'test-pod' creation without labels should be avoided.\n```", }, }, "create service in configured namespace": { @@ -41,12 +41,12 @@ func (c *context) testCreateResource(t *testing.T) { Namespace: "test", Specs: &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "test-service"}}, ExpectedSlackMessage: testutils.SlackMessage{ - Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Service create", Value: "Service `test-service` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\n```", Short: false}}, Footer: "BotKube"}}, + Attachments: []slack.Attachment{{Color: "good", Fields: []slack.AttachmentField{{Title: "Service create", Value: "Service *test/test-service* has been created in *test-cluster-1* cluster", Short: false}}, Footer: "BotKube"}}, }, ExpectedWebhookPayload: testutils.WebhookPayload{ EventMeta: notify.EventMeta{Kind: "Service", Name: "test-service", Namespace: "test", Cluster: "test-cluster-1"}, - EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: "", Messages: []string{"Resource created\n"}}, - Summary: "Service `test-service` in of cluster `test-cluster-1`, namespace `test` has been created:\n```Resource created\n```", + EventStatus: notify.EventStatus{Type: "create", Level: "info", Reason: "", Error: ""}, + Summary: "Service *test/test-service* has been created in *test-cluster-1* cluster", }, }, }