Merge pull request #94773 from tkashem/etcd-object-count
count of etcd object should be limited to the specified resource Kubernetes-commit: 9fdbf1cf89809763aa7b405a7e641d37f45d2e21
This commit is contained in:
commit
db2da9544d
|
|
@ -676,7 +676,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery",
|
"ImportPath": "k8s.io/apimachinery",
|
||||||
"Rev": "1173d23fd476"
|
"Rev": "2f44a17e43a6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/client-go",
|
"ImportPath": "k8s.io/client-go",
|
||||||
|
|
|
||||||
4
go.mod
4
go.mod
|
|
@ -42,7 +42,7 @@ require (
|
||||||
gopkg.in/square/go-jose.v2 v2.2.2
|
gopkg.in/square/go-jose.v2 v2.2.2
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
k8s.io/api v0.0.0-20200914174313-52bf62410745
|
k8s.io/api v0.0.0-20200914174313-52bf62410745
|
||||||
k8s.io/apimachinery v0.0.0-20200910171558-1173d23fd476
|
k8s.io/apimachinery v0.0.0-20200915234101-2f44a17e43a6
|
||||||
k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67
|
k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67
|
||||||
k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f
|
k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f
|
||||||
k8s.io/klog/v2 v2.2.0
|
k8s.io/klog/v2 v2.2.0
|
||||||
|
|
@ -55,7 +55,7 @@ require (
|
||||||
|
|
||||||
replace (
|
replace (
|
||||||
k8s.io/api => k8s.io/api v0.0.0-20200914174313-52bf62410745
|
k8s.io/api => k8s.io/api v0.0.0-20200914174313-52bf62410745
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20200910171558-1173d23fd476
|
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20200915234101-2f44a17e43a6
|
||||||
k8s.io/client-go => k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67
|
k8s.io/client-go => k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67
|
||||||
k8s.io/component-base => k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f
|
k8s.io/component-base => k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f
|
||||||
)
|
)
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -503,7 +503,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
k8s.io/api v0.0.0-20200914174313-52bf62410745/go.mod h1:UT3vnXQcd48N6K0IuGGYk1ufh1lolzq+pC4aE2BPvWA=
|
k8s.io/api v0.0.0-20200914174313-52bf62410745/go.mod h1:UT3vnXQcd48N6K0IuGGYk1ufh1lolzq+pC4aE2BPvWA=
|
||||||
k8s.io/apimachinery v0.0.0-20200910171558-1173d23fd476/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
|
k8s.io/apimachinery v0.0.0-20200915234101-2f44a17e43a6/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
|
||||||
k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67/go.mod h1:l+k6PpRBFWMCiLvf6k6opk7J/clbXd38cNBOo7k6jQg=
|
k8s.io/client-go v0.0.0-20200915085750-a32e6027fa67/go.mod h1:l+k6PpRBFWMCiLvf6k6opk7J/clbXd38cNBOo7k6jQg=
|
||||||
k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f/go.mod h1:KLUf6+rBAAlh4P5aX9t725mVdFgvY6LfYzl+QOveAV4=
|
k8s.io/component-base v0.0.0-20200911092040-c985e940ef8f/go.mod h1:KLUf6+rBAAlh4P5aX9t725mVdFgvY6LfYzl+QOveAV4=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
|
|
||||||
|
|
@ -452,6 +452,14 @@ func getNewItemFunc(listObj runtime.Object, v reflect.Value) func() runtime.Obje
|
||||||
|
|
||||||
func (s *store) Count(key string) (int64, error) {
|
func (s *store) Count(key string) (int64, error) {
|
||||||
key = path.Join(s.pathPrefix, key)
|
key = path.Join(s.pathPrefix, key)
|
||||||
|
|
||||||
|
// 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 !strings.HasSuffix(key, "/") {
|
||||||
|
key += "/"
|
||||||
|
}
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
getResp, err := s.client.KV.Get(context.Background(), key, clientv3.WithRange(clientv3.GetPrefixRangeEnd(key)), clientv3.WithCountOnly())
|
getResp, err := s.client.KV.Get(context.Background(), key, clientv3.WithRange(clientv3.GetPrefixRangeEnd(key)), clientv3.WithCountOnly())
|
||||||
metrics.RecordEtcdRequestLatency("listWithCount", key, startTime)
|
metrics.RecordEtcdRequestLatency("listWithCount", key, startTime)
|
||||||
|
|
|
||||||
|
|
@ -1818,6 +1818,12 @@ func testSetup(t *testing.T) (context.Context, *store, *integration.ClusterV3) {
|
||||||
func testPropogateStore(ctx context.Context, t *testing.T, store *store, obj *example.Pod) (string, *example.Pod) {
|
func testPropogateStore(ctx context.Context, t *testing.T, store *store, obj *example.Pod) (string, *example.Pod) {
|
||||||
// Setup store with a key and grab the output for returning.
|
// Setup store with a key and grab the output for returning.
|
||||||
key := "/testkey"
|
key := "/testkey"
|
||||||
|
return key, testPropogateStoreWithKey(ctx, t, store, key, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testPropogateStoreWithKey helps propagate store with objects, the given object will be stored at the specified key.
|
||||||
|
func testPropogateStoreWithKey(ctx context.Context, t *testing.T, store *store, key string, obj *example.Pod) *example.Pod {
|
||||||
|
// Setup store with the specified key and grab the output for returning.
|
||||||
v, err := conversion.EnforcePtr(obj)
|
v, err := conversion.EnforcePtr(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("unable to convert output object to pointer")
|
panic("unable to convert output object to pointer")
|
||||||
|
|
@ -1830,7 +1836,7 @@ func testPropogateStore(ctx context.Context, t *testing.T, store *store, obj *ex
|
||||||
if err := store.Create(ctx, key, obj, setOutput, 0); err != nil {
|
if err := store.Create(ctx, key, obj, setOutput, 0); err != nil {
|
||||||
t.Fatalf("Set failed: %v", err)
|
t.Fatalf("Set failed: %v", err)
|
||||||
}
|
}
|
||||||
return key, setOutput
|
return setOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrefix(t *testing.T) {
|
func TestPrefix(t *testing.T) {
|
||||||
|
|
@ -2075,3 +2081,41 @@ func TestConsistentList(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCount(t *testing.T) {
|
||||||
|
ctx, store, cluster := testSetup(t)
|
||||||
|
defer cluster.Terminate(t)
|
||||||
|
|
||||||
|
resourceA := "/foo.bar.io/abc"
|
||||||
|
|
||||||
|
// resourceA is intentionally a prefix of resourceB to ensure that the count
|
||||||
|
// for resourceA does not include any objects from resourceB.
|
||||||
|
resourceB := fmt.Sprintf("%sdef", resourceA)
|
||||||
|
|
||||||
|
resourceACountExpected := 5
|
||||||
|
for i := 1; i <= resourceACountExpected; i++ {
|
||||||
|
obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("foo-%d", i)}}
|
||||||
|
|
||||||
|
key := fmt.Sprintf("%s/%d", resourceA, i)
|
||||||
|
testPropogateStoreWithKey(ctx, t, store, key, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceBCount := 4
|
||||||
|
for i := 1; i <= resourceBCount; i++ {
|
||||||
|
obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("foo-%d", i)}}
|
||||||
|
|
||||||
|
key := fmt.Sprintf("%s/%d", resourceB, i)
|
||||||
|
testPropogateStoreWithKey(ctx, t, store, key, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceACountGot, err := store.Count(resourceA)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("store.Count failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// count for resourceA should not include the objects for resourceB
|
||||||
|
// even though resourceA is a prefix of resourceB.
|
||||||
|
if int64(resourceACountExpected) != resourceACountGot {
|
||||||
|
t.Fatalf("store.Count for resource %s: expected %d but got %d", resourceA, resourceACountExpected, resourceACountGot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue