@@ -16,7 +16,21 @@ limitations under the License.
16
16
17
17
package stormservice
18
18
19
- import "testing"
19
+ import (
20
+ "context"
21
+ "reflect"
22
+ "testing"
23
+
24
+ corev1 "k8s.io/api/core/v1"
25
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
+ "k8s.io/apimachinery/pkg/runtime"
27
+ "k8s.io/client-go/tools/record"
28
+ "sigs.k8s.io/controller-runtime/pkg/client"
29
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
30
+
31
+ orchestrationv1alpha1 "github.com/vllm-project/aibrix/api/orchestration/v1alpha1"
32
+ "github.com/vllm-project/aibrix/pkg/controller/constants"
33
+ )
20
34
21
35
func TestCalculateReplicas (t * testing.T ) {
22
36
type args struct {
@@ -112,3 +126,104 @@ func TestCalculateReplicas(t *testing.T) {
112
126
}
113
127
}
114
128
}
129
+
130
+ func TestSyncHeadlessService (t * testing.T ) {
131
+ scheme := runtime .NewScheme ()
132
+ _ = corev1 .AddToScheme (scheme )
133
+ _ = orchestrationv1alpha1 .AddToScheme (scheme )
134
+
135
+ tests := []struct {
136
+ name string
137
+ stormService * orchestrationv1alpha1.StormService
138
+ existingService * corev1.Service
139
+ wantError bool
140
+ }{
141
+ {
142
+ name : "create new headless service" ,
143
+ stormService : & orchestrationv1alpha1.StormService {
144
+ ObjectMeta : metav1.ObjectMeta {
145
+ Name : "test-storm" ,
146
+ Namespace : "default" ,
147
+ Labels : map [string ]string {
148
+ "app" : "test" ,
149
+ },
150
+ },
151
+ },
152
+ existingService : nil ,
153
+ wantError : false ,
154
+ },
155
+ {
156
+ name : "service already exists" ,
157
+ stormService : & orchestrationv1alpha1.StormService {
158
+ ObjectMeta : metav1.ObjectMeta {
159
+ Name : "test-storm" ,
160
+ Namespace : "default" ,
161
+ },
162
+ },
163
+ existingService : & corev1.Service {
164
+ ObjectMeta : metav1.ObjectMeta {
165
+ Name : "test-storm" ,
166
+ Namespace : "default" ,
167
+ },
168
+ Spec : corev1.ServiceSpec {
169
+ Type : corev1 .ServiceTypeClusterIP ,
170
+ ClusterIP : corev1 .ClusterIPNone ,
171
+ Selector : map [string ]string {}, // empty selector that should be updated
172
+ },
173
+ },
174
+ wantError : false ,
175
+ },
176
+ }
177
+
178
+ for _ , tt := range tests {
179
+ t .Run (tt .name , func (t * testing.T ) {
180
+ var objs []client.Object
181
+ if tt .existingService != nil {
182
+ objs = append (objs , tt .existingService )
183
+ }
184
+
185
+ fakeClient := fake .NewClientBuilder ().
186
+ WithScheme (scheme ).
187
+ WithObjects (objs ... ).
188
+ Build ()
189
+
190
+ r := & StormServiceReconciler {
191
+ Client : fakeClient ,
192
+ EventRecorder : & record.FakeRecorder {},
193
+ }
194
+
195
+ err := r .syncHeadlessService (context .TODO (), tt .stormService )
196
+
197
+ if (err != nil ) != tt .wantError {
198
+ t .Errorf ("syncHeadlessService() error = %v, wantError %v" , err , tt .wantError )
199
+ return
200
+ }
201
+
202
+ // Check if service was created/updated
203
+ service := & corev1.Service {}
204
+ err = fakeClient .Get (context .TODO (), client.ObjectKey {
205
+ Name : tt .stormService .Name ,
206
+ Namespace : tt .stormService .Namespace ,
207
+ }, service )
208
+
209
+ if err != nil {
210
+ t .Errorf ("Failed to get service: %v" , err )
211
+ return
212
+ }
213
+
214
+ // Verify service properties
215
+ if service .Spec .ClusterIP != corev1 .ClusterIPNone {
216
+ t .Errorf ("Expected ClusterIP to be None, got %s" , service .Spec .ClusterIP )
217
+ }
218
+
219
+ expectedSelector := map [string ]string {constants .StormServiceNameLabelKey : tt .stormService .Name }
220
+ if ! reflect .DeepEqual (service .Spec .Selector , expectedSelector ) {
221
+ t .Errorf ("Expected selector %v, got %v" , expectedSelector , service .Spec .Selector )
222
+ }
223
+
224
+ if service .Spec .Type != corev1 .ServiceTypeClusterIP {
225
+ t .Errorf ("Expected service type ClusterIP, got %v" , service .Spec .Type )
226
+ }
227
+ })
228
+ }
229
+ }
0 commit comments