@@ -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 : "my-sa" ,
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 : "my-sa" , 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 : "my-sa" , 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 {
@@ -413,6 +481,7 @@ func TestSAAnnotationRemoval(t *testing.T) {
413481 saCache : make (map [string ]* Entry ),
414482 annotationPrefix : "eks.amazonaws.com" ,
415483 webhookUsage : prometheus .NewGauge (prometheus.GaugeOpts {}),
484+ notifications : newNotifications (make (chan * Request , 10 )),
416485 }
417486
418487 c .addSA (oldSA )
@@ -476,6 +545,7 @@ func TestCachePrecedence(t *testing.T) {
476545 defaultTokenExpiration : pkg .DefaultTokenExpiration ,
477546 annotationPrefix : "eks.amazonaws.com" ,
478547 webhookUsage : prometheus .NewGauge (prometheus.GaugeOpts {}),
548+ notifications : newNotifications (make (chan * Request , 10 )),
479549 }
480550
481551 {
@@ -574,7 +644,15 @@ func TestRoleArnComposition(t *testing.T) {
574644 informerFactory := informers .NewSharedInformerFactory (fakeClient , 0 )
575645 informer := informerFactory .Core ().V1 ().ServiceAccounts ()
576646
577- cache := New (audience , "eks.amazonaws.com" , true , 86400 , informer , nil , testComposeRoleArn )
647+ cache := New (audience ,
648+ "eks.amazonaws.com" ,
649+ true ,
650+ 86400 ,
651+ informer ,
652+ nil ,
653+ testComposeRoleArn ,
654+ fakeClient .CoreV1 (),
655+ )
578656 stop := make (chan struct {})
579657 informerFactory .Start (stop )
580658 informerFactory .WaitForCacheSync (stop )
@@ -673,6 +751,7 @@ func TestGetCommonConfigurations(t *testing.T) {
673751 defaultAudience : "sts.amazonaws.com" ,
674752 annotationPrefix : "eks.amazonaws.com" ,
675753 webhookUsage : prometheus .NewGauge (prometheus.GaugeOpts {}),
754+ notifications : newNotifications (make (chan * Request , 10 )),
676755 }
677756
678757 if tc .serviceAccount != nil {
0 commit comments