Skip to content

Commit fe74545

Browse files
author
Jan Roehrich
committed
support for simultaneous cache requests for same SA
1 parent a45d9df commit fe74545

File tree

4 files changed

+164
-104
lines changed

4 files changed

+164
-104
lines changed

pkg/cache/cache.go

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
4357
type 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

5267
type 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

7691
type 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.
145154
func (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

166181
func (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

Comments
 (0)