Skip to content

Commit d63cfde

Browse files
authored
Merge pull request kubernetes-sigs#1510 from alvaroaleman/add-watch
🐛 Fakeclient: Support WithWatch
2 parents c6f353f + 2a2f6b4 commit d63cfde

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

pkg/client/fake/client.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"k8s.io/apimachinery/pkg/runtime/schema"
3232
utilrand "k8s.io/apimachinery/pkg/util/rand"
3333
"k8s.io/apimachinery/pkg/util/validation/field"
34+
"k8s.io/apimachinery/pkg/watch"
3435
"k8s.io/client-go/kubernetes/scheme"
3536
"k8s.io/client-go/testing"
3637

@@ -49,7 +50,7 @@ type fakeClient struct {
4950
scheme *runtime.Scheme
5051
}
5152

52-
var _ client.Client = &fakeClient{}
53+
var _ client.WithWatch = &fakeClient{}
5354

5455
const (
5556
maxNameLength = 63
@@ -61,7 +62,7 @@ const (
6162
// You can choose to initialize it with a slice of runtime.Object.
6263
//
6364
// Deprecated: Please use NewClientBuilder instead.
64-
func NewFakeClient(initObjs ...runtime.Object) client.Client {
65+
func NewFakeClient(initObjs ...runtime.Object) client.WithWatch {
6566
return NewClientBuilder().WithRuntimeObjects(initObjs...).Build()
6667
}
6768

@@ -70,7 +71,7 @@ func NewFakeClient(initObjs ...runtime.Object) client.Client {
7071
// You can choose to initialize it with a slice of runtime.Object.
7172
//
7273
// Deprecated: Please use NewClientBuilder instead.
73-
func NewFakeClientWithScheme(clientScheme *runtime.Scheme, initObjs ...runtime.Object) client.Client {
74+
func NewFakeClientWithScheme(clientScheme *runtime.Scheme, initObjs ...runtime.Object) client.WithWatch {
7475
return NewClientBuilder().WithScheme(clientScheme).WithRuntimeObjects(initObjs...).Build()
7576
}
7677

@@ -113,7 +114,7 @@ func (f *ClientBuilder) WithRuntimeObjects(initRuntimeObjs ...runtime.Object) *C
113114
}
114115

115116
// Build builds and returns a new fake client.
116-
func (f *ClientBuilder) Build() client.Client {
117+
func (f *ClientBuilder) Build() client.WithWatch {
117118
if f.scheme == nil {
118119
f.scheme = scheme.Scheme
119120
}
@@ -284,6 +285,23 @@ func (c *fakeClient) Get(ctx context.Context, key client.ObjectKey, obj client.O
284285
return err
285286
}
286287

288+
func (c *fakeClient) Watch(ctx context.Context, list client.ObjectList, opts ...client.ListOption) (watch.Interface, error) {
289+
gvk, err := apiutil.GVKForObject(list, c.scheme)
290+
if err != nil {
291+
return nil, err
292+
}
293+
294+
if strings.HasSuffix(gvk.Kind, "List") {
295+
gvk.Kind = gvk.Kind[:len(gvk.Kind)-4]
296+
}
297+
298+
listOpts := client.ListOptions{}
299+
listOpts.ApplyOptions(opts)
300+
301+
gvr, _ := meta.UnsafeGuessKindToResource(gvk)
302+
return c.tracker.Watch(gvr, listOpts.Namespace)
303+
}
304+
287305
func (c *fakeClient) List(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error {
288306
gvk, err := apiutil.GVKForObject(obj, c.scheme)
289307
if err != nil {

pkg/client/fake/client_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"encoding/json"
2222
"fmt"
23+
"time"
2324

2425
. "github.com/onsi/ginkgo"
2526
. "github.com/onsi/gomega"
@@ -33,14 +34,15 @@ import (
3334
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3435
"k8s.io/apimachinery/pkg/runtime"
3536
"k8s.io/apimachinery/pkg/types"
37+
"k8s.io/apimachinery/pkg/watch"
3638
"sigs.k8s.io/controller-runtime/pkg/client"
3739
)
3840

3941
var _ = Describe("Fake client", func() {
4042
var dep *appsv1.Deployment
4143
var dep2 *appsv1.Deployment
4244
var cm *corev1.ConfigMap
43-
var cl client.Client
45+
var cl client.WithWatch
4446

4547
BeforeEach(func() {
4648
dep = &appsv1.Deployment{
@@ -541,6 +543,32 @@ var _ = Describe("Fake client", func() {
541543
}
542544
})
543545

546+
It("should be able to watch", func() {
547+
By("Creating a watch")
548+
objWatch, err := cl.Watch(context.Background(), &corev1.ServiceList{})
549+
Expect(err).NotTo(HaveOccurred())
550+
551+
defer objWatch.Stop()
552+
553+
go func() {
554+
defer GinkgoRecover()
555+
// It is likely starting a new goroutine is slower than progressing
556+
// in the outer routine, sleep to make sure this is always true
557+
time.Sleep(100 * time.Millisecond)
558+
559+
err := cl.Create(context.Background(), &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "for-watch"}})
560+
Expect(err).ToNot(HaveOccurred())
561+
}()
562+
563+
event, ok := <-objWatch.ResultChan()
564+
Expect(ok).To(BeTrue())
565+
Expect(event.Type).To(Equal(watch.Added))
566+
567+
service, ok := event.Object.(*corev1.Service)
568+
Expect(ok).To(BeTrue())
569+
Expect(service.Name).To(Equal("for-watch"))
570+
})
571+
544572
Context("with the DryRun option", func() {
545573
It("should not create a new object", func() {
546574
By("Creating a new configmap with DryRun")

0 commit comments

Comments
 (0)