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.
This commit is contained in:
		@@ -21,11 +21,13 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/watch"
 | 
				
			||||||
	"k8s.io/client-go/informers"
 | 
						"k8s.io/client-go/informers"
 | 
				
			||||||
	"k8s.io/client-go/kubernetes/fake"
 | 
						"k8s.io/client-go/kubernetes/fake"
 | 
				
			||||||
 | 
						clienttesting "k8s.io/client-go/testing"
 | 
				
			||||||
	"k8s.io/client-go/tools/cache"
 | 
						"k8s.io/client-go/tools/cache"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,8 +36,20 @@ func TestFakeClient(t *testing.T) {
 | 
				
			|||||||
	ctx, cancel := context.WithCancel(context.Background())
 | 
						ctx, cancel := context.WithCancel(context.Background())
 | 
				
			||||||
	defer cancel()
 | 
						defer cancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						watcherStarted := make(chan struct{})
 | 
				
			||||||
	// Create the fake client.
 | 
						// Create the fake client.
 | 
				
			||||||
	client := fake.NewSimpleClientset()
 | 
						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.
 | 
						// We will create an informer that writes added pods to a channel.
 | 
				
			||||||
	pods := make(chan *v1.Pod, 1)
 | 
						pods := make(chan *v1.Pod, 1)
 | 
				
			||||||
@@ -57,6 +71,15 @@ func TestFakeClient(t *testing.T) {
 | 
				
			|||||||
	// we send any events to it.
 | 
						// we send any events to it.
 | 
				
			||||||
	cache.WaitForCacheSync(ctx.Done(), podInformer.HasSynced)
 | 
						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.
 | 
						// Inject an event into the fake client.
 | 
				
			||||||
	p := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "my-pod"}}
 | 
						p := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "my-pod"}}
 | 
				
			||||||
	_, err := client.CoreV1().Pods("test-ns").Create(context.TODO(), p, metav1.CreateOptions{})
 | 
						_, err := client.CoreV1().Pods("test-ns").Create(context.TODO(), p, metav1.CreateOptions{})
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user