@@ -40,19 +40,33 @@ type Entry struct {
4040 TokenExpiration int64
4141}
4242
43+ type Request struct {
44+ Name string
45+ Namespace string
46+ RequestNotification bool
47+ }
48+
49+ func (r Request ) CacheKey () string {
50+ return r .Namespace + "/" + r .Name
51+ }
52+ func (r Request ) WithNotification () Request {
53+ r .RequestNotification = true
54+ return r
55+ }
56+
4357type Response struct {
4458 RoleARN string
4559 Audience string
4660 UseRegionalSTS bool
4761 TokenExpiration int64
4862 FoundInSACache bool
4963 FoundInCMCache bool
64+ Notifier chan struct {}
5065}
5166
5267type ServiceAccountCache interface {
5368 Start (stop chan struct {})
54- Get (name , namespace string ) Response
55- GetOrNotify (name , namespace string , handler chan struct {}) Response
69+ Get (request Request ) Response
5670 GetCommonConfigurations (name , namespace string ) (useRegionalSTS bool , tokenExpiration int64 )
5771 // ToJSON returns cache contents as JSON string
5872 ToJSON () string
@@ -71,6 +85,7 @@ type serviceAccountCache struct {
7185 defaultTokenExpiration int64
7286 webhookUsage prometheus.Gauge
7387 notificationHandlers map [string ]chan struct {}
88+ handlerMu sync.Mutex
7489}
7590
7691type ComposeRoleArn struct {
@@ -96,23 +111,17 @@ func init() {
96111}
97112
98113// Get will return the cached configuration of the given ServiceAccount.
99- // It will first look at the set of ServiceAccounts configured using annotations. If none are found, it will look for any
100- // ServiceAccount configured through the pod-identity-webhook ConfigMap.
101- func (c * serviceAccountCache ) Get (name , namespace string ) Response {
102- return c .GetOrNotify (name , namespace , nil )
103- }
104-
105- // GetOrNotify will return the cached configuration of the given ServiceAccount.
106- // It will first look at the set of ServiceAccounts configured using annotations. If none is found, it will register
107- // handler to be notified as soon as a ServiceAccount with given key is populated to the cache. Afterwards it will check
108- // for a ServiceAccount configured through the pod-identity-webhook ConfigMap.
109- func (c * serviceAccountCache ) GetOrNotify (name , namespace string , handler chan struct {}) Response {
114+ // It will first look at the set of ServiceAccounts configured using annotations. If none is found and a notifier is
115+ // requested, it will register a handler to be notified as soon as a ServiceAccount with given key is populated to the
116+ // cache. Afterward it will check for a ServiceAccount configured through the pod-identity-webhook ConfigMap.
117+ func (c * serviceAccountCache ) Get (req Request ) Response {
110118 result := Response {
111119 TokenExpiration : pkg .DefaultTokenExpiration ,
112120 }
113- klog .V (5 ).Infof ("Fetching sa %s/%s from cache" , namespace , name )
121+ klog .V (5 ).Infof ("Fetching sa %s from cache" , req . CacheKey () )
114122 {
115- entry := c .getSAorNotify (name , namespace , handler )
123+ var entry * Entry
124+ entry , result .Notifier = c .getSA (req )
116125 if entry != nil {
117126 result .FoundInSACache = true
118127 }
@@ -125,7 +134,7 @@ func (c *serviceAccountCache) GetOrNotify(name, namespace string, handler chan s
125134 }
126135 }
127136 {
128- entry := c .getCM (name , namespace )
137+ entry := c .getCM (req . Name , req . Namespace )
129138 if entry != nil {
130139 result .FoundInCMCache = true
131140 result .RoleARN = entry .RoleARN
@@ -135,32 +144,38 @@ func (c *serviceAccountCache) GetOrNotify(name, namespace string, handler chan s
135144 return result
136145 }
137146 }
138- klog .V (5 ).Infof ("Service account %s/%s not found in cache" , namespace , name )
147+ klog .V (5 ).Infof ("Service account %s not found in cache" , req . CacheKey () )
139148 return result
140149}
141150
142151// GetCommonConfigurations returns the common configurations that also applies to the new mutation method(i.e Container Credentials).
143152// The config file for the container credentials does not contain "TokenExpiration" or "UseRegionalSTS". For backward compatibility,
144153// Use these fields if they are set in the sa annotations or config map.
145154func (c * serviceAccountCache ) GetCommonConfigurations (name , namespace string ) (useRegionalSTS bool , tokenExpiration int64 ) {
146- if entry := c .getSAorNotify ( name , namespace , nil ); entry != nil {
155+ if entry , _ := c .getSA ( Request { Name : name , Namespace : namespace , RequestNotification : false } ); entry != nil {
147156 return entry .UseRegionalSTS , entry .TokenExpiration
148157 } else if entry := c .getCM (name , namespace ); entry != nil {
149158 return entry .UseRegionalSTS , entry .TokenExpiration
150159 }
151160 return false , pkg .DefaultTokenExpiration
152161}
153162
154- func (c * serviceAccountCache ) getSAorNotify ( name , namespace string , handler chan struct {}) * Entry {
163+ func (c * serviceAccountCache ) getSA ( req Request ) ( * Entry , chan struct {}) {
155164 c .mu .RLock ()
156165 defer c .mu .RUnlock ()
157- entry , ok := c .saCache [namespace + "/" + name ]
158- if ! ok && handler != nil {
159- klog .V (5 ).Infof ("Service Account %s/%s not found in cache, adding notification handler" , namespace , name )
160- c .notificationHandlers [namespace + "/" + name ] = handler
161- return nil
166+ entry , ok := c .saCache [req .CacheKey ()]
167+ if ! ok && req .RequestNotification {
168+ klog .V (5 ).Infof ("Service Account %s not found in cache, adding notification handler" , req .CacheKey ())
169+ c .handlerMu .Lock ()
170+ defer c .handlerMu .Unlock ()
171+ notifier , found := c .notificationHandlers [req .CacheKey ()]
172+ if ! found {
173+ notifier = make (chan struct {})
174+ c .notificationHandlers [req .CacheKey ()] = notifier
175+ }
176+ return nil , notifier
162177 }
163- return entry
178+ return entry , nil
164179}
165180
166181func (c * serviceAccountCache ) getCM (name , namespace string ) * Entry {
@@ -253,9 +268,11 @@ func (c *serviceAccountCache) setSA(name, namespace string, entry *Entry) {
253268 klog .V (5 ).Infof ("Adding SA %q to SA cache: %+v" , key , entry )
254269 c .saCache [key ] = entry
255270
271+ c .handlerMu .Lock ()
272+ defer c .handlerMu .Unlock ()
256273 if handler , found := c .notificationHandlers [key ]; found {
257- klog .V (5 ).Infof ("Notifying handler for %q" , key )
258- handler <- struct {}{}
274+ klog .V (5 ).Infof ("Notifying handlers for %q" , key )
275+ close ( handler )
259276 delete (c .notificationHandlers , key )
260277 }
261278}
0 commit comments