Skip to content

Commit a658d59

Browse files
committed
Add unit tests
1 parent 514d6dd commit a658d59

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package service
2+
3+
import (
4+
"testing"
5+
6+
v1 "k8s.io/api/core/v1"
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
servicehelper "k8s.io/cloud-provider/service/helpers"
9+
)
10+
11+
// TestNeedsCleanup verifies that services with deletionTimestamp set are
12+
// correctly identified as needing cleanup, regardless of finalizer state.
13+
// This prevents a race condition where node updates trigger reconciliation
14+
// after the finalizer is removed but before the service is deleted from etcd.
15+
func TestNeedsCleanup(t *testing.T) {
16+
now := metav1.Now()
17+
18+
testCases := []struct {
19+
name string
20+
service *v1.Service
21+
expected bool
22+
}{
23+
{
24+
name: "service with deletionTimestamp and finalizer should need cleanup",
25+
service: &v1.Service{
26+
ObjectMeta: metav1.ObjectMeta{
27+
DeletionTimestamp: &now,
28+
Finalizers: []string{servicehelper.LoadBalancerCleanupFinalizer},
29+
},
30+
Spec: v1.ServiceSpec{
31+
Type: v1.ServiceTypeLoadBalancer,
32+
},
33+
},
34+
expected: true,
35+
},
36+
{
37+
name: "service with deletionTimestamp but no finalizer should need cleanup",
38+
service: &v1.Service{
39+
ObjectMeta: metav1.ObjectMeta{
40+
DeletionTimestamp: &now,
41+
Finalizers: []string{},
42+
},
43+
Spec: v1.ServiceSpec{
44+
Type: v1.ServiceTypeLoadBalancer,
45+
},
46+
},
47+
expected: true,
48+
},
49+
{
50+
name: "service without deletionTimestamp and without finalizer should not need cleanup",
51+
service: &v1.Service{
52+
ObjectMeta: metav1.ObjectMeta{
53+
Finalizers: []string{},
54+
},
55+
Spec: v1.ServiceSpec{
56+
Type: v1.ServiceTypeLoadBalancer,
57+
},
58+
},
59+
expected: false,
60+
},
61+
{
62+
name: "service without deletionTimestamp but with finalizer should not need cleanup",
63+
service: &v1.Service{
64+
ObjectMeta: metav1.ObjectMeta{
65+
Finalizers: []string{servicehelper.LoadBalancerCleanupFinalizer},
66+
},
67+
Spec: v1.ServiceSpec{
68+
Type: v1.ServiceTypeLoadBalancer,
69+
},
70+
},
71+
expected: false,
72+
},
73+
{
74+
name: "non-LoadBalancer service with finalizer should need cleanup",
75+
service: &v1.Service{
76+
ObjectMeta: metav1.ObjectMeta{
77+
Finalizers: []string{servicehelper.LoadBalancerCleanupFinalizer},
78+
},
79+
Spec: v1.ServiceSpec{
80+
Type: v1.ServiceTypeClusterIP,
81+
},
82+
},
83+
expected: true,
84+
},
85+
}
86+
87+
for _, tc := range testCases {
88+
t.Run(tc.name, func(t *testing.T) {
89+
result := needsCleanup(tc.service)
90+
if result != tc.expected {
91+
t.Errorf("needsCleanup() = %v, expected %v", result, tc.expected)
92+
}
93+
})
94+
}
95+
}
96+
97+
// TestNodeSyncService_DeletionTimestamp verifies that nodeSyncService returns
98+
// success (false) without attempting to sync when a service has deletionTimestamp set.
99+
func TestNodeSyncService_DeletionTimestamp(t *testing.T) {
100+
now := metav1.Now()
101+
102+
testCases := []struct {
103+
name string
104+
service *v1.Service
105+
}{
106+
{
107+
name: "nil service should return success",
108+
service: nil,
109+
},
110+
{
111+
name: "service with deletionTimestamp should return success without syncing",
112+
service: &v1.Service{
113+
ObjectMeta: metav1.ObjectMeta{
114+
DeletionTimestamp: &now,
115+
},
116+
Spec: v1.ServiceSpec{
117+
Type: v1.ServiceTypeLoadBalancer,
118+
},
119+
},
120+
},
121+
{
122+
name: "non-LoadBalancer service should return success",
123+
service: &v1.Service{
124+
Spec: v1.ServiceSpec{
125+
Type: v1.ServiceTypeClusterIP,
126+
},
127+
},
128+
},
129+
}
130+
131+
for _, tc := range testCases {
132+
t.Run(tc.name, func(t *testing.T) {
133+
c := &Controller{}
134+
135+
result := c.nodeSyncService(tc.service)
136+
if result != false {
137+
t.Errorf("nodeSyncService() returned needRetry=true, expected success (false)")
138+
}
139+
})
140+
}
141+
}

0 commit comments

Comments
 (0)