1
1
package backend
2
2
3
3
import (
4
+ "context"
4
5
"sync"
5
6
"testing"
6
7
8
+ "k8s.io/apimachinery/pkg/runtime"
9
+ "k8s.io/client-go/tools/record"
10
+ ctrl "sigs.k8s.io/controller-runtime"
11
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
12
+
7
13
"inference.networking.x-k8s.io/gateway-api-inference-extension/api/v1alpha1"
8
14
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9
15
"k8s.io/apimachinery/pkg/types"
10
16
)
11
17
12
18
var (
13
- service1 = & v1alpha1.InferenceModel {
19
+ infModel1 = & v1alpha1.InferenceModel {
14
20
Spec : v1alpha1.InferenceModelSpec {
15
21
ModelName : "fake model1" ,
16
22
PoolRef : v1alpha1.PoolObjectReference {Name : "test-pool" },
19
25
Name : "test-service" ,
20
26
},
21
27
}
22
- service1Modified = & v1alpha1.InferenceModel {
28
+ infModel1Modified = & v1alpha1.InferenceModel {
23
29
Spec : v1alpha1.InferenceModelSpec {
24
30
ModelName : "fake model1" ,
25
31
PoolRef : v1alpha1.PoolObjectReference {Name : "test-poolio" },
28
34
Name : "test-service" ,
29
35
},
30
36
}
31
- service2 = & v1alpha1.InferenceModel {
37
+ infModel2 = & v1alpha1.InferenceModel {
32
38
Spec : v1alpha1.InferenceModelSpec {
33
39
ModelName : "fake model" ,
34
40
PoolRef : v1alpha1.PoolObjectReference {Name : "test-pool" },
@@ -60,8 +66,8 @@ func TestUpdateDatastore_InferenceModelReconciler(t *testing.T) {
60
66
},
61
67
InferenceModels : & sync.Map {},
62
68
},
63
- incomingService : service1 ,
64
- wantInferenceModels : populateServiceMap (service1 ),
69
+ incomingService : infModel1 ,
70
+ wantInferenceModels : populateServiceMap (infModel1 ),
65
71
},
66
72
{
67
73
name : "Removing existing service." ,
@@ -75,9 +81,9 @@ func TestUpdateDatastore_InferenceModelReconciler(t *testing.T) {
75
81
ResourceVersion : "Old and boring" ,
76
82
},
77
83
},
78
- InferenceModels : populateServiceMap (service1 ),
84
+ InferenceModels : populateServiceMap (infModel1 ),
79
85
},
80
- incomingService : service1Modified ,
86
+ incomingService : infModel1Modified ,
81
87
wantInferenceModels : populateServiceMap (),
82
88
},
83
89
{
@@ -92,7 +98,7 @@ func TestUpdateDatastore_InferenceModelReconciler(t *testing.T) {
92
98
ResourceVersion : "Old and boring" ,
93
99
},
94
100
},
95
- InferenceModels : populateServiceMap (service1 ),
101
+ InferenceModels : populateServiceMap (infModel1 ),
96
102
},
97
103
incomingService : & v1alpha1.InferenceModel {
98
104
Spec : v1alpha1.InferenceModelSpec {
@@ -103,7 +109,7 @@ func TestUpdateDatastore_InferenceModelReconciler(t *testing.T) {
103
109
Name : "unrelated-service" ,
104
110
},
105
111
},
106
- wantInferenceModels : populateServiceMap (service1 ),
112
+ wantInferenceModels : populateServiceMap (infModel1 ),
107
113
},
108
114
{
109
115
name : "Add to existing" ,
@@ -117,27 +123,124 @@ func TestUpdateDatastore_InferenceModelReconciler(t *testing.T) {
117
123
ResourceVersion : "Old and boring" ,
118
124
},
119
125
},
120
- InferenceModels : populateServiceMap (service1 ),
126
+ InferenceModels : populateServiceMap (infModel1 ),
121
127
},
122
- incomingService : service2 ,
123
- wantInferenceModels : populateServiceMap (service1 , service2 ),
128
+ incomingService : infModel2 ,
129
+ wantInferenceModels : populateServiceMap (infModel1 , infModel2 ),
124
130
},
125
131
}
126
132
for _ , test := range tests {
127
133
t .Run (test .name , func (t * testing.T ) {
128
- InferenceModelReconciler := & InferenceModelReconciler {
134
+ reconciler := & InferenceModelReconciler {
129
135
Datastore : test .datastore ,
130
136
PoolNamespacedName : types.NamespacedName {Name : test .datastore .inferencePool .Name },
131
137
}
132
- InferenceModelReconciler .updateDatastore (test .incomingService )
138
+ reconciler .updateDatastore (test .incomingService )
133
139
134
- if ok := mapsEqual (InferenceModelReconciler .Datastore .InferenceModels , test .wantInferenceModels ); ! ok {
140
+ if ok := mapsEqual (reconciler .Datastore .InferenceModels , test .wantInferenceModels ); ! ok {
135
141
t .Error ("Maps are not equal" )
136
142
}
137
143
})
138
144
}
139
145
}
140
146
147
+ func TestReconcile_ResourceNotFound (t * testing.T ) {
148
+ // Set up the scheme.
149
+ scheme := runtime .NewScheme ()
150
+ _ = v1alpha1 .AddToScheme (scheme )
151
+
152
+ // Create a fake client with no InferenceModel objects.
153
+ fakeClient := fake .NewClientBuilder ().WithScheme (scheme ).Build ()
154
+
155
+ // Create a minimal datastore.
156
+ datastore := & K8sDatastore {
157
+ InferenceModels : & sync.Map {},
158
+ inferencePool : & v1alpha1.InferencePool {
159
+ ObjectMeta : metav1.ObjectMeta {Name : "test-pool" },
160
+ },
161
+ }
162
+
163
+ // Create the reconciler.
164
+ reconciler := & InferenceModelReconciler {
165
+ Client : fakeClient ,
166
+ Scheme : scheme ,
167
+ Record : record .NewFakeRecorder (10 ),
168
+ Datastore : datastore ,
169
+ PoolNamespacedName : types.NamespacedName {Name : "test-pool" },
170
+ }
171
+
172
+ // Create a request for a non-existent resource.
173
+ req := ctrl.Request {NamespacedName : types.NamespacedName {Name : "non-existent-model" , Namespace : "default" }}
174
+
175
+ // Call Reconcile.
176
+ result , err := reconciler .Reconcile (context .Background (), req )
177
+ if err != nil {
178
+ t .Fatalf ("expected no error when resource is not found, got %v" , err )
179
+ }
180
+
181
+ // Check that no requeue is requested.
182
+ if result .Requeue || result .RequeueAfter != 0 {
183
+ t .Errorf ("expected no requeue, got %+v" , result )
184
+ }
185
+ }
186
+
187
+ func TestReconcile_ResourceExists (t * testing.T ) {
188
+ // Set up the scheme.
189
+ scheme := runtime .NewScheme ()
190
+ _ = v1alpha1 .AddToScheme (scheme )
191
+
192
+ // Create an InferenceModel object.
193
+ existingModel := & v1alpha1.InferenceModel {
194
+ ObjectMeta : metav1.ObjectMeta {
195
+ Name : "existing-model" ,
196
+ Namespace : "default" ,
197
+ },
198
+ Spec : v1alpha1.InferenceModelSpec {
199
+ ModelName : "fake-model" ,
200
+ PoolRef : v1alpha1.PoolObjectReference {Name : "test-pool" },
201
+ },
202
+ }
203
+
204
+ // Create a fake client with the existing model.
205
+ fakeClient := fake .NewClientBuilder ().WithScheme (scheme ).WithObjects (existingModel ).Build ()
206
+
207
+ // Create a minimal datastore.
208
+ datastore := & K8sDatastore {
209
+ InferenceModels : & sync.Map {},
210
+ inferencePool : & v1alpha1.InferencePool {
211
+ ObjectMeta : metav1.ObjectMeta {Name : "test-pool" },
212
+ },
213
+ }
214
+
215
+ // Create the reconciler.
216
+ reconciler := & InferenceModelReconciler {
217
+ Client : fakeClient ,
218
+ Scheme : scheme ,
219
+ Record : record .NewFakeRecorder (10 ),
220
+ Datastore : datastore ,
221
+ PoolNamespacedName : types.NamespacedName {Name : "test-pool" , Namespace : "default" },
222
+ }
223
+
224
+ // Create a request for the existing resource.
225
+ req := ctrl.Request {NamespacedName : types.NamespacedName {Name : "existing-model" , Namespace : "default" }}
226
+
227
+ // Call Reconcile.
228
+ result , err := reconciler .Reconcile (context .Background (), req )
229
+ if err != nil {
230
+ t .Fatalf ("expected no error when resource exists, got %v" , err )
231
+ }
232
+
233
+ // Check that no requeue is requested.
234
+ if result .Requeue || result .RequeueAfter != 0 {
235
+ t .Errorf ("expected no requeue, got %+v" , result )
236
+ }
237
+
238
+ // Verify that the datastore was updated.
239
+ if _ , ok := datastore .InferenceModels .Load (existingModel .Spec .ModelName ); ! ok {
240
+ t .Errorf ("expected datastore to contain model %q" , existingModel .Spec .ModelName )
241
+ }
242
+ }
243
+
141
244
func populateServiceMap (services ... * v1alpha1.InferenceModel ) * sync.Map {
142
245
returnVal := & sync.Map {}
143
246
0 commit comments