Skip to content

Commit aeb87c4

Browse files
committed
hash cache keys
1 parent 889b381 commit aeb87c4

File tree

5 files changed

+121
-82
lines changed

5 files changed

+121
-82
lines changed

modules/common/client/cache/cache.go

+9-30
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cache
22

33
import (
4-
"fmt"
54
"sync"
65
"time"
76

@@ -13,9 +12,8 @@ import (
1312
)
1413

1514
var (
16-
cache *theine.Cache[string, any]
17-
contextCache *theine.Cache[string, string]
18-
cacheLocks sync.Map
15+
cache *theine.Cache[string, any]
16+
cacheLocks sync.Map
1917
)
2018

2119
func init() {
@@ -25,30 +23,10 @@ func init() {
2523
}
2624
}
2725

28-
func getCacheKey(token, key string) (string, error) {
29-
if !args.ClusterContextEnabled() {
30-
return key, nil
31-
}
32-
33-
contextKey, exists := contextCache.Get(token)
34-
if exists {
35-
klog.V(4).InfoS("context key found in cache", "key", contextKey)
36-
return fmt.Sprintf("%s:%s", contextKey, key), nil
37-
}
38-
39-
contextKey, err := exchangeToken(token)
40-
if err != nil {
41-
return "", err
42-
}
43-
44-
contextCache.SetWithTTL(token, contextKey, 1, args.CacheTTL())
45-
return fmt.Sprintf("%s:%s", contextKey, key), nil
46-
}
47-
48-
func Get[T any](token, key string) (T, bool, error) {
26+
func Get[T any](key Key) (T, bool, error) {
4927
typedValue := lo.Empty[T]()
5028

51-
cacheKey, err := getCacheKey(token, key)
29+
cacheKey, err := key.SHA()
5230
if err != nil {
5331
return typedValue, false, err
5432
}
@@ -61,18 +39,19 @@ func Get[T any](token, key string) (T, bool, error) {
6139
return typedValue, exists, nil
6240
}
6341

64-
func Set[T any](token, key string, value T) error {
65-
cacheKey, err := getCacheKey(token, key)
42+
func Set[T any](key Key, value T) error {
43+
cacheKey, err := key.SHA()
6644
if err != nil {
6745
return err
6846
}
47+
6948
_ = cache.SetWithTTL(cacheKey, value, 1, args.CacheTTL())
7049
return nil
7150
}
7251

73-
func DeferredLoad[T any](token, key string, loadFunc func() (T, error)) {
52+
func DeferredLoad[T any](key Key, loadFunc func() (T, error)) {
7453
go func() {
75-
cacheKey, err := getCacheKey(token, key)
54+
cacheKey, err := key.SHA()
7655
if err != nil {
7756
klog.ErrorS(err, "failed loading cache key", "key", cacheKey)
7857
return

modules/common/client/cache/client/core/pods.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ type pods struct {
2525
}
2626

2727
func (in *pods) List(ctx context.Context, opts metav1.ListOptions) (*corev1.PodList, error) {
28-
cachedList, found, err := cache.Get[*corev1.PodList](in.token, in.cacheKey())
28+
cacheKey := in.cacheKey(opts)
29+
30+
cachedList, found, err := cache.Get[*corev1.PodList](cacheKey)
2931
if err != nil {
3032
return nil, err
3133
}
@@ -36,8 +38,8 @@ func (in *pods) List(ctx context.Context, opts metav1.ListOptions) (*corev1.PodL
3638
return list, err
3739
}
3840

39-
klog.V(3).InfoS("pods not found in cache, initializing", "cache-key", in.cacheKey())
40-
return list, cache.Set[*corev1.PodList](in.token, in.cacheKey(), list)
41+
klog.V(3).InfoS("pods not found in cache, initializing", "cache-key", cacheKey)
42+
return list, cache.Set[*corev1.PodList](cacheKey, list)
4143
}
4244

4345
review, err := in.authorizationV1.SelfSubjectAccessReviews().Create(ctx, in.selfSubjectAccessReview(), metav1.CreateOptions{})
@@ -46,8 +48,8 @@ func (in *pods) List(ctx context.Context, opts metav1.ListOptions) (*corev1.PodL
4648
}
4749

4850
if review.Status.Allowed {
49-
klog.V(3).InfoS("pods found in cache, updating in background", "cache-key", in.cacheKey())
50-
cache.DeferredLoad[*corev1.PodList](in.token, in.cacheKey(), func() (*corev1.PodList, error) {
51+
klog.V(3).InfoS("pods found in cache, updating in background", "cache-key", cacheKey)
52+
cache.DeferredLoad[*corev1.PodList](cacheKey, func() (*corev1.PodList, error) {
5153
return in.PodInterface.List(ctx, opts)
5254
})
5355
return cachedList, nil
@@ -71,12 +73,8 @@ func (in *pods) selfSubjectAccessReview() *authorizationapiv1.SelfSubjectAccessR
7173
}
7274
}
7375

74-
func (in *pods) cacheKey() string {
75-
if len(in.namespace) == 0 {
76-
return types.ResourceKindPod
77-
}
78-
79-
return fmt.Sprintf("%s/%s", in.namespace, types.ResourceKindPod)
76+
func (in *pods) cacheKey(opts metav1.ListOptions) cache.Key {
77+
return cache.NewKey(types.ResourceKindPod, in.namespace, in.token, opts)
8078
}
8179

8280
func newPods(c *Client, namespace, token string) v1.PodInterface {

modules/common/client/cache/httpclient.go

-41
This file was deleted.

modules/common/client/cache/key.go

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package cache
2+
3+
import (
4+
"io"
5+
"net/http"
6+
7+
"github.com/Yiling-J/theine-go"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"k8s.io/dashboard/client/args"
10+
"k8s.io/dashboard/helpers"
11+
"k8s.io/dashboard/types"
12+
"k8s.io/klog/v2"
13+
)
14+
15+
var contextCache *theine.Cache[string, string]
16+
17+
type key struct {
18+
Kind types.ResourceKind
19+
Namespace string
20+
Opts metav1.ListOptions
21+
}
22+
23+
func (k key) SHA() (string, error) {
24+
k.Opts = metav1.ListOptions{LabelSelector: k.Opts.LabelSelector, FieldSelector: k.Opts.FieldSelector}
25+
return helpers.HashObject(k)
26+
}
27+
28+
type Key struct {
29+
key
30+
Token string
31+
context string
32+
}
33+
34+
func (k Key) SHA() (sha string, err error) {
35+
if !args.ClusterContextEnabled() {
36+
return k.key.SHA()
37+
}
38+
39+
contextKey, exists := contextCache.Get(k.Token)
40+
if !exists {
41+
contextKey, err = exchangeToken(k.Token)
42+
if err != nil {
43+
return "", err
44+
}
45+
46+
contextCache.SetWithTTL(k.Token, contextKey, 1, args.CacheTTL())
47+
}
48+
49+
k.Opts = metav1.ListOptions{LabelSelector: k.Opts.LabelSelector, FieldSelector: k.Opts.FieldSelector}
50+
k.Token = ""
51+
k.context = contextKey
52+
return helpers.HashObject(k)
53+
}
54+
55+
func NewKey(kind types.ResourceKind, namespace, token string, opts metav1.ListOptions) Key {
56+
return Key{
57+
key: key{Kind: kind, Namespace: namespace, Opts: opts},
58+
Token: token,
59+
}
60+
}
61+
62+
type tokenExchangeTransport struct {
63+
token string
64+
transport http.RoundTripper
65+
}
66+
67+
func (in *tokenExchangeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
68+
req.Header.Set("Authorization", "Bearer "+in.token)
69+
return in.transport.RoundTrip(req)
70+
}
71+
72+
func exchangeToken(token string) (string, error) {
73+
client := &http.Client{Transport: &tokenExchangeTransport{
74+
token: token,
75+
transport: http.DefaultTransport,
76+
}}
77+
78+
response, err := client.Get(args.TokenExchangeEndpoint())
79+
if err != nil {
80+
return "", err
81+
}
82+
83+
defer response.Body.Close()
84+
contextKey, err := io.ReadAll(response.Body)
85+
if err != nil {
86+
return "", err
87+
}
88+
89+
klog.V(3).InfoS("token exchange successful", "context", contextKey)
90+
return string(contextKey), nil
91+
}

modules/common/helpers/common.go

+12
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ package helpers
1616

1717
import (
1818
"crypto/rand"
19+
"crypto/sha256"
20+
"encoding/base32"
1921
"encoding/base64"
22+
"encoding/json"
2023
"os"
2124
"strings"
2225
)
@@ -56,3 +59,12 @@ func Random64BaseEncodedBytes(size int) string {
5659
bytes := RandomBytes(size)
5760
return base64.StdEncoding.EncodeToString(bytes)
5861
}
62+
63+
func HashObject(any interface{}) (string, error) {
64+
out, err := json.Marshal(any)
65+
if err != nil {
66+
return "", err
67+
}
68+
sha := sha256.Sum256(out)
69+
return base32.StdEncoding.EncodeToString(sha[:]), nil
70+
}

0 commit comments

Comments
 (0)