12
12
*/
13
13
package io .kubernetes .client .informer .impl ;
14
14
15
- import static com .github .tomakehurst .wiremock .client .WireMock .*;
15
+ import static com .github .tomakehurst .wiremock .client .WireMock .aResponse ;
16
+ import static com .github .tomakehurst .wiremock .client .WireMock .equalTo ;
17
+ import static com .github .tomakehurst .wiremock .client .WireMock .get ;
18
+ import static com .github .tomakehurst .wiremock .client .WireMock .getRequestedFor ;
19
+ import static com .github .tomakehurst .wiremock .client .WireMock .moreThan ;
20
+ import static com .github .tomakehurst .wiremock .client .WireMock .stubFor ;
21
+ import static com .github .tomakehurst .wiremock .client .WireMock .urlPathEqualTo ;
22
+ import static com .github .tomakehurst .wiremock .client .WireMock .verify ;
16
23
import static com .github .tomakehurst .wiremock .core .WireMockConfiguration .options ;
17
- import static org .junit .Assert .*;
24
+ import static org .junit .Assert .assertEquals ;
25
+ import static org .junit .Assert .assertFalse ;
26
+ import static org .junit .Assert .assertTrue ;
18
27
19
28
import com .github .tomakehurst .wiremock .junit .WireMockRule ;
20
29
import io .kubernetes .client .informer .EventType ;
21
30
import io .kubernetes .client .informer .ResourceEventHandler ;
22
31
import io .kubernetes .client .informer .SharedIndexInformer ;
23
32
import io .kubernetes .client .informer .SharedInformerFactory ;
33
+ import io .kubernetes .client .informer .exception .ObjectTransformException ;
24
34
import io .kubernetes .client .openapi .ApiClient ;
25
35
import io .kubernetes .client .openapi .ApiException ;
26
36
import io .kubernetes .client .openapi .JSON ;
35
45
import io .kubernetes .client .util .Watch ;
36
46
import java .io .IOException ;
37
47
import java .util .Arrays ;
48
+ import java .util .Collections ;
38
49
import java .util .concurrent .atomic .AtomicBoolean ;
39
50
import org .junit .Before ;
40
51
import org .junit .Rule ;
@@ -162,6 +173,130 @@ public void testAllNamespacedPodInformerNormalBehavior() throws InterruptedExcep
162
173
String startRV = "1000" ;
163
174
String endRV = "1001" ;
164
175
176
+ V1PodList podList =
177
+ new V1PodList ().metadata (new V1ListMeta ().resourceVersion (startRV )).items (Arrays .asList ());
178
+
179
+ stubFor (
180
+ get (urlPathEqualTo ("/api/v1/pods" ))
181
+ .withQueryParam ("watch" , equalTo ("false" ))
182
+ .willReturn (
183
+ aResponse ()
184
+ .withStatus (200 )
185
+ .withHeader ("Content-Type" , "application/json" )
186
+ .withBody (new JSON ().serialize (podList ))));
187
+
188
+ Watch .Response <V1Pod > watchResponse =
189
+ new Watch .Response <>(
190
+ EventType .ADDED .name (),
191
+ new V1Pod ()
192
+ .metadata (
193
+ new V1ObjectMeta ()
194
+ .namespace (namespace )
195
+ .name (podName )
196
+ .resourceVersion (endRV )
197
+ .labels (Collections .singletonMap ("foo" , "bar" ))
198
+ .annotations (Collections .singletonMap ("foo" , "bar" ))));
199
+
200
+ stubFor (
201
+ get (urlPathEqualTo ("/api/v1/pods" ))
202
+ .withQueryParam ("watch" , equalTo ("true" ))
203
+ .willReturn (
204
+ aResponse ()
205
+ .withStatus (200 )
206
+ .withHeader ("Content-Type" , "application/json" )
207
+ .withBody (new JSON ().serialize (watchResponse ))));
208
+
209
+ SharedInformerFactory factory = new SharedInformerFactory ();
210
+ SharedIndexInformer <V1Pod > podInformer =
211
+ factory .sharedIndexInformerFor (
212
+ (CallGeneratorParams params ) -> {
213
+ try {
214
+ return coreV1Api .listPodForAllNamespacesCall (
215
+ null ,
216
+ null ,
217
+ null ,
218
+ null ,
219
+ null ,
220
+ null ,
221
+ params .resourceVersion ,
222
+ null ,
223
+ params .timeoutSeconds ,
224
+ params .watch ,
225
+ null );
226
+ } catch (ApiException e ) {
227
+ throw new RuntimeException (e );
228
+ }
229
+ },
230
+ V1Pod .class ,
231
+ V1PodList .class );
232
+
233
+ podInformer .setTransform (
234
+ (obj ) -> {
235
+ // deepcopy
236
+ String json = new JSON ().serialize (obj );
237
+ V1Pod pod = new JSON ().deserialize (json , V1Pod .class );
238
+ // remove pod annotations
239
+ pod .getMetadata ().setAnnotations (null );
240
+ return pod ;
241
+ });
242
+
243
+ AtomicBoolean foundExistingPod = new AtomicBoolean (false );
244
+ AtomicBoolean transformed = new AtomicBoolean (false );
245
+ AtomicBoolean setTransformAfterStarted = new AtomicBoolean (false );
246
+ podInformer .addEventHandler (
247
+ new ResourceEventHandler <V1Pod >() {
248
+ @ Override
249
+ public void onAdd (V1Pod obj ) {
250
+ if (podName .equals (obj .getMetadata ().getName ())
251
+ && namespace .equals (obj .getMetadata ().getNamespace ())) {
252
+ foundExistingPod .set (true );
253
+ }
254
+ V1ObjectMeta metadata = obj .getMetadata ();
255
+ // check if the object was transformed
256
+ if (metadata .getLabels ().get ("foo" ).equals ("bar" )
257
+ && metadata .getAnnotations () == null ) {
258
+ transformed .set (true );
259
+ }
260
+ }
261
+
262
+ @ Override
263
+ public void onUpdate (V1Pod oldObj , V1Pod newObj ) {}
264
+
265
+ @ Override
266
+ public void onDelete (V1Pod obj , boolean deletedFinalStateUnknown ) {}
267
+ });
268
+ factory .startAllRegisteredInformers ();
269
+ Thread .sleep (1000 );
270
+
271
+ // can not set transform func if the informer has started
272
+ try {
273
+ podInformer .setTransform ((obj ) -> new V1Pod ());
274
+ setTransformAfterStarted .set (true );
275
+ } catch (IllegalStateException e ) {
276
+ }
277
+
278
+ assertTrue (foundExistingPod .get ());
279
+ assertTrue (transformed .get ());
280
+ assertFalse (setTransformAfterStarted .get ());
281
+ assertEquals (endRV , podInformer .lastSyncResourceVersion ());
282
+
283
+ verify (
284
+ 1 ,
285
+ getRequestedFor (urlPathEqualTo ("/api/v1/pods" )).withQueryParam ("watch" , equalTo ("false" )));
286
+ verify (
287
+ moreThan (1 ),
288
+ getRequestedFor (urlPathEqualTo ("/api/v1/pods" )).withQueryParam ("watch" , equalTo ("true" )));
289
+ factory .stopAllRegisteredInformers ();
290
+ }
291
+
292
+ @ Test
293
+ public void testAllNamespacedPodInformerTransformFailure () throws InterruptedException {
294
+
295
+ CoreV1Api coreV1Api = new CoreV1Api (client );
296
+
297
+ String startRV = "1000" ;
298
+ String endRV = "1001" ;
299
+
165
300
V1PodList podList =
166
301
new V1PodList ().metadata (new V1ListMeta ().resourceVersion (startRV )).items (Arrays .asList ());
167
302
@@ -213,6 +348,12 @@ public void testAllNamespacedPodInformerNormalBehavior() throws InterruptedExcep
213
348
},
214
349
V1Pod .class ,
215
350
V1PodList .class );
351
+
352
+ podInformer .setTransform (
353
+ (obj ) -> {
354
+ throw new ObjectTransformException ("test transform failure" );
355
+ });
356
+
216
357
AtomicBoolean foundExistingPod = new AtomicBoolean (false );
217
358
podInformer .addEventHandler (
218
359
new ResourceEventHandler <V1Pod >() {
@@ -233,7 +374,8 @@ public void onDelete(V1Pod obj, boolean deletedFinalStateUnknown) {}
233
374
factory .startAllRegisteredInformers ();
234
375
Thread .sleep (1000 );
235
376
236
- assertEquals (true , foundExistingPod .get ());
377
+ // cannot find the pod due to transform failure
378
+ assertFalse (foundExistingPod .get ());
237
379
assertEquals (endRV , podInformer .lastSyncResourceVersion ());
238
380
239
381
verify (
0 commit comments