From c0680975a75d66b89f71a5b7a92f295c59c4491d Mon Sep 17 00:00:00 2001 From: Yusuf Kanchwala Date: Fri, 7 Aug 2020 23:34:07 +0530 Subject: [PATCH] add notifier unit tests to runtime package --- pkg/runtime/executor.go | 4 +- pkg/runtime/executor_test.go | 68 +++++++++++++++++++--- pkg/runtime/notifications.go | 9 ++- pkg/runtime/notifications_test.go | 59 +++++++++++++++++++ pkg/runtime/testdata/invalid-notifier.toml | 6 ++ pkg/runtime/testdata/webhook.toml | 6 ++ 6 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 pkg/runtime/notifications_test.go create mode 100644 pkg/runtime/testdata/invalid-notifier.toml create mode 100644 pkg/runtime/testdata/webhook.toml diff --git a/pkg/runtime/executor.go b/pkg/runtime/executor.go index 40e22e558..54482321e 100644 --- a/pkg/runtime/executor.go +++ b/pkg/runtime/executor.go @@ -97,7 +97,9 @@ func (e *Executor) Execute() (normalized interface{}, err error) { // evaluate policies // send notifications, if configured - e.SendNotifications(normalized) + if err = e.SendNotifications(normalized); err != nil { + return normalized, err + } // successful return normalized, nil diff --git a/pkg/runtime/executor_test.go b/pkg/runtime/executor_test.go index 46b5ed607..3cb31d1ba 100644 --- a/pkg/runtime/executor_test.go +++ b/pkg/runtime/executor_test.go @@ -24,6 +24,8 @@ import ( iacProvider "github.com/accurics/terrascan/pkg/iac-providers" "github.com/accurics/terrascan/pkg/iac-providers/output" tfv12 "github.com/accurics/terrascan/pkg/iac-providers/terraform/v12" + "github.com/accurics/terrascan/pkg/notifications" + "github.com/accurics/terrascan/pkg/notifications/webhook" ) var ( @@ -85,6 +87,22 @@ func TestExecute(t *testing.T) { }, wantErr: nil, }, + { + name: "test SendNofitications no error", + executor: Executor{ + iacProvider: MockIacProvider{err: nil}, + notifiers: []notifications.Notifier{&MockNotifier{err: nil}}, + }, + wantErr: nil, + }, + { + name: "test SendNofitications no error", + executor: Executor{ + iacProvider: MockIacProvider{err: nil}, + notifiers: []notifications.Notifier{&MockNotifier{err: mockNotifierErr}}, + }, + wantErr: mockNotifierErr, + }, } for _, tt := range table { @@ -104,6 +122,7 @@ func TestInit(t *testing.T) { executor Executor wantErr error wantIacProvider iacProvider.IacProvider + wantNotifiers []notifications.Notifier }{ { name: "valid filePath", @@ -116,16 +135,51 @@ func TestInit(t *testing.T) { }, wantErr: nil, wantIacProvider: &tfv12.TfV12{}, + wantNotifiers: []notifications.Notifier{}, + }, + { + name: "valid notifier", + executor: Executor{ + filePath: "./testdata/testfile", + dirPath: "", + cloudType: "aws", + iacType: "terraform", + iacVersion: "v12", + configFile: "./testdata/webhook.toml", + }, + wantErr: nil, + wantIacProvider: &tfv12.TfV12{}, + wantNotifiers: []notifications.Notifier{&webhook.Webhook{}}, + }, + { + name: "config not present", + executor: Executor{ + filePath: "./testdata/testfile", + dirPath: "", + cloudType: "aws", + iacType: "terraform", + iacVersion: "v12", + configFile: "./testdata/does-not-exist", + }, + wantErr: fmt.Errorf("config file not present"), + wantIacProvider: &tfv12.TfV12{}, }, } for _, tt := range table { - gotErr := tt.executor.Init() - if !reflect.DeepEqual(gotErr, tt.wantErr) { - t.Errorf("unexpected error; gotErr: '%v', wantErr: '%v'", gotErr, tt.wantErr) - } - if !reflect.DeepEqual(tt.executor.iacProvider, tt.wantIacProvider) { - t.Errorf("got: '%v', want: '%v'", tt.executor.iacProvider, tt.wantIacProvider) - } + t.Run(tt.name, func(t *testing.T) { + gotErr := tt.executor.Init() + if !reflect.DeepEqual(gotErr, tt.wantErr) { + t.Errorf("unexpected error; gotErr: '%v', wantErr: '%v'", gotErr, tt.wantErr) + } + if !reflect.DeepEqual(tt.executor.iacProvider, tt.wantIacProvider) { + t.Errorf("got: '%v', want: '%v'", tt.executor.iacProvider, tt.wantIacProvider) + } + for i, notifier := range tt.executor.notifiers { + if !reflect.DeepEqual(reflect.TypeOf(notifier), reflect.TypeOf(tt.wantNotifiers[i])) { + t.Errorf("got: '%v', want: '%v'", reflect.TypeOf(notifier), reflect.TypeOf(tt.wantNotifiers[i])) + } + } + }) } } diff --git a/pkg/runtime/notifications.go b/pkg/runtime/notifications.go index 004b0497b..8cda3bf50 100644 --- a/pkg/runtime/notifications.go +++ b/pkg/runtime/notifications.go @@ -16,13 +16,20 @@ package runtime +import ( + "github.com/accurics/terrascan/pkg/utils" +) + // SendNotifications sends notifications via all the configured notifiers -func (e *Executor) SendNotifications(data interface{}) { +func (e *Executor) SendNotifications(data interface{}) error { + var allErrs error // send notifications using configured notifiers for _, notifier := range e.notifiers { err := notifier.SendNotification(data) if err != nil { + allErrs = utils.WrapError(err, allErrs) continue } } + return allErrs } diff --git a/pkg/runtime/notifications_test.go b/pkg/runtime/notifications_test.go new file mode 100644 index 000000000..def21bf65 --- /dev/null +++ b/pkg/runtime/notifications_test.go @@ -0,0 +1,59 @@ +package runtime + +import ( + "fmt" + "reflect" + "testing" + + "github.com/accurics/terrascan/pkg/notifications" +) + +// MockNotifier mocks notifications.Notifier interface +type MockNotifier struct { + err error +} + +var ( + mockNotifierErr = fmt.Errorf("mock notification error") +) + +func (m MockNotifier) Init(config interface{}) error { + return m.err +} + +func (m MockNotifier) SendNotification(config interface{}) error { + return m.err +} + +func TestSendNotifications(t *testing.T) { + + table := []struct { + name string + executor Executor + wantErr error + }{ + { + name: "no notifier error", + executor: Executor{ + notifiers: []notifications.Notifier{&MockNotifier{err: nil}}, + }, + wantErr: nil, + }, + { + name: "no notifier error", + executor: Executor{ + notifiers: []notifications.Notifier{&MockNotifier{err: mockNotifierErr}}, + }, + wantErr: mockNotifierErr, + }, + } + + for _, tt := range table { + t.Run(tt.name, func(t *testing.T) { + gotErr := tt.executor.SendNotifications("some data") + if !reflect.DeepEqual(gotErr, tt.wantErr) { + t.Errorf("incorrect error; got: '%v', want: '%v'", gotErr, tt.wantErr) + } + }) + } +} diff --git a/pkg/runtime/testdata/invalid-notifier.toml b/pkg/runtime/testdata/invalid-notifier.toml new file mode 100644 index 000000000..74c795e09 --- /dev/null +++ b/pkg/runtime/testdata/invalid-notifier.toml @@ -0,0 +1,6 @@ +# terrascan configuration file + +# notifications configuration +[notifications] + [notifications.invalid] + url = "https://httpbin.org/post" diff --git a/pkg/runtime/testdata/webhook.toml b/pkg/runtime/testdata/webhook.toml new file mode 100644 index 000000000..d1af36565 --- /dev/null +++ b/pkg/runtime/testdata/webhook.toml @@ -0,0 +1,6 @@ +# terrascan configuration file + +# notifications configuration +[notifications] + [notifications.webhook] + url = "https://httpbin.org/post"