From 0b10735cd72fbf5416a20d2bb7e525b7d8a1e716 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 17 Sep 2025 16:41:27 +0200 Subject: [PATCH] Extract the prepareKey function --- .../apiserver/pkg/storage/cacher/cacher.go | 25 +---------------- .../apiserver/pkg/storage/etcd3/store.go | 24 +++-------------- .../apiserver/pkg/storage/interfaces.go | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+), 45 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go index 2bdd30487fd..267e5b37358 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go @@ -21,7 +21,6 @@ import ( "fmt" "net/http" "reflect" - "strings" "sync" "time" @@ -1170,29 +1169,7 @@ func (c *Cacher) Stop() { } func (c *Cacher) prepareKey(key string, recursive bool) (string, error) { - if key == ".." || - strings.HasPrefix(key, "../") || - strings.HasSuffix(key, "/..") || - strings.Contains(key, "/../") { - return "", fmt.Errorf("invalid key: %q", key) - } - if key == "." || - strings.HasPrefix(key, "./") || - strings.HasSuffix(key, "/.") || - strings.Contains(key, "/./") { - return "", fmt.Errorf("invalid key: %q", key) - } - if key == "" || key == "/" { - return "", fmt.Errorf("empty key: %q", key) - } - // For recursive lists, we need to make sure the key ended with "/" so that we only - // get children "directories". e.g. if we have key "/a", "/a/b", "/ab", getting keys - // with prefix "/a" will return all three, while with prefix "/a/" will return only - // "/a/b" which is the correct answer. - if recursive && !strings.HasSuffix(key, "/") { - key += "/" - } - return key, nil + return storage.PrepareKey(key, recursive) } func forgetWatcher(c *Cacher, w *cacheWatcher, index int, scope namespacedName, triggerValue string, triggerSupported bool) func(bool) { diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go index c2685eda42f..61b0c6536ec 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go @@ -1105,33 +1105,15 @@ func (s *store) validateMinimumResourceVersion(minimumResourceVersion string, ac } func (s *store) prepareKey(key string, recursive bool) (string, error) { - if key == ".." || - strings.HasPrefix(key, "../") || - strings.HasSuffix(key, "/..") || - strings.Contains(key, "/../") { - return "", fmt.Errorf("invalid key: %q", key) - } - if key == "." || - strings.HasPrefix(key, "./") || - strings.HasSuffix(key, "/.") || - strings.Contains(key, "/./") { - return "", fmt.Errorf("invalid key: %q", key) - } - if key == "" || key == "/" { - return "", fmt.Errorf("empty key: %q", key) + key, err := storage.PrepareKey(key, recursive) + if err != nil { + return "", err } // We ensured that pathPrefix ends in '/' in construction, so skip any leading '/' in the key now. startIndex := 0 if key[0] == '/' { startIndex = 1 } - // For recursive requests, we need to make sure the key ended with "/" so that we only - // get children "directories". e.g. if we have key "/a", "/a/b", "/ab", getting keys - // with prefix "/a" will return all three, while with prefix "/a/" will return only - // "/a/b" which is the correct answer. - if recursive && !strings.HasSuffix(key, "/") { - key += "/" - } return s.pathPrefix + key[startIndex:], nil } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go b/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go index c158cdb1938..d8ea90bf2db 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/interfaces.go @@ -19,6 +19,7 @@ package storage import ( "context" "fmt" + "strings" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -390,3 +391,29 @@ type Stats struct { // Value is an estimate, meaning it doesn't need to provide accurate nor consistent. EstimatedAverageObjectSizeBytes int64 } + +func PrepareKey(key string, recursive bool) (string, error) { + if key == ".." || + strings.HasPrefix(key, "../") || + strings.HasSuffix(key, "/..") || + strings.Contains(key, "/../") { + return "", fmt.Errorf("invalid key: %q", key) + } + if key == "." || + strings.HasPrefix(key, "./") || + strings.HasSuffix(key, "/.") || + strings.Contains(key, "/./") { + return "", fmt.Errorf("invalid key: %q", key) + } + if key == "" || key == "/" { + return "", fmt.Errorf("empty key: %q", key) + } + // For recursive requests, we need to make sure the key ended with "/" so that we only + // get children "directories". e.g. if we have key "/a", "/a/b", "/ab", getting keys + // with prefix "/a" will return all three, while with prefix "/a/" will return only + // "/a/b" which is the correct answer. + if recursive && !strings.HasSuffix(key, "/") { + key += "/" + } + return key, nil +}