func testCheckEventType(t *testing.T, expectEventType watch.EventType, w watch.Interface) { select { case res := <-w.ResultChan(): if res.Type != expectEventType { t.Errorf("event type want=%v, get=%v", expectEventType, res.Type) } case <-time.After(wait.ForeverTestTimeout): t.Errorf("time out after waiting %v on ResultChan", wait.ForeverTestTimeout) } }
func observeCreation(w watch.Interface) { select { case event, _ := <-w.ResultChan(): if event.Type != watch.Added { framework.Failf("Failed to observe the creation: %v", event) } case <-time.After(30 * time.Second): framework.Failf("Timeout while waiting for observing the creation") } }
func waitForAnyPersistentVolumeClaimPhase(w watch.Interface, phase v1.PersistentVolumeClaimPhase) { for { event := <-w.ResultChan() claim, ok := event.Object.(*v1.PersistentVolumeClaim) if !ok { continue } if claim.Status.Phase == phase { glog.V(2).Infof("claim %q is %s", claim.Name, phase) break } } }
func waitForAnyPersistentVolumePhase(w watch.Interface, phase v1.PersistentVolumePhase) { for { event := <-w.ResultChan() volume, ok := event.Object.(*v1.PersistentVolume) if !ok { continue } if volume.Status.Phase == phase { glog.V(2).Infof("volume %q is %s", volume.Name, phase) break } } }
func testCheckResult(t *testing.T, i int, expectEventType watch.EventType, w watch.Interface, expectObj *api.Pod) { select { case res := <-w.ResultChan(): if res.Type != expectEventType { t.Errorf("#%d: event type want=%v, get=%v", i, expectEventType, res.Type) return } if !reflect.DeepEqual(expectObj, res.Object) { t.Errorf("#%d: obj want=\n%#v\nget=\n%#v", i, expectObj, res.Object) } case <-time.After(wait.ForeverTestTimeout): t.Errorf("#%d: time out after waiting %v on ResultChan", i, wait.ForeverTestTimeout) } }
func testCheckStop(t *testing.T, i int, w watch.Interface) { select { case e, ok := <-w.ResultChan(): if ok { var obj string switch e.Object.(type) { case *api.Pod: obj = e.Object.(*api.Pod).Name case *metav1.Status: obj = e.Object.(*metav1.Status).Message } t.Errorf("#%d: ResultChan should have been closed. Event: %s. Object: %s", i, e.Type, obj) } case <-time.After(wait.ForeverTestTimeout): t.Errorf("#%d: time out after waiting 1s on ResultChan", i) } }
func verifyWatchEvent(t *testing.T, w watch.Interface, eventType watch.EventType, eventObject runtime.Object) { _, _, line, _ := goruntime.Caller(1) select { case event := <-w.ResultChan(): if e, a := eventType, event.Type; e != a { t.Logf("(called from line %d)", line) t.Errorf("Expected: %s, got: %s", eventType, event.Type) } if e, a := eventObject, event.Object; !api.Semantic.DeepDerivative(e, a) { t.Logf("(called from line %d)", line) t.Errorf("Expected (%s): %#v, got: %#v", eventType, e, a) } case <-time.After(wait.ForeverTestTimeout): t.Logf("(called from line %d)", line) t.Errorf("Timed out waiting for an event") } }
func observeObjectDeletion(w watch.Interface) (obj runtime.Object) { deleted := false timeout := false timer := time.After(60 * time.Second) for !deleted && !timeout { select { case event, _ := <-w.ResultChan(): if event.Type == watch.Deleted { obj = event.Object deleted = true } case <-timer: timeout = true } } if !deleted { framework.Failf("Failed to observe pod deletion") } return }
func waitForPersistentVolumeClaimPhase(client *clientset.Clientset, claimName, namespace string, w watch.Interface, phase v1.PersistentVolumeClaimPhase) { // Check if the claim is already in requested phase claim, err := client.Core().PersistentVolumeClaims(namespace).Get(claimName, metav1.GetOptions{}) if err == nil && claim.Status.Phase == phase { return } // Wait for the phase for { event := <-w.ResultChan() claim, ok := event.Object.(*v1.PersistentVolumeClaim) if !ok { continue } if claim.Status.Phase == phase && claim.Name == claimName { glog.V(2).Infof("claim %q is %s", claim.Name, phase) break } } }
func waitForPersistentVolumePhase(client *clientset.Clientset, pvName string, w watch.Interface, phase v1.PersistentVolumePhase) { // Check if the volume is already in requested phase volume, err := client.Core().PersistentVolumes().Get(pvName, metav1.GetOptions{}) if err == nil && volume.Status.Phase == phase { return } // Wait for the phase for { event := <-w.ResultChan() volume, ok := event.Object.(*v1.PersistentVolume) if !ok { continue } if volume.Status.Phase == phase && volume.Name == pvName { glog.V(2).Infof("volume %q is %s", volume.Name, phase) break } } }
// ensure the watch delivers the requested and only the requested items. func consume(t *testing.T, w watch.Interface, rvs []string, done *sync.WaitGroup) { defer done.Done() for _, rv := range rvs { got, ok := <-w.ResultChan() if !ok { t.Errorf("%#v: unexpected channel close, wanted %v", rvs, rv) return } gotRV := got.Object.(*v1.Pod).ObjectMeta.ResourceVersion if e, a := rv, gotRV; e != a { t.Errorf("wanted %v, got %v", e, a) } else { t.Logf("Got %v as expected", gotRV) } } // We should not get anything else. got, open := <-w.ResultChan() if open { t.Errorf("%#v: unwanted object %#v", rvs, got) } }
// watchRollbackEvent watches for rollback events and returns rollback result func watchRollbackEvent(w watch.Interface) string { signals := make(chan os.Signal, 1) signal.Notify(signals, os.Interrupt, os.Kill, syscall.SIGTERM) for { select { case event, ok := <-w.ResultChan(): if !ok { return "" } obj, ok := event.Object.(*api.Event) if !ok { w.Stop() return "" } isRollback, result := isRollbackEvent(obj) if isRollback { w.Stop() return result } case <-signals: w.Stop() } } }
// watchHandler watches w and keeps *resourceVersion up to date. func (r *Reflector) watchHandler(w watch.Interface, resourceVersion *string, errc chan error, stopCh <-chan struct{}) error { start := time.Now() eventCount := 0 // Stopping the watcher should be idempotent and if we return from this function there's no way // we're coming back in with the same watch interface. defer w.Stop() loop: for { select { case <-stopCh: return errorStopRequested case err := <-errc: return err case event, ok := <-w.ResultChan(): if !ok { break loop } if event.Type == watch.Error { return apierrs.FromObject(event.Object) } if e, a := r.expectedType, reflect.TypeOf(event.Object); e != nil && e != a { utilruntime.HandleError(fmt.Errorf("%s: expected type %v, but watch event object had type %v", r.name, e, a)) continue } meta, err := meta.Accessor(event.Object) if err != nil { utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event)) continue } newResourceVersion := meta.GetResourceVersion() switch event.Type { case watch.Added: err := r.store.Add(event.Object) if err != nil { utilruntime.HandleError(fmt.Errorf("%s: unable to add watch event object (%#v) to store: %v", r.name, event.Object, err)) } case watch.Modified: err := r.store.Update(event.Object) if err != nil { utilruntime.HandleError(fmt.Errorf("%s: unable to update watch event object (%#v) to store: %v", r.name, event.Object, err)) } case watch.Deleted: // TODO: Will any consumers need access to the "last known // state", which is passed in event.Object? If so, may need // to change this. err := r.store.Delete(event.Object) if err != nil { utilruntime.HandleError(fmt.Errorf("%s: unable to delete watch event object (%#v) from store: %v", r.name, event.Object, err)) } default: utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event)) } *resourceVersion = newResourceVersion r.setLastSyncResourceVersion(newResourceVersion) eventCount++ } } watchDuration := time.Now().Sub(start) if watchDuration < 1*time.Second && eventCount == 0 { glog.V(4).Infof("%s: Unexpected watch close - watch lasted less than a second and no items received", r.name) return errors.New("very short watch") } glog.V(4).Infof("%s: Watch close - %v total %v items received", r.name, r.expectedType, eventCount) return nil }