From dba4f6eb667a5a61edbfb86c51ce25a9c01381e4 Mon Sep 17 00:00:00 2001 From: Fabian Kramm Date: Fri, 16 Aug 2024 12:10:57 +0200 Subject: [PATCH] refactor: importer adjustments --- pkg/controllers/resources/ingresses/syncer.go | 16 +++++- pkg/pro/import.go | 4 ++ pkg/syncer/importer.go | 4 ++ pkg/syncer/syncer.go | 56 ++++++++----------- pkg/syncer/types/syncer.go | 3 + 5 files changed, 49 insertions(+), 34 deletions(-) diff --git a/pkg/controllers/resources/ingresses/syncer.go b/pkg/controllers/resources/ingresses/syncer.go index b5f05eb28e..3142d88c05 100644 --- a/pkg/controllers/resources/ingresses/syncer.go +++ b/pkg/controllers/resources/ingresses/syncer.go @@ -10,7 +10,9 @@ import ( "github.com/loft-sh/vcluster/pkg/syncer/synccontext" "github.com/loft-sh/vcluster/pkg/syncer/translator" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" + "github.com/loft-sh/vcluster/pkg/util/translate" networkingv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -28,11 +30,13 @@ func NewSyncer(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &ingressSyncer{ GenericTranslator: translator.NewGenericTranslator(ctx, "ingress", &networkingv1.Ingress{}, mapper), + Importer: pro.NewImporter(mapper), }, nil } type ingressSyncer struct { syncertypes.GenericTranslator + syncertypes.Importer } var _ syncertypes.Syncer = &ingressSyncer{} @@ -82,5 +86,15 @@ func (s *ingressSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.Sy func (s *ingressSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*networkingv1.Ingress]) (_ ctrl.Result, retErr error) { // virtual object is not here anymore, so we delete - return syncer.DeleteHostObject(ctx, event.Host, "virtual object was deleted") + if event.IsDelete() || event.Host.DeletionTimestamp != nil { + return syncer.DeleteHostObject(ctx, event.Host, "virtual object was deleted") + } + + vIngress := translate.VirtualMetadata(event.Host, s.HostToVirtual(ctx, types.NamespacedName{Name: event.Host.Name, Namespace: event.Host.Namespace}, event.Host)) + err := pro.ApplyPatchesVirtualObject(ctx, nil, vIngress, event.Host, ctx.Config.Sync.ToHost.Ingresses.Translate) + if err != nil { + return ctrl.Result{}, err + } + + return syncer.CreateVirtualObject(ctx, event.Host, vIngress, s.EventRecorder()) } diff --git a/pkg/pro/import.go b/pkg/pro/import.go index 064f1c3965..005107ff11 100644 --- a/pkg/pro/import.go +++ b/pkg/pro/import.go @@ -15,3 +15,7 @@ type noopImporter struct{} func (n *noopImporter) Import(_ *synccontext.SyncContext, _ client.Object) (bool, error) { return false, nil } + +func (n *noopImporter) IgnoreHostObject(_ *synccontext.SyncContext, _ client.Object) bool { + return false +} diff --git a/pkg/syncer/importer.go b/pkg/syncer/importer.go index 8821d36eba..134caa62de 100644 --- a/pkg/syncer/importer.go +++ b/pkg/syncer/importer.go @@ -15,3 +15,7 @@ type noopImporter struct{} func (n *noopImporter) Import(_ *synccontext.SyncContext, _ client.Object) (bool, error) { return false, nil } + +func (n *noopImporter) IgnoreHostObject(_ *synccontext.SyncContext, _ client.Object) bool { + return false +} diff --git a/pkg/syncer/syncer.go b/pkg/syncer/syncer.go index 69ceb2c716..b930f6fc9b 100644 --- a/pkg/syncer/syncer.go +++ b/pkg/syncer/syncer.go @@ -163,6 +163,11 @@ func (r *SyncController) Reconcile(ctx context.Context, origReq ctrl.Request) (_ return ctrl.Result{}, err } + // check if we should ignore object + if importer, ok := r.syncer.(syncertypes.Importer); ok && importer.IgnoreHostObject(syncContext, pObj) { + return ctrl.Result{Requeue: true}, nil + } + // add mapping to context if !r.options.SkipMappingsRecording { syncContext.Context, err = synccontext.WithMappingFromObjects(syncContext.Context, pObj, vObj) @@ -391,21 +396,13 @@ func (r *SyncController) extractRequest(ctx *synccontext.SyncContext, req ctrl.R return req, pReq, nil } -func (r *SyncController) enqueueVirtual(ctx context.Context, obj client.Object, q workqueue.RateLimitingInterface, isDelete bool) { +func (r *SyncController) enqueueVirtual(_ context.Context, obj client.Object, q workqueue.RateLimitingInterface, isDelete bool) { if obj == nil { return } // add a new request for the host object as otherwise this information might be lost after a delete event if isDelete { - // add a new request for the host object - name := r.syncer.VirtualToHost(r.newSyncContext(ctx, obj.GetName()), types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) - if name.Name != "" { - q.Add(toDeleteRequest(toHostRequest(reconcile.Request{ - NamespacedName: name, - }))) - } - // add a new request for the virtual object q.Add(toDeleteRequest(reconcile.Request{ NamespacedName: types.NamespacedName{ @@ -441,39 +438,32 @@ func (r *SyncController) enqueuePhysical(ctx context.Context, obj client.Object, return } else if !managed { // check if we should import - - // don't import if object was deleted - if isDelete { - return + imported := false + if importer, ok := r.syncer.(syncertypes.Importer); ok && !isDelete { + imported, err = importer.Import(syncContext, obj) + if err != nil { + klog.Errorf("error importing object %v: %v", obj, err) + return + } } - // is importer? - importer, ok := r.syncer.(syncertypes.Importer) - if !ok { + // if not imported we exit here + if !imported { return } + } - // try to import - imported, err := importer.Import(syncContext, obj) - if err != nil { - klog.Errorf("error importing object %v: %v", obj, err) - return - } else if !imported { - // not imported, so just return - return - } + // check if we should ignore the host object + if importer, ok := r.syncer.(syncertypes.Importer); ok && importer.IgnoreHostObject(syncContext, obj) { + // since we check later anyways in the actual syncer again if we should ignore the object we only need to set + // isDelete = false here to make sure the event is propagated and not missed and the syncer is recreating the + // object correctly as soon as its deleted. However, we don't want it to be a delete event as this will delete + // the virtual object so we need to set that to false here. + isDelete = false } // add a new request for the virtual object as otherwise this information might be lost after a delete event if isDelete { - // add a new request for the virtual object - name := r.syncer.HostToVirtual(syncContext, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) - if name.Name != "" { - q.Add(toDeleteRequest(reconcile.Request{ - NamespacedName: name, - })) - } - // add a new request for the host object q.Add(toDeleteRequest(toHostRequest(reconcile.Request{ NamespacedName: types.NamespacedName{ diff --git a/pkg/syncer/types/syncer.go b/pkg/syncer/types/syncer.go index def9cea695..f9c5bdd030 100644 --- a/pkg/syncer/types/syncer.go +++ b/pkg/syncer/types/syncer.go @@ -27,6 +27,9 @@ type Syncer interface { type Importer interface { // Import imports the given host object into the virtual cluster Import(ctx *synccontext.SyncContext, pObj client.Object) (bool, error) + + // IgnoreHostObject is used to ignore certain objects during the import process + IgnoreHostObject(ctx *synccontext.SyncContext, pObj client.Object) bool } type Sync[T client.Object] interface {