fix the fake client example: how to handle a race between the fake client and informer

Note that the fake client isn't designed to work with informer. It
doesn't support resource version. It's encouraged to use a real client
in an integration/E2E test if you need to test complex behavior with
informer/controllers.

Kubernetes-commit: 942bc9b32e39bb9c6ca045c02b48cc84dfa86633
This commit is contained in:
Haowei Cai 2020-10-26 22:50:32 -07:00 committed by Kubernetes Publisher
parent 67a7335497
commit 7dddf976b8

View File

@ -21,11 +21,13 @@ import (
"testing"
"time"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
clienttesting "k8s.io/client-go/testing"
"k8s.io/client-go/tools/cache"
)
@ -34,8 +36,20 @@ func TestFakeClient(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
watcherStarted := make(chan struct{})
// Create the fake client.
client := fake.NewSimpleClientset()
// A catch-all watch reactor that allows us to inject the watcherStarted channel.
client.PrependWatchReactor("*", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
gvr := action.GetResource()
ns := action.GetNamespace()
watch, err := client.Tracker().Watch(gvr, ns)
if err != nil {
return false, nil, err
}
close(watcherStarted)
return true, watch, nil
})
// We will create an informer that writes added pods to a channel.
pods := make(chan *v1.Pod, 1)
@ -57,6 +71,15 @@ func TestFakeClient(t *testing.T) {
// we send any events to it.
cache.WaitForCacheSync(ctx.Done(), podInformer.HasSynced)
// The fake client doesn't support resource version. Any writes to the client
// after the informer's initial LIST and before the informer establishing the
// watcher will be missed by the informer. Therefore we wait until the watcher
// starts.
// Note that the fake client isn't designed to work with informer. It
// doesn't support resource version. It's encouraged to use a real client
// in an integration/E2E test if you need to test complex behavior with
// informer/controllers.
<-watcherStarted
// Inject an event into the fake client.
p := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "my-pod"}}
_, err := client.CoreV1().Pods("test-ns").Create(context.TODO(), p, metav1.CreateOptions{})