From 62d2737faa6cc3a2ddc6364765a3dd6562818fc0 Mon Sep 17 00:00:00 2001 From: Brad Davidson Date: Tue, 16 Dec 2025 00:11:04 +0000 Subject: [PATCH] lint: unchecked-type-assertion Adds a generic wrapper around lru.Cache Signed-off-by: Brad Davidson --- pkg/etcd/s3/s3.go | 7 ++--- pkg/etcd/s3/s3_test.go | 38 +++++++++++------------ pkg/server/handlers/handlers.go | 14 +++++++-- pkg/util/logger/logger.go | 5 ++- pkg/util/lru.go | 54 +++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 pkg/util/lru.go diff --git a/pkg/etcd/s3/s3.go b/pkg/etcd/s3/s3.go index f1aa7aa1cbe..94a174a5934 100644 --- a/pkg/etcd/s3/s3.go +++ b/pkg/etcd/s3/s3.go @@ -33,7 +33,6 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/utils/lru" ) var ( @@ -65,7 +64,7 @@ type Controller struct { tokenHash string nodeName string core core.Interface - clientCache *lru.Cache + clientCache *util.Cache[*Client] } // Client holds state for a given configuration - a preconfigured minio client, @@ -83,7 +82,7 @@ type Client struct { func Start(ctx context.Context, config *config.Control) (*Controller, error) { once.Do(func() { c := &Controller{ - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), nodeName: os.Getenv("NODE_NAME"), } @@ -161,7 +160,7 @@ func (c *Controller) GetClient(ctx context.Context, etcdS3 *config.EtcdS3) (*Cli // print the endpoint and bucket name to avoid leaking creds into the logs. if client, ok := c.clientCache.Get(*etcdS3); ok { logrus.Infof("Reusing cached S3 client for endpoint=%q bucket=%q folder=%q", scheme+etcdS3.Endpoint, etcdS3.Bucket, etcdS3.Folder) - return client.(*Client), nil + return client, nil } logrus.Infof("Attempting to create new S3 client for endpoint=%q bucket=%q folder=%q", scheme+etcdS3.Endpoint, etcdS3.Bucket, etcdS3.Folder) diff --git a/pkg/etcd/s3/s3_test.go b/pkg/etcd/s3/s3_test.go index b48ba20b01e..e8714a9b585 100644 --- a/pkg/etcd/s3/s3_test.go +++ b/pkg/etcd/s3/s3_test.go @@ -17,6 +17,7 @@ import ( "github.com/gorilla/mux" "github.com/k3s-io/k3s/pkg/daemons/config" "github.com/k3s-io/k3s/pkg/etcd/snapshot" + "github.com/k3s-io/k3s/pkg/util" "github.com/k3s-io/k3s/tests/mock" "github.com/rancher/dynamiclistener/cert" "github.com/rancher/wrangler/v3/pkg/generated/controllers/core" @@ -24,7 +25,6 @@ import ( "go.uber.org/mock/gomock" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/lru" ) var gmt = time.FixedZone("GMT", 0) @@ -65,7 +65,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID string tokenHash string nodeName string - clientCache *lru.Cache + clientCache *util.Cache[*Client] } type args struct { ctx context.Context @@ -88,7 +88,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -113,7 +113,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -139,7 +139,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -163,7 +163,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -190,7 +190,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { coreMock := mock.NewCore(gomock.NewController(t)) @@ -231,7 +231,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { coreMock := mock.NewCore(gomock.NewController(t)) @@ -287,7 +287,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -338,7 +338,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { coreMock := mock.NewCore(gomock.NewController(t)) @@ -364,7 +364,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { coreMock := mock.NewCore(gomock.NewController(t)) @@ -389,7 +389,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { coreMock := mock.NewCore(gomock.NewController(t)) @@ -412,7 +412,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, want: &Client{}, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -465,7 +465,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, want: &Client{}, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -495,7 +495,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { coreMock := mock.NewCore(gomock.NewController(t)) @@ -522,7 +522,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -550,7 +550,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { @@ -577,7 +577,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { coreMock := mock.NewCore(gomock.NewController(t)) @@ -603,7 +603,7 @@ func Test_UnitControllerGetClient(t *testing.T) { clusterID: "1234", tokenHash: "abcd", nodeName: "server01", - clientCache: lru.New(5), + clientCache: util.NewCache[*Client](5), }, wantErr: true, setup: func(t *testing.T, a args, f fields, c *Client) (core.Interface, error) { diff --git a/pkg/server/handlers/handlers.go b/pkg/server/handlers/handlers.go index 4c2650699a8..ca2371e1def 100644 --- a/pkg/server/handlers/handlers.go +++ b/pkg/server/handlers/handlers.go @@ -257,7 +257,12 @@ func signAndSend(resp http.ResponseWriter, req *http.Request, caCertFile, caKeyF util.SendError(err, resp, req) return } - key = pk.(crypto.Signer) + k, ok := pk.(crypto.Signer) + if !ok { + util.SendError(errors.New("type assertion failed"), resp, req) + return + } + key = k } // create the signed cert using dynamiclistener cert utils @@ -298,7 +303,12 @@ func getCACertAndKey(caCertFile, caKeyFile string) ([]*x509.Certificate, crypto. return nil, nil, err } - return caCert, caKey.(crypto.Signer), nil + k, ok := caKey.(crypto.Signer) + if !ok { + return nil, nil, errors.New("type assertion failed") + } + + return caCert, k, nil } // getCSR decodes a x509.CertificateRequest from a POST request body. diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index cc60dbb7c4c..a23e824fe74 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -28,7 +28,10 @@ func mapLevel(level int) logrus.Level { func mapKV(kvs []any) logrus.Fields { fields := logrus.Fields{} for i := 0; i < len(kvs); i += 2 { - k := kvs[i].(string) + k, ok := kvs[i].(string) + if !ok { + k = fmt.Sprint(kvs[i]) + } if len(kvs) > i+1 { fields[k] = kvs[i+1] } else { diff --git a/pkg/util/lru.go b/pkg/util/lru.go new file mode 100644 index 00000000000..c81e022a878 --- /dev/null +++ b/pkg/util/lru.go @@ -0,0 +1,54 @@ +package util + +import "k8s.io/utils/lru" + +// Cache is a generic wrapper around lru.Cache that handles type assertions when +// retrieving cached entries. +type Cache[T any] struct { + cache *lru.Cache +} + +func NewCache[T any](size int) *Cache[T] { + return &Cache[T]{ + cache: lru.New(size), + } +} + +func NewCacheWithEvictionFunc[T any](size int, f lru.EvictionFunc) *Cache[T] { + return &Cache[T]{ + cache: lru.NewWithEvictionFunc(size, f), + } +} + +func (c *Cache[T]) Add(key lru.Key, value T) { + c.cache.Add(key, value) +} + +func (c *Cache[T]) Clear() { + c.cache.Clear() +} + +func (c *Cache[T]) Get(key lru.Key) (value T, ok bool) { + v, ok := c.cache.Get(key) + if !ok { + return value, ok + } + value, ok = v.(T) + return value, ok +} + +func (c *Cache[T]) Len() int { + return c.cache.Len() +} + +func (c *Cache[T]) Remove(key lru.Key) { + c.cache.Remove(key) +} + +func (c *Cache[T]) RemoveOldest() { + c.cache.RemoveOldest() +} + +func (c *Cache[T]) SetEvictionFunc(f lru.EvictionFunc) { + c.cache.SetEvictionFunc(f) +}