@@ -35,6 +35,7 @@ func TestSaCache(t *testing.T) {
3535 defaultAudience : "sts.amazonaws.com" ,
3636 annotationPrefix : "eks.amazonaws.com" ,
3737 webhookUsage : prometheus .NewGauge (prometheus.GaugeOpts {}),
38+ notifications : newNotifications (make (chan * Request , 10 )),
3839 }
3940
4041 resp := cache .Get (Request {Name : "default" , Namespace : "default" })
@@ -69,9 +70,9 @@ func TestNotification(t *testing.T) {
6970
7071 t .Run ("with one notification handler" , func (t * testing.T ) {
7172 cache := & serviceAccountCache {
72- saCache : map [string ]* Entry {},
73- notificationHandlers : map [ string ] chan struct {}{} ,
74- webhookUsage : prometheus . NewGauge (prometheus. GaugeOpts {} ),
73+ saCache : map [string ]* Entry {},
74+ webhookUsage : prometheus . NewGauge (prometheus. GaugeOpts {}) ,
75+ notifications : newNotifications ( make ( chan * Request , 10 ) ),
7576 }
7677
7778 // test that the requested SA is not in the cache
@@ -106,9 +107,9 @@ func TestNotification(t *testing.T) {
106107
107108 t .Run ("with 10 notification handlers" , func (t * testing.T ) {
108109 cache := & serviceAccountCache {
109- saCache : map [string ]* Entry {},
110- notificationHandlers : map [ string ] chan struct {}{} ,
111- webhookUsage : prometheus . NewGauge (prometheus. GaugeOpts {} ),
110+ saCache : map [string ]* Entry {},
111+ webhookUsage : prometheus . NewGauge (prometheus. GaugeOpts {}) ,
112+ notifications : newNotifications ( make ( chan * Request , 5 ) ),
112113 }
113114
114115 // test that the requested SA is not in the cache
@@ -153,6 +154,63 @@ func TestNotification(t *testing.T) {
153154 })
154155}
155156
157+ func TestFetchFromAPIServer (t * testing.T ) {
158+ testSA := & v1.ServiceAccount {
159+ ObjectMeta : metav1.ObjectMeta {
160+ Name : "default" ,
161+ Namespace : "default" ,
162+ Annotations : map [string ]string {
163+ "eks.amazonaws.com/role-arn" : "arn:aws:iam::111122223333:role/s3-reader" ,
164+ "eks.amazonaws.com/token-expiration" : "3600" ,
165+ },
166+ },
167+ }
168+ fakeSAClient := fake .NewSimpleClientset (testSA )
169+
170+ // use an empty informer to simulate the need to fetch SA from api server:
171+ fakeEmptyClient := fake .NewSimpleClientset ()
172+ emptyInformerFactory := informers .NewSharedInformerFactory (fakeEmptyClient , 0 )
173+ emptyInformer := emptyInformerFactory .Core ().V1 ().ServiceAccounts ()
174+
175+ cache := New (
176+ "sts.amazonaws.com" ,
177+ "eks.amazonaws.com" ,
178+ true ,
179+ 86400 ,
180+ emptyInformer ,
181+ nil ,
182+ ComposeRoleArn {},
183+ fakeSAClient .CoreV1 (),
184+ )
185+
186+ stop := make (chan struct {})
187+ emptyInformerFactory .Start (stop )
188+ emptyInformerFactory .WaitForCacheSync (stop )
189+ cache .Start (stop )
190+ defer close (stop )
191+
192+ err := wait .ExponentialBackoff (wait.Backoff {Duration : 10 * time .Millisecond , Factor : 1.0 , Steps : 3 }, func () (bool , error ) {
193+ return len (fakeEmptyClient .Actions ()) != 0 , nil
194+ })
195+ if err != nil {
196+ t .Fatalf ("informer never called client: %v" , err )
197+ }
198+
199+ resp := cache .Get (Request {Name : "default" , Namespace : "default" , RequestNotification : true })
200+ assert .False (t , resp .FoundInCache , "Expected cache entry to not be found" )
201+
202+ // wait for the notification while we fetch the SA from the API server:
203+ select {
204+ case <- resp .Notifier :
205+ // expected
206+ // test that the requested SA is now in the cache
207+ resp := cache .Get (Request {Name : "default" , Namespace : "default" , RequestNotification : false })
208+ assert .True (t , resp .FoundInCache , "Expected cache entry to be found in cache" )
209+ case <- time .After (1 * time .Second ):
210+ t .Fatal ("timeout waiting for notification" )
211+ }
212+ }
213+
156214func TestNonRegionalSTS (t * testing.T ) {
157215 trueStr := "true"
158216 falseStr := "false"
@@ -237,7 +295,16 @@ func TestNonRegionalSTS(t *testing.T) {
237295
238296 testComposeRoleArn := ComposeRoleArn {}
239297
240- cache := New (audience , "eks.amazonaws.com" , tc .defaultRegionalSTS , 86400 , informer , nil , testComposeRoleArn )
298+ cache := New (
299+ audience ,
300+ "eks.amazonaws.com" ,
301+ tc .defaultRegionalSTS ,
302+ 86400 ,
303+ informer ,
304+ nil ,
305+ testComposeRoleArn ,
306+ fakeClient .CoreV1 (),
307+ )
241308 stop := make (chan struct {})
242309 informerFactory .Start (stop )
243310 informerFactory .WaitForCacheSync (stop )
@@ -295,7 +362,8 @@ func TestPopulateCacheFromCM(t *testing.T) {
295362 }
296363
297364 c := serviceAccountCache {
298- cmCache : make (map [string ]* Entry ),
365+ cmCache : make (map [string ]* Entry ),
366+ notifications : newNotifications (make (chan * Request , 10 )),
299367 }
300368
301369 {
@@ -353,6 +421,7 @@ func TestSAAnnotationRemoval(t *testing.T) {
353421 saCache : make (map [string ]* Entry ),
354422 annotationPrefix : "eks.amazonaws.com" ,
355423 webhookUsage : prometheus .NewGauge (prometheus.GaugeOpts {}),
424+ notifications : newNotifications (make (chan * Request , 10 )),
356425 }
357426
358427 c .addSA (oldSA )
@@ -416,6 +485,7 @@ func TestCachePrecedence(t *testing.T) {
416485 defaultTokenExpiration : pkg .DefaultTokenExpiration ,
417486 annotationPrefix : "eks.amazonaws.com" ,
418487 webhookUsage : prometheus .NewGauge (prometheus.GaugeOpts {}),
488+ notifications : newNotifications (make (chan * Request , 10 )),
419489 }
420490
421491 {
@@ -514,7 +584,15 @@ func TestRoleArnComposition(t *testing.T) {
514584 informerFactory := informers .NewSharedInformerFactory (fakeClient , 0 )
515585 informer := informerFactory .Core ().V1 ().ServiceAccounts ()
516586
517- cache := New (audience , "eks.amazonaws.com" , true , 86400 , informer , nil , testComposeRoleArn )
587+ cache := New (audience ,
588+ "eks.amazonaws.com" ,
589+ true ,
590+ 86400 ,
591+ informer ,
592+ nil ,
593+ testComposeRoleArn ,
594+ fakeClient .CoreV1 (),
595+ )
518596 stop := make (chan struct {})
519597 informerFactory .Start (stop )
520598 informerFactory .WaitForCacheSync (stop )
@@ -613,6 +691,7 @@ func TestGetCommonConfigurations(t *testing.T) {
613691 defaultAudience : "sts.amazonaws.com" ,
614692 annotationPrefix : "eks.amazonaws.com" ,
615693 webhookUsage : prometheus .NewGauge (prometheus.GaugeOpts {}),
694+ notifications : newNotifications (make (chan * Request , 10 )),
616695 }
617696
618697 if tc .serviceAccount != nil {
0 commit comments