1212*/
1313package io .kubernetes .client .informer .impl ;
1414
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 ;
1623import 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 ;
1827
1928import com .github .tomakehurst .wiremock .junit .WireMockRule ;
2029import io .kubernetes .client .informer .EventType ;
2130import io .kubernetes .client .informer .ResourceEventHandler ;
2231import io .kubernetes .client .informer .SharedIndexInformer ;
2332import io .kubernetes .client .informer .SharedInformerFactory ;
33+ import io .kubernetes .client .informer .exception .ObjectTransformException ;
2434import io .kubernetes .client .openapi .ApiClient ;
2535import io .kubernetes .client .openapi .ApiException ;
2636import io .kubernetes .client .openapi .JSON ;
3545import io .kubernetes .client .util .Watch ;
3646import java .io .IOException ;
3747import java .util .Arrays ;
48+ import java .util .Collections ;
3849import java .util .concurrent .atomic .AtomicBoolean ;
3950import org .junit .Before ;
4051import org .junit .Rule ;
@@ -162,6 +173,130 @@ public void testAllNamespacedPodInformerNormalBehavior() throws InterruptedExcep
162173 String startRV = "1000" ;
163174 String endRV = "1001" ;
164175
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+
165300 V1PodList podList =
166301 new V1PodList ().metadata (new V1ListMeta ().resourceVersion (startRV )).items (Arrays .asList ());
167302
@@ -213,6 +348,12 @@ public void testAllNamespacedPodInformerNormalBehavior() throws InterruptedExcep
213348 },
214349 V1Pod .class ,
215350 V1PodList .class );
351+
352+ podInformer .setTransform (
353+ (obj ) -> {
354+ throw new ObjectTransformException ("test transform failure" );
355+ });
356+
216357 AtomicBoolean foundExistingPod = new AtomicBoolean (false );
217358 podInformer .addEventHandler (
218359 new ResourceEventHandler <V1Pod >() {
@@ -233,7 +374,8 @@ public void onDelete(V1Pod obj, boolean deletedFinalStateUnknown) {}
233374 factory .startAllRegisteredInformers ();
234375 Thread .sleep (1000 );
235376
236- assertEquals (true , foundExistingPod .get ());
377+ // cannot find the pod due to transform failure
378+ assertFalse (foundExistingPod .get ());
237379 assertEquals (endRV , podInformer .lastSyncResourceVersion ());
238380
239381 verify (
0 commit comments