Skip to content

Commit 9efd834

Browse files
committed
Add unit test for machine controller reconcile
1 parent 3079910 commit 9efd834

File tree

2 files changed

+182
-2
lines changed

2 files changed

+182
-2
lines changed

pkg/controller/machine/controller.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
corev1 "k8s.io/api/core/v1"
2525
apierrors "k8s.io/apimachinery/pkg/api/errors"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2627
"k8s.io/apimachinery/pkg/runtime"
2728
"k8s.io/klog"
2829
clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
@@ -216,8 +217,18 @@ func (c *ReconcileMachine) delete(ctx context.Context, machine *clusterv1.Machin
216217

217218
func (c *ReconcileMachine) getCluster(ctx context.Context, machine *clusterv1.Machine) (*clusterv1.Cluster, error) {
218219
clusterList := clusterv1.ClusterList{}
219-
err := c.Client.List(ctx, client.InNamespace(machine.Namespace), &clusterList)
220-
if err != nil {
220+
listOptions := &client.ListOptions{
221+
Namespace: machine.Namespace,
222+
// This is set so the fake client can be used for unit test. See:
223+
// https://github.com/kubernetes-sigs/controller-runtime/issues/168
224+
Raw: &metav1.ListOptions{
225+
TypeMeta: metav1.TypeMeta{
226+
APIVersion: clusterv1.SchemeGroupVersion.String(),
227+
Kind: "Cluster",
228+
},
229+
},
230+
}
231+
if err := c.Client.List(ctx, listOptions, &clusterList); err != nil {
221232
return nil, err
222233
}
223234

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package machine
18+
19+
import (
20+
"reflect"
21+
"testing"
22+
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/apimachinery/pkg/types"
25+
"k8s.io/client-go/kubernetes/scheme"
26+
"sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
27+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
28+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
29+
)
30+
31+
func TestReconcileRequest(t *testing.T) {
32+
m1 := v1alpha1.Machine{
33+
TypeMeta: metav1.TypeMeta{
34+
Kind: "Machine",
35+
},
36+
ObjectMeta: metav1.ObjectMeta{
37+
Name: "create",
38+
Namespace: "default",
39+
},
40+
}
41+
m2 := v1alpha1.Machine{
42+
TypeMeta: metav1.TypeMeta{
43+
Kind: "Machine",
44+
},
45+
ObjectMeta: metav1.ObjectMeta{
46+
Name: "update",
47+
Namespace: "default",
48+
Finalizers: []string{v1alpha1.MachineFinalizer},
49+
},
50+
}
51+
time := metav1.Now()
52+
m3 := v1alpha1.Machine{
53+
TypeMeta: metav1.TypeMeta{
54+
Kind: "Machine",
55+
},
56+
ObjectMeta: metav1.ObjectMeta{
57+
Name: "delete",
58+
Namespace: "default",
59+
Finalizers: []string{v1alpha1.MachineFinalizer},
60+
DeletionTimestamp: &time,
61+
},
62+
}
63+
c := v1alpha1.Cluster{
64+
TypeMeta: metav1.TypeMeta{
65+
Kind: "Cluster",
66+
},
67+
ObjectMeta: metav1.ObjectMeta{
68+
Name: "cluster",
69+
Namespace: "default",
70+
},
71+
}
72+
cl := v1alpha1.ClusterList{
73+
TypeMeta: metav1.TypeMeta{
74+
Kind: "ClusterList",
75+
},
76+
Items: []v1alpha1.Cluster{c},
77+
}
78+
79+
type expected struct {
80+
createCallCount int64
81+
existCallCount int64
82+
updateCallCount int64
83+
deleteCallCount int64
84+
result reconcile.Result
85+
error bool
86+
}
87+
testCases := []struct {
88+
request reconcile.Request
89+
ExistsValue bool
90+
expected expected
91+
}{
92+
{
93+
request: reconcile.Request{NamespacedName: types.NamespacedName{Name: m1.Name, Namespace: m1.Namespace}},
94+
expected: expected{
95+
createCallCount: 1,
96+
existCallCount: 1,
97+
updateCallCount: 0,
98+
deleteCallCount: 0,
99+
result: reconcile.Result{},
100+
error: false,
101+
},
102+
},
103+
{
104+
request: reconcile.Request{NamespacedName: types.NamespacedName{Name: m2.Name, Namespace: m2.Namespace}},
105+
ExistsValue: true,
106+
expected: expected{
107+
createCallCount: 0,
108+
existCallCount: 1,
109+
updateCallCount: 1,
110+
deleteCallCount: 0,
111+
result: reconcile.Result{},
112+
error: false,
113+
},
114+
},
115+
{
116+
request: reconcile.Request{NamespacedName: types.NamespacedName{Name: m3.Name, Namespace: m3.Namespace}},
117+
ExistsValue: true,
118+
expected: expected{
119+
createCallCount: 0,
120+
existCallCount: 0,
121+
updateCallCount: 0,
122+
deleteCallCount: 1,
123+
result: reconcile.Result{},
124+
error: false,
125+
},
126+
},
127+
}
128+
129+
for _, tc := range testCases {
130+
a := newTestActuator()
131+
a.ExistsValue = tc.ExistsValue
132+
v1alpha1.AddToScheme(scheme.Scheme)
133+
r := &ReconcileMachine{
134+
Client: fake.NewFakeClient(&cl, &m1, &m2, &m3),
135+
scheme: scheme.Scheme,
136+
actuator: a,
137+
}
138+
139+
result, err := r.Reconcile(tc.request)
140+
gotError := (err != nil)
141+
if tc.expected.error != gotError {
142+
var errorExpectation string
143+
if !tc.expected.error {
144+
errorExpectation = "no"
145+
}
146+
t.Errorf("Case: %s. Expected %s error, got: %v", tc.request.Name, errorExpectation, err)
147+
}
148+
149+
if !reflect.DeepEqual(result, tc.expected.result) {
150+
t.Errorf("Case %s. Got: %v, expected %v", tc.request.Name, result, tc.expected.result)
151+
}
152+
153+
if a.CreateCallCount != tc.expected.createCallCount {
154+
t.Errorf("Case %s. Got: %d createCallCount, expected %d", tc.request.Name, a.CreateCallCount, tc.expected.createCallCount)
155+
}
156+
157+
if a.UpdateCallCount != tc.expected.updateCallCount {
158+
t.Errorf("Case %s. Got: %d updateCallCount, expected %d", tc.request.Name, a.UpdateCallCount, tc.expected.updateCallCount)
159+
}
160+
161+
if a.ExistsCallCount != tc.expected.existCallCount {
162+
t.Errorf("Case %s. Got: %d existCallCount, expected %d", tc.request.Name, a.ExistsCallCount, tc.expected.existCallCount)
163+
}
164+
165+
if a.DeleteCallCount != tc.expected.deleteCallCount {
166+
t.Errorf("Case %s. Got: %d deleteCallCount, expected %d", tc.request.Name, a.DeleteCallCount, tc.expected.deleteCallCount)
167+
}
168+
}
169+
}

0 commit comments

Comments
 (0)