From 0ca7e34e58b13c6953575ae4b541ffd490fe2052 Mon Sep 17 00:00:00 2001 From: Fabian Kramm Date: Mon, 15 Jul 2024 17:20:45 +0200 Subject: [PATCH] refactor: vcluster manager start --- cmd/vcluster/cmd/start.go | 8 +- pkg/constants/annotation.go | 4 + pkg/controllers/generic/export_syncer.go | 9 ++- pkg/controllers/generic/import_syncer.go | 4 + pkg/controllers/register.go | 29 ++++--- .../resources/configmaps/syncer.go | 3 +- .../resources/configmaps/translate.go | 6 +- .../resources/csidrivers/syncer.go | 3 +- pkg/controllers/resources/csinodes/syncer.go | 3 +- .../resources/csistoragecapacities/syncer.go | 7 +- .../csistoragecapacities/translate.go | 2 - .../csistoragecapacities/translate_test.go | 3 - .../csistoragecapacities/translator.go | 6 +- pkg/controllers/resources/endpoints/syncer.go | 19 +++-- .../resources/endpoints/translate.go | 15 ++-- pkg/controllers/resources/events/syncer.go | 4 + .../resources/events/syncer_test.go | 5 -- .../resources/ingressclasses/syncer.go | 3 +- .../resources/ingresses/register.go | 10 --- pkg/controllers/resources/ingresses/syncer.go | 31 ++++++-- .../resources/ingresses/translate.go | 27 ++++--- .../resources/namespaces/syncer.go | 3 +- .../resources/networkpolicies/syncer.go | 3 +- pkg/controllers/resources/nodes/syncer.go | 5 ++ .../persistentvolumeclaims/syncer.go | 2 +- .../persistentvolumes/fake_syncer.go | 2 +- .../resources/persistentvolumes/syncer.go | 30 +++++--- .../persistentvolumes/syncer_test.go | 39 ++++------ .../resources/persistentvolumes/translate.go | 22 +++--- .../resources/poddisruptionbudgets/syncer.go | 3 +- pkg/controllers/resources/pods/syncer.go | 9 ++- pkg/controllers/resources/pods/translate.go | 8 +- .../pods/translate/sa_token_secret.go | 43 +++++------ .../resources/pods/translate/translator.go | 22 ++++-- pkg/controllers/resources/pods/util.go | 5 +- .../resources/priorityclasses/syncer.go | 3 +- pkg/controllers/resources/secrets/syncer.go | 4 +- .../resources/serviceaccounts/syncer.go | 3 +- pkg/controllers/resources/services/syncer.go | 3 +- .../storageclasses/host_sc_syncer.go | 3 +- .../resources/storageclasses/syncer.go | 3 +- .../volumesnapshotclasses/syncer.go | 3 +- .../volumesnapshotcontents/syncer.go | 8 +- .../volumesnapshotcontents/syncer_test.go | 9 +-- .../volumesnapshotcontents/translate.go | 3 +- .../volumesnapshots/volumesnapshots/syncer.go | 3 +- pkg/controllers/syncer/syncer.go | 21 ++--- pkg/controllers/syncer/syncer_test.go | 13 ++-- pkg/controllers/syncer/testing/context.go | 6 +- .../syncer/translator/cluster_translator.go | 24 +++--- .../translator/mirror_name_translator.go | 7 +- .../translator/namespaced_translator.go | 24 +++--- .../syncer/translator/translator.go | 3 + pkg/mappings/generic/cluster.go | 23 ++++-- pkg/mappings/generic/mirror.go | 5 -- pkg/mappings/generic/namespaced.go | 43 +++++++++-- pkg/mappings/mappings.go | 45 +++++++++-- pkg/mappings/registermappings/register.go | 76 ++++++++++-------- pkg/mappings/resources/configmaps.go | 29 +++---- pkg/mappings/resources/csidrivers.go | 9 +-- pkg/mappings/resources/csinodes.go | 9 +-- .../resources/csistoragecapacities.go | 23 +++--- pkg/mappings/resources/endpoints.go | 9 +-- pkg/mappings/resources/events.go | 10 +-- pkg/mappings/resources/generic.go | 35 --------- pkg/mappings/resources/ingressclasses.go | 9 +-- pkg/mappings/resources/ingresses.go | 9 +-- pkg/mappings/resources/ingresses_legacy.go | 18 ----- pkg/mappings/resources/namespaces.go | 9 +-- pkg/mappings/resources/networkpolicies.go | 9 +-- pkg/mappings/resources/nodes.go | 9 +-- .../resources/persistentvolumeclaims.go | 9 +-- pkg/mappings/resources/persistentvolumes.go | 13 ++-- .../resources/poddisruptionbudgets.go | 9 +-- pkg/mappings/resources/pods.go | 9 +-- pkg/mappings/resources/priorityclasses.go | 21 ++--- pkg/mappings/resources/secrets.go | 9 +-- pkg/mappings/resources/serviceaccounts.go | 9 +-- pkg/mappings/resources/services.go | 9 +-- pkg/mappings/resources/storageclasses.go | 21 ++--- .../resources/volumesnapshotclasses.go | 9 +-- .../resources/volumesnapshotcontents.go | 20 ++--- pkg/mappings/resources/volumesnapshots.go | 15 +--- pkg/server/filters/metrics.go | 77 +++++++++---------- pkg/server/indicies.go | 38 +++++++++ pkg/server/server.go | 67 ++-------------- pkg/setup/controller_context.go | 8 -- pkg/setup/controllers.go | 53 +------------ pkg/setup/managers.go | 69 +++++++++++++++++ pkg/setup/proxy.go | 6 +- 90 files changed, 688 insertions(+), 702 deletions(-) delete mode 100644 pkg/controllers/resources/csistoragecapacities/translate_test.go delete mode 100644 pkg/controllers/resources/ingresses/register.go delete mode 100644 pkg/mappings/resources/generic.go delete mode 100644 pkg/mappings/resources/ingresses_legacy.go create mode 100644 pkg/server/indicies.go create mode 100644 pkg/setup/managers.go diff --git a/cmd/vcluster/cmd/start.go b/cmd/vcluster/cmd/start.go index 636a871c7e..c83281c92f 100644 --- a/cmd/vcluster/cmd/start.go +++ b/cmd/vcluster/cmd/start.go @@ -105,6 +105,12 @@ func ExecuteStart(ctx context.Context, options *StartOptions) error { return fmt.Errorf("start integrations: %w", err) } + // start managers + syncers, err := setup.StartManagers(controllerCtx) + if err != nil { + return fmt.Errorf("start managers: %w", err) + } + // start proxy err = setup.StartProxy(controllerCtx) if err != nil { @@ -133,7 +139,7 @@ func ExecuteStart(ctx context.Context, options *StartOptions) error { // start leader election + controllers err = StartLeaderElection(controllerCtx, func() error { - return setup.StartControllers(controllerCtx) + return setup.StartControllers(controllerCtx, syncers) }) if err != nil { return fmt.Errorf("start controllers: %w", err) diff --git a/pkg/constants/annotation.go b/pkg/constants/annotation.go index 538c654df6..1d01547d6d 100644 --- a/pkg/constants/annotation.go +++ b/pkg/constants/annotation.go @@ -8,6 +8,10 @@ const ( PausedReplicasAnnotation = "loft.sh/paused-replicas" PausedDateAnnotation = "loft.sh/paused-date" + HostClusterPersistentVolumeAnnotation = "vcluster.loft.sh/host-pv" + + HostClusterVSCAnnotation = "vcluster.loft.sh/host-volumesnapshotcontent" + // NodeSuffix is the dns suffix for our nodes NodeSuffix = "nodes.vcluster.com" diff --git a/pkg/controllers/generic/export_syncer.go b/pkg/controllers/generic/export_syncer.go index bb4df46248..9c713ad27d 100644 --- a/pkg/controllers/generic/export_syncer.go +++ b/pkg/controllers/generic/export_syncer.go @@ -7,6 +7,7 @@ import ( "time" "github.com/loft-sh/vcluster/pkg/config" + "github.com/loft-sh/vcluster/pkg/mappings/generic" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/klog/v2" @@ -98,12 +99,18 @@ func createExporterFromConfig(ctx *synccontext.RegisterContext, config *vcluster gvk := schema.FromAPIVersionAndKind(config.APIVersion, config.Kind) controllerID := fmt.Sprintf("%s/%s/GenericExport", strings.ToLower(gvk.Kind), strings.ToLower(gvk.Group)) + + mapper, err := generic.NewNamespacedMapper(ctx, obj, translate.Default.PhysicalName) + if err != nil { + return nil, err + } + return &exporter{ ObjectPatcher: &exportPatcher{ config: config, gvk: gvk, }, - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, controllerID, obj), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, controllerID, obj, mapper), patcher: NewPatcher(ctx.VirtualManager.GetClient(), ctx.PhysicalManager.GetClient(), hasStatusSubresource, log.New(controllerID)), gvk: gvk, diff --git a/pkg/controllers/generic/import_syncer.go b/pkg/controllers/generic/import_syncer.go index 0ad315ed28..b82b6eede9 100644 --- a/pkg/controllers/generic/import_syncer.go +++ b/pkg/controllers/generic/import_syncer.go @@ -241,6 +241,10 @@ func (s *importer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Objec var _ syncertypes.Syncer = &importer{} +func (s *importer) GroupVersionKind() schema.GroupVersionKind { + return s.gvk +} + func (s *importer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { // ignore all virtual resources that were not created by this controller if !s.isVirtualManaged(vObj) { diff --git a/pkg/controllers/register.go b/pkg/controllers/register.go index 618f09ef73..f742f84b0e 100644 --- a/pkg/controllers/register.go +++ b/pkg/controllers/register.go @@ -94,7 +94,7 @@ func isEnabled(enabled bool, fn BuildController) BuildController { return nil } -func Create(ctx *config.ControllerContext) ([]syncertypes.Object, error) { +func CreateSyncers(ctx *config.ControllerContext) ([]syncertypes.Object, error) { registerContext := util.ToRegisterContext(ctx) // register controllers for resource synchronization @@ -159,6 +159,7 @@ func RegisterIndices(ctx *config.ControllerContext, syncers []syncertypes.Object func RegisterControllers(ctx *config.ControllerContext, syncers []syncertypes.Object) error { registerContext := util.ToRegisterContext(ctx) + // start default endpoint controller err := k8sdefaultendpoint.Register(ctx) if err != nil { return err @@ -190,6 +191,7 @@ func RegisterControllers(ctx *config.ControllerContext, syncers []syncertypes.Ob return err } + // register generic sync controllers err = RegisterGenericSyncController(ctx) if err != nil { return err @@ -204,14 +206,23 @@ func RegisterControllers(ctx *config.ControllerContext, syncers []syncertypes.Ob if err != nil { return errors.Wrapf(err, "start %s syncer", v.Name()) } - } else { - // real syncer? - realSyncer, ok := v.(syncertypes.Syncer) - if ok { - err = syncer.RegisterSyncer(registerContext, realSyncer) - if err != nil { - return errors.Wrapf(err, "start %s syncer", v.Name()) - } + } + + // real syncer? + realSyncer, ok := v.(syncertypes.Syncer) + if ok { + err = syncer.RegisterSyncer(registerContext, realSyncer) + if err != nil { + return errors.Wrapf(err, "start %s syncer", v.Name()) + } + } + + // custom syncer? + customSyncer, ok := v.(syncertypes.ControllerStarter) + if ok { + err = customSyncer.Register(registerContext) + if err != nil { + return errors.Wrapf(err, "start %s syncer", v.Name()) } } } diff --git a/pkg/controllers/resources/configmaps/syncer.go b/pkg/controllers/resources/configmaps/syncer.go index f2f7e0b660..f713fe1c7b 100644 --- a/pkg/controllers/resources/configmaps/syncer.go +++ b/pkg/controllers/resources/configmaps/syncer.go @@ -8,6 +8,7 @@ import ( "github.com/loft-sh/vcluster/pkg/constants" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -22,7 +23,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &configMapSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "configmap", &corev1.ConfigMap{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "configmap", &corev1.ConfigMap{}, mappings.ConfigMaps()), syncAllConfigMaps: ctx.Config.Sync.ToHost.ConfigMaps.All, multiNamespaceMode: ctx.Config.Experimental.MultiNamespaceMode.Enabled, diff --git a/pkg/controllers/resources/configmaps/translate.go b/pkg/controllers/resources/configmaps/translate.go index 1f7104e54e..2c9090ea2c 100644 --- a/pkg/controllers/resources/configmaps/translate.go +++ b/pkg/controllers/resources/configmaps/translate.go @@ -4,17 +4,13 @@ import ( "context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" - "github.com/loft-sh/vcluster/pkg/mappings" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" - "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) func (s *configMapSyncer) translate(ctx context.Context, vObj client.Object) *corev1.ConfigMap { - pObj := s.TranslateMetadata(ctx, vObj).(*corev1.ConfigMap) - pObj.SetName(mappings.ConfigMaps().VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj).Name) - return pObj + return s.TranslateMetadata(ctx, vObj).(*corev1.ConfigMap) } func (s *configMapSyncer) translateUpdate(ctx context.Context, pObj, vObj *corev1.ConfigMap) *corev1.ConfigMap { diff --git a/pkg/controllers/resources/csidrivers/syncer.go b/pkg/controllers/resources/csidrivers/syncer.go index 4d5ef2a3a9..684f84c6db 100644 --- a/pkg/controllers/resources/csidrivers/syncer.go +++ b/pkg/controllers/resources/csidrivers/syncer.go @@ -5,6 +5,7 @@ import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" syncer "github.com/loft-sh/vcluster/pkg/types" storagev1 "k8s.io/api/storage/v1" @@ -15,7 +16,7 @@ import ( func New(_ *synccontext.RegisterContext) (syncer.Object, error) { return &csidriverSyncer{ - Translator: translator.NewMirrorPhysicalTranslator("csidriver", &storagev1.CSIDriver{}), + Translator: translator.NewMirrorPhysicalTranslator("csidriver", &storagev1.CSIDriver{}, mappings.CSIDrivers()), }, nil } diff --git a/pkg/controllers/resources/csinodes/syncer.go b/pkg/controllers/resources/csinodes/syncer.go index 994436759d..6af11bff58 100644 --- a/pkg/controllers/resources/csinodes/syncer.go +++ b/pkg/controllers/resources/csinodes/syncer.go @@ -5,6 +5,7 @@ import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" syncertypes "github.com/loft-sh/vcluster/pkg/types" corev1 "k8s.io/api/core/v1" @@ -18,7 +19,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &csinodeSyncer{ - Translator: translator.NewMirrorPhysicalTranslator("csinode", &storagev1.CSINode{}), + Translator: translator.NewMirrorPhysicalTranslator("csinode", &storagev1.CSINode{}, mappings.CSINodes()), virtualClient: ctx.VirtualManager.GetClient(), }, nil } diff --git a/pkg/controllers/resources/csistoragecapacities/syncer.go b/pkg/controllers/resources/csistoragecapacities/syncer.go index 6cc3c59b31..b74eaa4075 100644 --- a/pkg/controllers/resources/csistoragecapacities/syncer.go +++ b/pkg/controllers/resources/csistoragecapacities/syncer.go @@ -5,7 +5,6 @@ import ( "fmt" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" syncertypes "github.com/loft-sh/vcluster/pkg/types" @@ -25,6 +24,8 @@ import ( func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &csistoragecapacitySyncer{ + Mapper: mappings.CSIStorageCapacities(), + storageClassSyncEnabled: ctx.Config.Sync.ToHost.StorageClasses.Enabled, hostStorageClassSyncEnabled: ctx.Config.Sync.FromHost.StorageClasses.Enabled == "true", physicalClient: ctx.PhysicalManager.GetClient(), @@ -32,6 +33,8 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { } type csistoragecapacitySyncer struct { + mappings.Mapper + storageClassSyncEnabled bool hostStorageClassSyncEnabled bool physicalClient client.Client @@ -125,7 +128,7 @@ func (s *csistoragecapacitySyncer) enqueuePhysical(ctx context.Context, obj clie return } - name := mappings.Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("CSIStorageCapacity")).HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) + name := s.Mapper.HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) if name.Name != "" && name.Namespace != "" { q.Add(reconcile.Request{NamespacedName: name}) } diff --git a/pkg/controllers/resources/csistoragecapacities/translate.go b/pkg/controllers/resources/csistoragecapacities/translate.go index c6721c8b6f..1fc777e420 100644 --- a/pkg/controllers/resources/csistoragecapacities/translate.go +++ b/pkg/controllers/resources/csistoragecapacities/translate.go @@ -4,9 +4,7 @@ import ( "fmt" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" "github.com/loft-sh/vcluster/pkg/mappings" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" corev1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/equality" diff --git a/pkg/controllers/resources/csistoragecapacities/translate_test.go b/pkg/controllers/resources/csistoragecapacities/translate_test.go deleted file mode 100644 index ef63953e5e..0000000000 --- a/pkg/controllers/resources/csistoragecapacities/translate_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package csistoragecapacities - -// ensure translation matches storageclass translating diff --git a/pkg/controllers/resources/csistoragecapacities/translator.go b/pkg/controllers/resources/csistoragecapacities/translator.go index e9f1d0d387..b52a1c7f0f 100644 --- a/pkg/controllers/resources/csistoragecapacities/translator.go +++ b/pkg/controllers/resources/csistoragecapacities/translator.go @@ -29,15 +29,15 @@ func (s *csistoragecapacitySyncer) IsManaged(context.Context, client.Object) (bo // TranslateMetadata translates the object's metadata func (s *csistoragecapacitySyncer) TranslateMetadata(ctx context.Context, pObj client.Object) (client.Object, error) { - name := mappings.CSIStorageCapacities().HostToVirtual(ctx, types.NamespacedName{Name: pObj.GetName(), Namespace: pObj.GetNamespace()}, pObj) + pName := mappings.CSIStorageCapacities().HostToVirtual(ctx, types.NamespacedName{Name: pObj.GetName(), Namespace: pObj.GetNamespace()}, pObj) pObjCopy := pObj.DeepCopyObject() vObj, ok := pObjCopy.(client.Object) if !ok { return nil, fmt.Errorf("%q not a metadata object: %+v", pObj.GetName(), pObjCopy) } translate.ResetObjectMetadata(vObj) - vObj.SetName(name.Name) - vObj.SetNamespace(name.Namespace) + vObj.SetName(pName.Name) + vObj.SetNamespace(pName.Namespace) vObj.SetAnnotations(translate.Default.ApplyAnnotations(pObj, nil, []string{})) vObj.SetLabels(translate.Default.ApplyLabels(pObj, nil, []string{})) return vObj, nil diff --git a/pkg/controllers/resources/endpoints/syncer.go b/pkg/controllers/resources/endpoints/syncer.go index a55f95c14e..627e18abf9 100644 --- a/pkg/controllers/resources/endpoints/syncer.go +++ b/pkg/controllers/resources/endpoints/syncer.go @@ -1,6 +1,7 @@ package endpoints import ( + "errors" "fmt" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" @@ -20,7 +21,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &endpointsSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "endpoints", &corev1.Endpoints{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "endpoints", &corev1.Endpoints{}, mappings.Endpoints()), }, nil } @@ -39,12 +40,18 @@ func (s *endpointsSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, } defer func() { if err := patch.Patch(ctx, pObj, vObj); err != nil { - s.NamespacedTranslator.EventRecorder().Eventf(pObj, "Warning", "SyncError", "Error syncing: %v", err) - retErr = err + retErr = errors.Join(retErr, err) + } + + if retErr != nil { + s.NamespacedTranslator.EventRecorder().Eventf(pObj, "Warning", "SyncError", "Error syncing: %v", retErr) } }() - s.translateUpdate(ctx.Context, pObj.(*corev1.Endpoints), vObj.(*corev1.Endpoints)) + err = s.translateUpdate(ctx.Context, pObj.(*corev1.Endpoints), vObj.(*corev1.Endpoints)) + if err != nil { + return ctrl.Result{}, err + } return ctrl.Result{}, nil } @@ -75,7 +82,7 @@ func (s *endpointsSyncer) ReconcileStart(ctx *synccontext.SyncContext, req ctrl. } else if svc.Spec.Selector != nil { // check if it was a managed endpoints object before and delete it endpoints := &corev1.Endpoints{} - err := ctx.PhysicalClient.Get(ctx.Context, mappings.Endpoints().VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) + err = ctx.PhysicalClient.Get(ctx.Context, s.VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) if err != nil { if !kerrors.IsNotFound(err) { klog.Infof("Error retrieving endpoints: %v", err) @@ -104,7 +111,7 @@ func (s *endpointsSyncer) ReconcileStart(ctx *synccontext.SyncContext, req ctrl. // check if it was a Kubernetes managed endpoints object before and delete it endpoints := &corev1.Endpoints{} - err = ctx.PhysicalClient.Get(ctx.Context, mappings.Endpoints().VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) + err = ctx.PhysicalClient.Get(ctx.Context, s.VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) if err == nil && (endpoints.Annotations == nil || endpoints.Annotations[translate.NameAnnotation] == "") { klog.Infof("Refresh endpoints in physical cluster because they should be managed by vCluster now") err = ctx.PhysicalClient.Delete(ctx.Context, endpoints) diff --git a/pkg/controllers/resources/endpoints/translate.go b/pkg/controllers/resources/endpoints/translate.go index dd5338f8aa..14be4d5e42 100644 --- a/pkg/controllers/resources/endpoints/translate.go +++ b/pkg/controllers/resources/endpoints/translate.go @@ -3,9 +3,7 @@ package endpoints import ( "context" - "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" "github.com/loft-sh/vcluster/pkg/mappings" - "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" "sigs.k8s.io/controller-runtime/pkg/client" @@ -24,7 +22,7 @@ func (s *endpointsSyncer) translate(ctx context.Context, vObj client.Object) *co return endpoints } -func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) { +func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) error { // translate the addresses for i, subset := range endpoints.Subsets { for j, addr := range subset.Addresses { @@ -50,12 +48,17 @@ func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) { } } } + + return nil } -func (s *endpointsSyncer) translateUpdate(ctx context.Context, pObj, vObj *corev1.Endpoints) { +func (s *endpointsSyncer) translateUpdate(ctx context.Context, pObj, vObj *corev1.Endpoints) error { // check subsets translated := vObj.DeepCopy() - s.translateSpec(translated) + err := s.translateSpec(translated) + if err != nil { + return err + } if !equality.Semantic.DeepEqual(translated.Subsets, pObj.Subsets) { pObj.Subsets = translated.Subsets } @@ -67,4 +70,6 @@ func (s *endpointsSyncer) translateUpdate(ctx context.Context, pObj, vObj *corev pObj.Annotations = annotations pObj.Labels = labels } + + return nil } diff --git a/pkg/controllers/resources/events/syncer.go b/pkg/controllers/resources/events/syncer.go index ff8478a3a6..ed7c3e04a9 100644 --- a/pkg/controllers/resources/events/syncer.go +++ b/pkg/controllers/resources/events/syncer.go @@ -20,12 +20,16 @@ import ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &eventSyncer{ + Mapper: mappings.Events(), + virtualClient: ctx.VirtualManager.GetClient(), hostClient: ctx.PhysicalManager.GetClient(), }, nil } type eventSyncer struct { + mappings.Mapper + virtualClient client.Client hostClient client.Client } diff --git a/pkg/controllers/resources/events/syncer_test.go b/pkg/controllers/resources/events/syncer_test.go index 3e02b7ef8f..681dac614b 100644 --- a/pkg/controllers/resources/events/syncer_test.go +++ b/pkg/controllers/resources/events/syncer_test.go @@ -5,7 +5,6 @@ import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" generictesting "github.com/loft-sh/vcluster/pkg/controllers/syncer/testing" - "github.com/loft-sh/vcluster/pkg/mappings/resources" "github.com/loft-sh/vcluster/pkg/util/translate" "gotest.tools/assert" corev1 "k8s.io/api/core/v1" @@ -15,10 +14,6 @@ import ( ) func newFakeSyncer(t *testing.T, ctx *synccontext.RegisterContext) (*synccontext.SyncContext, *eventSyncer) { - // we need that index here as well otherwise we wouldn't find the related pod - err := resources.RegisterPodsMapper(ctx) - assert.NilError(t, err) - syncContext, object := generictesting.FakeStartSyncer(t, ctx, New) return syncContext, object.(*eventSyncer) } diff --git a/pkg/controllers/resources/ingressclasses/syncer.go b/pkg/controllers/resources/ingressclasses/syncer.go index 3dad11342c..2fc38f3162 100644 --- a/pkg/controllers/resources/ingressclasses/syncer.go +++ b/pkg/controllers/resources/ingressclasses/syncer.go @@ -5,6 +5,7 @@ import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" syncer "github.com/loft-sh/vcluster/pkg/types" networkingv1 "k8s.io/api/networking/v1" @@ -15,7 +16,7 @@ import ( func New(_ *synccontext.RegisterContext) (syncer.Object, error) { return &ingressClassSyncer{ - Translator: translator.NewMirrorPhysicalTranslator("ingressclass", &networkingv1.IngressClass{}), + Translator: translator.NewMirrorPhysicalTranslator("ingressclass", &networkingv1.IngressClass{}, mappings.IngressClasses()), }, nil } diff --git a/pkg/controllers/resources/ingresses/register.go b/pkg/controllers/resources/ingresses/register.go deleted file mode 100644 index e7e34813c1..0000000000 --- a/pkg/controllers/resources/ingresses/register.go +++ /dev/null @@ -1,10 +0,0 @@ -package ingresses - -import ( - synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - syncer "github.com/loft-sh/vcluster/pkg/types" -) - -func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { - return NewSyncer(ctx) -} diff --git a/pkg/controllers/resources/ingresses/syncer.go b/pkg/controllers/resources/ingresses/syncer.go index a3aa4667bc..3c618d542c 100644 --- a/pkg/controllers/resources/ingresses/syncer.go +++ b/pkg/controllers/resources/ingresses/syncer.go @@ -16,9 +16,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) +func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { + return NewSyncer(ctx) +} + func NewSyncer(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &ingressSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "ingress", &networkingv1.Ingress{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "ingress", &networkingv1.Ingress{}, mappings.Ingresses()), }, nil } @@ -29,7 +33,12 @@ type ingressSyncer struct { var _ syncertypes.Syncer = &ingressSyncer{} func (s *ingressSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostCreate(ctx, vObj, s.translate(ctx.Context, vObj.(*networkingv1.Ingress))) + pObj, err := s.translate(ctx.Context, vObj.(*networkingv1.Ingress)) + if err != nil { + return ctrl.Result{}, err + } + + return s.SyncToHostCreate(ctx, vObj, pObj) } func (s *ingressSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (_ ctrl.Result, retErr error) { @@ -45,12 +54,13 @@ func (s *ingressSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, v }() pIngress, vIngress, source, target := synccontext.Cast[*networkingv1.Ingress](ctx, pObj, vObj) - target.Spec.IngressClassName = source.Spec.IngressClassName - vIngress.Status = pIngress.Status + err = s.translateUpdate(ctx.Context, pIngress, vIngress) + if err != nil { + return ctrl.Result{}, err + } - s.translateUpdate(ctx.Context, pIngress, vIngress) return ctrl.Result{}, nil } @@ -85,13 +95,18 @@ func translateIngressAnnotations(annotations map[string]string, ingressNamespace if len(splitted) == 1 { // If value is only "secret" secret := splitted[0] foundSecrets = append(foundSecrets, ingressNamespace+"/"+secret) - newAnnotations[k] = mappings.VirtualToHostName(secret, ingressNamespace, mappings.Secrets()) + pName, err := mappings.VirtualToHostName(secret, ingressNamespace, mappings.Secrets()) + if err == nil { + newAnnotations[k] = pName + } } else if len(splitted) == 2 { // If value is "namespace/secret" namespace := splitted[0] secret := splitted[1] foundSecrets = append(foundSecrets, namespace+"/"+secret) - pName := mappings.VirtualToHost(secret, namespace, mappings.Secrets()) - newAnnotations[k] = pName.Namespace + "/" + pName.Name + pName, err := mappings.VirtualToHost(secret, namespace, mappings.Secrets()) + if err == nil { + newAnnotations[k] = pName.Namespace + "/" + pName.Name + } } else { newAnnotations[k] = v } diff --git a/pkg/controllers/resources/ingresses/translate.go b/pkg/controllers/resources/ingresses/translate.go index 5e47d29f0b..98cf816069 100644 --- a/pkg/controllers/resources/ingresses/translate.go +++ b/pkg/controllers/resources/ingresses/translate.go @@ -5,8 +5,6 @@ import ( "encoding/json" "strings" - "github.com/loft-sh/vcluster/pkg/controllers/resources/ingresses/util" - "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/util/translate" networkingv1 "k8s.io/api/networking/v1" @@ -21,11 +19,16 @@ const ( ActionsSuffix = "/actions." ) -func (s *ingressSyncer) translate(ctx context.Context, vIngress *networkingv1.Ingress) *networkingv1.Ingress { +func (s *ingressSyncer) translate(ctx context.Context, vIngress *networkingv1.Ingress) (*networkingv1.Ingress, error) { newIngress := s.TranslateMetadata(ctx, vIngress).(*networkingv1.Ingress) - newIngress.Spec = *translateSpec(vIngress.Namespace, &vIngress.Spec) + pSpec, err := translateSpec(vIngress.Namespace, &vIngress.Spec) + if err != nil { + return nil, err + } + + newIngress.Spec = *pSpec newIngress.Annotations, _ = translateIngressAnnotations(newIngress.Annotations, vIngress.Namespace) - return newIngress + return newIngress, nil } func (s *ingressSyncer) TranslateMetadata(ctx context.Context, vObj client.Object) client.Object { @@ -42,17 +45,21 @@ func (s *ingressSyncer) TranslateMetadataUpdate(ctx context.Context, vObj client return s.NamespacedTranslator.TranslateMetadataUpdate(ctx, vIngress, pObj) } -func (s *ingressSyncer) translateUpdate(ctx context.Context, pObj, vObj *networkingv1.Ingress) { - pObj.Spec = *translateSpec(vObj.Namespace, &vObj.Spec) +func (s *ingressSyncer) translateUpdate(ctx context.Context, pObj, vObj *networkingv1.Ingress) error { + pSpec, err := translateSpec(vObj.Namespace, &vObj.Spec) + if err != nil { + return err + } + pObj.Spec = *pSpec _, translatedAnnotations, translatedLabels := s.TranslateMetadataUpdate(ctx, vObj, pObj) translatedAnnotations, _ = translateIngressAnnotations(translatedAnnotations, vObj.Namespace) - pObj.Annotations = translatedAnnotations pObj.Labels = translatedLabels + return nil } -func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) *networkingv1.IngressSpec { +func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) (*networkingv1.IngressSpec, error) { retSpec := vIngressSpec.DeepCopy() if retSpec.DefaultBackend != nil { if retSpec.DefaultBackend.Service != nil && retSpec.DefaultBackend.Service.Name != "" { @@ -82,7 +89,7 @@ func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) *ne } } - return retSpec + return retSpec, nil } func getActionOrConditionValue(annotation, actionOrCondition string) string { diff --git a/pkg/controllers/resources/namespaces/syncer.go b/pkg/controllers/resources/namespaces/syncer.go index 68a6cddf7c..c271aa5e2d 100644 --- a/pkg/controllers/resources/namespaces/syncer.go +++ b/pkg/controllers/resources/namespaces/syncer.go @@ -5,6 +5,7 @@ import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" syncertypes "github.com/loft-sh/vcluster/pkg/types" corev1 "k8s.io/api/core/v1" @@ -36,7 +37,7 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { namespaceLabels[VClusterNamespaceAnnotation] = ctx.CurrentNamespace return &namespaceSyncer{ - Translator: translator.NewClusterTranslator(ctx, "namespace", &corev1.Namespace{}, excludedAnnotations...), + Translator: translator.NewClusterTranslator(ctx, "namespace", &corev1.Namespace{}, mappings.Namespaces(), excludedAnnotations...), workloadServiceAccountName: ctx.Config.ControlPlane.Advanced.WorkloadServiceAccount.Name, namespaceLabels: namespaceLabels, }, nil diff --git a/pkg/controllers/resources/networkpolicies/syncer.go b/pkg/controllers/resources/networkpolicies/syncer.go index ed614d2d9d..35bd7c2938 100644 --- a/pkg/controllers/resources/networkpolicies/syncer.go +++ b/pkg/controllers/resources/networkpolicies/syncer.go @@ -3,6 +3,7 @@ package networkpolicies import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" syncertypes "github.com/loft-sh/vcluster/pkg/types" networkingv1 "k8s.io/api/networking/v1" @@ -12,7 +13,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &networkPolicySyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "networkpolicy", &networkingv1.NetworkPolicy{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "networkpolicy", &networkingv1.NetworkPolicy{}, mappings.NetworkPolicies()), }, nil } diff --git a/pkg/controllers/resources/nodes/syncer.go b/pkg/controllers/resources/nodes/syncer.go index 2ebd9bc98f..786382148f 100644 --- a/pkg/controllers/resources/nodes/syncer.go +++ b/pkg/controllers/resources/nodes/syncer.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/loft-sh/vcluster/pkg/mappings" "k8s.io/client-go/util/workqueue" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/cache" @@ -50,6 +51,8 @@ func NewSyncer(ctx *synccontext.RegisterContext, nodeServiceProvider nodeservice } return &nodeSyncer{ + Mapper: mappings.Nodes(), + enableScheduler: ctx.Config.ControlPlane.Advanced.VirtualScheduler.Enabled, enforceNodeSelector: true, @@ -67,6 +70,8 @@ func NewSyncer(ctx *synccontext.RegisterContext, nodeServiceProvider nodeservice } type nodeSyncer struct { + mappings.Mapper + nodeSelector labels.Selector physicalClient client.Client virtualClient client.Client diff --git a/pkg/controllers/resources/persistentvolumeclaims/syncer.go b/pkg/controllers/resources/persistentvolumeclaims/syncer.go index b18264e669..791d8ef7f4 100644 --- a/pkg/controllers/resources/persistentvolumeclaims/syncer.go +++ b/pkg/controllers/resources/persistentvolumeclaims/syncer.go @@ -38,7 +38,7 @@ func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { storageClassesEnabled := ctx.Config.Sync.ToHost.StorageClasses.Enabled excludedAnnotations := []string{bindCompletedAnnotation, boundByControllerAnnotation, storageProvisionerAnnotation} return &persistentVolumeClaimSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "persistent-volume-claim", &corev1.PersistentVolumeClaim{}, excludedAnnotations...), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "persistent-volume-claim", &corev1.PersistentVolumeClaim{}, mappings.PersistentVolumeClaims(), excludedAnnotations...), storageClassesEnabled: storageClassesEnabled, schedulerEnabled: ctx.Config.ControlPlane.Advanced.VirtualScheduler.Enabled, diff --git a/pkg/controllers/resources/persistentvolumes/fake_syncer.go b/pkg/controllers/resources/persistentvolumes/fake_syncer.go index 6b12d7e098..9ff42a8084 100644 --- a/pkg/controllers/resources/persistentvolumes/fake_syncer.go +++ b/pkg/controllers/resources/persistentvolumes/fake_syncer.go @@ -19,7 +19,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func NewFakeSyncer(*synccontext.RegisterContext) (syncer.Object, error) { +func NewFakeSyncer(_ *synccontext.RegisterContext) (syncer.Object, error) { return &fakePersistentVolumeSyncer{}, nil } diff --git a/pkg/controllers/resources/persistentvolumes/syncer.go b/pkg/controllers/resources/persistentvolumes/syncer.go index 7cb88d7426..21a13ac719 100644 --- a/pkg/controllers/resources/persistentvolumes/syncer.go +++ b/pkg/controllers/resources/persistentvolumes/syncer.go @@ -4,6 +4,7 @@ import ( "context" "time" + "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/controllers/syncer" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" @@ -24,13 +25,12 @@ import ( ) const ( - HostClusterPersistentVolumeAnnotation = "vcluster.loft.sh/host-pv" - LockPersistentVolume = "vcluster.loft.sh/lock" + LockPersistentVolume = "vcluster.loft.sh/lock" ) func NewSyncer(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &persistentVolumeSyncer{ - Translator: translator.NewClusterTranslator(ctx, "persistentvolume", &corev1.PersistentVolume{}, HostClusterPersistentVolumeAnnotation), + Translator: translator.NewClusterTranslator(ctx, "persistentvolume", &corev1.PersistentVolume{}, mappings.PersistentVolumes(), constants.HostClusterPersistentVolumeAnnotation), virtualClient: ctx.VirtualManager.GetClient(), }, nil @@ -71,7 +71,7 @@ var _ syncertypes.Syncer = &persistentVolumeSyncer{} func (s *persistentVolumeSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { vPv := vObj.(*corev1.PersistentVolume) - if vPv.DeletionTimestamp != nil || (vPv.Annotations != nil && vPv.Annotations[HostClusterPersistentVolumeAnnotation] != "") { + if vPv.DeletionTimestamp != nil || (vPv.Annotations != nil && vPv.Annotations[constants.HostClusterPersistentVolumeAnnotation] != "") { if len(vPv.Finalizers) > 0 { // delete the finalizer here so that the object can be deleted vPv.Finalizers = []string{} @@ -83,9 +83,13 @@ func (s *persistentVolumeSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj c return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vPv) } - pPv := s.translate(ctx.Context, vPv) + pPv, err := s.translate(ctx.Context, vPv) + if err != nil { + return ctrl.Result{}, err + } + ctx.Log.Infof("create physical persistent volume %s, because there is a virtual persistent volume", pPv.Name) - err := ctx.PhysicalClient.Create(ctx.Context, pPv) + err = ctx.PhysicalClient.Create(ctx.Context, pPv) if err != nil { return ctrl.Result{}, err } @@ -135,8 +139,10 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. } // check if there is a corresponding virtual pvc - updatedObj := s.translateUpdateBackwards(vPersistentVolume, pPersistentVolume, vPvc) - if updatedObj != nil { + updatedObj, err := s.translateUpdateBackwards(vPersistentVolume, pPersistentVolume, vPvc) + if err != nil { + return ctrl.Result{}, err + } else if updatedObj != nil { ctx.Log.Infof("update virtual persistent volume %s, because spec has changed", vPersistentVolume.Name) translator.PrintChanges(vPersistentVolume, updatedObj, ctx.Log) err = ctx.VirtualClient.Update(ctx.Context, updatedObj) @@ -164,7 +170,7 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. } // update the physical persistent volume if the virtual has changed - if vPersistentVolume.Annotations == nil || vPersistentVolume.Annotations[HostClusterPersistentVolumeAnnotation] == "" { + if vPersistentVolume.Annotations == nil || vPersistentVolume.Annotations[constants.HostClusterPersistentVolumeAnnotation] == "" { if vPersistentVolume.DeletionTimestamp != nil { if pPersistentVolume.DeletionTimestamp != nil { return ctrl.Result{}, nil @@ -181,8 +187,10 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. return ctrl.Result{}, err } - updatedPv := s.translateUpdate(ctx.Context, vPersistentVolume, pPersistentVolume) - if updatedPv != nil { + updatedPv, err := s.translateUpdate(ctx.Context, vPersistentVolume, pPersistentVolume) + if err != nil { + return ctrl.Result{}, err + } else if updatedPv != nil { ctx.Log.Infof("update physical persistent volume %s, because spec or annotations have changed", updatedPv.Name) translator.PrintChanges(pPersistentVolume, updatedPv, ctx.Log) err := ctx.PhysicalClient.Update(ctx.Context, updatedPv) diff --git a/pkg/controllers/resources/persistentvolumes/syncer_test.go b/pkg/controllers/resources/persistentvolumes/syncer_test.go index 5cb9e8d51a..15e6f91c90 100644 --- a/pkg/controllers/resources/persistentvolumes/syncer_test.go +++ b/pkg/controllers/resources/persistentvolumes/syncer_test.go @@ -8,12 +8,10 @@ import ( "gotest.tools/assert" "k8s.io/apimachinery/pkg/api/resource" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/loft-sh/vcluster/pkg/constants" generictesting "github.com/loft-sh/vcluster/pkg/controllers/syncer/testing" "github.com/loft-sh/vcluster/pkg/util/translate" + "k8s.io/apimachinery/pkg/types" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -22,11 +20,6 @@ import ( ) func newFakeSyncer(t *testing.T, ctx *synccontext.RegisterContext) (*synccontext.SyncContext, *persistentVolumeSyncer) { - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.PersistentVolumeClaim{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.Default.PhysicalName(rawObj.GetName(), rawObj.GetNamespace())} - }) - assert.NilError(t, err) - syncContext, object := generictesting.FakeStartSyncer(t, ctx, NewSyncer) return syncContext, object.(*persistentVolumeSyncer) } @@ -51,7 +44,7 @@ func TestSync(t *testing.T) { basePvObjectMeta := metav1.ObjectMeta{ Name: "testpv", Annotations: map[string]string{ - HostClusterPersistentVolumeAnnotation: "testpv", + constants.HostClusterPersistentVolumeAnnotation: "testpv", }, } basePvWithDelTSObjectMeta := metav1.ObjectMeta{ @@ -110,20 +103,6 @@ func TestSync(t *testing.T) { Message: "someMessage", }, } - backwardRetainPPv := &corev1.PersistentVolume{ - ObjectMeta: basePvObjectMeta, - Spec: corev1.PersistentVolumeSpec{ - PersistentVolumeReclaimPolicy: corev1.PersistentVolumeReclaimRetain, - ClaimRef: &corev1.ObjectReference{ - Name: "retainPVC-x-test-x-suffix", - Namespace: "test", - }, - StorageClassName: "vcluster-retainSC-x-test-x-suffix", - }, - Status: corev1.PersistentVolumeStatus{ - Phase: corev1.VolumeReleased, - }, - } backwardRetainInitialVPv := &corev1.PersistentVolume{ ObjectMeta: basePvObjectMeta, Spec: corev1.PersistentVolumeSpec{ @@ -194,6 +173,20 @@ func TestSync(t *testing.T) { PersistentVolumeReclaimPolicy: corev1.PersistentVolumeReclaimDelete, }, } + backwardRetainPPv := &corev1.PersistentVolume{ + ObjectMeta: basePvObjectMeta, + Spec: corev1.PersistentVolumeSpec{ + PersistentVolumeReclaimPolicy: corev1.PersistentVolumeReclaimRetain, + ClaimRef: &corev1.ObjectReference{ + Name: "retainPVC-x-test-x-suffix", + Namespace: "test", + }, + StorageClassName: "retainSC", + }, + Status: corev1.PersistentVolumeStatus{ + Phase: corev1.VolumeReleased, + }, + } generictesting.RunTests(t, []*generictesting.SyncTest{ { diff --git a/pkg/controllers/resources/persistentvolumes/translate.go b/pkg/controllers/resources/persistentvolumes/translate.go index e5081f3f67..96e1748454 100644 --- a/pkg/controllers/resources/persistentvolumes/translate.go +++ b/pkg/controllers/resources/persistentvolumes/translate.go @@ -3,6 +3,7 @@ package persistentvolumes import ( "context" + "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/util/translate" @@ -11,14 +12,14 @@ import ( "k8s.io/apimachinery/pkg/types" ) -func (s *persistentVolumeSyncer) translate(ctx context.Context, vPv *corev1.PersistentVolume) *corev1.PersistentVolume { +func (s *persistentVolumeSyncer) translate(ctx context.Context, vPv *corev1.PersistentVolume) (*corev1.PersistentVolume, error) { // translate the persistent volume pPV := s.TranslateMetadata(ctx, vPv).(*corev1.PersistentVolume) pPV.Spec.ClaimRef = nil - pPV.Spec.StorageClassName = mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) // TODO: translate the storage secrets - return pPV + pPV.Spec.StorageClassName = mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) + return pPV, nil } func (s *persistentVolumeSyncer) translateBackwards(pPv *corev1.PersistentVolume, vPvc *corev1.PersistentVolumeClaim) *corev1.PersistentVolume { @@ -43,11 +44,11 @@ func (s *persistentVolumeSyncer) translateBackwards(pPv *corev1.PersistentVolume if vObj.Annotations == nil { vObj.Annotations = map[string]string{} } - vObj.Annotations[HostClusterPersistentVolumeAnnotation] = pPv.Name + vObj.Annotations[constants.HostClusterPersistentVolumeAnnotation] = pPv.Name return vObj } -func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume, vPvc *corev1.PersistentVolumeClaim) *corev1.PersistentVolume { +func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume, vPvc *corev1.PersistentVolumeClaim) (*corev1.PersistentVolume, error) { var updated *corev1.PersistentVolume // build virtual persistent volume @@ -68,8 +69,7 @@ func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.Persistent // when the PVC gets deleted } else { // check if SC was created on virtual - storageClassPhysicalName := mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) - isStorageClassCreatedOnVirtual = equality.Semantic.DeepEqual(storageClassPhysicalName, translatedSpec.StorageClassName) + isStorageClassCreatedOnVirtual = vPv.Spec.StorageClassName != mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) // check if claim was created on virtual if vPv.Spec.ClaimRef != nil && translatedSpec.ClaimRef != nil { @@ -99,15 +99,15 @@ func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.Persistent } // check pv size - if vPv.Annotations != nil && vPv.Annotations[HostClusterPersistentVolumeAnnotation] != "" && !equality.Semantic.DeepEqual(pPv.Spec.Capacity, vPv.Spec.Capacity) { + if vPv.Annotations != nil && vPv.Annotations[constants.HostClusterPersistentVolumeAnnotation] != "" && !equality.Semantic.DeepEqual(pPv.Spec.Capacity, vPv.Spec.Capacity) { updated = translator.NewIfNil(updated, vPv) updated.Spec.Capacity = translatedSpec.Capacity } - return updated + return updated, nil } -func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume) *corev1.PersistentVolume { +func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume) (*corev1.PersistentVolume, error) { var updated *corev1.PersistentVolume // TODO: translate the storage secrets @@ -160,5 +160,5 @@ func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev updated.Labels = updatedLabels } - return updated + return updated, nil } diff --git a/pkg/controllers/resources/poddisruptionbudgets/syncer.go b/pkg/controllers/resources/poddisruptionbudgets/syncer.go index 39e1885275..7dc3b7953f 100644 --- a/pkg/controllers/resources/poddisruptionbudgets/syncer.go +++ b/pkg/controllers/resources/poddisruptionbudgets/syncer.go @@ -3,6 +3,7 @@ package poddisruptionbudgets import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" policyv1 "k8s.io/api/policy/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -11,7 +12,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &pdbSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "podDisruptionBudget", &policyv1.PodDisruptionBudget{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "podDisruptionBudget", &policyv1.PodDisruptionBudget{}, mappings.PodDisruptionBudgets()), }, nil } diff --git a/pkg/controllers/resources/pods/syncer.go b/pkg/controllers/resources/pods/syncer.go index 7139c6c6b6..f2a49e9f26 100644 --- a/pkg/controllers/resources/pods/syncer.go +++ b/pkg/controllers/resources/pods/syncer.go @@ -2,9 +2,11 @@ package pods import ( "context" + "fmt" "reflect" "time" + "github.com/loft-sh/vcluster/pkg/mappings" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/klog/v2" @@ -67,7 +69,7 @@ func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { } // create new namespaced translator - namespacedTranslator := translator.NewNamespacedTranslator(ctx, "pod", &corev1.Pod{}) + namespacedTranslator := translator.NewNamespacedTranslator(ctx, "pod", &corev1.Pod{}, mappings.Pods()) // create pod translator podTranslator, err := translatepods.NewTranslator(ctx, namespacedTranslator.EventRecorder()) @@ -307,7 +309,10 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj // translate services to environment variables serviceEnv := translatepods.ServicesToEnvironmentVariables(vPod.Spec.EnableServiceLinks, ptrServiceList, kubeIP) for i := range vPod.Spec.EphemeralContainers { - envVar, envFrom := s.podTranslator.TranslateContainerEnv(vPod.Spec.EphemeralContainers[i].Env, vPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := s.podTranslator.TranslateContainerEnv(vPod.Spec.EphemeralContainers[i].Env, vPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv) + if err != nil { + return ctrl.Result{}, fmt.Errorf("translate container env: %w", err) + } vPod.Spec.EphemeralContainers[i].Env = envVar vPod.Spec.EphemeralContainers[i].EnvFrom = envFrom } diff --git a/pkg/controllers/resources/pods/translate.go b/pkg/controllers/resources/pods/translate.go index b734432b7b..f10932d7fd 100644 --- a/pkg/controllers/resources/pods/translate.go +++ b/pkg/controllers/resources/pods/translate.go @@ -87,13 +87,19 @@ func (s *podSyncer) findKubernetesDNSIP(ctx *synccontext.SyncContext) (string, e return "", errors.New("specialservices default not initialized") } + // translate service name + pService, err := mappings.VirtualToHostName(specialservices.DefaultKubeDNSServiceName, specialservices.DefaultKubeDNSServiceNamespace, mappings.Services()) + if err != nil { + return "", err + } + // first try to find the actual synced service, then fallback to a different if we have a suffix (only in the case of integrated coredns) pClient, namespace := specialservices.Default.DNSNamespace(ctx) ip := s.translateAndFindService( ctx, pClient, namespace, - mappings.VirtualToHostName(specialservices.DefaultKubeDNSServiceName, specialservices.DefaultKubeDNSServiceNamespace, mappings.Services()), + pService, ) if ip == "" { return "", fmt.Errorf("waiting for DNS service IP") diff --git a/pkg/controllers/resources/pods/translate/sa_token_secret.go b/pkg/controllers/resources/pods/translate/sa_token_secret.go index 94636767a3..d9a30ab5e4 100644 --- a/pkg/controllers/resources/pods/translate/sa_token_secret.go +++ b/pkg/controllers/resources/pods/translate/sa_token_secret.go @@ -69,32 +69,27 @@ func SATokenSecret(ctx context.Context, pClient client.Client, vPod *corev1.Pod, existingSecret = nil } - // secret does not exist we need to create it - if existingSecret == nil { - // create to secret with the given token - secret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: SecretNameFromPodName(vPod.Name, vPod.Namespace), - Namespace: translate.Default.PhysicalNamespace(vPod.Namespace), - - Annotations: map[string]string{ - translate.SkipBackSyncInMultiNamespaceMode: "true", - }, + // create to secret with the given token + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: SecretNameFromPodName(vPod.Name, vPod.Namespace), + Namespace: translate.Default.PhysicalNamespace(vPod.Namespace), + + Annotations: map[string]string{ + translate.SkipBackSyncInMultiNamespaceMode: "true", }, - Type: corev1.SecretTypeOpaque, - StringData: tokens, - } - if translate.Owner != nil { - secret.SetOwnerReferences(translate.GetOwnerReference(nil)) - } - - // create the service account secret - err = pClient.Create(ctx, secret) - if err != nil { - return err - } + }, + Type: corev1.SecretTypeOpaque, + StringData: tokens, + } + if translate.Owner != nil { + secret.SetOwnerReferences(translate.GetOwnerReference(nil)) + } - return nil + // create the service account secret + err = pClient.Create(ctx, secret) + if err != nil { + return err } return nil diff --git a/pkg/controllers/resources/pods/translate/translator.go b/pkg/controllers/resources/pods/translate/translator.go index 29afc60e2e..bdfec3e36a 100644 --- a/pkg/controllers/resources/pods/translate/translator.go +++ b/pkg/controllers/resources/pods/translate/translator.go @@ -55,7 +55,7 @@ type Translator interface { Translate(ctx context.Context, vPod *corev1.Pod, services []*corev1.Service, dnsIP string, kubeIP string) (*corev1.Pod, error) Diff(ctx context.Context, vPod, pPod *corev1.Pod) (*corev1.Pod, error) - TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *corev1.Pod, serviceEnvMap map[string]string) ([]corev1.EnvVar, []corev1.EnvFromSource) + TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *corev1.Pod, serviceEnvMap map[string]string) ([]corev1.EnvVar, []corev1.EnvFromSource, error) } func NewTranslator(ctx *synccontext.RegisterContext, eventRecorder record.EventRecorder) (Translator, error) { @@ -295,7 +295,10 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate containers for i := range pPod.Spec.Containers { - envVar, envFrom := t.TranslateContainerEnv(pPod.Spec.Containers[i].Env, pPod.Spec.Containers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := t.TranslateContainerEnv(pPod.Spec.Containers[i].Env, pPod.Spec.Containers[i].EnvFrom, vPod, serviceEnv) + if err != nil { + return nil, err + } pPod.Spec.Containers[i].Env = envVar pPod.Spec.Containers[i].EnvFrom = envFrom pPod.Spec.Containers[i].Image = t.imageTranslator.Translate(pPod.Spec.Containers[i].Image) @@ -303,7 +306,10 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate init containers for i := range pPod.Spec.InitContainers { - envVar, envFrom := t.TranslateContainerEnv(pPod.Spec.InitContainers[i].Env, pPod.Spec.InitContainers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := t.TranslateContainerEnv(pPod.Spec.InitContainers[i].Env, pPod.Spec.InitContainers[i].EnvFrom, vPod, serviceEnv) + if err != nil { + return nil, err + } pPod.Spec.InitContainers[i].Env = envVar pPod.Spec.InitContainers[i].EnvFrom = envFrom pPod.Spec.InitContainers[i].Image = t.imageTranslator.Translate(pPod.Spec.InitContainers[i].Image) @@ -311,7 +317,10 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate ephemeral containers for i := range pPod.Spec.EphemeralContainers { - envVar, envFrom := t.TranslateContainerEnv(pPod.Spec.EphemeralContainers[i].Env, pPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := t.TranslateContainerEnv(pPod.Spec.EphemeralContainers[i].Env, pPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv) + if err != nil { + return nil, err + } pPod.Spec.EphemeralContainers[i].Env = envVar pPod.Spec.EphemeralContainers[i].EnvFrom = envFrom pPod.Spec.EphemeralContainers[i].Image = t.imageTranslator.Translate(pPod.Spec.EphemeralContainers[i].Image) @@ -418,6 +427,7 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo pPod.Spec.Volumes[i].RBD.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].RBD.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].FlexVolume != nil && pPod.Spec.Volumes[i].FlexVolume.SecretRef != nil { + pPod.Spec.Volumes[i].FlexVolume.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].FlexVolume.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].Cinder != nil && pPod.Spec.Volumes[i].Cinder.SecretRef != nil { @@ -599,7 +609,7 @@ func translateFieldRef(fieldSelector *corev1.ObjectFieldSelector) { } } -func (t *translator) TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *corev1.Pod, serviceEnvMap map[string]string) ([]corev1.EnvVar, []corev1.EnvFromSource) { +func (t *translator) TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []corev1.EnvFromSource, vPod *corev1.Pod, serviceEnvMap map[string]string) ([]corev1.EnvVar, []corev1.EnvFromSource, error) { envNameMap := make(map[string]struct{}) for j, env := range envVar { translateDownwardAPI(&envVar[j]) @@ -640,7 +650,7 @@ func (t *translator) TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []cor } // additional env vars should come first to allow for dependent environment variables envVar = append(additionalEnvVars, envVar...) - return envVar, envFrom + return envVar, envFrom, nil } func translateDownwardAPI(env *corev1.EnvVar) { diff --git a/pkg/controllers/resources/pods/util.go b/pkg/controllers/resources/pods/util.go index b59325a0f5..dde9330522 100644 --- a/pkg/controllers/resources/pods/util.go +++ b/pkg/controllers/resources/pods/util.go @@ -41,7 +41,10 @@ func SecretNamesFromVolumes(pod *corev1.Pod) []string { // check if projected volume source is a serviceaccount and in such a case // we re-write it as a secret too, handle accordingly if pod.Spec.Volumes[i].Projected.Sources[j].ServiceAccountToken != nil { - secrets = append(secrets, pod.Namespace+"/"+podtranslate.SecretNameFromPodName(pod.Name, pod.Namespace)) + pSecret, err := podtranslate.SecretNameFromPodName(pod.Name, pod.Namespace) + if err == nil { + secrets = append(secrets, pod.Namespace+"/"+pSecret) + } } } } diff --git a/pkg/controllers/resources/priorityclasses/syncer.go b/pkg/controllers/resources/priorityclasses/syncer.go index 27947ffc8b..9e8ca80bc6 100644 --- a/pkg/controllers/resources/priorityclasses/syncer.go +++ b/pkg/controllers/resources/priorityclasses/syncer.go @@ -5,6 +5,7 @@ import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" syncer "github.com/loft-sh/vcluster/pkg/types" schedulingv1 "k8s.io/api/scheduling/v1" @@ -15,7 +16,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &priorityClassSyncer{ - Translator: translator.NewClusterTranslator(ctx, "priorityclass", &schedulingv1.PriorityClass{}), + Translator: translator.NewClusterTranslator(ctx, "priorityclass", &schedulingv1.PriorityClass{}, mappings.PriorityClasses()), }, nil } diff --git a/pkg/controllers/resources/secrets/syncer.go b/pkg/controllers/resources/secrets/syncer.go index a6f65b7d30..32d6747acd 100644 --- a/pkg/controllers/resources/secrets/syncer.go +++ b/pkg/controllers/resources/secrets/syncer.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" "k8s.io/apimachinery/pkg/api/equality" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -34,7 +35,7 @@ func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { func NewSyncer(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &secretSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "secret", &corev1.Secret{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "secret", &corev1.Secret{}, mappings.Secrets()), includeIngresses: ctx.Config.Sync.ToHost.Ingresses.Enabled, @@ -165,7 +166,6 @@ func (s *secretSyncer) isSecretUsed(ctx *synccontext.SyncContext, vObj runtime.O // check if we also sync ingresses if s.includeIngresses { ingressesList := &networkingv1.IngressList{} - err := ctx.VirtualClient.List(ctx.Context, ingressesList, client.MatchingFields{constants.IndexByIngressSecret: secret.Namespace + "/" + secret.Name}) if err != nil { return false, err diff --git a/pkg/controllers/resources/serviceaccounts/syncer.go b/pkg/controllers/resources/serviceaccounts/syncer.go index e34a061572..94065bee9f 100644 --- a/pkg/controllers/resources/serviceaccounts/syncer.go +++ b/pkg/controllers/resources/serviceaccounts/syncer.go @@ -2,6 +2,7 @@ package serviceaccounts import ( "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" syncer "github.com/loft-sh/vcluster/pkg/types" @@ -12,7 +13,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &serviceAccountSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "serviceaccount", &corev1.ServiceAccount{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "serviceaccount", &corev1.ServiceAccount{}, mappings.ServiceAccounts()), }, nil } diff --git a/pkg/controllers/resources/services/syncer.go b/pkg/controllers/resources/services/syncer.go index fc938d4777..560a2985bd 100644 --- a/pkg/controllers/resources/services/syncer.go +++ b/pkg/controllers/resources/services/syncer.go @@ -8,6 +8,7 @@ import ( "github.com/loft-sh/vcluster/pkg/controllers/syncer" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/specialservices" syncertypes "github.com/loft-sh/vcluster/pkg/types" @@ -26,7 +27,7 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { // exclude "field.cattle.io/publicEndpoints" annotation used by Rancher, // because if it is also installed in the host cluster, it will be // overriding it, which would cause endless updates back and forth. - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "service", &corev1.Service{}, "field.cattle.io/publicEndpoints"), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "service", &corev1.Service{}, mappings.Services(), "field.cattle.io/publicEndpoints"), serviceName: ctx.Config.WorkloadService, }, nil diff --git a/pkg/controllers/resources/storageclasses/host_sc_syncer.go b/pkg/controllers/resources/storageclasses/host_sc_syncer.go index 1970488b4a..42ee8d5923 100644 --- a/pkg/controllers/resources/storageclasses/host_sc_syncer.go +++ b/pkg/controllers/resources/storageclasses/host_sc_syncer.go @@ -3,6 +3,7 @@ package storageclasses import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" storagev1 "k8s.io/api/storage/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -11,7 +12,7 @@ import ( func NewHostStorageClassSyncer(*synccontext.RegisterContext) (syncer.Object, error) { return &hostStorageClassSyncer{ - Translator: translator.NewMirrorPhysicalTranslator("host-storageclass", &storagev1.StorageClass{}), + Translator: translator.NewMirrorPhysicalTranslator("host-storageclass", &storagev1.StorageClass{}, mappings.StorageClasses()), }, nil } diff --git a/pkg/controllers/resources/storageclasses/syncer.go b/pkg/controllers/resources/storageclasses/syncer.go index d7c95a2a12..a9b159fc53 100644 --- a/pkg/controllers/resources/storageclasses/syncer.go +++ b/pkg/controllers/resources/storageclasses/syncer.go @@ -3,6 +3,7 @@ package storageclasses import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" storagev1 "k8s.io/api/storage/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -13,7 +14,7 @@ var DefaultStorageClassAnnotation = "storageclass.kubernetes.io/is-default-class func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &storageClassSyncer{ - Translator: translator.NewClusterTranslator(ctx, "storageclass", &storagev1.StorageClass{}, DefaultStorageClassAnnotation), + Translator: translator.NewClusterTranslator(ctx, "storageclass", &storagev1.StorageClass{}, mappings.StorageClasses(), DefaultStorageClassAnnotation), }, nil } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go index 69f04baf9e..ae028473cf 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go @@ -2,6 +2,7 @@ package volumesnapshotclasses import ( "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" "github.com/loft-sh/vcluster/pkg/util" @@ -13,7 +14,7 @@ import ( func New(_ *synccontext.RegisterContext) (syncer.Object, error) { return &volumeSnapshotClassSyncer{ - Translator: translator.NewMirrorPhysicalTranslator("volumesnapshotclass", &volumesnapshotv1.VolumeSnapshotClass{}), + Translator: translator.NewMirrorPhysicalTranslator("volumesnapshotclass", &volumesnapshotv1.VolumeSnapshotClass{}, mappings.VolumeSnapshotClasses()), }, nil } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go index e1511cf54f..ffbf206f09 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go @@ -4,6 +4,7 @@ import ( "context" "time" + "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" @@ -21,13 +22,12 @@ import ( ) const ( - HostClusterVSCAnnotation = "vcluster.loft.sh/host-volumesnapshotcontent" PhysicalVSCGarbageCollectionFinalizer = "vcluster.loft.sh/physical-volumesnapshotcontent-gc" ) func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &volumeSnapshotContentSyncer{ - Translator: translator.NewClusterTranslator(ctx, "volume-snapshot-content", &volumesnapshotv1.VolumeSnapshotContent{}), + Translator: translator.NewClusterTranslator(ctx, "volume-snapshot-content", &volumesnapshotv1.VolumeSnapshotContent{}, mappings.VolumeSnapshotContents()), virtualClient: ctx.VirtualManager.GetClient(), }, nil @@ -67,7 +67,7 @@ var _ syncer.Syncer = &volumeSnapshotContentSyncer{} func (s *volumeSnapshotContentSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { vVSC := vObj.(*volumesnapshotv1.VolumeSnapshotContent) - if vVSC.DeletionTimestamp != nil || (vVSC.Annotations != nil && vVSC.Annotations[HostClusterVSCAnnotation] != "") { + if vVSC.DeletionTimestamp != nil || (vVSC.Annotations != nil && vVSC.Annotations[constants.HostClusterVSCAnnotation] != "") { if len(vVSC.Finalizers) > 0 { // delete the finalizer here so that the object can be deleted vVSC.Finalizers = []string{} @@ -161,7 +161,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl } // update the physical VolumeSnapshotContent if the virtual has changed - if vVSC.Annotations == nil || vVSC.Annotations[HostClusterVSCAnnotation] == "" { + if vVSC.Annotations == nil || vVSC.Annotations[constants.HostClusterVSCAnnotation] == "" { if vVSC.DeletionTimestamp != nil { if pVSC.DeletionTimestamp != nil { return ctrl.Result{}, nil diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go index 22f007b5e7..9eb1b7a9cb 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go @@ -4,8 +4,8 @@ import ( "testing" "time" + "github.com/loft-sh/vcluster/pkg/constants" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/mappings/resources" "gotest.tools/assert" "k8s.io/utils/ptr" @@ -23,11 +23,6 @@ const ( ) func newFakeSyncer(t *testing.T, ctx *synccontext.RegisterContext) (*synccontext.SyncContext, *volumeSnapshotContentSyncer) { - err := resources.RegisterVolumeSnapshotContentsMapper(ctx) - assert.NilError(t, err) - err = resources.RegisterVolumeSnapshotsMapper(ctx) - assert.NilError(t, err) - syncContext, object := generictesting.FakeStartSyncer(t, ctx, New) return syncContext, object.(*volumeSnapshotContentSyncer) } @@ -110,7 +105,7 @@ func TestSync(t *testing.T) { if vDynamic.Annotations == nil { vDynamic.Annotations = map[string]string{} } - vDynamic.Annotations[HostClusterVSCAnnotation] = pDynamic.Name + vDynamic.Annotations[constants.HostClusterVSCAnnotation] = pDynamic.Name vDynamic.Spec.VolumeSnapshotRef = corev1.ObjectReference{ Name: vVolumeSnapshot.Name, Namespace: vVolumeSnapshot.Namespace, diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go index 213007317a..b5fc01e8d6 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go @@ -4,6 +4,7 @@ import ( "context" volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" + "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" "github.com/loft-sh/vcluster/pkg/mappings" corev1 "k8s.io/api/core/v1" @@ -35,7 +36,7 @@ func (s *volumeSnapshotContentSyncer) translateBackwards(pVSC *volumesnapshotv1. if vObj.Annotations == nil { vObj.Annotations = map[string]string{} } - vObj.Annotations[HostClusterVSCAnnotation] = pVSC.Name + vObj.Annotations[constants.HostClusterVSCAnnotation] = pVSC.Name return vObj } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go index e92ea18377..21381830ba 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go @@ -2,6 +2,7 @@ package volumesnapshots import ( "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" "github.com/loft-sh/vcluster/pkg/util" @@ -22,7 +23,7 @@ var ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &volumeSnapshotSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "volume-snapshot", &volumesnapshotv1.VolumeSnapshot{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "volume-snapshot", &volumesnapshotv1.VolumeSnapshot{}, mappings.VolumeSnapshots()), }, nil } diff --git a/pkg/controllers/syncer/syncer.go b/pkg/controllers/syncer/syncer.go index 34178d899f..43d819d735 100644 --- a/pkg/controllers/syncer/syncer.go +++ b/pkg/controllers/syncer/syncer.go @@ -7,15 +7,11 @@ import ( "time" "github.com/loft-sh/vcluster/pkg/constants" - "github.com/loft-sh/vcluster/pkg/mappings" - "github.com/loft-sh/vcluster/pkg/scheme" "github.com/loft-sh/vcluster/pkg/util/translate" "github.com/moby/locker" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/workqueue" "k8s.io/klog/v2" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" controller2 "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/source" @@ -39,14 +35,8 @@ func NewSyncController(ctx *synccontext.RegisterContext, syncer syncertypes.Sync options = optionsProvider.WithOptions() } - gvk, err := apiutil.GVKForObject(syncer.Resource(), scheme.Scheme) - if err != nil { - return nil, err - } - return &SyncController{ syncer: syncer, - gvk: gvk, log: loghelper.New(syncer.Name()), vEventRecorder: ctx.VirtualManager.GetEventRecorderFor(syncer.Name() + "-syncer"), @@ -73,7 +63,6 @@ func RegisterSyncer(ctx *synccontext.RegisterContext, syncer syncertypes.Syncer) type SyncController struct { syncer syncertypes.Syncer - gvk schema.GroupVersionKind log loghelper.Logger vEventRecorder record.EventRecorder @@ -198,7 +187,7 @@ func (r *SyncController) getObjectsFromPhysical(ctx *synccontext.SyncContext, re } // get virtual object - exclude, vObj, err = r.getVirtualObject(ctx.Context, mappings.Default.ByGVK(r.gvk).HostToVirtual(ctx.Context, req.NamespacedName, pObj)) + exclude, vObj, err = r.getVirtualObject(ctx.Context, r.syncer.HostToVirtual(ctx.Context, req.NamespacedName, pObj)) if err != nil { return nil, nil, err } else if exclude { @@ -218,7 +207,7 @@ func (r *SyncController) getObjectsFromVirtual(ctx *synccontext.SyncContext, req } // get physical object - exclude, pObj, err = r.getPhysicalObject(ctx.Context, mappings.Default.ByGVK(r.gvk).VirtualToHost(ctx.Context, req.NamespacedName, vObj), vObj) + exclude, pObj, err = r.getPhysicalObject(ctx.Context, r.syncer.VirtualToHost(ctx.Context, req.NamespacedName, vObj), vObj) if err != nil { return nil, nil, err } else if exclude { @@ -345,7 +334,7 @@ func (r *SyncController) extractRequest(ctx context.Context, req ctrl.Request) ( } // try to get virtual name from physical - req.NamespacedName = mappings.Default.ByGVK(r.gvk).HostToVirtual(ctx, pReq.NamespacedName, pObj) + req.NamespacedName = r.syncer.HostToVirtual(ctx, pReq.NamespacedName, pObj) } return req, pReq, nil @@ -358,7 +347,7 @@ func (r *SyncController) enqueueVirtual(ctx context.Context, obj client.Object, // add a new request for the host object as otherwise this information might be lost after a delete event if isDelete { - name := mappings.Default.ByGVK(r.gvk).VirtualToHost(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) + name := r.syncer.VirtualToHost(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) if name.Name != "" { q.Add(toHostRequest(reconcile.Request{ NamespacedName: name, @@ -391,7 +380,7 @@ func (r *SyncController) enqueuePhysical(ctx context.Context, obj client.Object, // add a new request for the virtual object as otherwise this information might be lost after a delete event if isDelete { - name := mappings.Default.ByGVK(r.gvk).HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) + name := r.syncer.HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) if name.Name != "" { q.Add(reconcile.Request{ NamespacedName: name, diff --git a/pkg/controllers/syncer/syncer_test.go b/pkg/controllers/syncer/syncer_test.go index bb47b869ef..7fd8a53f90 100644 --- a/pkg/controllers/syncer/syncer_test.go +++ b/pkg/controllers/syncer/syncer_test.go @@ -6,6 +6,7 @@ import ( "sort" "testing" + "github.com/loft-sh/vcluster/pkg/mappings/registermappings" "github.com/loft-sh/vcluster/pkg/scheme" testingutil "github.com/loft-sh/vcluster/pkg/util/testing" "github.com/loft-sh/vcluster/pkg/util/translate" @@ -81,7 +82,7 @@ func TestReconcile(t *testing.T) { Syncer func(ctx *synccontext.RegisterContext) (syncertypes.Object, error) - EnqueObjs []types.NamespacedName + EnqueueObjs []types.NamespacedName InitialPhysicalState []runtime.Object InitialVirtualState []runtime.Object @@ -100,7 +101,7 @@ func TestReconcile(t *testing.T) { Name: "should sync down", Syncer: NewMockSyncer, - EnqueObjs: []types.NamespacedName{ + EnqueueObjs: []types.NamespacedName{ {Name: "a", Namespace: namespaceInVclusterA}, }, @@ -157,7 +158,6 @@ func TestReconcile(t *testing.T) { translate.NameAnnotation: "a", translate.NamespaceAnnotation: namespaceInVclusterA, translate.UIDAnnotation: "123", - translate.KindAnnotation: corev1.SchemeGroupVersion.WithKind("Secret").String(), }, Labels: map[string]string{ translate.NamespaceLabel: namespaceInVclusterA, @@ -173,7 +173,7 @@ func TestReconcile(t *testing.T) { Name: "should fail to sync down when object of desired name already exists", Syncer: NewMockSyncer, - EnqueObjs: []types.NamespacedName{ + EnqueueObjs: []types.NamespacedName{ {Name: "a", Namespace: namespaceInVclusterA}, }, @@ -271,6 +271,7 @@ func TestReconcile(t *testing.T) { vClient := testingutil.NewFakeClient(scheme.Scheme, tc.InitialVirtualState...) fakeContext := generictesting.NewFakeRegisterContext(generictesting.NewFakeConfig(), pClient, vClient) + registermappings.MustRegisterMappings(fakeContext) syncerImpl, err := tc.Syncer(fakeContext) assert.NilError(t, err) @@ -282,6 +283,8 @@ func TestReconcile(t *testing.T) { vEventRecorder: &testingutil.FakeEventRecorder{}, physicalClient: pClient, + gvk: corev1.SchemeGroupVersion.WithKind("Secret"), + currentNamespace: fakeContext.CurrentNamespace, currentNamespaceClient: fakeContext.CurrentNamespaceClient, @@ -292,7 +295,7 @@ func TestReconcile(t *testing.T) { } // execute - for _, req := range tc.EnqueObjs { + for _, req := range tc.EnqueueObjs { _, err = controller.Reconcile(ctx, ctrl.Request{NamespacedName: req}) } if tc.shouldErr { diff --git a/pkg/controllers/syncer/testing/context.go b/pkg/controllers/syncer/testing/context.go index 1f2d1f6d60..5a4b87773b 100644 --- a/pkg/controllers/syncer/testing/context.go +++ b/pkg/controllers/syncer/testing/context.go @@ -6,6 +6,7 @@ import ( vclusterconfig "github.com/loft-sh/vcluster/config" "github.com/loft-sh/vcluster/pkg/config" + "github.com/loft-sh/vcluster/pkg/mappings/registermappings" "github.com/loft-sh/vcluster/pkg/util/translate" "github.com/loft-sh/vcluster/pkg/util/log" @@ -50,7 +51,7 @@ func FakeStartSyncer(t *testing.T, ctx *synccontext.RegisterContext, create func func NewFakeRegisterContext(vConfig *config.VirtualClusterConfig, pClient *testingutil.FakeIndexClient, vClient *testingutil.FakeIndexClient) *synccontext.RegisterContext { translate.Default = translate.NewSingleNamespaceTranslator(DefaultTestTargetNamespace) - return &synccontext.RegisterContext{ + registerCtx := &synccontext.RegisterContext{ Context: context.Background(), Config: vConfig, CurrentNamespace: DefaultTestCurrentNamespace, @@ -58,6 +59,9 @@ func NewFakeRegisterContext(vConfig *config.VirtualClusterConfig, pClient *testi VirtualManager: newFakeManager(vClient), PhysicalManager: newFakeManager(pClient), } + + registermappings.MustRegisterMappings(registerCtx) + return registerCtx } func NewFakeConfig() *config.VirtualClusterConfig { diff --git a/pkg/controllers/syncer/translator/cluster_translator.go b/pkg/controllers/syncer/translator/cluster_translator.go index 3e94be70ed..bca11c34a1 100644 --- a/pkg/controllers/syncer/translator/cluster_translator.go +++ b/pkg/controllers/syncer/translator/cluster_translator.go @@ -2,28 +2,20 @@ package translator import ( context2 "context" - "fmt" "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/mappings" - "github.com/loft-sh/vcluster/pkg/scheme" "github.com/loft-sh/vcluster/pkg/util/translate" "k8s.io/apimachinery/pkg/api/equality" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" ) -func NewClusterTranslator(ctx *context.RegisterContext, name string, obj client.Object, excludedAnnotations ...string) Translator { - gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) - if err != nil { - panic(fmt.Sprintf("Retrieve GVK for object failed: %v", err)) - } - +func NewClusterTranslator(ctx *context.RegisterContext, name string, obj client.Object, mapper mappings.Mapper, excludedAnnotations ...string) Translator { return &clusterTranslator{ + Mapper: mapper, + name: name, - gvk: gvk, excludedAnnotations: excludedAnnotations, virtualClient: ctx.VirtualManager.GetClient(), @@ -33,8 +25,9 @@ func NewClusterTranslator(ctx *context.RegisterContext, name string, obj client. } type clusterTranslator struct { + mappings.Mapper + name string - gvk schema.GroupVersionKind virtualClient client.Client obj client.Object @@ -55,7 +48,12 @@ func (n *clusterTranslator) IsManaged(_ context2.Context, pObj client.Object) (b } func (n *clusterTranslator) TranslateMetadata(ctx context2.Context, vObj client.Object) client.Object { - pObj, err := translate.Default.SetupMetadataWithName(vObj, mappings.Default.ByGVK(n.gvk).VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj)) + nameNamespace, err := n.Mapper.VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj) + if err != nil { + return nil + } + + pObj, err := translate.Default.SetupMetadataWithName(vObj, nameNamespace) if err != nil { return nil } diff --git a/pkg/controllers/syncer/translator/mirror_name_translator.go b/pkg/controllers/syncer/translator/mirror_name_translator.go index 9090384c42..dbddfa8259 100644 --- a/pkg/controllers/syncer/translator/mirror_name_translator.go +++ b/pkg/controllers/syncer/translator/mirror_name_translator.go @@ -3,18 +3,23 @@ package translator import ( "context" + "github.com/loft-sh/vcluster/pkg/mappings" "k8s.io/apimachinery/pkg/api/equality" "sigs.k8s.io/controller-runtime/pkg/client" ) -func NewMirrorPhysicalTranslator(name string, obj client.Object) Translator { +func NewMirrorPhysicalTranslator(name string, obj client.Object, mapper mappings.Mapper) Translator { return &mirrorPhysicalTranslator{ + Mapper: mapper, + name: name, obj: obj, } } type mirrorPhysicalTranslator struct { + mappings.Mapper + name string obj client.Object } diff --git a/pkg/controllers/syncer/translator/namespaced_translator.go b/pkg/controllers/syncer/translator/namespaced_translator.go index 48086aa925..8c9843fef6 100644 --- a/pkg/controllers/syncer/translator/namespaced_translator.go +++ b/pkg/controllers/syncer/translator/namespaced_translator.go @@ -2,32 +2,24 @@ package translator import ( context2 "context" - "fmt" "reflect" "time" "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/mappings" - "github.com/loft-sh/vcluster/pkg/scheme" "github.com/loft-sh/vcluster/pkg/util/translate" kerrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" ) -func NewNamespacedTranslator(ctx *context.RegisterContext, name string, obj client.Object, excludedAnnotations ...string) NamespacedTranslator { - gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) - if err != nil { - panic(fmt.Sprintf("Retrieve GVK for object failed: %v", err)) - } - +func NewNamespacedTranslator(ctx *context.RegisterContext, name string, obj client.Object, mapper mappings.Mapper, excludedAnnotations ...string) NamespacedTranslator { return &namespacedTranslator{ + Mapper: mapper, + name: name, - gvk: gvk, syncedLabels: ctx.Config.Experimental.SyncSettings.SyncLabels, excludedAnnotations: excludedAnnotations, @@ -40,8 +32,9 @@ func NewNamespacedTranslator(ctx *context.RegisterContext, name string, obj clie } type namespacedTranslator struct { + mappings.Mapper + name string - gvk schema.GroupVersionKind excludedAnnotations []string syncedLabels []string @@ -102,7 +95,12 @@ func (n *namespacedTranslator) IsManaged(_ context2.Context, pObj client.Object) } func (n *namespacedTranslator) TranslateMetadata(ctx context2.Context, vObj client.Object) client.Object { - pObj, err := translate.Default.SetupMetadataWithName(vObj, mappings.Default.ByGVK(n.gvk).VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj)) + nameNamespace, err := n.Mapper.VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj) + if err != nil { + return nil + } + + pObj, err := translate.Default.SetupMetadataWithName(vObj, nameNamespace) if err != nil { return nil } diff --git a/pkg/controllers/syncer/translator/translator.go b/pkg/controllers/syncer/translator/translator.go index 1de797559b..934e690d46 100644 --- a/pkg/controllers/syncer/translator/translator.go +++ b/pkg/controllers/syncer/translator/translator.go @@ -4,6 +4,7 @@ import ( "context" syncercontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "github.com/loft-sh/vcluster/pkg/mappings" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -19,6 +20,8 @@ type Translator interface { // ObjectManager is used to convert virtual to physical names and vice versa type ObjectManager interface { + mappings.Mapper + // IsManaged determines if a physical object is managed by the vcluster IsManaged(context.Context, client.Object) (bool, error) } diff --git a/pkg/mappings/generic/cluster.go b/pkg/mappings/generic/cluster.go index 951f0d291f..c2550f96f5 100644 --- a/pkg/mappings/generic/cluster.go +++ b/pkg/mappings/generic/cluster.go @@ -10,18 +10,29 @@ import ( "github.com/loft-sh/vcluster/pkg/scheme" "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/translate" + kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" ) -func NewClusterMapper(ctx *synccontext.RegisterContext, obj client.Object, nameTranslator translate.PhysicalNameClusterFunc) (mappings.Mapper, error) { +func NewClusterMapper(ctx *synccontext.RegisterContext, obj client.Object, nameTranslator translate.PhysicalNameClusterFunc, options ...MapperOption) (mappings.Mapper, error) { gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) if err != nil { return nil, fmt.Errorf("retrieve GVK for object failed: %w", err) } + mapperOptions := getOptions(options...) + if !mapperOptions.SkipIndex { + err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, obj.DeepCopyObject().(client.Object), constants.IndexByPhysicalName, func(rawObj client.Object) []string { + return []string{nameTranslator(rawObj.GetName(), rawObj)} + }) + if err != nil { + return nil, fmt.Errorf("index field: %w", err) + } + } + return &clusterMapper{ obj: obj, gvk: gvk, @@ -41,12 +52,6 @@ func (n *clusterMapper) GroupVersionKind() schema.GroupVersionKind { return n.gvk } -func (n *clusterMapper) Init(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, n.obj.DeepCopyObject().(client.Object), constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{n.nameTranslator(rawObj.GetName(), rawObj)} - }) -} - func (n *clusterMapper) VirtualToHost(_ context2.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { return types.NamespacedName{ Name: n.nameTranslator(req.Name, vObj), @@ -67,6 +72,10 @@ func (n *clusterMapper) HostToVirtual(ctx context2.Context, req types.Namespaced vObj := n.obj.DeepCopyObject().(client.Object) err := clienthelper.GetByIndex(ctx, n.virtualClient, vObj, constants.IndexByPhysicalName, req.Name) if err != nil { + if !kerrors.IsNotFound(err) && !kerrors.IsConflict(err) { + panic(err.Error()) + } + return types.NamespacedName{} } diff --git a/pkg/mappings/generic/mirror.go b/pkg/mappings/generic/mirror.go index 84fb145717..9583d79ebc 100644 --- a/pkg/mappings/generic/mirror.go +++ b/pkg/mappings/generic/mirror.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/scheme" "k8s.io/apimachinery/pkg/runtime/schema" @@ -28,10 +27,6 @@ type mirrorPhysicalMapper struct { gvk schema.GroupVersionKind } -func (n *mirrorPhysicalMapper) Init(_ *synccontext.RegisterContext) error { - return nil -} - func (n *mirrorPhysicalMapper) GroupVersionKind() schema.GroupVersionKind { return n.gvk } diff --git a/pkg/mappings/generic/namespaced.go b/pkg/mappings/generic/namespaced.go index e2ff790aa4..c0e1f6f765 100644 --- a/pkg/mappings/generic/namespaced.go +++ b/pkg/mappings/generic/namespaced.go @@ -10,18 +10,49 @@ import ( "github.com/loft-sh/vcluster/pkg/scheme" "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/translate" + kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" ) -func NewNamespacedMapper(ctx *synccontext.RegisterContext, obj client.Object, translateName translate.PhysicalNameFunc) (mappings.Mapper, error) { +type MapperOption func(options *MapperOptions) + +func SkipIndex() MapperOption { + return func(options *MapperOptions) { + options.SkipIndex = true + } +} + +type MapperOptions struct { + SkipIndex bool +} + +func getOptions(options ...MapperOption) *MapperOptions { + newOptions := &MapperOptions{} + for _, option := range options { + option(newOptions) + } + return newOptions +} + +func NewNamespacedMapper(ctx *synccontext.RegisterContext, obj client.Object, translateName translate.PhysicalNameFunc, options ...MapperOption) (mappings.Mapper, error) { gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) if err != nil { return nil, fmt.Errorf("retrieve GVK for object failed: %w", err) } + mapperOptions := getOptions(options...) + if !mapperOptions.SkipIndex { + err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, obj.DeepCopyObject().(client.Object), constants.IndexByPhysicalName, func(rawObj client.Object) []string { + return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translateName(rawObj.GetName(), rawObj.GetNamespace())} + }) + if err != nil { + return nil, fmt.Errorf("index field: %w", err) + } + } + return &namespacedMapper{ translateName: translateName, virtualClient: ctx.VirtualManager.GetClient(), @@ -41,12 +72,6 @@ func (n *namespacedMapper) GroupVersionKind() schema.GroupVersionKind { return n.gvk } -func (n *namespacedMapper) Init(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, n.obj.DeepCopyObject().(client.Object), constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + n.translateName(rawObj.GetName(), rawObj.GetNamespace())} - }) -} - func (n *namespacedMapper) VirtualToHost(_ context2.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { return types.NamespacedName{ Namespace: translate.Default.PhysicalNamespace(req.Namespace), @@ -68,6 +93,10 @@ func (n *namespacedMapper) HostToVirtual(ctx context2.Context, req types.Namespa vObj := n.obj.DeepCopyObject().(client.Object) err := clienthelper.GetByIndex(ctx, n.virtualClient, vObj, constants.IndexByPhysicalName, req.Namespace+"/"+req.Name) if err != nil { + if !kerrors.IsNotFound(err) && !kerrors.IsConflict(err) { + panic(err.Error()) + } + return types.NamespacedName{} } diff --git a/pkg/mappings/mappings.go b/pkg/mappings/mappings.go index ab3313558c..cfbde6d762 100644 --- a/pkg/mappings/mappings.go +++ b/pkg/mappings/mappings.go @@ -4,8 +4,9 @@ import ( "context" volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" - synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" + policyv1 "k8s.io/api/policy/v1" schedulingv1 "k8s.io/api/scheduling/v1" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -23,9 +24,6 @@ type Mapper interface { // GroupVersionKind retrieves the group version kind GroupVersionKind() schema.GroupVersionKind - // Init initializes the mapper - Init(ctx *synccontext.RegisterContext) error - // VirtualToHost translates a virtual name to a physical name VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName @@ -41,6 +39,14 @@ func ByGVK(gvk schema.GroupVersionKind) Mapper { return Default.ByGVK(gvk) } +func CSIDrivers() Mapper { + return Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("CSIDriver")) +} + +func CSINodes() Mapper { + return Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("CSINode")) +} + func CSIStorageCapacities() Mapper { return Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("CSIStorageCapacity")) } @@ -49,9 +55,24 @@ func VolumeSnapshotContents() Mapper { return Default.ByGVK(volumesnapshotv1.SchemeGroupVersion.WithKind("VolumeSnapshotContent")) } +func NetworkPolicies() Mapper { + return Default.ByGVK(networkingv1.SchemeGroupVersion.WithKind("NetworkPolicy")) +} + +func Nodes() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Node")) +} + +func PodDisruptionBudgets() Mapper { + return Default.ByGVK(policyv1.SchemeGroupVersion.WithKind("PodDisruptionBudget")) +} + func VolumeSnapshots() Mapper { return Default.ByGVK(volumesnapshotv1.SchemeGroupVersion.WithKind("VolumeSnapshot")) } +func VolumeSnapshotClasses() Mapper { + return Default.ByGVK(volumesnapshotv1.SchemeGroupVersion.WithKind("VolumeSnapshotClass")) +} func Events() Mapper { return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Event")) @@ -89,6 +110,18 @@ func StorageClasses() Mapper { return Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("StorageClass")) } +func IngressClasses() Mapper { + return Default.ByGVK(networkingv1.SchemeGroupVersion.WithKind("IngressClass")) +} + +func Namespaces() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Namespace")) +} + +func Ingresses() Mapper { + return Default.ByGVK(networkingv1.SchemeGroupVersion.WithKind("Ingress")) +} + func PersistentVolumeClaims() Mapper { return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("PersistentVolumeClaim")) } @@ -97,10 +130,6 @@ func PriorityClasses() Mapper { return Default.ByGVK(schedulingv1.SchemeGroupVersion.WithKind("PriorityClass")) } -func NamespacedName(obj client.Object) types.NamespacedName { - return types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()} -} - func VirtualToHostName(vName, vNamespace string, mapper Mapper) string { return mapper.VirtualToHost(context.TODO(), types.NamespacedName{Name: vName, Namespace: vNamespace}, nil).Name } diff --git a/pkg/mappings/registermappings/register.go b/pkg/mappings/registermappings/register.go index e961f225f6..54a933f23d 100644 --- a/pkg/mappings/registermappings/register.go +++ b/pkg/mappings/registermappings/register.go @@ -4,48 +4,60 @@ import ( "fmt" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/mappings/resources" ) -type registerMapping func(ctx *synccontext.RegisterContext) error - -var mappings = []registerMapping{ - resources.RegisterSecretsMapper, - resources.RegisterConfigMapsMapper, - resources.RegisterCSIDriversMapper, - resources.RegisterCSINodesMapper, - resources.RegisterCSIStorageCapacitiesMapper, - resources.RegisterEndpointsMapper, - resources.RegisterEventsMapper, - resources.RegisterIngressClassesMapper, - resources.RegisterIngressesMapper, - resources.RegisterIngressesLegacyMapper, - resources.RegisterNamespacesMapper, - resources.RegisterNetworkPoliciesMapper, - resources.RegisterNodesMapper, - resources.RegisterPersistentVolumeClaimsMapper, - resources.RegisterServiceAccountsMapper, - resources.RegisterServiceMapper, - resources.RegisterPriorityClassesMapper, - resources.RegisterPodDisruptionBudgetsMapper, - resources.RegisterPersistentVolumesMapper, - resources.RegisterPodsMapper, - resources.RegisterStorageClassesMapper, - resources.RegisterVolumeSnapshotClassesMapper, - resources.RegisterVolumeSnapshotContentsMapper, - resources.RegisterVolumeSnapshotsMapper, - resources.RegisterGenericExporterMappers, +type CreateMapper func(ctx *synccontext.RegisterContext) (mappings.Mapper, error) + +var DefaultResourceMappings = []CreateMapper{ + resources.CreateSecretsMapper, + resources.CreateConfigMapsMapper, + resources.CreateCSIDriversMapper, + resources.CreateCSINodesMapper, + resources.CreateCSIStorageCapacitiesMapper, + resources.CreateEndpointsMapper, + resources.CreateEventsMapper, + resources.CreateIngressClassesMapper, + resources.CreateIngressesMapper, + resources.CreateNamespacesMapper, + resources.CreateNetworkPoliciesMapper, + resources.CreateNodesMapper, + resources.CreatePersistentVolumeClaimsMapper, + resources.CreateServiceAccountsMapper, + resources.CreateServiceMapper, + resources.CreatePriorityClassesMapper, + resources.CreatePodDisruptionBudgetsMapper, + resources.CreatePersistentVolumesMapper, + resources.CreatePodsMapper, + resources.CreateStorageClassesMapper, + resources.CreateVolumeSnapshotClassesMapper, + resources.CreateVolumeSnapshotContentsMapper, + resources.CreateVolumeSnapshotsMapper, +} + +func MustRegisterMappings(ctx *synccontext.RegisterContext) { + err := RegisterMappings(ctx) + if err != nil { + panic(err.Error()) + } } func RegisterMappings(ctx *synccontext.RegisterContext) error { - for _, register := range mappings { - if register == nil { + // create mappers + for _, createFunc := range DefaultResourceMappings { + if createFunc == nil { continue } - err := register(ctx) + mapper, err := createFunc(ctx) + if err != nil { + return fmt.Errorf("create mapper: %w", err) + } + + err = mappings.Default.AddMapper(mapper) if err != nil { - return fmt.Errorf("register mapping: %w", err) + return fmt.Errorf("add mapper %s: %w", mapper.GroupVersionKind().String(), err) } } diff --git a/pkg/mappings/resources/configmaps.go b/pkg/mappings/resources/configmaps.go index d479001ee8..4838580356 100644 --- a/pkg/mappings/resources/configmaps.go +++ b/pkg/mappings/resources/configmaps.go @@ -13,29 +13,30 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func RegisterConfigMapsMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &corev1.ConfigMap{}, translate.Default.PhysicalName) +func CreateConfigMapsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + mapper, err := generic.NewNamespacedMapper(ctx, &corev1.ConfigMap{}, translate.Default.PhysicalName, generic.SkipIndex()) if err != nil { - return err + return nil, err } - return mappings.Default.AddMapper(&configMapsMapper{ - Mapper: mapper, - }) -} - -type configMapsMapper struct { - mappings.Mapper -} - -func (s *configMapsMapper) Init(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.ConfigMap{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { + err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.ConfigMap{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { if !translate.Default.SingleNamespaceTarget() && rawObj.GetName() == "kube-root-ca.crt" { return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName)} } return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.Default.PhysicalName(rawObj.GetName(), rawObj.GetNamespace())} }) + if err != nil { + return nil, err + } + + return &configMapsMapper{ + Mapper: mapper, + }, nil +} + +type configMapsMapper struct { + mappings.Mapper } func (s *configMapsMapper) VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { diff --git a/pkg/mappings/resources/csidrivers.go b/pkg/mappings/resources/csidrivers.go index 2c61b6ad1d..6b45370b45 100644 --- a/pkg/mappings/resources/csidrivers.go +++ b/pkg/mappings/resources/csidrivers.go @@ -7,11 +7,6 @@ import ( storagev1 "k8s.io/api/storage/v1" ) -func RegisterCSIDriversMapper(_ *synccontext.RegisterContext) error { - mapper, err := generic.NewMirrorPhysicalMapper(&storagev1.CSINode{}) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateCSIDriversMapper(_ *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewMirrorPhysicalMapper(&storagev1.CSINode{}) } diff --git a/pkg/mappings/resources/csinodes.go b/pkg/mappings/resources/csinodes.go index 2d7d039b36..d51131f2c6 100644 --- a/pkg/mappings/resources/csinodes.go +++ b/pkg/mappings/resources/csinodes.go @@ -7,11 +7,6 @@ import ( storagev1 "k8s.io/api/storage/v1" ) -func RegisterCSINodesMapper(_ *synccontext.RegisterContext) error { - mapper, err := generic.NewMirrorPhysicalMapper(&storagev1.CSIDriver{}) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateCSINodesMapper(_ *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewMirrorPhysicalMapper(&storagev1.CSIDriver{}) } diff --git a/pkg/mappings/resources/csistoragecapacities.go b/pkg/mappings/resources/csistoragecapacities.go index e54215b658..137d55f9d9 100644 --- a/pkg/mappings/resources/csistoragecapacities.go +++ b/pkg/mappings/resources/csistoragecapacities.go @@ -14,12 +14,19 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -var gvk = storagev1.SchemeGroupVersion.WithKind("CSIStorageCapacity") - -func RegisterCSIStorageCapacitiesMapper(ctx *synccontext.RegisterContext) error { - return mappings.Default.AddMapper(&csiStorageCapacitiesMapper{ +func CreateCSIStorageCapacitiesMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + s := &csiStorageCapacitiesMapper{ physicalClient: ctx.PhysicalManager.GetClient(), + } + + err := ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx.Context, &storagev1.CSIStorageCapacity{}, constants.IndexByVirtualName, func(rawObj client.Object) []string { + return []string{s.HostToVirtual(ctx.Context, types.NamespacedName{Name: rawObj.GetName(), Namespace: rawObj.GetNamespace()}, rawObj).Name} }) + if err != nil { + return nil, err + } + + return s, nil } type csiStorageCapacitiesMapper struct { @@ -27,13 +34,7 @@ type csiStorageCapacitiesMapper struct { } func (s *csiStorageCapacitiesMapper) GroupVersionKind() schema.GroupVersionKind { - return gvk -} - -func (s *csiStorageCapacitiesMapper) Init(ctx *synccontext.RegisterContext) error { - return ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx.Context, &storagev1.CSIStorageCapacity{}, constants.IndexByVirtualName, func(rawObj client.Object) []string { - return []string{s.HostToVirtual(ctx.Context, types.NamespacedName{Name: rawObj.GetName(), Namespace: rawObj.GetNamespace()}, rawObj).Name} - }) + return storagev1.SchemeGroupVersion.WithKind("CSIStorageCapacity") } func (s *csiStorageCapacitiesMapper) HostToVirtual(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { diff --git a/pkg/mappings/resources/endpoints.go b/pkg/mappings/resources/endpoints.go index 3e047070ec..4eb4610bfa 100644 --- a/pkg/mappings/resources/endpoints.go +++ b/pkg/mappings/resources/endpoints.go @@ -8,11 +8,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -func RegisterEndpointsMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &corev1.Endpoints{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateEndpointsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &corev1.Endpoints{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/events.go b/pkg/mappings/resources/events.go index d7e0c207a6..98d67997c3 100644 --- a/pkg/mappings/resources/events.go +++ b/pkg/mappings/resources/events.go @@ -26,10 +26,10 @@ var AcceptedKinds = map[schema.GroupVersionKind]bool{ corev1.SchemeGroupVersion.WithKind("ConfigMap"): true, } -func RegisterEventsMapper(ctx *synccontext.RegisterContext) error { - return mappings.Default.AddMapper(&eventMapper{ +func CreateEventsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return &eventMapper{ virtualClient: ctx.VirtualManager.GetClient(), - }) + }, nil } type eventMapper struct { @@ -40,10 +40,6 @@ func (s *eventMapper) GroupVersionKind() schema.GroupVersionKind { return corev1.SchemeGroupVersion.WithKind("Event") } -func (s *eventMapper) Init(_ *synccontext.RegisterContext) error { - return nil -} - func (s *eventMapper) VirtualToHost(_ context.Context, _ types.NamespacedName, _ client.Object) types.NamespacedName { // we ignore virtual events here, we only react on host events and sync them to the virtual cluster return types.NamespacedName{} diff --git a/pkg/mappings/resources/generic.go b/pkg/mappings/resources/generic.go deleted file mode 100644 index b078621745..0000000000 --- a/pkg/mappings/resources/generic.go +++ /dev/null @@ -1,35 +0,0 @@ -package resources - -import ( - "fmt" - - synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/mappings" - "github.com/loft-sh/vcluster/pkg/mappings/generic" - "github.com/loft-sh/vcluster/pkg/util/translate" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" -) - -func RegisterGenericExporterMappers(ctx *synccontext.RegisterContext) error { - exporterConfig := ctx.Config.Experimental.GenericSync - if len(exporterConfig.Exports) == 0 { - return nil - } - - for _, exportConfig := range exporterConfig.Exports { - obj := &unstructured.Unstructured{} - obj.SetKind(exportConfig.Kind) - obj.SetAPIVersion(exportConfig.APIVersion) - mapper, err := generic.NewNamespacedMapper(ctx, obj, translate.Default.PhysicalName) - if err != nil { - return err - } - - err = mappings.Default.AddMapper(mapper) - if err != nil { - return fmt.Errorf("add mapper: %w", err) - } - } - - return nil -} diff --git a/pkg/mappings/resources/ingressclasses.go b/pkg/mappings/resources/ingressclasses.go index 26337a55c5..8baac5d3e2 100644 --- a/pkg/mappings/resources/ingressclasses.go +++ b/pkg/mappings/resources/ingressclasses.go @@ -7,11 +7,6 @@ import ( networkingv1 "k8s.io/api/networking/v1" ) -func RegisterIngressClassesMapper(_ *synccontext.RegisterContext) error { - mapper, err := generic.NewMirrorPhysicalMapper(&networkingv1.IngressClass{}) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateIngressClassesMapper(_ *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewMirrorPhysicalMapper(&networkingv1.IngressClass{}) } diff --git a/pkg/mappings/resources/ingresses.go b/pkg/mappings/resources/ingresses.go index 98aa20a323..f19ddb3c4d 100644 --- a/pkg/mappings/resources/ingresses.go +++ b/pkg/mappings/resources/ingresses.go @@ -8,11 +8,6 @@ import ( networkingv1 "k8s.io/api/networking/v1" ) -func RegisterIngressesMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &networkingv1.Ingress{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateIngressesMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &networkingv1.Ingress{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/ingresses_legacy.go b/pkg/mappings/resources/ingresses_legacy.go deleted file mode 100644 index 0f4a5e385d..0000000000 --- a/pkg/mappings/resources/ingresses_legacy.go +++ /dev/null @@ -1,18 +0,0 @@ -package resources - -import ( - synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/mappings" - "github.com/loft-sh/vcluster/pkg/mappings/generic" - "github.com/loft-sh/vcluster/pkg/util/translate" - networkingv1beta1 "k8s.io/api/networking/v1beta1" -) - -func RegisterIngressesLegacyMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &networkingv1beta1.Ingress{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) -} diff --git a/pkg/mappings/resources/namespaces.go b/pkg/mappings/resources/namespaces.go index 98887c7191..66f0aa650e 100644 --- a/pkg/mappings/resources/namespaces.go +++ b/pkg/mappings/resources/namespaces.go @@ -9,13 +9,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func RegisterNamespacesMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewClusterMapper(ctx, &corev1.Namespace{}, func(vName string, _ client.Object) string { +func CreateNamespacesMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewClusterMapper(ctx, &corev1.Namespace{}, func(vName string, _ client.Object) string { return translate.Default.PhysicalNamespace(vName) }) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) } diff --git a/pkg/mappings/resources/networkpolicies.go b/pkg/mappings/resources/networkpolicies.go index b333d65d5f..801c73de7e 100644 --- a/pkg/mappings/resources/networkpolicies.go +++ b/pkg/mappings/resources/networkpolicies.go @@ -8,11 +8,6 @@ import ( networkingv1 "k8s.io/api/networking/v1" ) -func RegisterNetworkPoliciesMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &networkingv1.NetworkPolicy{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateNetworkPoliciesMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &networkingv1.NetworkPolicy{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/nodes.go b/pkg/mappings/resources/nodes.go index 2ec31df28e..5cffb222f5 100644 --- a/pkg/mappings/resources/nodes.go +++ b/pkg/mappings/resources/nodes.go @@ -7,11 +7,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -func RegisterNodesMapper(_ *synccontext.RegisterContext) error { - mapper, err := generic.NewMirrorPhysicalMapper(&corev1.Node{}) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateNodesMapper(_ *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewMirrorPhysicalMapper(&corev1.Node{}) } diff --git a/pkg/mappings/resources/persistentvolumeclaims.go b/pkg/mappings/resources/persistentvolumeclaims.go index 3ef0e1f81f..baa9b5be1b 100644 --- a/pkg/mappings/resources/persistentvolumeclaims.go +++ b/pkg/mappings/resources/persistentvolumeclaims.go @@ -8,11 +8,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -func RegisterPersistentVolumeClaimsMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &corev1.PersistentVolumeClaim{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreatePersistentVolumeClaimsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &corev1.PersistentVolumeClaim{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/persistentvolumes.go b/pkg/mappings/resources/persistentvolumes.go index 5f4f7d3ee5..3d5fd571e3 100644 --- a/pkg/mappings/resources/persistentvolumes.go +++ b/pkg/mappings/resources/persistentvolumes.go @@ -4,7 +4,6 @@ import ( "context" "github.com/loft-sh/vcluster/pkg/constants" - "github.com/loft-sh/vcluster/pkg/controllers/resources/persistentvolumes" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/mappings/generic" @@ -16,17 +15,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func RegisterPersistentVolumesMapper(ctx *synccontext.RegisterContext) error { +func CreatePersistentVolumesMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { mapper, err := generic.NewClusterMapper(ctx, &corev1.PersistentVolume{}, translatePersistentVolumeName) if err != nil { - return err + return nil, err } - return mappings.Default.AddMapper(&persistentVolumeMapper{ + return &persistentVolumeMapper{ Mapper: mapper, virtualClient: ctx.VirtualManager.GetClient(), - }) + }, nil } type persistentVolumeMapper struct { @@ -68,9 +67,9 @@ func translatePersistentVolumeName(name string, vObj client.Object) string { } vPv, ok := vObj.(*corev1.PersistentVolume) - if !ok || vPv.Annotations == nil || vPv.Annotations[persistentvolumes.HostClusterPersistentVolumeAnnotation] == "" { + if !ok || vPv.Annotations == nil || vPv.Annotations[constants.HostClusterPersistentVolumeAnnotation] == "" { return translate.Default.PhysicalNameClusterScoped(name) } - return vPv.Annotations[persistentvolumes.HostClusterPersistentVolumeAnnotation] + return vPv.Annotations[constants.HostClusterPersistentVolumeAnnotation] } diff --git a/pkg/mappings/resources/poddisruptionbudgets.go b/pkg/mappings/resources/poddisruptionbudgets.go index e166930b52..b25a77b345 100644 --- a/pkg/mappings/resources/poddisruptionbudgets.go +++ b/pkg/mappings/resources/poddisruptionbudgets.go @@ -8,11 +8,6 @@ import ( policyv1 "k8s.io/api/policy/v1" ) -func RegisterPodDisruptionBudgetsMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &policyv1.PodDisruptionBudget{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreatePodDisruptionBudgetsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &policyv1.PodDisruptionBudget{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/pods.go b/pkg/mappings/resources/pods.go index 3acd13445f..61d4d72c2f 100644 --- a/pkg/mappings/resources/pods.go +++ b/pkg/mappings/resources/pods.go @@ -8,11 +8,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -func RegisterPodsMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &corev1.Pod{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreatePodsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &corev1.Pod{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/priorityclasses.go b/pkg/mappings/resources/priorityclasses.go index 5ba7d70926..9fd4384e47 100644 --- a/pkg/mappings/resources/priorityclasses.go +++ b/pkg/mappings/resources/priorityclasses.go @@ -9,22 +9,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func RegisterPriorityClassesMapper(ctx *synccontext.RegisterContext) error { - var ( - mapper mappings.Mapper - err error - ) +func CreatePriorityClassesMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { if !ctx.Config.Sync.ToHost.PriorityClasses.Enabled { - mapper, err = generic.NewMirrorPhysicalMapper(&schedulingv1.PriorityClass{}) - } else { - mapper, err = generic.NewClusterMapper(ctx, &schedulingv1.PriorityClass{}, func(vName string, _ client.Object) string { - // we have to prefix with vCluster as system is reserved - return translate.Default.PhysicalNameClusterScoped(vName) - }) - } - if err != nil { - return err + return generic.NewMirrorPhysicalMapper(&schedulingv1.PriorityClass{}) } - return mappings.Default.AddMapper(mapper) + return generic.NewClusterMapper(ctx, &schedulingv1.PriorityClass{}, func(vName string, _ client.Object) string { + // we have to prefix with vCluster as system is reserved + return translate.Default.PhysicalNameClusterScoped(vName) + }) } diff --git a/pkg/mappings/resources/secrets.go b/pkg/mappings/resources/secrets.go index 1b7dfe254e..6ed721aad9 100644 --- a/pkg/mappings/resources/secrets.go +++ b/pkg/mappings/resources/secrets.go @@ -8,11 +8,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -func RegisterSecretsMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &corev1.Secret{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateSecretsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &corev1.Secret{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/serviceaccounts.go b/pkg/mappings/resources/serviceaccounts.go index 37c04937b6..c513d615fa 100644 --- a/pkg/mappings/resources/serviceaccounts.go +++ b/pkg/mappings/resources/serviceaccounts.go @@ -8,11 +8,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -func RegisterServiceAccountsMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &corev1.ServiceAccount{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateServiceAccountsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &corev1.ServiceAccount{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/services.go b/pkg/mappings/resources/services.go index 4809213853..04ee89c2a9 100644 --- a/pkg/mappings/resources/services.go +++ b/pkg/mappings/resources/services.go @@ -8,11 +8,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -func RegisterServiceMapper(ctx *synccontext.RegisterContext) error { - mapper, err := generic.NewNamespacedMapper(ctx, &corev1.Service{}, translate.Default.PhysicalName) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateServiceMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewNamespacedMapper(ctx, &corev1.Service{}, translate.Default.PhysicalName) } diff --git a/pkg/mappings/resources/storageclasses.go b/pkg/mappings/resources/storageclasses.go index 43f224bfea..706af13393 100644 --- a/pkg/mappings/resources/storageclasses.go +++ b/pkg/mappings/resources/storageclasses.go @@ -9,21 +9,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func RegisterStorageClassesMapper(ctx *synccontext.RegisterContext) error { - var ( - mapper mappings.Mapper - err error - ) - if !ctx.Config.Sync.ToHost.PriorityClasses.Enabled { - mapper, err = generic.NewMirrorPhysicalMapper(&storagev1.StorageClass{}) - } else { - mapper, err = generic.NewClusterMapper(ctx, &storagev1.StorageClass{}, func(name string, _ client.Object) string { - return translate.Default.PhysicalNameClusterScoped(name) - }) - } - if err != nil { - return err +func CreateStorageClassesMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { + if !ctx.Config.Sync.ToHost.StorageClasses.Enabled { + return generic.NewMirrorPhysicalMapper(&storagev1.StorageClass{}) } - return mappings.Default.AddMapper(mapper) + return generic.NewClusterMapper(ctx, &storagev1.StorageClass{}, func(name string, _ client.Object) string { + return translate.Default.PhysicalNameClusterScoped(name) + }) } diff --git a/pkg/mappings/resources/volumesnapshotclasses.go b/pkg/mappings/resources/volumesnapshotclasses.go index 779b5f867a..0f49a5d9bb 100644 --- a/pkg/mappings/resources/volumesnapshotclasses.go +++ b/pkg/mappings/resources/volumesnapshotclasses.go @@ -7,11 +7,6 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings/generic" ) -func RegisterVolumeSnapshotClassesMapper(_ *synccontext.RegisterContext) error { - mapper, err := generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshotClass{}) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) +func CreateVolumeSnapshotClassesMapper(_ *synccontext.RegisterContext) (mappings.Mapper, error) { + return generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshotClass{}) } diff --git a/pkg/mappings/resources/volumesnapshotcontents.go b/pkg/mappings/resources/volumesnapshotcontents.go index 3c2c156f6b..1c73f370b0 100644 --- a/pkg/mappings/resources/volumesnapshotcontents.go +++ b/pkg/mappings/resources/volumesnapshotcontents.go @@ -5,7 +5,6 @@ import ( volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" "github.com/loft-sh/vcluster/pkg/constants" - "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/mappings/generic" @@ -16,26 +15,21 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func RegisterVolumeSnapshotContentsMapper(ctx *synccontext.RegisterContext) error { +func CreateVolumeSnapshotContentsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { if !ctx.Config.Sync.ToHost.VolumeSnapshots.Enabled { - mapper, err := generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshotContent{}) - if err != nil { - return err - } - - return mappings.Default.AddMapper(mapper) + return generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshotContent{}) } mapper, err := generic.NewClusterMapper(ctx, &volumesnapshotv1.VolumeSnapshotContent{}, translateVolumeSnapshotContentName) if err != nil { - return err + return nil, err } - return mappings.Default.AddMapper(&volumeSnapshotContentMapper{ + return &volumeSnapshotContentMapper{ Mapper: mapper, virtualClient: ctx.VirtualManager.GetClient(), - }) + }, nil } type volumeSnapshotContentMapper struct { @@ -77,9 +71,9 @@ func translateVolumeSnapshotContentName(name string, vObj client.Object) string } vVSC, ok := vObj.(*volumesnapshotv1.VolumeSnapshotContent) - if !ok || vVSC.Annotations == nil || vVSC.Annotations[volumesnapshotcontents.HostClusterVSCAnnotation] == "" { + if !ok || vVSC.Annotations == nil || vVSC.Annotations[constants.HostClusterVSCAnnotation] == "" { return translate.Default.PhysicalNameClusterScoped(name) } - return vVSC.Annotations[volumesnapshotcontents.HostClusterVSCAnnotation] + return vVSC.Annotations[constants.HostClusterVSCAnnotation] } diff --git a/pkg/mappings/resources/volumesnapshots.go b/pkg/mappings/resources/volumesnapshots.go index 930d301a8e..46f383e965 100644 --- a/pkg/mappings/resources/volumesnapshots.go +++ b/pkg/mappings/resources/volumesnapshots.go @@ -8,19 +8,10 @@ import ( "github.com/loft-sh/vcluster/pkg/util/translate" ) -func RegisterVolumeSnapshotsMapper(ctx *synccontext.RegisterContext) error { - var ( - mapper mappings.Mapper - err error - ) +func CreateVolumeSnapshotsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, error) { if !ctx.Config.Sync.ToHost.VolumeSnapshots.Enabled { - mapper, err = generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshot{}) - } else { - mapper, err = generic.NewNamespacedMapper(ctx, &volumesnapshotv1.VolumeSnapshot{}, translate.Default.PhysicalName) - } - if err != nil { - return err + return generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshot{}) } - return mappings.Default.AddMapper(mapper) + return generic.NewNamespacedMapper(ctx, &volumesnapshotv1.VolumeSnapshot{}, translate.Default.PhysicalName) } diff --git a/pkg/server/filters/metrics.go b/pkg/server/filters/metrics.go index 6e0ab1af21..452d252bf2 100644 --- a/pkg/server/filters/metrics.go +++ b/pkg/server/filters/metrics.go @@ -14,8 +14,8 @@ import ( "strings" "github.com/loft-sh/vcluster/pkg/constants" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/server/handler" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" requestpkg "github.com/loft-sh/vcluster/pkg/util/request" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/types" "k8s.io/apiserver/pkg/audit" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" @@ -89,13 +90,13 @@ func WithMetricsProxy(h http.Handler, localConfig *rest.Config, cachedVirtualCli }) } -func rewritePrometheusMetrics(req *http.Request, data []byte, vClient client.Client) ([]byte, error) { +func rewritePrometheusMetrics(req *http.Request, data []byte) ([]byte, error) { metricsFamilies, err := MetricsDecode(data) if err != nil { return nil, err } - metricsFamilies, err = MetricsRewrite(req.Context(), metricsFamilies, vClient) + metricsFamilies, err = MetricsRewrite(req.Context(), metricsFamilies) if err != nil { return nil, err } @@ -122,7 +123,7 @@ func handleNodeRequest(localConfig *rest.Config, vClient client.Client, w http.R // now rewrite the metrics newData := data if IsKubeletMetrics(req.URL.Path) { - newData, err = rewritePrometheusMetrics(req, data, vClient) + newData, err = rewritePrometheusMetrics(req, data) if err != nil { return false, err } @@ -150,18 +151,22 @@ func rewriteStats(ctx context.Context, data []byte, vClient client.Client) ([]by newPods := []statsv1alpha1.PodStats{} for _, pod := range stats.Pods { // search if we can find the pod by name in the virtual cluster - podList := &corev1.PodList{} - err := vClient.List(ctx, podList, client.MatchingFields{constants.IndexByPhysicalName: pod.PodRef.Namespace + "/" + pod.PodRef.Name}) - if err != nil { - return nil, err + name := mappings.Pods().HostToVirtual(ctx, types.NamespacedName{Name: pod.PodRef.Name, Namespace: pod.PodRef.Namespace}, nil) + if name.Name == "" { + continue } - // skip the metric if the pod couldn't be found in the virtual cluster - if len(podList.Items) == 0 { - continue + // query the pod from the virtual cluster + vPod := &corev1.Pod{} + err := vClient.Get(ctx, name, vPod) + if err != nil { + if kerrors.IsNotFound(err) { + continue + } + + return nil, err } - vPod := podList.Items[0] pod.PodRef.Name = vPod.Name pod.PodRef.Namespace = vPod.Namespace pod.PodRef.UID = string(vPod.UID) @@ -169,11 +174,11 @@ func rewriteStats(ctx context.Context, data []byte, vClient client.Client) ([]by newVolumes := []statsv1alpha1.VolumeStats{} for _, volume := range pod.VolumeStats { if volume.PVCRef != nil { - vPVC := &corev1.PersistentVolumeClaim{} - err = clienthelper.GetByIndex(ctx, vClient, vPVC, constants.IndexByPhysicalName, volume.PVCRef.Namespace+"/"+volume.PVCRef.Name) - if err != nil { - return nil, err + vPVC := mappings.PersistentVolumeClaims().HostToVirtual(ctx, types.NamespacedName{Name: volume.PVCRef.Name, Namespace: volume.PVCRef.Namespace}, nil) + if vPVC.Name == "" { + continue } + volume.PVCRef.Name = vPVC.Name volume.PVCRef.Namespace = vPVC.Namespace } @@ -251,7 +256,7 @@ func MetricsEncode(metricsFamilies []*dto.MetricFamily, format expfmt.Format) ([ return buffer.Bytes(), nil } -func MetricsRewrite(ctx context.Context, metricsFamilies []*dto.MetricFamily, vClient client.Client) ([]*dto.MetricFamily, error) { +func MetricsRewrite(ctx context.Context, metricsFamilies []*dto.MetricFamily) ([]*dto.MetricFamily, error) { resultMetricsFamily := []*dto.MetricFamily{} // rewrite metrics @@ -260,7 +265,7 @@ func MetricsRewrite(ctx context.Context, metricsFamilies []*dto.MetricFamily, vC for _, m := range fam.Metric { var ( pod string - persistentvolumeclaim string + persistentColumeClaim string namespace string ) for _, l := range m.Label { @@ -269,12 +274,12 @@ func MetricsRewrite(ctx context.Context, metricsFamilies []*dto.MetricFamily, vC } else if l.GetName() == "namespace" { namespace = l.GetValue() } else if l.GetName() == "persistentvolumeclaim" { - persistentvolumeclaim = l.GetValue() + persistentColumeClaim = l.GetValue() } } // Add metrics that are pod and namespace independent - if persistentvolumeclaim == "" && pod == "" { + if persistentColumeClaim == "" && pod == "" { newMetrics = append(newMetrics, m) continue } @@ -282,37 +287,25 @@ func MetricsRewrite(ctx context.Context, metricsFamilies []*dto.MetricFamily, vC // rewrite pod if pod != "" { // search if we can find the pod by name in the virtual cluster - podList := &corev1.PodList{} - err := vClient.List(ctx, podList, client.MatchingFields{constants.IndexByPhysicalName: namespace + "/" + pod}) - if err != nil { - return nil, err - } - - // skip the metric if the pod couldn't be found in the virtual cluster - if len(podList.Items) == 0 { + name := mappings.Pods().HostToVirtual(ctx, types.NamespacedName{Name: pod, Namespace: namespace}, nil) + if name.Name == "" { continue } - pod = podList.Items[0].Name - namespace = podList.Items[0].Namespace + pod = name.Name + namespace = name.Namespace } // rewrite persistentvolumeclaim - if persistentvolumeclaim != "" { + if persistentColumeClaim != "" { // search if we can find the pvc by name in the virtual cluster - pvcList := &corev1.PersistentVolumeClaimList{} - err := vClient.List(ctx, pvcList, client.MatchingFields{constants.IndexByPhysicalName: namespace + "/" + persistentvolumeclaim}) - if err != nil { - return nil, err - } - - // skip the metric if the pvc couldn't be found in the virtual cluster - if len(pvcList.Items) == 0 { + pvcName := mappings.PersistentVolumeClaims().HostToVirtual(ctx, types.NamespacedName{Name: persistentColumeClaim, Namespace: namespace}, nil) + if pvcName.Name == "" { continue } - persistentvolumeclaim = pvcList.Items[0].Name - namespace = pvcList.Items[0].Namespace + persistentColumeClaim = pvcName.Name + namespace = pvcName.Namespace } // exchange label values @@ -324,7 +317,7 @@ func MetricsRewrite(ctx context.Context, metricsFamilies []*dto.MetricFamily, vC l.Value = &namespace } if l.GetName() == "persistentvolumeclaim" { - l.Value = &persistentvolumeclaim + l.Value = &persistentColumeClaim } } diff --git a/pkg/server/indicies.go b/pkg/server/indicies.go new file mode 100644 index 0000000000..de0084a2c5 --- /dev/null +++ b/pkg/server/indicies.go @@ -0,0 +1,38 @@ +package server + +import ( + "github.com/loft-sh/vcluster/pkg/config" + "github.com/loft-sh/vcluster/pkg/constants" + "github.com/loft-sh/vcluster/pkg/controllers/resources/nodes" + "github.com/loft-sh/vcluster/pkg/controllers/resources/nodes/nodeservice" + "github.com/loft-sh/vcluster/pkg/util/translate" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// RegisterIndices adds the server indices to the managers +func RegisterIndices(ctx *config.ControllerContext) error { + // index services by ip + if ctx.Config.Networking.Advanced.ProxyKubelets.ByIP { + err := ctx.LocalManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Service{}, constants.IndexByClusterIP, func(object client.Object) []string { + svc := object.(*corev1.Service) + if len(svc.Labels) == 0 || svc.Labels[nodeservice.ServiceClusterLabel] != translate.VClusterName { + return nil + } + + return []string{svc.Spec.ClusterIP} + }) + if err != nil { + return err + } + } + + err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Node{}, constants.IndexByHostName, func(rawObj client.Object) []string { + return []string{nodes.GetNodeHost(rawObj.GetName()), nodes.GetNodeHostLegacy(rawObj.GetName(), ctx.Config.WorkloadNamespace)} + }) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/server/server.go b/pkg/server/server.go index c25e35436d..baa640a8b4 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -15,9 +15,6 @@ import ( "github.com/loft-sh/vcluster/pkg/authorization/impersonationauthorizer" "github.com/loft-sh/vcluster/pkg/authorization/kubeletauthorizer" "github.com/loft-sh/vcluster/pkg/config" - "github.com/loft-sh/vcluster/pkg/constants" - "github.com/loft-sh/vcluster/pkg/controllers/resources/nodes" - "github.com/loft-sh/vcluster/pkg/controllers/resources/nodes/nodeservice" "github.com/loft-sh/vcluster/pkg/plugin" "github.com/loft-sh/vcluster/pkg/server/cert" "github.com/loft-sh/vcluster/pkg/server/filters" @@ -26,7 +23,6 @@ import ( "github.com/loft-sh/vcluster/pkg/util/blockingcacheclient" "github.com/loft-sh/vcluster/pkg/util/pluginhookclient" "github.com/loft-sh/vcluster/pkg/util/serverhelper" - "github.com/loft-sh/vcluster/pkg/util/translate" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -93,74 +89,25 @@ func NewServer(ctx *config.ControllerContext, requestHeaderCaFile, clientCaFile return nil, err } - cachedLocalClient, err := createCachedClient(ctx.Context, localConfig, ctx.Config.WorkloadNamespace, uncachedLocalClient.RESTMapper(), uncachedLocalClient.Scheme(), func(cache cache.Cache) error { - if ctx.Config.Networking.Advanced.ProxyKubelets.ByIP { - err := cache.IndexField(ctx.Context, &corev1.Service{}, constants.IndexByClusterIP, func(object client.Object) []string { - svc := object.(*corev1.Service) - if len(svc.Labels) == 0 || svc.Labels[nodeservice.ServiceClusterLabel] != translate.VClusterName { - return nil - } - - return []string{svc.Spec.ClusterIP} - }) - if err != nil { - return err - } - } - - return nil - }) - if err != nil { - return nil, err - } - cachedVirtualClient, err := createCachedClient(ctx.Context, virtualConfig, corev1.NamespaceAll, uncachedVirtualClient.RESTMapper(), uncachedVirtualClient.Scheme(), func(cache cache.Cache) error { - err := cache.IndexField(ctx.Context, &corev1.PersistentVolumeClaim{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.Default.PhysicalName(rawObj.GetName(), rawObj.GetNamespace())} - }) - if err != nil { - return err - } - - err = cache.IndexField(ctx.Context, &corev1.Node{}, constants.IndexByHostName, func(rawObj client.Object) []string { - return []string{nodes.GetNodeHost(rawObj.GetName()), nodes.GetNodeHostLegacy(rawObj.GetName(), ctx.Config.WorkloadNamespace)} - }) - if err != nil { - return err - } - - err = cache.IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.Default.PhysicalName(rawObj.GetName(), rawObj.GetNamespace())} - }) - if err != nil { - return err - } - return nil - }) - if err != nil { - return nil, err - } - // wrap clients uncachedVirtualClient = pluginhookclient.WrapVirtualClient(uncachedVirtualClient) - cachedVirtualClient = pluginhookclient.WrapVirtualClient(cachedVirtualClient) uncachedLocalClient = pluginhookclient.WrapPhysicalClient(uncachedLocalClient) - cachedLocalClient = pluginhookclient.WrapPhysicalClient(cachedLocalClient) - certSyncer, err := cert.NewSyncer(ctx.Context, ctx.Config.WorkloadNamespace, cachedLocalClient, ctx.Config) + certSyncer, err := cert.NewSyncer(ctx.Context, ctx.Config.WorkloadNamespace, ctx.LocalManager.GetClient(), ctx.Config) if err != nil { return nil, errors.Wrap(err, "create cert syncer") } s := &Server{ uncachedVirtualClient: uncachedVirtualClient, - cachedVirtualClient: cachedVirtualClient, + cachedVirtualClient: ctx.VirtualManager.GetClient(), certSyncer: certSyncer, handler: http.NewServeMux(), fakeKubeletIPs: ctx.Config.Networking.Advanced.ProxyKubelets.ByIP, currentNamespace: ctx.Config.WorkloadNamespace, - currentNamespaceClient: cachedLocalClient, + currentNamespaceClient: ctx.LocalManager.GetClient(), requestHeaderCaFile: requestHeaderCaFile, clientCaFile: clientCaFile, @@ -204,9 +151,9 @@ func NewServer(ctx *config.ControllerContext, requestHeaderCaFile, clientCaFile // pre hooks clients := config.Clients{ UncachedVirtualClient: uncachedVirtualClient, - CachedVirtualClient: cachedVirtualClient, + CachedVirtualClient: ctx.VirtualManager.GetClient(), UncachedHostClient: uncachedLocalClient, - CachedHostClient: cachedLocalClient, + CachedHostClient: ctx.LocalManager.GetClient(), HostConfig: localConfig, VirtualConfig: virtualConfig, } @@ -216,13 +163,13 @@ func NewServer(ctx *config.ControllerContext, requestHeaderCaFile, clientCaFile h = filters.WithServiceCreateRedirect(h, uncachedLocalClient, uncachedVirtualClient, virtualConfig, ctx.Config.Experimental.SyncSettings.SyncLabels) h = filters.WithRedirect(h, localConfig, uncachedLocalClient.Scheme(), uncachedVirtualClient, admissionHandler, s.redirectResources) - h = filters.WithMetricsProxy(h, localConfig, cachedVirtualClient) + h = filters.WithMetricsProxy(h, localConfig, ctx.VirtualManager.GetClient()) // inject apis if ctx.Config.Sync.FromHost.Nodes.Enabled && ctx.Config.Sync.FromHost.Nodes.SyncBackChanges { h = filters.WithNodeChanges(ctx.Context, h, uncachedLocalClient, uncachedVirtualClient, virtualConfig) } - h = filters.WithFakeKubelet(h, localConfig, cachedVirtualClient) + h = filters.WithFakeKubelet(h, localConfig, ctx.VirtualManager.GetClient()) h = filters.WithK3sConnect(h) if os.Getenv("DEBUG") == "true" { diff --git a/pkg/setup/controller_context.go b/pkg/setup/controller_context.go index 833e461975..6e40b936f0 100644 --- a/pkg/setup/controller_context.go +++ b/pkg/setup/controller_context.go @@ -8,13 +8,11 @@ import ( "github.com/loft-sh/vcluster/pkg/config" "github.com/loft-sh/vcluster/pkg/controllers/resources/nodes" - "github.com/loft-sh/vcluster/pkg/mappings/registermappings" "github.com/loft-sh/vcluster/pkg/plugin" "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/scheme" "github.com/loft-sh/vcluster/pkg/telemetry" "github.com/loft-sh/vcluster/pkg/util/blockingcacheclient" - util "github.com/loft-sh/vcluster/pkg/util/context" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" @@ -100,12 +98,6 @@ func NewControllerContext(ctx context.Context, options *config.VirtualClusterCon return nil, err } - // register resource mappings - err = registermappings.RegisterMappings(util.ToRegisterContext(controllerContext)) - if err != nil { - return nil, fmt.Errorf("register resource mappings: %w", err) - } - return controllerContext, nil } diff --git a/pkg/setup/controllers.go b/pkg/setup/controllers.go index 781384aecf..e7a7c6384d 100644 --- a/pkg/setup/controllers.go +++ b/pkg/setup/controllers.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func StartControllers(controllerContext *config.ControllerContext) error { +func StartControllers(controllerContext *config.ControllerContext, syncers []syncertypes.Object) error { // exchange control plane client controlPlaneClient, err := pro.ExchangeControlPlaneClient(controllerContext) if err != nil { @@ -37,7 +37,6 @@ func StartControllers(controllerContext *config.ControllerContext) error { } // start coredns & create syncers - var syncers []syncertypes.Object if !controllerContext.Config.Experimental.SyncSettings.DisableSync { // setup CoreDNS according to the manifest file // skip this if both integrated and dedicated coredns @@ -59,18 +58,6 @@ func StartControllers(controllerContext *config.ControllerContext) error { } } }() - - // init syncers - syncers, err = controllers.Create(controllerContext) - if err != nil { - return errors.Wrap(err, "instantiate controllers") - } - } - - // start managers - err = StartManagers(controllerContext, syncers) - if err != nil { - return err } // sync remote Endpoints @@ -205,44 +192,6 @@ func SyncKubernetesService(ctx *config.ControllerContext) error { return nil } -func StartManagers(controllerContext *config.ControllerContext, syncers []syncertypes.Object) error { - // execute controller initializers to setup prereqs, etc. - err := controllers.ExecuteInitializers(controllerContext, syncers) - if err != nil { - return errors.Wrap(err, "execute initializers") - } - - // register indices - err = controllers.RegisterIndices(controllerContext, syncers) - if err != nil { - return err - } - - // start the local manager - go func() { - err := controllerContext.LocalManager.Start(controllerContext.Context) - if err != nil { - panic(err) - } - }() - - // start the virtual cluster manager - go func() { - err := controllerContext.VirtualManager.Start(controllerContext.Context) - if err != nil { - panic(err) - } - }() - - // Wait for caches to be synced - klog.Infof("Starting local & virtual managers...") - controllerContext.LocalManager.GetCache().WaitForCacheSync(controllerContext.Context) - controllerContext.VirtualManager.GetCache().WaitForCacheSync(controllerContext.Context) - klog.Infof("Successfully started local & virtual manager") - - return nil -} - func WriteKubeConfigToSecret(ctx context.Context, currentNamespace string, currentNamespaceClient client.Client, options *config.VirtualClusterConfig, syncerConfig *clientcmdapi.Config) error { syncerConfig, err := CreateVClusterKubeConfig(syncerConfig, options) if err != nil { diff --git a/pkg/setup/managers.go b/pkg/setup/managers.go new file mode 100644 index 0000000000..206ab67dea --- /dev/null +++ b/pkg/setup/managers.go @@ -0,0 +1,69 @@ +package setup + +import ( + "fmt" + + "github.com/loft-sh/vcluster/pkg/config" + "github.com/loft-sh/vcluster/pkg/controllers" + "github.com/loft-sh/vcluster/pkg/mappings/registermappings" + "github.com/loft-sh/vcluster/pkg/server" + syncertypes "github.com/loft-sh/vcluster/pkg/types" + util "github.com/loft-sh/vcluster/pkg/util/context" + "k8s.io/klog/v2" +) + +func StartManagers(controllerContext *config.ControllerContext) ([]syncertypes.Object, error) { + // register resource mappings + err := registermappings.RegisterMappings(util.ToRegisterContext(controllerContext)) + if err != nil { + return nil, fmt.Errorf("register resource mappings: %w", err) + } + + // index fields for server + err = server.RegisterIndices(controllerContext) + if err != nil { + return nil, fmt.Errorf("register server indices: %w", err) + } + + // init syncers + syncers, err := controllers.CreateSyncers(controllerContext) + if err != nil { + return nil, fmt.Errorf("create syncers: %w", err) + } + + // execute controller initializers to setup prereqs, etc. + err = controllers.ExecuteInitializers(controllerContext, syncers) + if err != nil { + return nil, fmt.Errorf("execute initializers: %w", err) + } + + // register indices + err = controllers.RegisterIndices(controllerContext, syncers) + if err != nil { + return nil, fmt.Errorf("register indices: %w", err) + } + + // start the local manager + go func() { + err := controllerContext.LocalManager.Start(controllerContext.Context) + if err != nil { + panic(err) + } + }() + + // start the virtual cluster manager + go func() { + err := controllerContext.VirtualManager.Start(controllerContext.Context) + if err != nil { + panic(err) + } + }() + + // Wait for caches to be synced + klog.Infof("Starting local & virtual managers...") + controllerContext.LocalManager.GetCache().WaitForCacheSync(controllerContext.Context) + controllerContext.VirtualManager.GetCache().WaitForCacheSync(controllerContext.Context) + klog.Infof("Successfully started local & virtual manager") + + return syncers, nil +} diff --git a/pkg/setup/proxy.go b/pkg/setup/proxy.go index 1e7d0e6aa1..d0a73bbf9d 100644 --- a/pkg/setup/proxy.go +++ b/pkg/setup/proxy.go @@ -17,7 +17,11 @@ func StartProxy(ctx *config.ControllerContext) error { } // start the proxy - proxyServer, err := server.NewServer(ctx, ctx.Config.VirtualClusterKubeConfig().RequestHeaderCACert, ctx.Config.VirtualClusterKubeConfig().ClientCACert) + proxyServer, err := server.NewServer( + ctx, + ctx.Config.VirtualClusterKubeConfig().RequestHeaderCACert, + ctx.Config.VirtualClusterKubeConfig().ClientCACert, + ) if err != nil { return err }