Skip to content

Commit 9fdbf1c

Browse files
authored
Merge pull request kubernetes#94773 from tkashem/etcd-object-count
count of etcd object should be limited to the specified resource
2 parents ea5ca74 + 7e44586 commit 9fdbf1c

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,14 @@ func getNewItemFunc(listObj runtime.Object, v reflect.Value) func() runtime.Obje
452452

453453
func (s *store) Count(key string) (int64, error) {
454454
key = path.Join(s.pathPrefix, key)
455+
456+
// We need to make sure the key ended with "/" so that we only get children "directories".
457+
// e.g. if we have key "/a", "/a/b", "/ab", getting keys with prefix "/a" will return all three,
458+
// while with prefix "/a/" will return only "/a/b" which is the correct answer.
459+
if !strings.HasSuffix(key, "/") {
460+
key += "/"
461+
}
462+
455463
startTime := time.Now()
456464
getResp, err := s.client.KV.Get(context.Background(), key, clientv3.WithRange(clientv3.GetPrefixRangeEnd(key)), clientv3.WithCountOnly())
457465
metrics.RecordEtcdRequestLatency("listWithCount", key, startTime)

staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,12 @@ func testSetup(t *testing.T) (context.Context, *store, *integration.ClusterV3) {
18181818
func testPropogateStore(ctx context.Context, t *testing.T, store *store, obj *example.Pod) (string, *example.Pod) {
18191819
// Setup store with a key and grab the output for returning.
18201820
key := "/testkey"
1821+
return key, testPropogateStoreWithKey(ctx, t, store, key, obj)
1822+
}
1823+
1824+
// testPropogateStoreWithKey helps propagate store with objects, the given object will be stored at the specified key.
1825+
func testPropogateStoreWithKey(ctx context.Context, t *testing.T, store *store, key string, obj *example.Pod) *example.Pod {
1826+
// Setup store with the specified key and grab the output for returning.
18211827
v, err := conversion.EnforcePtr(obj)
18221828
if err != nil {
18231829
panic("unable to convert output object to pointer")
@@ -1830,7 +1836,7 @@ func testPropogateStore(ctx context.Context, t *testing.T, store *store, obj *ex
18301836
if err := store.Create(ctx, key, obj, setOutput, 0); err != nil {
18311837
t.Fatalf("Set failed: %v", err)
18321838
}
1833-
return key, setOutput
1839+
return setOutput
18341840
}
18351841

18361842
func TestPrefix(t *testing.T) {
@@ -2075,3 +2081,41 @@ func TestConsistentList(t *testing.T) {
20752081
}
20762082

20772083
}
2084+
2085+
func TestCount(t *testing.T) {
2086+
ctx, store, cluster := testSetup(t)
2087+
defer cluster.Terminate(t)
2088+
2089+
resourceA := "/foo.bar.io/abc"
2090+
2091+
// resourceA is intentionally a prefix of resourceB to ensure that the count
2092+
// for resourceA does not include any objects from resourceB.
2093+
resourceB := fmt.Sprintf("%sdef", resourceA)
2094+
2095+
resourceACountExpected := 5
2096+
for i := 1; i <= resourceACountExpected; i++ {
2097+
obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("foo-%d", i)}}
2098+
2099+
key := fmt.Sprintf("%s/%d", resourceA, i)
2100+
testPropogateStoreWithKey(ctx, t, store, key, obj)
2101+
}
2102+
2103+
resourceBCount := 4
2104+
for i := 1; i <= resourceBCount; i++ {
2105+
obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("foo-%d", i)}}
2106+
2107+
key := fmt.Sprintf("%s/%d", resourceB, i)
2108+
testPropogateStoreWithKey(ctx, t, store, key, obj)
2109+
}
2110+
2111+
resourceACountGot, err := store.Count(resourceA)
2112+
if err != nil {
2113+
t.Fatalf("store.Count failed: %v", err)
2114+
}
2115+
2116+
// count for resourceA should not include the objects for resourceB
2117+
// even though resourceA is a prefix of resourceB.
2118+
if int64(resourceACountExpected) != resourceACountGot {
2119+
t.Fatalf("store.Count for resource %s: expected %d but got %d", resourceA, resourceACountExpected, resourceACountGot)
2120+
}
2121+
}

0 commit comments

Comments
 (0)