@@ -29,6 +29,7 @@ import (
29
29
"k8s.io/apimachinery/pkg/api/errors"
30
30
"k8s.io/apimachinery/pkg/api/meta"
31
31
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32
+ "k8s.io/apimachinery/pkg/fields"
32
33
"k8s.io/apimachinery/pkg/runtime"
33
34
utilerrors "k8s.io/apimachinery/pkg/util/errors"
34
35
"k8s.io/apimachinery/pkg/watch"
@@ -37,6 +38,7 @@ import (
37
38
"k8s.io/client-go/dynamic"
38
39
"k8s.io/client-go/kubernetes"
39
40
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
41
+ "k8s.io/client-go/tools/cache"
40
42
watchtools "k8s.io/client-go/tools/watch"
41
43
"k8s.io/kubernetes/pkg/kubectl"
42
44
"k8s.io/kubernetes/pkg/kubectl/cmd/attach"
@@ -490,18 +492,41 @@ func (o *RunOptions) removeCreatedObjects(f cmdutil.Factory, createdObjects []*R
490
492
491
493
// waitForPod watches the given pod until the exitCondition is true
492
494
func waitForPod (podClient corev1client.PodsGetter , ns , name string , exitCondition watchtools.ConditionFunc ) (* corev1.Pod , error ) {
493
- w , err := podClient .Pods (ns ).Watch (metav1 .SingleObject (metav1.ObjectMeta {Name : name }))
494
- if err != nil {
495
- return nil , err
496
- }
497
-
498
495
// TODO: expose the timeout
499
496
ctx , cancel := watchtools .ContextWithOptionalTimeout (context .Background (), 0 * time .Second )
500
497
defer cancel ()
498
+
499
+ preconditionFunc := func (store cache.Store ) (bool , error ) {
500
+ _ , exists , err := store .Get (& metav1.ObjectMeta {Namespace : ns , Name : name })
501
+ if err != nil {
502
+ return true , err
503
+ }
504
+ if ! exists {
505
+ // We need to make sure we see the object in the cache before we start waiting for events
506
+ // or we would be waiting for the timeout if such object didn't exist.
507
+ // (e.g. it was deleted before we started informers so they wouldn't even see the delete event)
508
+ return true , errors .NewNotFound (corev1 .Resource ("pods" ), name )
509
+ }
510
+
511
+ return false , nil
512
+ }
513
+
514
+ fieldSelector := fields .OneTermEqualSelector ("metadata.name" , name ).String ()
515
+ lw := & cache.ListWatch {
516
+ ListFunc : func (options metav1.ListOptions ) (runtime.Object , error ) {
517
+ options .FieldSelector = fieldSelector
518
+ return podClient .Pods (ns ).List (options )
519
+ },
520
+ WatchFunc : func (options metav1.ListOptions ) (watch.Interface , error ) {
521
+ options .FieldSelector = fieldSelector
522
+ return podClient .Pods (ns ).Watch (options )
523
+ },
524
+ }
525
+
501
526
intr := interrupt .New (nil , cancel )
502
527
var result * corev1.Pod
503
- err = intr .Run (func () error {
504
- ev , err := watchtools .UntilWithoutRetry (ctx , w , func (ev watch.Event ) (bool , error ) {
528
+ err : = intr .Run (func () error {
529
+ ev , err := watchtools .UntilWithSync (ctx , lw , & corev1. Pod {}, preconditionFunc , func (ev watch.Event ) (bool , error ) {
505
530
return exitCondition (ev )
506
531
})
507
532
if ev != nil {
@@ -510,11 +535,6 @@ func waitForPod(podClient corev1client.PodsGetter, ns, name string, exitConditio
510
535
return err
511
536
})
512
537
513
- // Fix generic not found error.
514
- if err != nil && errors .IsNotFound (err ) {
515
- err = errors .NewNotFound (corev1 .Resource ("pods" ), name )
516
- }
517
-
518
538
return result , err
519
539
}
520
540
0 commit comments