diff --git a/internal/client/client.go b/internal/client/client.go new file mode 100644 index 0000000..56cb469 --- /dev/null +++ b/internal/client/client.go @@ -0,0 +1,71 @@ +package client + +import ( + "context" + "sync" + "time" + + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type cachedSecret struct { + secret *corev1.Secret + fetchUnixTime int64 +} + +type extendedClient struct { + client.Client + cachedSecrets []*cachedSecret + // add a mux to lock the operations on the cache + mux *sync.Mutex +} + +// NewExtendedClient returns an extended client capable of caching secrets on the 'Get' operation +func NewExtendedClient(baseClient client.Client) client.Client { + return &extendedClient{ + Client: baseClient, + } +} + +func (e *extendedClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { + if _, ok := obj.(*corev1.Secret); !ok { + return e.Client.Get(ctx, key, obj, opts...) + } + + e.mux.Lock() + defer e.mux.Unlock() + + // check if in cache + for _, cache := range e.cachedSecrets { + if cache.secret.Namespace == key.Namespace && cache.secret.Name == key.Name { + if time.Now().Unix()-cache.fetchUnixTime < 180 { + cache.secret.DeepCopyInto(obj.(*corev1.Secret)) + return nil + } + break + } + } + + if err := e.Client.Get(ctx, key, obj); err != nil { + return err + } + + // check if the secret is already in cache if so replace it + for _, cache := range e.cachedSecrets { + if cache.secret.Namespace == key.Namespace && cache.secret.Name == key.Name { + cache.secret = obj.(*corev1.Secret) + cache.fetchUnixTime = time.Now().Unix() + return nil + } + } + + if secret, ok := obj.(*corev1.Secret); ok { + e.cachedSecrets = append(e.cachedSecrets, &cachedSecret{ + secret: secret, + fetchUnixTime: time.Now().Unix(), + }) + } + + return nil +} diff --git a/internal/client/doc.go b/internal/client/doc.go new file mode 100644 index 0000000..1f01c8f --- /dev/null +++ b/internal/client/doc.go @@ -0,0 +1,3 @@ +// Package client provides an extended client that is capable of caching multiple secrets without relying on +// 'list and watch' +package client