Skip to content

Commit a94447d

Browse files
committed
add ut for node selector
Signed-off-by: bingshen.wbs <[email protected]>
1 parent 9fb9928 commit a94447d

File tree

3 files changed

+219
-19
lines changed

3 files changed

+219
-19
lines changed

cmd/controller/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,10 @@ func main() {
169169
}
170170

171171
if err = (&controller.NodeReconciler{
172-
Client: mgr.GetClient(),
173-
Scheme: mgr.GetScheme(),
174-
EriClient: eriClient,
172+
Client: mgr.GetClient(),
173+
Scheme: mgr.GetScheme(),
174+
EriClient: eriClient,
175+
CtrlConfig: config.GetConfig(),
175176
}).SetupWithManager(mgr); err != nil {
176177
setupLog.Error(err, "unable to create controller", "controller", "Node")
177178
os.Exit(1)

internal/controller/node_controller.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"time"
66

7-
"github.com/AliyunContainerService/alibabacloud-erdma-controller/internal/config"
87
"github.com/AliyunContainerService/alibabacloud-erdma-controller/internal/types"
98
"github.com/samber/lo"
109
k8stypes "k8s.io/apimachinery/pkg/types"
@@ -34,8 +33,9 @@ const (
3433
// NodeReconciler reconciles a ERdmaDevice object
3534
type NodeReconciler struct {
3635
client.Client
37-
Scheme *runtime.Scheme
38-
EriClient *EriClient
36+
Scheme *runtime.Scheme
37+
EriClient *EriClient
38+
CtrlConfig *types.Config
3939
}
4040

4141
// +kubebuilder:rbac:groups=network.alibabacloud.com,resources=erdmadevices,verbs=get;list;watch;create;update;patch;delete
@@ -178,14 +178,29 @@ func (r *NodeReconciler) OwnNode(node *v1.Node) bool {
178178
if node == nil {
179179
return false
180180
}
181-
for k, v := range config.GetConfig().NodeSelector {
181+
for k, v := range r.CtrlConfig.NodeSelector {
182182
if node.Labels[k] != v {
183183
return false
184184
}
185185
}
186186
return true
187187
}
188188

189+
func (r *NodeReconciler) PredictNodeUpdate(oldNode, newNode *v1.Node) bool {
190+
if !r.OwnNode(newNode) {
191+
return false
192+
}
193+
if !r.OwnNode(oldNode) && r.OwnNode(newNode) {
194+
return true
195+
}
196+
197+
if newNode.DeletionTimestamp != nil {
198+
return true
199+
}
200+
201+
return oldNode.Spec.ProviderID != newNode.Spec.ProviderID
202+
}
203+
189204
// SetupWithManager sets up the controller with the Manager.
190205
func (r *NodeReconciler) SetupWithManager(mgr ctrl.Manager) error {
191206
pred := predicate.TypedFuncs[*v1.Node]{
@@ -196,18 +211,7 @@ func (r *NodeReconciler) SetupWithManager(mgr ctrl.Manager) error {
196211
return r.OwnNode(e.Object)
197212
},
198213
UpdateFunc: func(e event.TypedUpdateEvent[*v1.Node]) bool {
199-
if !r.OwnNode(e.ObjectNew) {
200-
return false
201-
}
202-
if !r.OwnNode(e.ObjectOld) && r.OwnNode(e.ObjectNew) {
203-
return true
204-
}
205-
206-
if e.ObjectNew.DeletionTimestamp != nil {
207-
return true
208-
}
209-
210-
return e.ObjectOld.Spec.ProviderID != e.ObjectNew.Spec.ProviderID
214+
return r.PredictNodeUpdate(e.ObjectOld, e.ObjectNew)
211215
},
212216
GenericFunc: func(e event.TypedGenericEvent[*v1.Node]) bool {
213217
return r.OwnNode(e.Object)
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package controller
2+
3+
import (
4+
"github.com/AliyunContainerService/alibabacloud-erdma-controller/internal/types"
5+
"testing"
6+
7+
v1 "k8s.io/api/core/v1"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
)
10+
11+
func TestNodeReconciler_OwnNode(t *testing.T) {
12+
testcases := []struct {
13+
name string
14+
selector map[string]string
15+
node *v1.Node
16+
expected bool
17+
}{
18+
{
19+
name: "node is nil",
20+
selector: nil,
21+
node: nil,
22+
expected: false,
23+
},
24+
{
25+
name: "selector all nodes",
26+
selector: nil,
27+
node: &v1.Node{
28+
ObjectMeta: metav1.ObjectMeta{
29+
Labels: map[string]string{
30+
"kubernetes.io/nodename": "cn-hangzhou.1.1.1.1",
31+
},
32+
},
33+
},
34+
expected: true,
35+
},
36+
{
37+
name: "selector match",
38+
selector: map[string]string{
39+
"selector1": "value1",
40+
},
41+
node: &v1.Node{
42+
ObjectMeta: metav1.ObjectMeta{
43+
Labels: map[string]string{
44+
"kubernetes.io/nodename": "cn-hangzhou.1.1.1.1",
45+
"selector1": "value1",
46+
},
47+
},
48+
},
49+
expected: true,
50+
},
51+
{
52+
name: "selector partial match",
53+
selector: map[string]string{
54+
"selector1": "value1",
55+
"selector2": "value2",
56+
},
57+
node: &v1.Node{
58+
ObjectMeta: metav1.ObjectMeta{
59+
Labels: map[string]string{
60+
"kubernetes.io/nodename": "cn-hangzhou.1.1.1.1",
61+
"selector1": "value1",
62+
},
63+
},
64+
},
65+
expected: false,
66+
},
67+
}
68+
for _, tc := range testcases {
69+
t.Run(tc.name, func(t *testing.T) {
70+
r := &NodeReconciler{
71+
CtrlConfig: &types.Config{
72+
NodeSelector: tc.selector,
73+
},
74+
}
75+
result := r.OwnNode(tc.node)
76+
if result != tc.expected {
77+
t.Errorf("expected %v, but got %v", tc.expected, result)
78+
}
79+
})
80+
}
81+
}
82+
83+
func TestPredictNodeUpdate(t *testing.T) {
84+
tests := []struct {
85+
name string
86+
oldNode *v1.Node
87+
newNode *v1.Node
88+
expected bool
89+
}{
90+
{
91+
name: "New node not owned",
92+
oldNode: &v1.Node{
93+
ObjectMeta: metav1.ObjectMeta{
94+
Name: "node1",
95+
Labels: map[string]string{
96+
"test-key": "test-value",
97+
},
98+
},
99+
},
100+
newNode: &v1.Node{
101+
ObjectMeta: metav1.ObjectMeta{
102+
Name: "node1",
103+
Labels: map[string]string{
104+
"test-key": "different-value",
105+
},
106+
},
107+
},
108+
expected: false,
109+
},
110+
{
111+
name: "Old node not owned, new node owned",
112+
oldNode: &v1.Node{
113+
ObjectMeta: metav1.ObjectMeta{
114+
Name: "node1",
115+
Labels: map[string]string{
116+
"test-key": "not-owned",
117+
},
118+
},
119+
},
120+
newNode: &v1.Node{
121+
ObjectMeta: metav1.ObjectMeta{
122+
Name: "node1",
123+
Labels: map[string]string{
124+
"test-key": "test-value",
125+
},
126+
},
127+
},
128+
expected: true,
129+
},
130+
{
131+
name: "Node with deletion timestamp",
132+
oldNode: &v1.Node{
133+
ObjectMeta: metav1.ObjectMeta{
134+
Name: "node1",
135+
Labels: map[string]string{
136+
"test-key": "test-value",
137+
},
138+
},
139+
},
140+
newNode: &v1.Node{
141+
ObjectMeta: metav1.ObjectMeta{
142+
Name: "node1",
143+
DeletionTimestamp: &metav1.Time{},
144+
Labels: map[string]string{
145+
"test-key": "test-value",
146+
},
147+
},
148+
},
149+
expected: true,
150+
},
151+
{
152+
name: "ProviderID changed",
153+
oldNode: &v1.Node{
154+
ObjectMeta: metav1.ObjectMeta{
155+
Name: "node1",
156+
Labels: map[string]string{
157+
"test-key": "test-value",
158+
},
159+
},
160+
Spec: v1.NodeSpec{
161+
ProviderID: "old-provider-id",
162+
},
163+
},
164+
newNode: &v1.Node{
165+
ObjectMeta: metav1.ObjectMeta{
166+
Name: "node1",
167+
Labels: map[string]string{
168+
"test-key": "test-value",
169+
},
170+
},
171+
Spec: v1.NodeSpec{
172+
ProviderID: "new-provider-id",
173+
},
174+
},
175+
expected: true,
176+
},
177+
}
178+
179+
reconciler := &NodeReconciler{
180+
CtrlConfig: &types.Config{
181+
NodeSelector: map[string]string{
182+
"test-key": "test-value",
183+
},
184+
},
185+
}
186+
187+
for _, tt := range tests {
188+
t.Run(tt.name, func(t *testing.T) {
189+
result := reconciler.PredictNodeUpdate(tt.oldNode, tt.newNode)
190+
if result != tt.expected {
191+
t.Errorf("PredictNodeUpdate() = %v, expected %v", result, tt.expected)
192+
}
193+
})
194+
}
195+
}

0 commit comments

Comments
 (0)