@@ -224,13 +224,12 @@ public async Task WatcherIntegrationTest()
224224 var started = new AsyncManualResetEvent ( ) ;
225225 var connectionClosed = new AsyncManualResetEvent ( ) ;
226226
227- var watcher = kubernetes . BatchV1 . ListNamespacedJobWithHttpMessagesAsync (
227+ var watcher = kubernetes . BatchV1 . WatchListNamespacedJob (
228228 job . Metadata . NamespaceProperty ,
229229 fieldSelector : $ "metadata.name={ job . Metadata . Name } ",
230230 resourceVersion : job . Metadata . ResourceVersion ,
231231 timeoutSeconds : 30 ,
232- watch : true ) . Watch < V1Job , V1JobList > (
233- ( type , source ) =>
232+ onEvent : ( type , source ) =>
234233 {
235234 Debug . WriteLine ( $ "Watcher 1: { type } , { source } ") ;
236235 events . Add ( new Tuple < WatchEventType , V1Job > ( type , source ) ) ;
@@ -250,6 +249,86 @@ public async Task WatcherIntegrationTest()
250249 new V1DeleteOptions ( ) { PropagationPolicy = "Foreground" } ) . ConfigureAwait ( false ) ;
251250 }
252251
252+ [ MinikubeFact ]
253+ public async Task WatcherIntegrationTestAsyncEnumerable ( )
254+ {
255+ using var kubernetes = CreateClient ( ) ;
256+
257+ var job = await kubernetes . BatchV1 . CreateNamespacedJobAsync (
258+ new V1Job ( )
259+ {
260+ ApiVersion = "batch/v1" ,
261+ Kind = V1Job . KubeKind ,
262+ Metadata = new V1ObjectMeta ( ) { Name = nameof ( WatcherIntegrationTestAsyncEnumerable ) . ToLowerInvariant ( ) } ,
263+ Spec = new V1JobSpec ( )
264+ {
265+ Template = new V1PodTemplateSpec ( )
266+ {
267+ Spec = new V1PodSpec ( )
268+ {
269+ Containers = new List < V1Container > ( )
270+ {
271+ new V1Container ( )
272+ {
273+ Image = "ubuntu" ,
274+ Name = "runner" ,
275+ Command = new List < string > ( ) { "/bin/bash" , "-c" , "--" } ,
276+ Args = new List < string > ( )
277+ {
278+ "trap : TERM INT; sleep infinity & wait" ,
279+ } ,
280+ } ,
281+ } ,
282+ RestartPolicy = "Never" ,
283+ } ,
284+ } ,
285+ } ,
286+ } ,
287+ "default" ) . ConfigureAwait ( false ) ;
288+
289+ var events = new Collection < Tuple < WatchEventType , V1Job > > ( ) ;
290+
291+ var started = new AsyncManualResetEvent ( ) ;
292+ var watchCompleted = new AsyncManualResetEvent ( ) ;
293+
294+ // Start async enumerable watch in background task to mimic callback behavior
295+ var watchTask = Task . Run ( async ( ) =>
296+ {
297+ try
298+ {
299+ await foreach ( var ( type , source ) in kubernetes . BatchV1 . WatchListNamespacedJobAsync (
300+ job . Metadata . NamespaceProperty ,
301+ fieldSelector : $ "metadata.name={ job . Metadata . Name } ",
302+ resourceVersion : job . Metadata . ResourceVersion ,
303+ timeoutSeconds : 30 ) . ConfigureAwait ( false ) )
304+ {
305+ Debug . WriteLine ( $ "AsyncEnumerable Watcher: { type } , { source } ") ;
306+ events . Add ( new Tuple < WatchEventType , V1Job > ( type , source ) ) ;
307+ job = source ;
308+ started . Set ( ) ;
309+ }
310+ }
311+ catch ( Exception ex )
312+ {
313+ Debug . WriteLine ( $ "Watch exception: { ex . GetType ( ) . FullName } : { ex . Message } ") ;
314+ }
315+ finally
316+ {
317+ watchCompleted . Set ( ) ;
318+ }
319+ } ) ;
320+
321+ await started . WaitAsync ( ) . ConfigureAwait ( false ) ;
322+
323+ await Task . WhenAny ( watchCompleted . WaitAsync ( ) , Task . Delay ( TimeSpan . FromMinutes ( 3 ) ) ) . ConfigureAwait ( false ) ;
324+ Assert . True ( watchCompleted . IsSet ) ;
325+
326+ var st = await kubernetes . BatchV1 . DeleteNamespacedJobAsync (
327+ job . Metadata . Name ,
328+ job . Metadata . NamespaceProperty ,
329+ new V1DeleteOptions ( ) { PropagationPolicy = "Foreground" } ) . ConfigureAwait ( false ) ;
330+ }
331+
253332 [ MinikubeFact ]
254333 public void LeaderIntegrationTest ( )
255334 {
0 commit comments