Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proxy list with rv=0 no longer access member cluster etcd #4896

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion pkg/search/proxy/store/multi_cluster_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ func (c *MultiClusterCache) List(ctx context.Context, gvr schema.GroupVersionRes
utiltrace.Field{Key: "cluster", Value: cluster},
utiltrace.Field{Key: "options", Value: fmt.Sprintf("%#v", options)},
)
klog.V(4).Infof("List member cluster %v with %#v", cluster, options)
obj, err := cache.List(ctx, options)
if err != nil {
return 0, "", err
Expand Down Expand Up @@ -295,7 +296,16 @@ func (c *MultiClusterCache) List(ctx context.Context, gvr schema.GroupVersionRes
if err := c.fillMissingClusterResourceVersion(ctx, responseResourceVersion, clusters, gvr); err != nil {
return nil, err
}
responseContinue.RV = responseResourceVersion.String()

// responseContinue.Cluster is empty, means paging is over, and continue will not be responded.
if responseContinue.Cluster != "" {
// If request rv is 0, then response rv is also 0, making next request visit cache again.
if o.ResourceVersion == "0" {
responseContinue.RV = "0"
} else {
responseContinue.RV = responseResourceVersion.String()
}
}

if resultObject == nil {
resultObject = &metav1.List{
Expand Down
71 changes: 71 additions & 0 deletions test/e2e/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package e2e

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"sort"
Expand Down Expand Up @@ -535,6 +537,26 @@ var _ = ginkgo.Describe("[karmada-search] karmada search testing", ginkgo.Ordere
_, err := c.CoreV1().Nodes().Patch(context.TODO(), name, types.StrategicMergePatchType, data, metav1.PatchOptions{})
klog.Warningf("Clean node %v's annotation %v failed: %v", name, anno, err)
}

decodeMultiClusterRV = func(mcrv string) map[string]string {
decoded, err := base64.RawURLEncoding.DecodeString(mcrv)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

m := make(map[string]string)
err = json.Unmarshal(decoded, &m)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
return m
}

decodeMultiClusterContinue = func(mcc string) (rv, cluster, continuous string) {
decoded, err := base64.RawURLEncoding.DecodeString(mcc)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

m := make(map[string]string)
err = json.Unmarshal(decoded, &m)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
return m["cluster"], m["rv"], m["continue"]
}
)

ginkgo.BeforeAll(func() {
Expand Down Expand Up @@ -641,6 +663,55 @@ var _ = ginkgo.Describe("[karmada-search] karmada search testing", ginkgo.Ordere
gomega.Expect(list2.Items).Should(gomega.HaveLen(total - len(list1.Items)))
})

ginkgo.It("could chunk list nodes with rv=0", func() {
fromM1, err := m1Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
ginkgo.By(fmt.Sprintf("list %v nodes from member1", len(fromM1.Items)))

fromM2, err := m2Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
ginkgo.By(fmt.Sprintf("list %v nodes from member2", len(fromM2.Items)))

var list1 *corev1.NodeList
ginkgo.By("1st list", func() {
gomega.Eventually(func(g gomega.Gomega) {
var err error
list1, err = proxyClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{Limit: 1, ResourceVersion: "0"})
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(list1.Items).ShouldNot(gomega.BeEmpty())
}, pollTimeout, pollInterval).Should(gomega.Succeed())

gomega.Expect(list1.Items).Should(gomega.HaveLen(len(fromM1.Items)))

mcrv := decodeMultiClusterRV(list1.ResourceVersion)
gomega.Expect(mcrv[member1]).ShouldNot(gomega.BeEmpty())
gomega.Expect(mcrv[member2]).ShouldNot(gomega.BeEmpty())

cluster, rv, continuous := decodeMultiClusterContinue(list1.Continue)
gomega.Expect(cluster).Should(gomega.Equal(member2))
gomega.Expect(rv).Should(gomega.Equal("0"))
gomega.Expect(continuous).Should(gomega.BeEmpty())
})

ginkgo.By("2nd list", func() {
var list2 *corev1.NodeList
gomega.Eventually(func(g gomega.Gomega) {
var err error
list2, err = proxyClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{Limit: 1, Continue: list1.Continue})
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(list2.Items).ShouldNot(gomega.BeEmpty())
}, pollTimeout, pollInterval).Should(gomega.Succeed())

gomega.Expect(list2.Items).Should(gomega.HaveLen(len(fromM2.Items)))

mcrv := decodeMultiClusterRV(list2.ResourceVersion)
gomega.Expect(mcrv[member1]).ShouldNot(gomega.BeEmpty())
gomega.Expect(mcrv[member2]).ShouldNot(gomega.BeEmpty())

gomega.Expect(list2.Continue).Should(gomega.BeEmpty())
})
})

ginkgo.It("could list & watch nodes", func() {
var listObj *corev1.NodeList
gomega.Eventually(func(g gomega.Gomega) {
Expand Down
Loading