From 2a81bf1090aef6c4246f3e84cb9e6b9d58f89b2f Mon Sep 17 00:00:00 2001 From: Derek Whatley Date: Fri, 26 Mar 2021 13:53:55 -0400 Subject: [PATCH] Check for resource staleness, requeue if stale --- pkg/cache/stale.go | 79 +++++++++++++++++++ .../directimagemigration_controller.go | 20 +++-- .../directimagestreammigration_controller.go | 21 +++-- .../directvolumemigration_controller.go | 19 ++++- ...irectvolumemigrationprogress_controller.go | 19 ++++- .../miganalytic/miganalytics_controller.go | 18 ++++- .../migcluster/migcluster_controller.go | 20 ++++- pkg/controller/mighook/mighook_controller.go | 18 ++++- .../migmigration/migmigration_controller.go | 20 ++++- pkg/controller/migplan/migplan_controller.go | 18 ++++- .../migstorage/migstorage_controller.go | 18 ++++- 11 files changed, 240 insertions(+), 30 deletions(-) create mode 100644 pkg/cache/stale.go diff --git a/pkg/cache/stale.go b/pkg/cache/stale.go new file mode 100644 index 000000000..0dffbeda7 --- /dev/null +++ b/pkg/cache/stale.go @@ -0,0 +1,79 @@ +/* +Copyright 2021 Red Hat Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cache + +import ( + "sync" + + "k8s.io/apimachinery/pkg/types" +) + +// Functions in this file solve the problem of duplicate reconciles when the cached +// client hasn't received the latest resource and feeds a stale resource to controller. +// We will reject reconciling a resource if its generation is older than one we've +// successfully reconciled. + +// UIDToGenerationMap keeps track of highest observed generation of a particular resource UID +type UIDToGenerationMap struct { + mutex sync.RWMutex + resourceUIDtoGeneration map[types.UID]int64 +} + +// CreateUIDToGenerationMap creates a new UID => generation map +func CreateUIDToGenerationMap() *UIDToGenerationMap { + uidGenMap := UIDToGenerationMap{} + uidGenMap.resourceUIDtoGeneration = make(map[types.UID]int64) + return &uidGenMap +} + +// getGenerationForUID returns the latest successfully reconciled resource generation +// returns -1 if not found. +func (u *UIDToGenerationMap) getGenerationForUID(resourceUID types.UID) int64 { + u.mutex.Lock() + defer u.mutex.Unlock() + generation, ok := u.resourceUIDtoGeneration[resourceUID] + if !ok { + return -1 + } + return generation +} + +// setGenerationForUID returns the latest successfully reconciled resource generation +func (u *UIDToGenerationMap) setGenerationForUID(resourceUID types.UID, generation int64) { + u.mutex.Lock() + defer u.mutex.Unlock() + u.resourceUIDtoGeneration[resourceUID] = generation +} + +// IsCacheStale checks if the cached client is providing a resource we've successfully reconciled. +func (u *UIDToGenerationMap) IsCacheStale(resourceUID types.UID, generation int64) bool { + reconciledGeneration := u.getGenerationForUID(resourceUID) + // Resource should be reconciled if we've never seen it + if generation == -1 { + return false + } + // Resource is stale if we've reconciled a newer generation + if generation < reconciledGeneration { + return true + } + return false +} + +// RecordReconciledGeneration records that a resource UID generation was pushed back to the APIserver +func (u *UIDToGenerationMap) RecordReconciledGeneration(resourceUID types.UID, generation int64) { + u.setGenerationForUID(resourceUID, generation) +} diff --git a/pkg/controller/directimagemigration/directimagemigration_controller.go b/pkg/controller/directimagemigration/directimagemigration_controller.go index 26ba299a4..7e793f26c 100644 --- a/pkg/controller/directimagemigration/directimagemigration_controller.go +++ b/pkg/controller/directimagemigration/directimagemigration_controller.go @@ -22,6 +22,7 @@ import ( "github.com/konveyor/controller/pkg/logging" migapi "github.com/konveyor/mig-controller/pkg/apis/migration/v1alpha1" + "github.com/konveyor/mig-controller/pkg/cache" migref "github.com/konveyor/mig-controller/pkg/reference" "github.com/opentracing/opentracing-go" "k8s.io/apimachinery/pkg/api/errors" @@ -46,9 +47,10 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { return &ReconcileDirectImageMigration{ - Client: mgr.GetClient(), - scheme: mgr.GetScheme(), - EventRecorder: mgr.GetRecorder("directimagemigration_controller"), + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("directimagemigration_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), } } @@ -99,8 +101,9 @@ var _ reconcile.Reconciler = &ReconcileDirectImageMigration{} type ReconcileDirectImageMigration struct { client.Client record.EventRecorder - scheme *runtime.Scheme - tracer opentracing.Tracer + scheme *runtime.Scheme + tracer opentracing.Tracer + uidGenerationMap *cache.UIDToGenerationMap } // Reconcile reads that state of the cluster for a DirectImageMigration object and makes changes based on the state read @@ -126,6 +129,13 @@ func (r *ReconcileDirectImageMigration) Reconcile(request reconcile.Request) (re return reconcile.Result{Requeue: true}, err } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(imageMigration.UID, imageMigration.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(imageMigration.UID, imageMigration.Generation) + // Set up jaeger tracing reconcileSpan := r.initTracer(imageMigration) if reconcileSpan != nil { diff --git a/pkg/controller/directimagestreammigration/directimagestreammigration_controller.go b/pkg/controller/directimagestreammigration/directimagestreammigration_controller.go index e6db521f6..b67bce9b5 100644 --- a/pkg/controller/directimagestreammigration/directimagestreammigration_controller.go +++ b/pkg/controller/directimagestreammigration/directimagestreammigration_controller.go @@ -22,6 +22,7 @@ import ( "github.com/konveyor/controller/pkg/logging" migapi "github.com/konveyor/mig-controller/pkg/apis/migration/v1alpha1" + "github.com/konveyor/mig-controller/pkg/cache" migref "github.com/konveyor/mig-controller/pkg/reference" "github.com/opentracing/opentracing-go" "k8s.io/apimachinery/pkg/api/errors" @@ -46,9 +47,10 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { return &ReconcileDirectImageStreamMigration{ - Client: mgr.GetClient(), - scheme: mgr.GetScheme(), - EventRecorder: mgr.GetRecorder("directimagestreammigration_controller"), + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("directimagestreammigration_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), } } @@ -90,8 +92,9 @@ var _ reconcile.Reconciler = &ReconcileDirectImageStreamMigration{} type ReconcileDirectImageStreamMigration struct { client.Client record.EventRecorder - scheme *runtime.Scheme - tracer opentracing.Tracer + scheme *runtime.Scheme + tracer opentracing.Tracer + uidGenerationMap *cache.UIDToGenerationMap } // Reconcile reads that state of the cluster for a DirectImageStreamMigration object and makes changes based on the state read @@ -117,6 +120,14 @@ func (r *ReconcileDirectImageStreamMigration) Reconcile(request reconcile.Reques return reconcile.Result{Requeue: true}, err } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(imageStreamMigration.UID, imageStreamMigration.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration( + imageStreamMigration.UID, imageStreamMigration.Generation) + // Set up jaeger tracing reconcileSpan, err := r.initTracer(*imageStreamMigration) if reconcileSpan != nil { diff --git a/pkg/controller/directvolumemigration/directvolumemigration_controller.go b/pkg/controller/directvolumemigration/directvolumemigration_controller.go index f7475b2d5..d8ffba608 100644 --- a/pkg/controller/directvolumemigration/directvolumemigration_controller.go +++ b/pkg/controller/directvolumemigration/directvolumemigration_controller.go @@ -22,6 +22,7 @@ import ( "github.com/konveyor/controller/pkg/logging" migapi "github.com/konveyor/mig-controller/pkg/apis/migration/v1alpha1" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/opentracing/opentracing-go" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -43,7 +44,11 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileDirectVolumeMigration{Client: mgr.GetClient(), scheme: mgr.GetScheme()} + return &ReconcileDirectVolumeMigration{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -79,8 +84,9 @@ var _ reconcile.Reconciler = &ReconcileDirectVolumeMigration{} // ReconcileDirectVolumeMigration reconciles a DirectVolumeMigration object type ReconcileDirectVolumeMigration struct { client.Client - scheme *runtime.Scheme - tracer opentracing.Tracer + scheme *runtime.Scheme + tracer opentracing.Tracer + uidGenerationMap *cache.UIDToGenerationMap } // Reconcile reads that state of the cluster for a DirectVolumeMigration object and makes changes based on the state read @@ -107,6 +113,13 @@ func (r *ReconcileDirectVolumeMigration) Reconcile(request reconcile.Request) (r return reconcile.Result{Requeue: true}, err } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(direct.UID, direct.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(direct.UID, direct.Generation) + // Set up jaeger tracing reconcileSpan := r.initTracer(direct) if reconcileSpan != nil { diff --git a/pkg/controller/directvolumemigrationprogress/directvolumemigrationprogress_controller.go b/pkg/controller/directvolumemigrationprogress/directvolumemigrationprogress_controller.go index 1d6ac995e..c2943700a 100644 --- a/pkg/controller/directvolumemigrationprogress/directvolumemigrationprogress_controller.go +++ b/pkg/controller/directvolumemigrationprogress/directvolumemigrationprogress_controller.go @@ -25,6 +25,7 @@ import ( "strings" "time" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/konveyor/mig-controller/pkg/errorutil" "github.com/opentracing/opentracing-go" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -78,7 +79,11 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileDirectVolumeMigrationProgress{Client: mgr.GetClient(), scheme: mgr.GetScheme()} + return &ReconcileDirectVolumeMigrationProgress{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -113,8 +118,9 @@ var _ reconcile.Reconciler = &ReconcileDirectVolumeMigrationProgress{} // ReconcileDirectVolumeMigrationProgress reconciles a DirectVolumeMigrationProgress object type ReconcileDirectVolumeMigrationProgress struct { client.Client - scheme *runtime.Scheme - tracer opentracing.Tracer + scheme *runtime.Scheme + tracer opentracing.Tracer + uidGenerationMap *cache.UIDToGenerationMap } // Reconcile reads that state of the cluster for a DirectVolumeMigrationProgress object and makes changes based on the state read @@ -137,6 +143,13 @@ func (r *ReconcileDirectVolumeMigrationProgress) Reconcile(request reconcile.Req return reconcile.Result{Requeue: true}, err } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(pvProgress.UID, pvProgress.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(pvProgress.UID, pvProgress.Generation) + // Set up jaeger tracing reconcileSpan, err := r.initTracer(*pvProgress) if reconcileSpan != nil { diff --git a/pkg/controller/miganalytic/miganalytics_controller.go b/pkg/controller/miganalytic/miganalytics_controller.go index 5169c3e4e..051c416a9 100644 --- a/pkg/controller/miganalytic/miganalytics_controller.go +++ b/pkg/controller/miganalytic/miganalytics_controller.go @@ -26,6 +26,7 @@ import ( "github.com/konveyor/controller/pkg/logging" "github.com/konveyor/mig-controller/pkg/apis/migration/v1alpha1" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/konveyor/mig-controller/pkg/compat" "github.com/konveyor/mig-controller/pkg/errorutil" "github.com/konveyor/mig-controller/pkg/gvk" @@ -72,7 +73,12 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileMigAnalytic{Client: mgr.GetClient(), scheme: mgr.GetScheme(), EventRecorder: mgr.GetRecorder("miganalytic_controller")} + return &ReconcileMigAnalytic{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("miganalytic_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -107,7 +113,8 @@ type ReconcileMigAnalytic struct { client.Client record.EventRecorder - scheme *runtime.Scheme + scheme *runtime.Scheme + uidGenerationMap *cache.UIDToGenerationMap } // MigAnalyticPersistentVolumeDetails defines extended properties of a volume discovered by MigAnalytic @@ -138,6 +145,13 @@ func (r *ReconcileMigAnalytic) Reconcile(request reconcile.Request) (reconcile.R return reconcile.Result{Requeue: true}, nil } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(analytic.UID, analytic.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(analytic.UID, analytic.Generation) + // Exit early if the MigAnalytic already has a ready condition // and Refresh boolean is unset if analytic.Status.IsReady() && !analytic.Spec.Refresh { diff --git a/pkg/controller/migcluster/migcluster_controller.go b/pkg/controller/migcluster/migcluster_controller.go index 745fbbf11..dd865942e 100644 --- a/pkg/controller/migcluster/migcluster_controller.go +++ b/pkg/controller/migcluster/migcluster_controller.go @@ -20,6 +20,7 @@ import ( "context" "time" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/konveyor/mig-controller/pkg/errorutil" "github.com/konveyor/controller/pkg/logging" @@ -48,7 +49,12 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) *ReconcileMigCluster { - return &ReconcileMigCluster{Client: mgr.GetClient(), scheme: mgr.GetScheme(), EventRecorder: mgr.GetRecorder("migcluster_controller")} + return &ReconcileMigCluster{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("migcluster_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -101,8 +107,9 @@ type ReconcileMigCluster struct { k8sclient.Client record.EventRecorder - scheme *runtime.Scheme - Controller controller.Controller + scheme *runtime.Scheme + Controller controller.Controller + uidGenerationMap *cache.UIDToGenerationMap } func (r *ReconcileMigCluster) Reconcile(request reconcile.Request) (reconcile.Result, error) { @@ -121,6 +128,13 @@ func (r *ReconcileMigCluster) Reconcile(request reconcile.Request) (reconcile.Re return reconcile.Result{Requeue: true}, nil } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(cluster.UID, cluster.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(cluster.UID, cluster.Generation) + // Report reconcile error. defer func() { log.Info("CR", "conditions", cluster.Status.Conditions) diff --git a/pkg/controller/mighook/mighook_controller.go b/pkg/controller/mighook/mighook_controller.go index c68f40a23..ae8e3d9f9 100644 --- a/pkg/controller/mighook/mighook_controller.go +++ b/pkg/controller/mighook/mighook_controller.go @@ -19,6 +19,7 @@ package mighook import ( "context" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/konveyor/mig-controller/pkg/errorutil" "github.com/konveyor/controller/pkg/logging" @@ -44,7 +45,12 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileMigHook{Client: mgr.GetClient(), scheme: mgr.GetScheme(), EventRecorder: mgr.GetRecorder("mighook_controller")} + return &ReconcileMigHook{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("mighook_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -74,7 +80,8 @@ type ReconcileMigHook struct { client.Client record.EventRecorder - scheme *runtime.Scheme + scheme *runtime.Scheme + uidGenerationMap *cache.UIDToGenerationMap } func (r *ReconcileMigHook) Reconcile(request reconcile.Request) (reconcile.Result, error) { @@ -93,6 +100,13 @@ func (r *ReconcileMigHook) Reconcile(request reconcile.Request) (reconcile.Resul return reconcile.Result{Requeue: true}, nil } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(hook.UID, hook.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(hook.UID, hook.Generation) + // Report reconcile error. defer func() { log.Info("CR", "conditions", hook.Status.Conditions) diff --git a/pkg/controller/migmigration/migmigration_controller.go b/pkg/controller/migmigration/migmigration_controller.go index c27da8a41..4525fc850 100644 --- a/pkg/controller/migmigration/migmigration_controller.go +++ b/pkg/controller/migmigration/migmigration_controller.go @@ -24,6 +24,7 @@ import ( liberr "github.com/konveyor/controller/pkg/error" "github.com/konveyor/controller/pkg/logging" migapi "github.com/konveyor/mig-controller/pkg/apis/migration/v1alpha1" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/konveyor/mig-controller/pkg/errorutil" migref "github.com/konveyor/mig-controller/pkg/reference" "github.com/opentracing/opentracing-go" @@ -50,7 +51,12 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileMigMigration{Client: mgr.GetClient(), scheme: mgr.GetScheme(), EventRecorder: mgr.GetRecorder("migmigration_controller")} + return &ReconcileMigMigration{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("migmigration_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -139,8 +145,9 @@ type ReconcileMigMigration struct { client.Client record.EventRecorder - scheme *runtime.Scheme - tracer opentracing.Tracer + scheme *runtime.Scheme + tracer opentracing.Tracer + uidGenerationMap *cache.UIDToGenerationMap } // Reconcile performs Migrations based on the data in MigMigration @@ -163,6 +170,13 @@ func (r *ReconcileMigMigration) Reconcile(request reconcile.Request) (reconcile. return reconcile.Result{Requeue: true}, nil } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(migration.UID, migration.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(migration.UID, migration.Generation) + // Get jaeger spans for migration and reconcile _, reconcileSpan := r.initTracer(migration) if reconcileSpan != nil { diff --git a/pkg/controller/migplan/migplan_controller.go b/pkg/controller/migplan/migplan_controller.go index e12ce92e9..65ddde7e5 100644 --- a/pkg/controller/migplan/migplan_controller.go +++ b/pkg/controller/migplan/migplan_controller.go @@ -24,6 +24,7 @@ import ( "strings" "time" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/konveyor/mig-controller/pkg/errorutil" liberr "github.com/konveyor/controller/pkg/error" @@ -68,7 +69,12 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileMigPlan{Client: mgr.GetClient(), scheme: mgr.GetScheme(), EventRecorder: mgr.GetRecorder("migplan_controller")} + return &ReconcileMigPlan{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("migplan_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -174,7 +180,8 @@ type ReconcileMigPlan struct { client.Client record.EventRecorder - scheme *runtime.Scheme + scheme *runtime.Scheme + uidGenerationMap *cache.UIDToGenerationMap } func (r *ReconcileMigPlan) Reconcile(request reconcile.Request) (reconcile.Result, error) { @@ -193,6 +200,13 @@ func (r *ReconcileMigPlan) Reconcile(request reconcile.Request) (reconcile.Resul return reconcile.Result{Requeue: true}, err } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(plan.UID, plan.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(plan.UID, plan.Generation) + // Report reconcile error. defer func() { // This should only be turned on in debug mode IMO, diff --git a/pkg/controller/migstorage/migstorage_controller.go b/pkg/controller/migstorage/migstorage_controller.go index 42bef9dfe..c65d05989 100644 --- a/pkg/controller/migstorage/migstorage_controller.go +++ b/pkg/controller/migstorage/migstorage_controller.go @@ -20,6 +20,7 @@ import ( "context" "time" + "github.com/konveyor/mig-controller/pkg/cache" "github.com/konveyor/mig-controller/pkg/errorutil" "github.com/konveyor/controller/pkg/logging" @@ -47,7 +48,12 @@ func Add(mgr manager.Manager) error { // newReconciler returns a new reconcile.Reconciler func newReconciler(mgr manager.Manager) reconcile.Reconciler { - return &ReconcileMigStorage{Client: mgr.GetClient(), scheme: mgr.GetScheme(), EventRecorder: mgr.GetRecorder("migstorage_controller")} + return &ReconcileMigStorage{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + EventRecorder: mgr.GetRecorder("migstorage_controller"), + uidGenerationMap: cache.CreateUIDToGenerationMap(), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler @@ -100,7 +106,8 @@ type ReconcileMigStorage struct { client.Client record.EventRecorder - scheme *runtime.Scheme + scheme *runtime.Scheme + uidGenerationMap *cache.UIDToGenerationMap } func (r *ReconcileMigStorage) Reconcile(request reconcile.Request) (reconcile.Result, error) { @@ -119,6 +126,13 @@ func (r *ReconcileMigStorage) Reconcile(request reconcile.Request) (reconcile.Re return reconcile.Result{Requeue: true}, nil } + // Check if cache is still catching up + if r.uidGenerationMap.IsCacheStale(storage.UID, storage.Generation) { + return reconcile.Result{Requeue: true}, nil + } + // Record reconciled generation + defer r.uidGenerationMap.RecordReconciledGeneration(storage.UID, storage.Generation) + // Report reconcile error. defer func() { log.Info("CR", "conditions", storage.Status.Conditions)