From 3853a9b77db211762716a1cf48588de8edfa8442 Mon Sep 17 00:00:00 2001 From: James Peach Date: Wed, 29 Jul 2020 01:10:41 +1000 Subject: [PATCH] Sync the informer cache on each test. (#9) This change should have been made a long time ago. On test start up, sync the informer caches right before we start to run any checks. This ensures that cluster precondition checks are reliable. Signed-off-by: James Peach --- pkg/driver/object.go | 22 ++++++++++++++++++++++ pkg/test/runner.go | 11 +++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/pkg/driver/object.go b/pkg/driver/object.go index 667a5df..9091a81 100644 --- a/pkg/driver/object.go +++ b/pkg/driver/object.go @@ -73,6 +73,10 @@ type ObjectDriver interface { // watchers. InformOn(gvr schema.GroupVersionResource) error + // WaitForCacheSync waits until all the informers created + // by the driver have synced. + WaitForCacheSync(timeout time.Duration) error + // Watch registers an event handler to receive events from // all the informers managed by the driver. Watch(cache.ResourceEventHandler) func() @@ -217,6 +221,24 @@ func (o *objectDriver) InformOn(gvr schema.GroupVersionResource) error { return nil } +func (o *objectDriver) WaitForCacheSync(timeout time.Duration) error { + var synced []cache.InformerSynced + + for _, i := range o.informerPool { + synced = append(synced, i.Informer().HasSynced) + } + + stopChan := make(chan struct{}) + timer := time.AfterFunc(timeout, func() { close(stopChan) }) + defer timer.Stop() + + if !cache.WaitForCacheSync(stopChan, synced...) { + return errors.New("informer cache sync timed out") + } + + return nil +} + func (o *objectDriver) Apply(obj *unstructured.Unstructured) (*OperationResult, error) { obj = obj.DeepCopy() // Copy in case we set the namespace. gvk := obj.GetObjectKind().GroupVersionKind() diff --git a/pkg/test/runner.go b/pkg/test/runner.go index 68f9bd3..14db8e5 100644 --- a/pkg/test/runner.go +++ b/pkg/test/runner.go @@ -92,14 +92,14 @@ func PreserveObjectsOpt() RunOpt { }) } -// WatchResourceOpt disables automatic object deletion. +// WatchResourceOpt adds an explicit informer for the given resource. func WatchResourceOpt(gvr schema.GroupVersionResource) RunOpt { return RunOpt(func(tc *testContext) { tc.watchedResources = append(tc.watchedResources, gvr) }) } -// DryRunOpt enables Kuberentes dry-run mode (TODO). +// DryRunOpt enables Kubernetes dry-run mode (TODO). func DryRunOpt() RunOpt { return RunOpt(func(tc *testContext) { tc.dryRun = true @@ -188,6 +188,13 @@ func Run(testDoc *doc.Document, opts ...RunOpt) error { tc.objectDriver.InformOn(gvr) } + // Let the informers sync. For most environments, this + // timeout is far too long. Eventually we can make it a flag + // to tune it down. + if err := tc.objectDriver.WaitForCacheSync(5 * time.Minute); err != nil { + return err + } + if err := storeResourceVersions(tc.kubeDriver, tc.regoDriver); err != nil { return err }