@@ -22,7 +22,7 @@ import (
2222 kubetesting "k8s.io/client-go/testing"
2323 "k8s.io/client-go/tools/cache"
2424
25- "github.com/argoproj/notifications-engine/pkg/api"
25+ notificationApi "github.com/argoproj/notifications-engine/pkg/api"
2626 "github.com/argoproj/notifications-engine/pkg/mocks"
2727 "github.com/argoproj/notifications-engine/pkg/services"
2828 "github.com/argoproj/notifications-engine/pkg/subscriptions"
@@ -72,7 +72,6 @@ func newController(t *testing.T, ctx context.Context, client dynamic.Interface,
7272 mockCtrl .Finish ()
7373 }()
7474 mockAPI := mocks .NewMockAPI (mockCtrl )
75- mockAPI .EXPECT ().GetConfig ().Return (api.Config {}).AnyTimes ()
7675 resourceClient := client .Resource (testGVR )
7776 informer := cache .NewSharedIndexInformer (
7877 & cache.ListWatch {
@@ -98,6 +97,45 @@ func newController(t *testing.T, ctx context.Context, client dynamic.Interface,
9897 return c , mockAPI , nil
9998}
10099
100+ func newControllerWithNamespaceSupport (t * testing.T , ctx context.Context , client dynamic.Interface , opts ... Opts ) (* notificationController , map [string ]notificationApi.API , error ) {
101+ mockCtrl := gomock .NewController (t )
102+ go func () {
103+ <- ctx .Done ()
104+ mockCtrl .Finish ()
105+ }()
106+
107+ resourceClient := client .Resource (testGVR )
108+ informer := cache .NewSharedIndexInformer (
109+ & cache.ListWatch {
110+ ListFunc : func (options v1.ListOptions ) (object runtime.Object , err error ) {
111+ return resourceClient .List (context .Background (), options )
112+ },
113+ WatchFunc : func (options v1.ListOptions ) (watch.Interface , error ) {
114+ return resourceClient .Watch (context .Background (), options )
115+ },
116+ },
117+ & unstructured.Unstructured {},
118+ time .Minute ,
119+ cache.Indexers {},
120+ )
121+
122+ go informer .Run (ctx .Done ())
123+
124+ apiMap := make (map [string ]notificationApi.API )
125+ mockAPIDefault := mocks .NewMockAPI (mockCtrl )
126+ apiMap ["default" ] = mockAPIDefault
127+
128+ mockAPISelfService := mocks .NewMockAPI (mockCtrl )
129+ apiMap ["selfservice_namespace" ] = mockAPISelfService
130+
131+ c := NewControllerWithNamespaceSupport (resourceClient , informer , & mocks.FakeFactory {ApiMap : apiMap }, opts ... )
132+ if ! cache .WaitForCacheSync (ctx .Done (), informer .HasSynced ) {
133+ return nil , nil , errors .New ("failed to sync informers" )
134+ }
135+
136+ return c , apiMap , nil
137+ }
138+
101139func TestSendsNotificationIfTriggered (t * testing.T ) {
102140 ctx , cancel := context .WithCancel (context .TODO ())
103141 defer cancel ()
@@ -109,6 +147,7 @@ func TestSendsNotificationIfTriggered(t *testing.T) {
109147 assert .NoError (t , err )
110148
111149 receivedObj := map [string ]interface {}{}
150+ api .EXPECT ().GetConfig ().Return (notificationApi.Config {}).AnyTimes ()
112151 api .EXPECT ().RunTrigger ("my-trigger" , gomock .Any ()).Return ([]triggers.ConditionResult {{Triggered : true , Templates : []string {"test" }}}, nil )
113152 api .EXPECT ().Send (mock .MatchedBy (func (obj map [string ]interface {}) bool {
114153 receivedObj = obj
@@ -123,22 +162,23 @@ func TestSendsNotificationIfTriggered(t *testing.T) {
123162 assert .NoError (t , err )
124163
125164 state := NewState (annotations [notifiedAnnotationKey ])
126- assert .NotNil (t , state [StateItemKey ("mock" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" })])
165+ assert .NotNil (t , state [StateItemKey (false , "" , "mock" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" })])
127166 assert .Equal (t , app .Object , receivedObj )
128167}
129168
130169func TestDoesNotSendNotificationIfAnnotationPresent (t * testing.T ) {
131170 ctx , cancel := context .WithCancel (context .TODO ())
132171 defer cancel ()
133172 state := NotificationsState {}
134- _ = state .SetAlreadyNotified ("my-trigger" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" }, true )
173+ _ = state .SetAlreadyNotified (false , "" , "my-trigger" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" }, true )
135174 app := newResource ("test" , withAnnotations (map [string ]string {
136175 subscriptions .SubscribeAnnotationKey ("my-trigger" , "mock" ): "recipient" ,
137176 notifiedAnnotationKey : mustToJson (state ),
138177 }))
139178 ctrl , api , err := newController (t , ctx , newFakeClient (app ))
140179 assert .NoError (t , err )
141180
181+ api .EXPECT ().GetConfig ().Return (notificationApi.Config {}).AnyTimes ()
142182 api .EXPECT ().RunTrigger ("my-trigger" , gomock .Any ()).Return ([]triggers.ConditionResult {{Triggered : true , Templates : []string {"test" }}}, nil )
143183
144184 _ , err = ctrl .processResourceWithAPI (api , app , logEntry , & NotificationEventSequence {})
@@ -153,14 +193,15 @@ func TestRemovesAnnotationIfNoTrigger(t *testing.T) {
153193 defer cancel ()
154194
155195 state := NotificationsState {}
156- _ = state .SetAlreadyNotified ("my-trigger" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" }, true )
196+ _ = state .SetAlreadyNotified (false , "" , "my-trigger" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" }, true )
157197 app := newResource ("test" , withAnnotations (map [string ]string {
158198 subscriptions .SubscribeAnnotationKey ("my-trigger" , "mock" ): "recipient" ,
159199 notifiedAnnotationKey : mustToJson (state ),
160200 }))
161201 ctrl , api , err := newController (t , ctx , newFakeClient (app ))
162202 assert .NoError (t , err )
163203
204+ api .EXPECT ().GetConfig ().Return (notificationApi.Config {}).AnyTimes ()
164205 api .EXPECT ().RunTrigger ("my-trigger" , gomock .Any ()).Return ([]triggers.ConditionResult {{Triggered : false }}, nil )
165206
166207 annotations , err := ctrl .processResourceWithAPI (api , app , logEntry , & NotificationEventSequence {})
@@ -177,7 +218,7 @@ func TestUpdatedAnnotationsSavedAsPatch(t *testing.T) {
177218 defer cancel ()
178219
179220 state := NotificationsState {}
180- _ = state .SetAlreadyNotified ("my-trigger" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" }, true )
221+ _ = state .SetAlreadyNotified (false , "" , "my-trigger" , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" }, true )
181222
182223 app := newResource ("test" , withAnnotations (map [string ]string {
183224 subscriptions .SubscribeAnnotationKey ("my-trigger" , "mock" ): "recipient" ,
@@ -193,6 +234,7 @@ func TestUpdatedAnnotationsSavedAsPatch(t *testing.T) {
193234 })
194235 ctrl , api , err := newController (t , ctx , client )
195236 assert .NoError (t , err )
237+ api .EXPECT ().GetConfig ().Return (notificationApi.Config {}).AnyTimes ()
196238 api .EXPECT ().RunTrigger ("my-trigger" , gomock .Any ()).Return ([]triggers.ConditionResult {{Triggered : false }}, nil )
197239
198240 go ctrl .Run (1 , ctx .Done ())
@@ -324,6 +366,7 @@ func TestWithEventCallback(t *testing.T) {
324366
325367 ctrl , api , err := newController (t , ctx , newFakeClient (app ), WithEventCallback (mockEventCallback ))
326368 ctrl .namespaceSupport = false
369+ api .EXPECT ().GetConfig ().Return (notificationApi.Config {}).AnyTimes ()
327370 assert .NoError (t , err )
328371 ctrl .apiFactory = & mocks.FakeFactory {Api : api , Err : tc .apiErr }
329372
@@ -349,3 +392,96 @@ func TestWithEventCallback(t *testing.T) {
349392 })
350393 }
351394}
395+
396+ // verify annotations after calling processResourceWithAPI when using self-service
397+ func TestProcessResourceWithAPIWithSelfService (t * testing.T ) {
398+ ctx , cancel := context .WithCancel (context .TODO ())
399+ defer cancel ()
400+ app := newResource ("test" , withAnnotations (map [string ]string {
401+ subscriptions .SubscribeAnnotationKey ("my-trigger" , "mock" ): "recipient" ,
402+ }))
403+
404+ ctrl , api , err := newController (t , ctx , newFakeClient (app ))
405+ assert .NoError (t , err )
406+ ctrl .namespaceSupport = true
407+
408+ trigger := "my-trigger"
409+ namespace := "my-namespace"
410+
411+ receivedObj := map [string ]interface {}{}
412+
413+ //SelfService API: config has IsSelfServiceConfig set to true
414+ api .EXPECT ().GetConfig ().Return (notificationApi.Config {IsSelfServiceConfig : true , Namespace : namespace }).AnyTimes ()
415+ api .EXPECT ().RunTrigger (trigger , gomock .Any ()).Return ([]triggers.ConditionResult {{Triggered : true , Templates : []string {"test" }}}, nil )
416+ api .EXPECT ().Send (mock .MatchedBy (func (obj map [string ]interface {}) bool {
417+ receivedObj = obj
418+ return true
419+ }), []string {"test" }, services.Destination {Service : "mock" , Recipient : "recipient" }).Return (nil )
420+
421+ annotations , err := ctrl .processResourceWithAPI (api , app , logEntry , & NotificationEventSequence {})
422+ if err != nil {
423+ logEntry .Errorf ("Failed to process: %v" , err )
424+ }
425+
426+ assert .NoError (t , err )
427+
428+ state := NewState (annotations [notifiedAnnotationKey ])
429+ assert .NotZero (t , state [StateItemKey (true , namespace , trigger , triggers.ConditionResult {}, services.Destination {Service : "mock" , Recipient : "recipient" })])
430+ assert .Equal (t , app .Object , receivedObj )
431+ }
432+
433+ // verify notification sent to both default and self-service configuration after calling processResourceWithAPI when using self-service
434+ func TestProcessItemsWithSelfService (t * testing.T ) {
435+ const triggerName = "my-trigger"
436+ destination := services.Destination {Service : "mock" , Recipient : "recipient" }
437+
438+ var actualSequence * NotificationEventSequence
439+ mockEventCallback := func (eventSequence NotificationEventSequence ) {
440+ actualSequence = & eventSequence
441+ }
442+
443+ ctx , cancel := context .WithCancel (context .TODO ())
444+ defer cancel ()
445+ app := newResource ("test" , withAnnotations (map [string ]string {
446+ subscriptions .SubscribeAnnotationKey ("my-trigger" , "mock" ): "recipient" ,
447+ }))
448+
449+ ctrl , apiMap , err := newControllerWithNamespaceSupport (t , ctx , newFakeClient (app ), WithEventCallback (mockEventCallback ))
450+ assert .NoError (t , err )
451+
452+ ctrl .namespaceSupport = true
453+ //SelfService API: config has IsSelfServiceConfig set to true
454+ apiMap ["selfservice_namespace" ].(* mocks.MockAPI ).EXPECT ().GetConfig ().Return (notificationApi.Config {IsSelfServiceConfig : true , Namespace : "selfservice_namespace" }).Times (3 )
455+ apiMap ["selfservice_namespace" ].(* mocks.MockAPI ).EXPECT ().RunTrigger (triggerName , gomock .Any ()).Return ([]triggers.ConditionResult {{Triggered : true , Templates : []string {"test" }}}, nil )
456+ apiMap ["selfservice_namespace" ].(* mocks.MockAPI ).EXPECT ().Send (mock .MatchedBy (func (obj map [string ]interface {}) bool {
457+ return true
458+ }), []string {"test" }, destination ).Return (nil ).AnyTimes ()
459+
460+ apiMap ["default" ].(* mocks.MockAPI ).EXPECT ().GetConfig ().Return (notificationApi.Config {IsSelfServiceConfig : false , Namespace : "default" }).Times (3 )
461+ apiMap ["default" ].(* mocks.MockAPI ).EXPECT ().RunTrigger (triggerName , gomock .Any ()).Return ([]triggers.ConditionResult {{Triggered : true , Templates : []string {"test" }}}, nil )
462+ apiMap ["default" ].(* mocks.MockAPI ).EXPECT ().Send (mock .MatchedBy (func (obj map [string ]interface {}) bool {
463+ return true
464+ }), []string {"test" }, destination ).Return (nil ).AnyTimes ()
465+
466+ ctrl .apiFactory = & mocks.FakeFactory {ApiMap : apiMap }
467+
468+ ctrl .processQueueItem ()
469+
470+ assert .Equal (t , app , actualSequence .Resource )
471+
472+ expectedDeliveries := []NotificationDelivery {
473+ {
474+ Trigger : triggerName ,
475+ Destination : destination ,
476+ },
477+ {
478+ Trigger : triggerName ,
479+ Destination : destination ,
480+ },
481+ }
482+ for i , event := range actualSequence .Delivered {
483+ assert .Equal (t , expectedDeliveries [i ].Trigger , event .Trigger )
484+ assert .Equal (t , expectedDeliveries [i ].Destination , event .Destination )
485+ }
486+
487+ }
0 commit comments