mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-09-19 06:31:47 +00:00
fix bug in jwtcachefiller caused when status update returns error
Co-authored-by: Ashish Amarnath <ashish.amarnath@broadcom.com>
This commit is contained in:
co-authored by
Ashish Amarnath
parent
a888083c50
commit
f5da417450
@@ -36,6 +36,7 @@ type Key struct {
|
||||
|
||||
type Value interface {
|
||||
authenticator.Token
|
||||
Close()
|
||||
}
|
||||
|
||||
// New returns an empty cache.
|
||||
@@ -45,21 +46,31 @@ func New() *Cache {
|
||||
|
||||
// Get an authenticator by key.
|
||||
func (c *Cache) Get(key Key) Value {
|
||||
res, _ := c.cache.Load(key)
|
||||
if res == nil {
|
||||
v, _ := c.cache.Load(key)
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
return res.(Value)
|
||||
return v.(Value)
|
||||
}
|
||||
|
||||
// Store an authenticator into the cache.
|
||||
// Store an authenticator into the cache. If overwriting a value in the cache, closes the overwritten value.
|
||||
func (c *Cache) Store(key Key, value Value) {
|
||||
c.cache.Store(key, value)
|
||||
previousValue, _ := c.cache.Swap(key, value)
|
||||
// Wait until after it has been overwritten in the cache to close it, to ensure that it is only closed
|
||||
// after it is not available for cache reads anymore.
|
||||
if previousValue != nil {
|
||||
previousValue.(Value).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Delete an authenticator from the cache.
|
||||
// Delete an authenticator from the cache. Closes the authenticator after removing it from the cache.
|
||||
func (c *Cache) Delete(key Key) {
|
||||
c.cache.Delete(key)
|
||||
deletedValue, _ := c.cache.LoadAndDelete(key)
|
||||
// Wait until after it has been removed from the cache to close it, to ensure that it is only closed
|
||||
// after it is not available for cache reads anymore.
|
||||
if deletedValue != nil {
|
||||
deletedValue.(Value).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Keys currently stored in the cache.
|
||||
|
||||
@@ -19,35 +19,52 @@ import (
|
||||
|
||||
authenticationv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
loginapi "go.pinniped.dev/generated/latest/apis/concierge/login"
|
||||
"go.pinniped.dev/internal/mocks/mocktokenauthenticator"
|
||||
"go.pinniped.dev/internal/mocks/mockcachevalue"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
t.Cleanup(func() {
|
||||
ctrl.Finish()
|
||||
})
|
||||
|
||||
cache := New()
|
||||
require.NotNil(t, cache)
|
||||
|
||||
key1 := Key{Name: "authenticator-one"}
|
||||
mockToken1 := mocktokenauthenticator.NewMockToken(ctrl)
|
||||
cache.Store(key1, mockToken1)
|
||||
require.Equal(t, mockToken1, cache.Get(key1))
|
||||
mockValue1 := mockcachevalue.NewMockValue(ctrl)
|
||||
require.Nil(t, cache.Get(key1))
|
||||
cache.Store(key1, mockValue1)
|
||||
require.Equal(t, mockValue1, cache.Get(key1))
|
||||
require.Equal(t, 1, len(cache.Keys()))
|
||||
|
||||
key2 := Key{Name: "authenticator-two"}
|
||||
mockToken2 := mocktokenauthenticator.NewMockToken(ctrl)
|
||||
cache.Store(key2, mockToken2)
|
||||
require.Equal(t, mockToken2, cache.Get(key2))
|
||||
mockValue2 := mockcachevalue.NewMockValue(ctrl)
|
||||
cache.Store(key2, mockValue2)
|
||||
require.Equal(t, mockValue2, cache.Get(key2))
|
||||
require.Equal(t, 2, len(cache.Keys()))
|
||||
|
||||
// Assert that Close() has not been called yet, and it should be called by the end of the test.
|
||||
mockValue1.EXPECT().Close().Times(1)
|
||||
mockValue2.EXPECT().Close().Times(1)
|
||||
|
||||
for _, key := range cache.Keys() {
|
||||
cache.Delete(key)
|
||||
}
|
||||
require.Zero(t, len(cache.Keys()))
|
||||
|
||||
key3 := Key{Name: "authenticator-three"}
|
||||
mockValue3 := mockcachevalue.NewMockValue(ctrl)
|
||||
cache.Store(key3, mockValue3)
|
||||
require.Equal(t, mockValue3, cache.Get(key3))
|
||||
require.Equal(t, 1, len(cache.Keys()))
|
||||
mockValue4 := mockcachevalue.NewMockValue(ctrl)
|
||||
// Assert that Close() has not been called yet, and it should be called by the end of the test.
|
||||
mockValue3.EXPECT().Close().Times(1)
|
||||
cache.Store(key3, mockValue4) // overwrite
|
||||
|
||||
// Fill the cache back up with a fixed set of keys, but inserted in shuffled order.
|
||||
keysInExpectedOrder := []Key{
|
||||
{APIGroup: "a", Kind: "a", Name: "a"},
|
||||
@@ -92,7 +109,7 @@ func TestAuthenticateTokenCredentialRequest(t *testing.T) {
|
||||
mockCache := func(t *testing.T, res *authenticator.Response, authenticated bool, err error) *Cache {
|
||||
ctrl := gomock.NewController(t)
|
||||
t.Cleanup(ctrl.Finish)
|
||||
m := mocktokenauthenticator.NewMockToken(ctrl)
|
||||
m := mockcachevalue.NewMockValue(ctrl)
|
||||
m.EXPECT().AuthenticateToken(audienceFreeContext{}, validRequest.Spec.Token).Return(res, authenticated, err)
|
||||
c := New()
|
||||
c.Store(validRequestKey, m)
|
||||
@@ -137,7 +154,7 @@ func TestAuthenticateTokenCredentialRequest(t *testing.T) {
|
||||
t.Run("context is cancelled", func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
t.Cleanup(ctrl.Finish)
|
||||
m := mocktokenauthenticator.NewMockToken(ctrl)
|
||||
m := mockcachevalue.NewMockValue(ctrl)
|
||||
m.EXPECT().AuthenticateToken(gomock.Any(), validRequest.Spec.Token).DoAndReturn(
|
||||
func(ctx context.Context, token string) (*authenticator.Response, bool, error) {
|
||||
select {
|
||||
|
||||
Reference in New Issue
Block a user