Skip to content

Commit 0a0a451

Browse files
authored
Replace fake.Client using a mock instead (kubernetes-sigs#69)
To be able to add more test-cases, we need to use a mock for the client interface. We do so using the 'gomock' library. This PR replaces the fake.Client in favor of using the new auto-generated mock based on the Client interface. MGMT-10532
1 parent d1fccce commit 0a0a451

File tree

8 files changed

+609
-174
lines changed

8 files changed

+609
-174
lines changed

controllers/module_reconciler_test.go

+91-59
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
. "github.com/onsi/gomega"
99
ootov1alpha1 "github.com/qbarrand/oot-operator/api/v1alpha1"
1010
"github.com/qbarrand/oot-operator/internal/build"
11+
"github.com/qbarrand/oot-operator/internal/client"
1112
"github.com/qbarrand/oot-operator/internal/daemonset"
1213
"github.com/qbarrand/oot-operator/internal/metrics"
1314
"github.com/qbarrand/oot-operator/internal/module"
@@ -16,7 +17,6 @@ import (
1617
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1718
"k8s.io/apimachinery/pkg/types"
1819
"k8s.io/apimachinery/pkg/util/sets"
19-
"sigs.k8s.io/controller-runtime/pkg/client/fake"
2020
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2121
)
2222

@@ -28,6 +28,7 @@ var _ = Describe("ModuleReconciler", func() {
2828
Describe("Reconcile", func() {
2929
var (
3030
ctrl *gomock.Controller
31+
clnt *client.MockClient
3132
mockBM *build.MockManager
3233
mockCU *module.MockConditionsUpdater
3334
mockDC *daemonset.MockDaemonSetCreator
@@ -37,6 +38,7 @@ var _ = Describe("ModuleReconciler", func() {
3738

3839
BeforeEach(func() {
3940
ctrl = gomock.NewController(GinkgoT())
41+
clnt = client.NewMockClient(ctrl)
4042
mockBM = build.NewMockManager(ctrl)
4143
mockCU = module.NewMockConditionsUpdater(ctrl)
4244
mockDC = daemonset.NewMockDaemonSetCreator(ctrl)
@@ -64,29 +66,31 @@ var _ = Describe("ModuleReconciler", func() {
6466
},
6567
}
6668

67-
nodeList := v1.NodeList{
68-
Items: []v1.Node{
69-
{
70-
ObjectMeta: metav1.ObjectMeta{Name: "node1"},
71-
},
72-
},
73-
}
74-
75-
client := fake.
76-
NewClientBuilder().
77-
WithScheme(scheme).
78-
WithObjects(&mod).
79-
WithLists(&nodeList).
80-
Build()
69+
ctx := context.TODO()
8170

82-
mr := NewModuleReconciler(client, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
71+
gomock.InOrder(
72+
clnt.EXPECT().Get(ctx, req.NamespacedName, gomock.Any()).DoAndReturn(
73+
func(_ interface{}, _ interface{}, m *ootov1alpha1.Module) error {
74+
m.ObjectMeta = mod.ObjectMeta
75+
m.Spec = mod.Spec
76+
return nil
77+
},
78+
),
79+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
80+
func(_ interface{}, list *ootov1alpha1.ModuleList, _ ...interface{}) error {
81+
list.Items = []ootov1alpha1.Module{mod}
82+
return nil
83+
},
84+
),
85+
mockMetrics.EXPECT().SetExistingKMMOModules(1),
86+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()),
87+
)
8388

84-
ctx := context.TODO()
89+
mr := NewModuleReconciler(clnt, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
8590

8691
dsByKernelVersion := make(map[string]*appsv1.DaemonSet)
8792

8893
gomock.InOrder(
89-
mockMetrics.EXPECT().SetExistingKMMOModules(1),
9094
mockDC.EXPECT().ModuleDaemonSetsByKernelVersion(ctx, moduleName, namespace).Return(dsByKernelVersion, nil),
9195
mockDC.EXPECT().GarbageCollect(ctx, dsByKernelVersion, sets.NewString()),
9296
)
@@ -116,20 +120,30 @@ var _ = Describe("ModuleReconciler", func() {
116120
},
117121
}
118122

119-
c := fake.
120-
NewClientBuilder().
121-
WithScheme(scheme).
122-
WithObjects(&mod, &ds).
123-
Build()
124-
125-
mr := NewModuleReconciler(c, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
126-
127123
ctx := context.TODO()
124+
gomock.InOrder(
125+
clnt.EXPECT().Get(ctx, req.NamespacedName, gomock.Any()).DoAndReturn(
126+
func(_ interface{}, _ interface{}, m *ootov1alpha1.Module) error {
127+
m.ObjectMeta = mod.ObjectMeta
128+
m.Spec = mod.Spec
129+
return nil
130+
},
131+
),
132+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
133+
func(_ interface{}, list *ootov1alpha1.ModuleList, _ ...interface{}) error {
134+
list.Items = []ootov1alpha1.Module{mod}
135+
return nil
136+
},
137+
),
138+
mockMetrics.EXPECT().SetExistingKMMOModules(1),
139+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()),
140+
)
141+
142+
mr := NewModuleReconciler(clnt, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
128143

129144
dsByKernelVersion := map[string]*appsv1.DaemonSet{kernelVersion: &ds}
130145

131146
gomock.InOrder(
132-
mockMetrics.EXPECT().SetExistingKMMOModules(1),
133147
mockDC.EXPECT().ModuleDaemonSetsByKernelVersion(ctx, moduleName, namespace).Return(dsByKernelVersion, nil),
134148
mockDC.EXPECT().GarbageCollect(ctx, dsByKernelVersion, sets.NewString()),
135149
)
@@ -179,16 +193,32 @@ var _ = Describe("ModuleReconciler", func() {
179193
},
180194
}
181195

182-
c := fake.
183-
NewClientBuilder().
184-
WithScheme(scheme).
185-
WithObjects(&mod).
186-
WithLists(&nodeList).
187-
Build()
196+
ctx := context.TODO()
188197

189-
mr := NewModuleReconciler(c, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
198+
gomock.InOrder(
199+
clnt.EXPECT().Get(ctx, req.NamespacedName, gomock.Any()).DoAndReturn(
200+
func(_ interface{}, _ interface{}, m *ootov1alpha1.Module) error {
201+
m.ObjectMeta = mod.ObjectMeta
202+
m.Spec = mod.Spec
203+
return nil
204+
},
205+
),
206+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
207+
func(_ interface{}, list *ootov1alpha1.ModuleList, _ ...interface{}) error {
208+
return nil
209+
},
210+
),
211+
mockMetrics.EXPECT().SetExistingKMMOModules(0),
212+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
213+
func(_ interface{}, list *v1.NodeList, _ ...interface{}) error {
214+
list.Items = nodeList.Items
215+
return nil
216+
},
217+
),
218+
clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()),
219+
)
190220

191-
ctx := context.TODO()
221+
mr := NewModuleReconciler(clnt, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
192222

193223
ds := appsv1.DaemonSet{
194224
ObjectMeta: metav1.ObjectMeta{
@@ -198,7 +228,6 @@ var _ = Describe("ModuleReconciler", func() {
198228
}
199229

200230
gomock.InOrder(
201-
mockMetrics.EXPECT().SetExistingKMMOModules(1),
202231
mockKM.EXPECT().GetNodeOSConfig(&nodeList.Items[0]).Return(&osConfig),
203232
mockKM.EXPECT().FindMappingForKernel(mappings, kernelVersion).Return(&mappings[0], nil),
204233
mockKM.EXPECT().PrepareKernelMapping(&mappings[0], &osConfig).Return(&mappings[0], nil),
@@ -210,12 +239,6 @@ var _ = Describe("ModuleReconciler", func() {
210239
res, err := mr.Reconcile(context.TODO(), req)
211240
Expect(err).NotTo(HaveOccurred())
212241
Expect(res).To(Equal(reconcile.Result{}))
213-
214-
dsList := appsv1.DaemonSetList{}
215-
216-
err = c.List(ctx, &dsList)
217-
Expect(err).NotTo(HaveOccurred())
218-
Expect(dsList.Items).To(HaveLen(1))
219242
})
220243

221244
It("should patch the DaemonSet when it already exists", func() {
@@ -272,21 +295,38 @@ var _ = Describe("ModuleReconciler", func() {
272295
},
273296
}
274297

275-
c := fake.
276-
NewClientBuilder().
277-
WithScheme(scheme).
278-
WithObjects(&mod, &ds).
279-
WithLists(&nodeList).
280-
Build()
298+
ctx := context.TODO()
281299

282-
mr := NewModuleReconciler(c, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
300+
gomock.InOrder(
301+
clnt.EXPECT().Get(ctx, req.NamespacedName, gomock.Any()).DoAndReturn(
302+
func(_ interface{}, _ interface{}, m *ootov1alpha1.Module) error {
303+
m.ObjectMeta = mod.ObjectMeta
304+
m.Spec = mod.Spec
305+
return nil
306+
},
307+
),
308+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
309+
func(_ interface{}, list *ootov1alpha1.ModuleList, _ ...interface{}) error {
310+
list.Items = []ootov1alpha1.Module{mod}
311+
return nil
312+
},
313+
),
314+
mockMetrics.EXPECT().SetExistingKMMOModules(1),
315+
clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
316+
func(_ interface{}, list *v1.NodeList, _ ...interface{}) error {
317+
list.Items = nodeList.Items
318+
return nil
319+
},
320+
),
321+
clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()),
322+
clnt.EXPECT().Patch(ctx, gomock.Any(), gomock.Any()),
323+
)
283324

284-
ctx := context.TODO()
325+
mr := NewModuleReconciler(clnt, mockBM, mockDC, mockKM, mockCU, mockMetrics, nil)
285326

286327
dsByKernelVersion := map[string]*appsv1.DaemonSet{kernelVersion: &ds}
287328

288329
gomock.InOrder(
289-
mockMetrics.EXPECT().SetExistingKMMOModules(1),
290330
mockKM.EXPECT().GetNodeOSConfig(&nodeList.Items[0]).Return(&osConfig),
291331
mockKM.EXPECT().FindMappingForKernel(mappings, kernelVersion).Return(&mappings[0], nil),
292332
mockKM.EXPECT().PrepareKernelMapping(&mappings[0], &osConfig).Return(&mappings[0], nil),
@@ -301,14 +341,6 @@ var _ = Describe("ModuleReconciler", func() {
301341
res, err := mr.Reconcile(context.TODO(), req)
302342
Expect(err).NotTo(HaveOccurred())
303343
Expect(res).To(Equal(reconcile.Result{}))
304-
305-
dsList := appsv1.DaemonSetList{}
306-
307-
err = c.List(ctx, &dsList)
308-
Expect(err).NotTo(HaveOccurred())
309-
Expect(dsList.Items).To(HaveLen(1))
310-
Expect(dsList.Items[0].Name).To(Equal(dsName))
311-
Expect(dsList.Items[0].Labels).To(HaveKeyWithValue("test", "test"))
312344
})
313345
})
314346
})

controllers/node_kernel_reconciler_test.go

+42-25
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,44 @@ package controllers
22

33
import (
44
"context"
5+
"errors"
56

7+
"github.com/golang/mock/gomock"
68
. "github.com/onsi/ginkgo/v2"
79
. "github.com/onsi/gomega"
10+
"github.com/qbarrand/oot-operator/internal/client"
811
v1 "k8s.io/api/core/v1"
912
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1013
"k8s.io/apimachinery/pkg/types"
1114
runtimectrl "sigs.k8s.io/controller-runtime"
12-
"sigs.k8s.io/controller-runtime/pkg/client/fake"
1315
)
1416

1517
var _ = Describe("NodeKernelReconciler", func() {
1618
Describe("Reconcile", func() {
19+
var (
20+
gCtrl *gomock.Controller
21+
clnt *client.MockClient
22+
)
23+
BeforeEach(func() {
24+
gCtrl = gomock.NewController(GinkgoT())
25+
clnt = client.NewMockClient(gCtrl)
26+
})
1727
const (
1828
kernelVersion = "1.2.3"
1929
labelName = "label-name"
2030
nodeName = "node-name"
2131
)
2232

2333
It("should return an error if the node cannot be found anymore", func() {
24-
nkr := NewNodeKernelReconciler(fake.NewClientBuilder().Build(), labelName, nil)
34+
ctx := context.TODO()
35+
clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Return(errors.New("some error"))
36+
37+
nkr := NewNodeKernelReconciler(clnt, labelName, nil)
2538
req := runtimectrl.Request{
2639
NamespacedName: types.NamespacedName{Name: nodeName},
2740
}
2841

29-
_, err := nkr.Reconcile(context.TODO(), req)
42+
_, err := nkr.Reconcile(ctx, req)
3043
Expect(err).To(HaveOccurred())
3144
})
3245

@@ -38,24 +51,26 @@ var _ = Describe("NodeKernelReconciler", func() {
3851
},
3952
}
4053

41-
client := fake.NewClientBuilder().WithObjects(&node).Build()
42-
43-
nkr := NewNodeKernelReconciler(client, labelName, nil)
54+
ctx := context.TODO()
55+
gomock.InOrder(
56+
clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
57+
func(_ interface{}, _ interface{}, n *v1.Node) error {
58+
n.ObjectMeta = node.ObjectMeta
59+
n.Status = node.Status
60+
return nil
61+
},
62+
),
63+
clnt.EXPECT().Patch(ctx, gomock.Any(), gomock.Any()),
64+
)
65+
66+
nkr := NewNodeKernelReconciler(clnt, labelName, nil)
4467
req := runtimectrl.Request{
4568
NamespacedName: types.NamespacedName{Name: nodeName},
4669
}
4770

48-
ctx := context.TODO()
49-
5071
res, err := nkr.Reconcile(ctx, req)
5172
Expect(err).NotTo(HaveOccurred())
5273
Expect(res).To(Equal(res))
53-
54-
updatedNode := v1.Node{}
55-
56-
err = client.Get(ctx, types.NamespacedName{Name: nodeName}, &updatedNode)
57-
Expect(err).NotTo(HaveOccurred())
58-
Expect(updatedNode.Labels).To(HaveKeyWithValue(labelName, kernelVersion))
5974
})
6075

6176
It("should set the label if it already exists", func() {
@@ -69,24 +84,26 @@ var _ = Describe("NodeKernelReconciler", func() {
6984
},
7085
}
7186

72-
client := fake.NewClientBuilder().WithObjects(&node).Build()
73-
74-
nkr := NewNodeKernelReconciler(client, labelName, nil)
87+
ctx := context.TODO()
88+
gomock.InOrder(
89+
clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).DoAndReturn(
90+
func(_ interface{}, _ interface{}, n *v1.Node) error {
91+
n.ObjectMeta = node.ObjectMeta
92+
n.Status = node.Status
93+
return nil
94+
},
95+
),
96+
clnt.EXPECT().Patch(ctx, gomock.Any(), gomock.Any()),
97+
)
98+
99+
nkr := NewNodeKernelReconciler(clnt, labelName, nil)
75100
req := runtimectrl.Request{
76101
NamespacedName: types.NamespacedName{Name: nodeName},
77102
}
78103

79-
ctx := context.TODO()
80-
81104
res, err := nkr.Reconcile(ctx, req)
82105
Expect(err).NotTo(HaveOccurred())
83106
Expect(res).To(Equal(res))
84-
85-
updatedNode := v1.Node{}
86-
87-
err = client.Get(ctx, types.NamespacedName{Name: nodeName}, &updatedNode)
88-
Expect(err).NotTo(HaveOccurred())
89-
Expect(updatedNode.Labels).To(HaveKeyWithValue(labelName, kernelVersion))
90107
})
91108
})
92109
})

0 commit comments

Comments
 (0)