From 2d1afe6a2a1956d563881cb660e3fbe7c3d5c444 Mon Sep 17 00:00:00 2001 From: Fabian Kramm Date: Thu, 11 Jul 2024 19:01:18 +0200 Subject: [PATCH 1/4] refactor: add method to connect to virtual etcd --- pkg/constants/constants.go | 7 ++ pkg/etcd/client.go | 197 +++++++++++++++++++++++++++++++++++++ pkg/etcd/util.go | 35 +------ pkg/k0s/k0s.go | 2 +- pkg/k3s/k3s.go | 2 +- pkg/k8s/k8s.go | 9 +- 6 files changed, 214 insertions(+), 38 deletions(-) create mode 100644 pkg/constants/constants.go create mode 100644 pkg/etcd/client.go diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go new file mode 100644 index 0000000000..6598737a45 --- /dev/null +++ b/pkg/constants/constants.go @@ -0,0 +1,7 @@ +package constants + +const ( + K8sKineEndpoint = "unix:///data/kine.sock" + K3sKineEndpoint = "unix:///data/server/kine.sock" + K0sKineEndpoint = "unix:///run/k0s/kine/kine.sock:2379" +) diff --git a/pkg/etcd/client.go b/pkg/etcd/client.go new file mode 100644 index 0000000000..fe865ababe --- /dev/null +++ b/pkg/etcd/client.go @@ -0,0 +1,197 @@ +package etcd + +import ( + "context" + "errors" + "fmt" + + vconfig "github.com/loft-sh/vcluster/config" + "github.com/loft-sh/vcluster/pkg/config" + "github.com/loft-sh/vcluster/pkg/constants" + clientv3 "go.etcd.io/etcd/client/v3" +) + +type Value struct { + Key []byte + Data []byte + Revision int64 +} + +var ( + ErrNotFound = errors.New("etcdwrapper: key not found") +) + +type Client interface { + List(ctx context.Context, key string, rev int) ([]Value, error) + Get(ctx context.Context, key string) (Value, error) + Put(ctx context.Context, key string, value []byte) error + Create(ctx context.Context, key string, value []byte) error + Update(ctx context.Context, key string, revision int64, value []byte) error + Delete(ctx context.Context, key string, revision int64) error + Compact(ctx context.Context, revision int64) (int64, error) + Close() error +} + +type client struct { + c *clientv3.Client +} + +func NewFromConfig(ctx context.Context, vConfig *config.VirtualClusterConfig) (Client, error) { + // start kine embedded or external + var ( + etcdEndpoints string + etcdCertificates *Certificates + ) + + // handle different backing store's + if vConfig.ControlPlane.BackingStore.Etcd.Deploy.Enabled || vConfig.ControlPlane.BackingStore.Etcd.Embedded.Enabled { + // embedded or deployed etcd + etcdCertificates = &Certificates{ + CaCert: "/data/pki/etcd/ca.crt", + ServerCert: "/data/pki/apiserver-etcd-client.crt", + ServerKey: "/data/pki/apiserver-etcd-client.key", + } + + if vConfig.ControlPlane.BackingStore.Etcd.Embedded.Enabled { + etcdEndpoints = "https://127.0.0.1:2379" + } else { + etcdEndpoints = "https://" + vConfig.Name + "-etcd:2379" + } + } else if vConfig.Distro() == vconfig.K8SDistro || vConfig.Distro() == vconfig.EKSDistro { + etcdEndpoints = constants.K8sKineEndpoint + } else if vConfig.Distro() == vconfig.K3SDistro { + etcdEndpoints = constants.K3sKineEndpoint + } else if vConfig.Distro() == vconfig.K0SDistro { + if (vConfig.ControlPlane.BackingStore.Database.Embedded.Enabled && vConfig.ControlPlane.BackingStore.Database.Embedded.DataSource != "") || + vConfig.ControlPlane.BackingStore.Database.External.Enabled { + etcdEndpoints = constants.K0sKineEndpoint + } else { + etcdEndpoints = "https://127.0.0.1:2379" + etcdCertificates = &Certificates{ + CaCert: "/data/k0s/pki/etcd/ca.crt", + ServerCert: "/data/k0s/pki/apiserver-etcd-client.crt", + ServerKey: "/data/k0s/pki/apiserver-etcd-client.key", + } + } + } + + return New(ctx, etcdCertificates, etcdEndpoints) +} + +func New(ctx context.Context, certificates *Certificates, endpoints ...string) (Client, error) { + err := WaitForEtcd(ctx, certificates, endpoints...) + if err != nil { + return nil, err + } + + etcdClient, err := GetEtcdClient(ctx, certificates, endpoints...) + if err != nil { + return nil, err + } + + return &client{ + c: etcdClient, + }, nil +} + +func (c *client) List(ctx context.Context, key string, rev int) ([]Value, error) { + resp, err := c.c.Get(ctx, key, clientv3.WithPrefix(), clientv3.WithRev(int64(rev))) + if err != nil { + return nil, err + } + + var vals []Value + for _, kv := range resp.Kvs { + vals = append(vals, Value{ + Key: kv.Key, + Data: kv.Value, + Revision: kv.ModRevision, + }) + } + + return vals, nil +} + +func (c *client) Get(ctx context.Context, key string) (Value, error) { + resp, err := c.c.Get(ctx, key) + if err != nil { + return Value{}, err + } + + if len(resp.Kvs) == 1 { + return Value{ + Key: resp.Kvs[0].Key, + Data: resp.Kvs[0].Value, + Revision: resp.Kvs[0].ModRevision, + }, nil + } + + return Value{}, ErrNotFound +} + +func (c *client) Put(ctx context.Context, key string, value []byte) error { + val, err := c.Get(ctx, key) + if err != nil { + return err + } + if val.Revision == 0 { + return c.Create(ctx, key, value) + } + return c.Update(ctx, key, val.Revision, value) +} + +func (c *client) Create(ctx context.Context, key string, value []byte) error { + resp, err := c.c.Txn(ctx). + If(clientv3.Compare(clientv3.ModRevision(key), "=", 0)). + Then(clientv3.OpPut(key, string(value))). + Commit() + if err != nil { + return err + } + if !resp.Succeeded { + return fmt.Errorf("key exists") + } + return nil +} + +func (c *client) Update(ctx context.Context, key string, revision int64, value []byte) error { + resp, err := c.c.Txn(ctx). + If(clientv3.Compare(clientv3.ModRevision(key), "=", revision)). + Then(clientv3.OpPut(key, string(value))). + Else(clientv3.OpGet(key)). + Commit() + if err != nil { + return err + } + if !resp.Succeeded { + return fmt.Errorf("revision %d doesnt match", revision) + } + return nil +} + +func (c *client) Delete(ctx context.Context, key string, revision int64) error { + resp, err := c.c.Txn(ctx). + If(clientv3.Compare(clientv3.ModRevision(key), "=", revision)). + Then(clientv3.OpDelete(key)). + Else(clientv3.OpGet(key)). + Commit() + if err != nil { + return err + } + if !resp.Succeeded { + return fmt.Errorf("revision %d doesnt match", revision) + } + return nil +} + +func (c *client) Compact(ctx context.Context, revision int64) (int64, error) { + resp, err := c.c.Compact(ctx, revision) + if resp != nil { + return resp.Header.GetRevision(), err + } + return 0, err +} + +func (c *client) Close() error { + return c.c.Close() +} diff --git a/pkg/etcd/util.go b/pkg/etcd/util.go index cb09904194..6a6187f8c8 100644 --- a/pkg/etcd/util.go +++ b/pkg/etcd/util.go @@ -24,37 +24,10 @@ type Certificates struct { ServerKey string } -func EndpointsAndCertificatesFromFlags(flags []string) ([]string, *Certificates, error) { - certificates := &Certificates{} - endpoints := []string{} - - // parse flags - for _, arg := range flags { - if strings.HasPrefix(arg, "--etcd-servers=") { - endpoints = strings.Split(strings.TrimPrefix(arg, "--etcd-servers="), ",") - } else if strings.HasPrefix(arg, "--etcd-cafile=") { - certificates.CaCert = strings.TrimPrefix(arg, "--etcd-cafile=") - } else if strings.HasPrefix(arg, "--etcd-certfile=") { - certificates.ServerCert = strings.TrimPrefix(arg, "--etcd-certfile=") - } else if strings.HasPrefix(arg, "--etcd-keyfile=") { - certificates.ServerKey = strings.TrimPrefix(arg, "--etcd-keyfile=") - } - } - - // fail if etcd servers is not found - if len(endpoints) == 0 { - return nil, nil, fmt.Errorf("couldn't find flag --etcd-servers within api-server flags") - } else if certificates.CaCert == "" || certificates.ServerCert == "" || certificates.ServerKey == "" { - return endpoints, nil, nil - } - return endpoints, certificates, nil -} - -func WaitForEtcdClient(parentCtx context.Context, certificates *Certificates, endpoints ...string) (*clientv3.Client, error) { - var etcdClient *clientv3.Client +func WaitForEtcd(parentCtx context.Context, certificates *Certificates, endpoints ...string) error { var err error waitErr := wait.PollUntilContextTimeout(parentCtx, time.Second, waitForClientTimeout, true, func(ctx context.Context) (bool, error) { - etcdClient, err = GetEtcdClient(parentCtx, certificates, endpoints...) + etcdClient, err := GetEtcdClient(parentCtx, certificates, endpoints...) if err == nil { defer func() { _ = etcdClient.Close() @@ -70,10 +43,10 @@ func WaitForEtcdClient(parentCtx context.Context, certificates *Certificates, en return false, nil }) if waitErr != nil { - return nil, fmt.Errorf("error waiting for etcdclient: %w", err) + return fmt.Errorf("error waiting for etcd: %w", err) } - return etcdClient, nil + return nil } // GetEtcdClient returns an etcd client connected to the specified endpoints. diff --git a/pkg/k0s/k0s.go b/pkg/k0s/k0s.go index d0f4a3284e..1fb755402b 100644 --- a/pkg/k0s/k0s.go +++ b/pkg/k0s/k0s.go @@ -96,7 +96,7 @@ func StartK0S(ctx context.Context, cancel context.CancelFunc, vConfig *config.Vi // wait until etcd is up and running if vConfig.ControlPlane.BackingStore.Etcd.Deploy.Enabled { - _, err := etcd.WaitForEtcdClient(ctx, &etcd.Certificates{ + err := etcd.WaitForEtcd(ctx, &etcd.Certificates{ CaCert: "/data/k0s/pki/etcd/ca.crt", ServerCert: "/data/k0s/pki/apiserver-etcd-client.crt", ServerKey: "/data/k0s/pki/apiserver-etcd-client.key", diff --git a/pkg/k3s/k3s.go b/pkg/k3s/k3s.go index 97d3c95e37..d0062a9338 100644 --- a/pkg/k3s/k3s.go +++ b/pkg/k3s/k3s.go @@ -52,7 +52,7 @@ func StartK3S(ctx context.Context, vConfig *config.VirtualClusterConfig, service } if vConfig.ControlPlane.BackingStore.Etcd.Deploy.Enabled { // wait until etcd is up and running - _, err := etcd.WaitForEtcdClient(ctx, &etcd.Certificates{ + err := etcd.WaitForEtcd(ctx, &etcd.Certificates{ CaCert: "/data/pki/etcd/ca.crt", ServerCert: "/data/pki/apiserver-etcd-client.crt", ServerKey: "/data/pki/apiserver-etcd-client.key", diff --git a/pkg/k8s/k8s.go b/pkg/k8s/k8s.go index 0349508f0d..dd5aea7df5 100644 --- a/pkg/k8s/k8s.go +++ b/pkg/k8s/k8s.go @@ -12,6 +12,7 @@ import ( vclusterconfig "github.com/loft-sh/vcluster/config" "github.com/loft-sh/vcluster/pkg/config" + "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/etcd" "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/util/commandwriter" @@ -19,8 +20,6 @@ import ( "k8s.io/klog/v2" ) -const KineEndpoint = "unix:///data/kine.sock" - func StartK8S( ctx context.Context, serviceCIDR string, @@ -51,7 +50,7 @@ func StartK8S( args = append(args, "--key-file="+vConfig.ControlPlane.BackingStore.Database.External.KeyFile) args = append(args, "--cert-file="+vConfig.ControlPlane.BackingStore.Database.External.CertFile) args = append(args, "--metrics-bind-address=0") - args = append(args, "--listen-address="+KineEndpoint) + args = append(args, "--listen-address="+constants.K8sKineEndpoint) // now start kine err := RunCommand(ctx, args, "kine") @@ -60,7 +59,7 @@ func StartK8S( } }() - etcdEndpoints = KineEndpoint + etcdEndpoints = constants.K8sKineEndpoint } else if vConfig.ControlPlane.BackingStore.Database.External.Enabled { // call out to the pro code var err error @@ -126,7 +125,7 @@ func StartK8S( args = append(args, apiServer.ExtraArgs...) // wait until etcd is up and running - _, err := etcd.WaitForEtcdClient(ctx, etcdCertificates, etcdEndpoints) + err := etcd.WaitForEtcd(ctx, etcdCertificates, etcdEndpoints) if err != nil { return err } From a05c4d716c0a7374917597449bf60d0a92604c8e Mon Sep 17 00:00:00 2001 From: Fabian Kramm Date: Fri, 12 Jul 2024 09:12:45 +0200 Subject: [PATCH 2/4] refactor: separate mappings --- cmd/vcluster/cmd/start.go | 7 +- pkg/constants/indices.go | 1 - .../resources/configmaps/syncer.go | 37 ----- .../resources/configmaps/translate.go | 3 +- .../resources/csistoragecapacities/syncer.go | 5 +- .../csistoragecapacities/translate.go | 14 +- .../csistoragecapacities/translator.go | 41 +---- pkg/controllers/resources/endpoints/syncer.go | 5 +- .../resources/endpoints/syncer_test.go | 5 +- .../resources/endpoints/translate.go | 12 +- pkg/controllers/resources/events/syncer.go | 121 +------------- .../resources/events/syncer_test.go | 7 +- .../resources/ingressclasses/syncer.go | 2 +- pkg/controllers/resources/ingresses/syncer.go | 6 +- .../resources/ingresses/translate.go | 9 +- .../resources/namespaces/syncer.go | 16 +- pkg/controllers/resources/nodes/syncer.go | 12 +- .../resources/nodes/syncer_test.go | 5 +- pkg/controllers/resources/nodes/translate.go | 2 +- .../persistentvolumeclaims/syncer.go | 15 +- .../persistentvolumeclaims/translate.go | 18 ++- .../resources/persistentvolumes/syncer.go | 75 ++------- .../resources/persistentvolumes/translate.go | 26 +-- pkg/controllers/resources/pods/syncer.go | 6 - pkg/controllers/resources/pods/translate.go | 7 +- .../pods/translate/sa_token_secret.go | 5 +- .../resources/pods/translate/translator.go | 65 ++++---- .../resources/priorityclasses/syncer.go | 23 +-- pkg/controllers/resources/secrets/syncer.go | 8 +- .../resources/storageclasses/syncer.go | 23 +-- .../volumesnapshotcontents/syncer.go | 73 ++------- .../volumesnapshotcontents/syncer_test.go | 9 +- .../volumesnapshotcontents/translate.go | 7 +- .../volumesnapshots/volumesnapshots/syncer.go | 7 +- .../volumesnapshots/translate.go | 7 +- pkg/controllers/syncer/syncer.go | 35 ++-- .../syncer/translator/cluster_translator.go | 57 +++---- .../translator/mirror_name_translator.go | 9 -- .../translator/namespaced_translator.go | 79 ++------- .../syncer/translator/translator.go | 16 +- .../metricsserver/metricsserver.go | 22 +-- pkg/mappings/generic/cluster.go | 77 +++++++++ pkg/mappings/generic/mirror.go | 45 ++++++ pkg/mappings/generic/namespaced.go | 78 +++++++++ pkg/mappings/mappings.go | 110 +++++++++++++ pkg/mappings/registermappings/register.go | 53 ++++++ pkg/mappings/resources/configmaps.go | 64 ++++++++ pkg/mappings/resources/csidrivers.go | 17 ++ pkg/mappings/resources/csinodes.go | 17 ++ .../resources/csistoragecapacities.go | 66 ++++++++ pkg/mappings/resources/endpoints.go | 18 +++ pkg/mappings/resources/events.go | 151 ++++++++++++++++++ pkg/mappings/resources/generic.go | 35 ++++ pkg/mappings/resources/ingressclasses.go | 17 ++ pkg/mappings/resources/ingresses.go | 18 +++ pkg/mappings/resources/ingresses_legacy.go | 18 +++ pkg/mappings/resources/namespaces.go | 21 +++ pkg/mappings/resources/networkpolicies.go | 18 +++ pkg/mappings/resources/nodes.go | 17 ++ .../resources/persistentvolumeclaims.go | 18 +++ pkg/mappings/resources/persistentvolumes.go | 76 +++++++++ .../resources/poddisruptionbudgets.go | 18 +++ pkg/mappings/resources/pods.go | 18 +++ pkg/mappings/resources/priorityclasses.go | 30 ++++ pkg/mappings/resources/secrets.go | 18 +++ pkg/mappings/resources/serviceaccounts.go | 18 +++ pkg/mappings/resources/services.go | 18 +++ pkg/mappings/resources/storageclasses.go | 29 ++++ .../resources/volumesnapshotclasses.go | 17 ++ .../resources/volumesnapshotcontents.go | 85 ++++++++++ pkg/mappings/resources/volumesnapshots.go | 26 +++ pkg/mappings/store.go | 54 +++++++ pkg/server/filters/redirect.go | 7 +- pkg/server/filters/service.go | 6 +- pkg/setup/controller_context.go | 8 + pkg/types/types.go | 2 +- pkg/util/translate/multi_namespace.go | 15 +- pkg/util/translate/single_namespace.go | 35 ++-- pkg/util/translate/types.go | 12 +- 79 files changed, 1560 insertions(+), 692 deletions(-) create mode 100644 pkg/mappings/generic/cluster.go create mode 100644 pkg/mappings/generic/mirror.go create mode 100644 pkg/mappings/generic/namespaced.go create mode 100644 pkg/mappings/mappings.go create mode 100644 pkg/mappings/registermappings/register.go create mode 100644 pkg/mappings/resources/configmaps.go create mode 100644 pkg/mappings/resources/csidrivers.go create mode 100644 pkg/mappings/resources/csinodes.go create mode 100644 pkg/mappings/resources/csistoragecapacities.go create mode 100644 pkg/mappings/resources/endpoints.go create mode 100644 pkg/mappings/resources/events.go create mode 100644 pkg/mappings/resources/generic.go create mode 100644 pkg/mappings/resources/ingressclasses.go create mode 100644 pkg/mappings/resources/ingresses.go create mode 100644 pkg/mappings/resources/ingresses_legacy.go create mode 100644 pkg/mappings/resources/namespaces.go create mode 100644 pkg/mappings/resources/networkpolicies.go create mode 100644 pkg/mappings/resources/nodes.go create mode 100644 pkg/mappings/resources/persistentvolumeclaims.go create mode 100644 pkg/mappings/resources/persistentvolumes.go create mode 100644 pkg/mappings/resources/poddisruptionbudgets.go create mode 100644 pkg/mappings/resources/pods.go create mode 100644 pkg/mappings/resources/priorityclasses.go create mode 100644 pkg/mappings/resources/secrets.go create mode 100644 pkg/mappings/resources/serviceaccounts.go create mode 100644 pkg/mappings/resources/services.go create mode 100644 pkg/mappings/resources/storageclasses.go create mode 100644 pkg/mappings/resources/volumesnapshotclasses.go create mode 100644 pkg/mappings/resources/volumesnapshotcontents.go create mode 100644 pkg/mappings/resources/volumesnapshots.go create mode 100644 pkg/mappings/store.go diff --git a/cmd/vcluster/cmd/start.go b/cmd/vcluster/cmd/start.go index 2ea33b1da3..636a871c7e 100644 --- a/cmd/vcluster/cmd/start.go +++ b/cmd/vcluster/cmd/start.go @@ -126,11 +126,8 @@ func ExecuteStart(ctx context.Context, options *StartOptions) error { } } - if err := pro.ConnectToPlatform( - ctx, - vConfig, - controllerCtx.VirtualManager, - ); err != nil { + // connect to vCluster platform if configured + if err := pro.ConnectToPlatform(ctx, vConfig, controllerCtx.VirtualManager); err != nil { return fmt.Errorf("connect to platform: %w", err) } diff --git a/pkg/constants/indices.go b/pkg/constants/indices.go index 6ba9f39b9e..d43ac9c3fe 100644 --- a/pkg/constants/indices.go +++ b/pkg/constants/indices.go @@ -6,7 +6,6 @@ const ( IndexByPhysicalName = "IndexByPhysicalName" IndexByVirtualName = "IndexByVirtualName" IndexByAssigned = "IndexByAssigned" - IndexByStorageClass = "IndexByStorageClass" IndexByIngressSecret = "IndexByIngressSecret" IndexByPodSecret = "IndexByPodSecret" IndexByConfigMap = "IndexByConfigMap" diff --git a/pkg/controllers/resources/configmaps/syncer.go b/pkg/controllers/resources/configmaps/syncer.go index 58c23238b6..f2f7e0b660 100644 --- a/pkg/controllers/resources/configmaps/syncer.go +++ b/pkg/controllers/resources/configmaps/syncer.go @@ -9,7 +9,6 @@ import ( synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" syncer "github.com/loft-sh/vcluster/pkg/types" - "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" @@ -39,43 +38,7 @@ type configMapSyncer struct { var _ syncer.IndicesRegisterer = &configMapSyncer{} -func (s *configMapSyncer) VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { - if s.multiNamespaceMode && req.Name == "kube-root-ca.crt" { - return types.NamespacedName{ - Name: translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName), - Namespace: s.NamespacedTranslator.VirtualToHost(ctx, req, vObj).Namespace, - } - } - - return s.NamespacedTranslator.VirtualToHost(ctx, req, vObj) -} - -func (s *configMapSyncer) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { - if s.multiNamespaceMode && req.Name == translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName) { - return types.NamespacedName{ - Name: "kube-root-ca.crt", - Namespace: s.NamespacedTranslator.HostToVirtual(ctx, req, pObj).Namespace, - } - } else if s.multiNamespaceMode && req.Name == "kube-root-ca.crt" { - // ignore kube-root-ca.crt from host - return types.NamespacedName{} - } - - return s.NamespacedTranslator.HostToVirtual(ctx, req, pObj) -} - func (s *configMapSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.ConfigMap{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - if s.multiNamespaceMode && 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 err - } - // index pods by their used config maps return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByConfigMap, func(rawObj client.Object) []string { pod := rawObj.(*corev1.Pod) diff --git a/pkg/controllers/resources/configmaps/translate.go b/pkg/controllers/resources/configmaps/translate.go index 7133d86657..1f7104e54e 100644 --- a/pkg/controllers/resources/configmaps/translate.go +++ b/pkg/controllers/resources/configmaps/translate.go @@ -4,6 +4,7 @@ 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" @@ -12,7 +13,7 @@ import ( func (s *configMapSyncer) translate(ctx context.Context, vObj client.Object) *corev1.ConfigMap { pObj := s.TranslateMetadata(ctx, vObj).(*corev1.ConfigMap) - pObj.SetName(s.VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj).Name) + pObj.SetName(mappings.ConfigMaps().VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj).Name) return pObj } diff --git a/pkg/controllers/resources/csistoragecapacities/syncer.go b/pkg/controllers/resources/csistoragecapacities/syncer.go index 9620f13671..6cc3c59b31 100644 --- a/pkg/controllers/resources/csistoragecapacities/syncer.go +++ b/pkg/controllers/resources/csistoragecapacities/syncer.go @@ -5,6 +5,8 @@ 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" storagev1 "k8s.io/api/storage/v1" @@ -97,6 +99,7 @@ func (s *csistoragecapacitySyncer) ModifyController(ctx *synccontext.RegisterCon if err != nil { return nil, fmt.Errorf("failed to add allNSCache to physical manager: %w", err) } + return builder.WatchesRawSource(source.Kind(allNSCache, s.Resource(), &handler.Funcs{ CreateFunc: func(_ context.Context, ce event.CreateEvent, rli workqueue.RateLimitingInterface) { obj := ce.Object @@ -122,7 +125,7 @@ func (s *csistoragecapacitySyncer) enqueuePhysical(ctx context.Context, obj clie return } - name := s.HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) + name := mappings.Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("CSIStorageCapacity")).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 e6ed1d4eb0..c6721c8b6f 100644 --- a/pkg/controllers/resources/csistoragecapacities/translate.go +++ b/pkg/controllers/resources/csistoragecapacities/translate.go @@ -3,28 +3,30 @@ package csistoragecapacities import ( "fmt" - "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" "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" - kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) // returns virtual scname, shouldSync func (s *csistoragecapacitySyncer) fetchVirtualStorageClass(ctx *synccontext.SyncContext, physName string) (string, bool, error) { if s.storageClassSyncEnabled { - sc := &storagev1.StorageClass{} // the csistorage capacity being synced to the virtual cluster needs the name of the virtual storage cluster - err := clienthelper.GetByIndex(ctx.Context, ctx.VirtualClient, sc, constants.IndexByPhysicalName, physName) - if kerrors.IsNotFound(err) { + vName := mappings.StorageClasses().HostToVirtual(ctx.Context, types.NamespacedName{Name: physName}, nil) + if vName.Name == "" { return "", true, nil } - return sc.Name, false, nil + + return vName.Name, false, nil } + return physName, false, nil } diff --git a/pkg/controllers/resources/csistoragecapacities/translator.go b/pkg/controllers/resources/csistoragecapacities/translator.go index 8ab343cdfb..e9f1d0d387 100644 --- a/pkg/controllers/resources/csistoragecapacities/translator.go +++ b/pkg/controllers/resources/csistoragecapacities/translator.go @@ -4,10 +4,8 @@ import ( "context" "fmt" - "github.com/loft-sh/vcluster/pkg/constants" - synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "github.com/loft-sh/vcluster/pkg/mappings" syncer "github.com/loft-sh/vcluster/pkg/types" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/translate" storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/equality" @@ -29,44 +27,9 @@ func (s *csistoragecapacitySyncer) IsManaged(context.Context, client.Object) (bo return true, nil } -func (s *csistoragecapacitySyncer) RegisterIndices(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} - }) -} - -// translate namespace -func (s *csistoragecapacitySyncer) HostToVirtual(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { - return types.NamespacedName{Name: translate.SafeConcatName(req.Name, "x", req.Namespace), Namespace: "kube-system"} -} -func (s *csistoragecapacitySyncer) VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { - // if the virtual object is annotated with the physical name and namespace, return that - if vObj != nil { - vAnnotations := vObj.GetAnnotations() - if vAnnotations != nil && vAnnotations[translate.NameAnnotation] != "" { - return types.NamespacedName{ - Namespace: vAnnotations[translate.NamespaceAnnotation], - Name: vAnnotations[translate.NameAnnotation], - } - } - } - - sc := &storagev1.CSIStorageCapacity{} - pObj := sc.DeepCopyObject().(client.Object) - err := clienthelper.GetByIndex(ctx, s.physicalClient, pObj, constants.IndexByVirtualName, req.Name) - if err != nil { - return types.NamespacedName{} - } - - return types.NamespacedName{ - Namespace: pObj.GetNamespace(), - Name: pObj.GetName(), - } -} - // TranslateMetadata translates the object's metadata func (s *csistoragecapacitySyncer) TranslateMetadata(ctx context.Context, pObj client.Object) (client.Object, error) { - name := s.HostToVirtual(ctx, types.NamespacedName{Name: pObj.GetName(), Namespace: pObj.GetNamespace()}, pObj) + name := mappings.CSIStorageCapacities().HostToVirtual(ctx, types.NamespacedName{Name: pObj.GetName(), Namespace: pObj.GetNamespace()}, pObj) pObjCopy := pObj.DeepCopyObject() vObj, ok := pObjCopy.(client.Object) if !ok { diff --git a/pkg/controllers/resources/endpoints/syncer.go b/pkg/controllers/resources/endpoints/syncer.go index c3c7ded7c9..a55f95c14e 100644 --- a/pkg/controllers/resources/endpoints/syncer.go +++ b/pkg/controllers/resources/endpoints/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" "github.com/loft-sh/vcluster/pkg/specialservices" syncer "github.com/loft-sh/vcluster/pkg/types" @@ -74,7 +75,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, s.NamespacedTranslator.VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) + err := ctx.PhysicalClient.Get(ctx.Context, mappings.Endpoints().VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) if err != nil { if !kerrors.IsNotFound(err) { klog.Infof("Error retrieving endpoints: %v", err) @@ -103,7 +104,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, s.NamespacedTranslator.VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) + err = ctx.PhysicalClient.Get(ctx.Context, mappings.Endpoints().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/syncer_test.go b/pkg/controllers/resources/endpoints/syncer_test.go index 7576f07eb0..2c01273a6f 100644 --- a/pkg/controllers/resources/endpoints/syncer_test.go +++ b/pkg/controllers/resources/endpoints/syncer_test.go @@ -110,9 +110,10 @@ func TestExistingEndpoints(t *testing.T) { }, Sync: func(ctx *synccontext.RegisterContext) { _, fakeSyncer := newFakeSyncer(t, ctx) - syncController := syncer.NewSyncController(ctx, fakeSyncer) + syncController, err := syncer.NewSyncController(ctx, fakeSyncer) + assert.NilError(t, err) - _, err := syncController.Reconcile(ctx.Context, ctrl.Request{NamespacedName: types.NamespacedName{ + _, err = syncController.Reconcile(ctx.Context, ctrl.Request{NamespacedName: types.NamespacedName{ Namespace: vEndpoints.Namespace, Name: vEndpoints.Name, }}) diff --git a/pkg/controllers/resources/endpoints/translate.go b/pkg/controllers/resources/endpoints/translate.go index d963917710..dd5338f8aa 100644 --- a/pkg/controllers/resources/endpoints/translate.go +++ b/pkg/controllers/resources/endpoints/translate.go @@ -3,6 +3,8 @@ 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" @@ -27,8 +29,9 @@ func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) { for i, subset := range endpoints.Subsets { for j, addr := range subset.Addresses { if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" { - endpoints.Subsets[i].Addresses[j].TargetRef.Name = translate.Default.PhysicalName(addr.TargetRef.Name, addr.TargetRef.Namespace) - endpoints.Subsets[i].Addresses[j].TargetRef.Namespace = translate.Default.PhysicalNamespace(endpoints.Namespace) + nameNamespace := mappings.VirtualToHost(addr.TargetRef.Name, addr.TargetRef.Namespace, mappings.Pods()) + endpoints.Subsets[i].Addresses[j].TargetRef.Name = nameNamespace.Name + endpoints.Subsets[i].Addresses[j].TargetRef.Namespace = nameNamespace.Namespace // TODO: set the actual values here endpoints.Subsets[i].Addresses[j].TargetRef.UID = "" @@ -37,8 +40,9 @@ func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) { } for j, addr := range subset.NotReadyAddresses { if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" { - endpoints.Subsets[i].NotReadyAddresses[j].TargetRef.Name = translate.Default.PhysicalName(addr.TargetRef.Name, addr.TargetRef.Namespace) - endpoints.Subsets[i].NotReadyAddresses[j].TargetRef.Namespace = translate.Default.PhysicalNamespace(endpoints.Namespace) + nameNamespace := mappings.VirtualToHost(addr.TargetRef.Name, addr.TargetRef.Namespace, mappings.Pods()) + endpoints.Subsets[i].NotReadyAddresses[j].TargetRef.Name = nameNamespace.Name + endpoints.Subsets[i].NotReadyAddresses[j].TargetRef.Namespace = nameNamespace.Namespace // TODO: set the actual values here endpoints.Subsets[i].NotReadyAddresses[j].TargetRef.UID = "" diff --git a/pkg/controllers/resources/events/syncer.go b/pkg/controllers/resources/events/syncer.go index 708f130273..ff8478a3a6 100644 --- a/pkg/controllers/resources/events/syncer.go +++ b/pkg/controllers/resources/events/syncer.go @@ -2,36 +2,22 @@ package events import ( "context" - "errors" - "fmt" "strings" - "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" + "github.com/loft-sh/vcluster/pkg/mappings/resources" syncer "github.com/loft-sh/vcluster/pkg/types" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" kerrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - "k8s.io/klog/v2" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) -var AcceptedKinds = map[schema.GroupVersionKind]bool{ - corev1.SchemeGroupVersion.WithKind("Pod"): true, - corev1.SchemeGroupVersion.WithKind("Service"): true, - corev1.SchemeGroupVersion.WithKind("Endpoint"): true, - corev1.SchemeGroupVersion.WithKind("Secret"): true, - corev1.SchemeGroupVersion.WithKind("ConfigMap"): true, -} - func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &eventSyncer{ virtualClient: ctx.VirtualManager.GetClient(), @@ -53,32 +39,7 @@ func (s *eventSyncer) Name() string { } func (s *eventSyncer) IsManaged(ctx context.Context, pObj client.Object) (bool, error) { - return s.HostToVirtual(ctx, types.NamespacedName{Namespace: pObj.GetNamespace(), Name: pObj.GetName()}, pObj).Name != "", nil -} - -func (s *eventSyncer) 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{} -} - -func (s *eventSyncer) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { - involvedObject, err := s.getInvolvedObject(ctx, pObj) - if err != nil { - if err := IgnoreAcceptableErrors(err); err != nil { - klog.Infof("Error retrieving involved object for %s/%s: %v", req.Namespace, req.Name, err) - } - return types.NamespacedName{} - } - - pEvent, ok := pObj.(*corev1.Event) - if !ok { - return types.NamespacedName{} - } - - return types.NamespacedName{ - Namespace: involvedObject.GetNamespace(), - Name: hostEventNameToVirtual(pEvent.GetName(), pEvent.InvolvedObject.Name, involvedObject.GetName()), - } + return mappings.Events().HostToVirtual(ctx, types.NamespacedName{Namespace: pObj.GetNamespace(), Name: pObj.GetName()}, pObj).Name != "", nil } var _ syncer.Syncer = &eventSyncer{} @@ -97,7 +58,7 @@ func (s *eventSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vOb vOldEvent := vEvent.DeepCopy() vEvent, err := s.buildVirtualEvent(ctx.Context, pEvent) if err != nil { - return ctrl.Result{}, IgnoreAcceptableErrors(err) + return ctrl.Result{}, resources.IgnoreAcceptableErrors(err) } // reset metadata @@ -126,7 +87,7 @@ func (s *eventSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Ob // build the virtual event vObj, err := s.buildVirtualEvent(ctx.Context, pObj.(*corev1.Event)) if err != nil { - return ctrl.Result{}, IgnoreAcceptableErrors(err) + return ctrl.Result{}, resources.IgnoreAcceptableErrors(err) } // make sure namespace is not being deleted @@ -155,7 +116,7 @@ func (s *eventSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Ob func (s *eventSyncer) buildVirtualEvent(ctx context.Context, pEvent *corev1.Event) (*corev1.Event, error) { // retrieve involved object - involvedObject, err := s.getInvolvedObject(ctx, pEvent) + involvedObject, err := resources.GetInvolvedObject(ctx, s.virtualClient, pEvent) if err != nil { return nil, err } @@ -172,78 +133,10 @@ func (s *eventSyncer) buildVirtualEvent(ctx context.Context, pEvent *corev1.Even vObj.InvolvedObject.ResourceVersion = involvedObject.GetResourceVersion() // rewrite name - vObj.Name = hostEventNameToVirtual(vObj.Name, pEvent.InvolvedObject.Name, vObj.InvolvedObject.Name) + vObj.Name = resources.HostEventNameToVirtual(vObj.Name, pEvent.InvolvedObject.Name, vObj.InvolvedObject.Name) // we replace namespace/name & name in messages so that it seems correct vObj.Message = strings.ReplaceAll(vObj.Message, pEvent.InvolvedObject.Namespace+"/"+pEvent.InvolvedObject.Name, vObj.InvolvedObject.Namespace+"/"+vObj.InvolvedObject.Name) vObj.Message = strings.ReplaceAll(vObj.Message, pEvent.InvolvedObject.Name, vObj.InvolvedObject.Name) return vObj, nil } - -func hostEventNameToVirtual(hostName string, hostInvolvedObjectName, virtualInvolvedObjectName string) string { - // replace name of object - if strings.HasPrefix(hostName, hostInvolvedObjectName) { - hostName = strings.Replace(hostName, hostInvolvedObjectName, virtualInvolvedObjectName, 1) - } - - return hostName -} - -var ( - ErrNilPhysicalObject = errors.New("events: nil pObject") - ErrKindNotAccepted = errors.New("events: kind not accpted") - ErrNotFound = errors.New("events: not found") -) - -func IgnoreAcceptableErrors(err error) error { - if errors.Is(err, ErrNilPhysicalObject) || - errors.Is(err, ErrKindNotAccepted) || - errors.Is(err, ErrNotFound) { - return nil - } - - return err -} - -// getInvolvedObject returns the related object from the vCLuster. -// Alternatively returns a ErrNilPhysicalObject, ErrKindNotAccepted or ErrNotFound. -func (s *eventSyncer) getInvolvedObject(ctx context.Context, pObj client.Object) (metav1.Object, error) { - if pObj == nil { - return nil, ErrNilPhysicalObject - } - - pEvent, ok := pObj.(*corev1.Event) - if !ok { - return nil, errors.New("object is not of type event") - } - - // check if the involved object is accepted - gvk := pEvent.InvolvedObject.GroupVersionKind() - if !AcceptedKinds[gvk] { - return nil, ErrKindNotAccepted - } - - // create new virtual object - vInvolvedObj, err := s.virtualClient.Scheme().New(gvk) - if err != nil { - return nil, err - } - - // get involved object - err = clienthelper.GetByIndex(ctx, s.virtualClient, vInvolvedObj, constants.IndexByPhysicalName, pEvent.Namespace+"/"+pEvent.InvolvedObject.Name) - if err != nil { - if !kerrors.IsNotFound(err) { - return nil, err - } - - return nil, fmt.Errorf("%w: %w", ErrNotFound, err) - } - - // we found the related object - m, err := meta.Accessor(vInvolvedObj) - if err != nil { - return nil, err - } - - return m, nil -} diff --git a/pkg/controllers/resources/events/syncer_test.go b/pkg/controllers/resources/events/syncer_test.go index b13a7643d2..3e02b7ef8f 100644 --- a/pkg/controllers/resources/events/syncer_test.go +++ b/pkg/controllers/resources/events/syncer_test.go @@ -3,23 +3,20 @@ package events import ( "testing" - "github.com/loft-sh/vcluster/pkg/constants" 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" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/client" ) 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 := ctx.VirtualManager.GetFieldIndexer().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())} - }) + err := resources.RegisterPodsMapper(ctx) assert.NilError(t, err) syncContext, object := generictesting.FakeStartSyncer(t, ctx, New) diff --git a/pkg/controllers/resources/ingressclasses/syncer.go b/pkg/controllers/resources/ingressclasses/syncer.go index 7f90c4b640..3dad11342c 100644 --- a/pkg/controllers/resources/ingressclasses/syncer.go +++ b/pkg/controllers/resources/ingressclasses/syncer.go @@ -13,7 +13,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func New(*synccontext.RegisterContext) (syncer.Object, error) { +func New(_ *synccontext.RegisterContext) (syncer.Object, error) { return &ingressClassSyncer{ Translator: translator.NewMirrorPhysicalTranslator("ingressclass", &networkingv1.IngressClass{}), }, nil diff --git a/pkg/controllers/resources/ingresses/syncer.go b/pkg/controllers/resources/ingresses/syncer.go index 560f722773..a3aa4667bc 100644 --- a/pkg/controllers/resources/ingresses/syncer.go +++ b/pkg/controllers/resources/ingresses/syncer.go @@ -6,6 +6,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" "github.com/loft-sh/vcluster/pkg/util/translate" @@ -84,12 +85,13 @@ 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] = translate.Default.PhysicalName(secret, ingressNamespace) + newAnnotations[k] = mappings.VirtualToHostName(secret, ingressNamespace, mappings.Secrets()) } else if len(splitted) == 2 { // If value is "namespace/secret" namespace := splitted[0] secret := splitted[1] foundSecrets = append(foundSecrets, namespace+"/"+secret) - newAnnotations[k] = translate.Default.PhysicalNamespace(namespace) + "/" + translate.Default.PhysicalName(secret, namespace) + pName := mappings.VirtualToHost(secret, namespace, mappings.Secrets()) + 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 de59a2392f..5e47d29f0b 100644 --- a/pkg/controllers/resources/ingresses/translate.go +++ b/pkg/controllers/resources/ingresses/translate.go @@ -5,6 +5,9 @@ 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" "k8s.io/klog/v2" @@ -53,7 +56,7 @@ func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) *ne retSpec := vIngressSpec.DeepCopy() if retSpec.DefaultBackend != nil { if retSpec.DefaultBackend.Service != nil && retSpec.DefaultBackend.Service.Name != "" { - retSpec.DefaultBackend.Service.Name = translate.Default.PhysicalName(retSpec.DefaultBackend.Service.Name, namespace) + retSpec.DefaultBackend.Service.Name = mappings.VirtualToHostName(retSpec.DefaultBackend.Service.Name, namespace, mappings.Services()) } if retSpec.DefaultBackend.Resource != nil { retSpec.DefaultBackend.Resource.Name = translate.Default.PhysicalName(retSpec.DefaultBackend.Resource.Name, namespace) @@ -64,7 +67,7 @@ func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) *ne if rule.HTTP != nil { for j, path := range rule.HTTP.Paths { if path.Backend.Service != nil && path.Backend.Service.Name != "" { - retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name = translate.Default.PhysicalName(retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name, namespace) + retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name = mappings.VirtualToHostName(retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name, namespace, mappings.Services()) } if path.Backend.Resource != nil { retSpec.Rules[i].HTTP.Paths[j].Backend.Resource.Name = translate.Default.PhysicalName(retSpec.Rules[i].HTTP.Paths[j].Backend.Resource.Name, namespace) @@ -75,7 +78,7 @@ func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) *ne for i, tls := range retSpec.TLS { if tls.SecretName != "" { - retSpec.TLS[i].SecretName = translate.Default.PhysicalName(retSpec.TLS[i].SecretName, namespace) + retSpec.TLS[i].SecretName = mappings.VirtualToHostName(retSpec.TLS[i].SecretName, namespace, mappings.Secrets()) } } diff --git a/pkg/controllers/resources/namespaces/syncer.go b/pkg/controllers/resources/namespaces/syncer.go index 9ae64d1656..68a6cddf7c 100644 --- a/pkg/controllers/resources/namespaces/syncer.go +++ b/pkg/controllers/resources/namespaces/syncer.go @@ -3,12 +3,10 @@ package namespaces import ( "fmt" - "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/patcher" syncertypes "github.com/loft-sh/vcluster/pkg/types" - "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -38,7 +36,7 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { namespaceLabels[VClusterNamespaceAnnotation] = ctx.CurrentNamespace return &namespaceSyncer{ - Translator: translator.NewClusterTranslator(ctx, "namespace", &corev1.Namespace{}, NamespaceNameTranslator, excludedAnnotations...), + Translator: translator.NewClusterTranslator(ctx, "namespace", &corev1.Namespace{}, excludedAnnotations...), workloadServiceAccountName: ctx.Config.ControlPlane.Advanced.WorkloadServiceAccount.Name, namespaceLabels: namespaceLabels, }, nil @@ -50,14 +48,6 @@ type namespaceSyncer struct { namespaceLabels map[string]string } -var _ syncertypes.IndicesRegisterer = &namespaceSyncer{} - -func (s *namespaceSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Namespace{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{NamespaceNameTranslator(rawObj.GetName(), rawObj)} - }) -} - var _ syncertypes.Syncer = &namespaceSyncer{} func (s *namespaceSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { @@ -106,7 +96,3 @@ func (s *namespaceSyncer) EnsureWorkloadServiceAccount(ctx *synccontext.SyncCont _, err := controllerutil.CreateOrPatch(ctx.Context, ctx.PhysicalClient, svc, func() error { return nil }) return err } - -func NamespaceNameTranslator(vName string, _ client.Object) string { - return translate.Default.PhysicalNamespace(vName) -} diff --git a/pkg/controllers/resources/nodes/syncer.go b/pkg/controllers/resources/nodes/syncer.go index 946d99524d..2ebd9bc98f 100644 --- a/pkg/controllers/resources/nodes/syncer.go +++ b/pkg/controllers/resources/nodes/syncer.go @@ -188,7 +188,7 @@ func modifyController(ctx *synccontext.RegisterContext, nodeServiceProvider node }() bld = bld.WatchesRawSource(source.Kind(ctx.PhysicalManager.GetCache(), &corev1.Pod{}, handler.TypedEnqueueRequestsFromMapFunc(func(_ context.Context, pod *corev1.Pod) []reconcile.Request { - if pod == nil || !translate.Default.IsManaged(pod, translate.Default.PhysicalName) || pod.Spec.NodeName == "" { + if pod == nil || !translate.Default.IsManaged(pod) || pod.Spec.NodeName == "" { return []reconcile.Request{} } @@ -226,7 +226,7 @@ func (s *nodeSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { func registerIndices(ctx *synccontext.RegisterContext) error { err := ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { pod := rawObj.(*corev1.Pod) - if !translate.Default.IsManaged(pod, translate.Default.PhysicalName) || pod.Spec.NodeName == "" { + if !translate.Default.IsManaged(pod) || pod.Spec.NodeName == "" { return nil } return []string{pod.Spec.NodeName} @@ -244,14 +244,6 @@ func registerIndices(ctx *synccontext.RegisterContext) error { }) } -func (s *nodeSyncer) VirtualToHost(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { - return req -} - -func (s *nodeSyncer) HostToVirtual(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { - return types.NamespacedName{Name: req.Name} -} - func (s *nodeSyncer) IsManaged(_ context.Context, _ client.Object) (bool, error) { return true, nil } diff --git a/pkg/controllers/resources/nodes/syncer_test.go b/pkg/controllers/resources/nodes/syncer_test.go index b816311197..8e3f105655 100644 --- a/pkg/controllers/resources/nodes/syncer_test.go +++ b/pkg/controllers/resources/nodes/syncer_test.go @@ -61,9 +61,10 @@ func TestNodeDeletion(t *testing.T) { }, Sync: func(ctx *synccontext.RegisterContext) { _, nodesSyncer := newFakeSyncer(t, ctx) - syncController := syncer.NewSyncController(ctx, nodesSyncer) + syncController, err := syncer.NewSyncController(ctx, nodesSyncer) + assert.NilError(t, err) - _, err := syncController.Reconcile(ctx.Context, controllerruntime.Request{NamespacedName: baseName}) + _, err = syncController.Reconcile(ctx.Context, controllerruntime.Request{NamespacedName: baseName}) assert.NilError(t, err) }, }, diff --git a/pkg/controllers/resources/nodes/translate.go b/pkg/controllers/resources/nodes/translate.go index 13ed686b11..008edc37b7 100644 --- a/pkg/controllers/resources/nodes/translate.go +++ b/pkg/controllers/resources/nodes/translate.go @@ -188,7 +188,7 @@ func (s *nodeSyncer) translateUpdateStatus(ctx *synccontext.SyncContext, pNode * klog.Errorf("Error listing pods: %v", err) } else { for _, pod := range podList.Items { - if !translate.Default.IsManaged(&pod, translate.Default.PhysicalName) { + if !translate.Default.IsManaged(&pod) { // count pods that are not synced by this vcluster nonVClusterPods++ } diff --git a/pkg/controllers/resources/persistentvolumeclaims/syncer.go b/pkg/controllers/resources/persistentvolumeclaims/syncer.go index 357cb71107..b18264e669 100644 --- a/pkg/controllers/resources/persistentvolumeclaims/syncer.go +++ b/pkg/controllers/resources/persistentvolumeclaims/syncer.go @@ -2,16 +2,16 @@ package persistentvolumeclaims import ( "context" + "fmt" "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/controllers/syncer/translator" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/pkg/errors" "k8s.io/klog/v2" - "github.com/loft-sh/vcluster/pkg/constants" syncer "github.com/loft-sh/vcluster/pkg/types" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/loghelper" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" @@ -180,14 +180,13 @@ func (s *persistentVolumeClaimSyncer) ensurePersistentVolume(ctx *synccontext.Sy if pObj.Spec.VolumeName != "" && vObj.Spec.VolumeName != pObj.Spec.VolumeName { newVolumeName := pObj.Spec.VolumeName if !s.useFakePersistentVolumes { - vObj := &corev1.PersistentVolume{} - err = clienthelper.GetByIndex(ctx.Context, ctx.VirtualClient, vObj, constants.IndexByPhysicalName, pObj.Spec.VolumeName) - if err != nil { - log.Infof("error retrieving virtual persistent volume %s: %v", pObj.Spec.VolumeName, err) - return false, err + vName := mappings.PersistentVolumes().HostToVirtual(ctx.Context, types.NamespacedName{Name: pObj.Spec.VolumeName}, nil) + if vName.Name == "" { + log.Infof("error retrieving virtual persistent volume %s: not found", pObj.Spec.VolumeName) + return false, fmt.Errorf("error retrieving virtual persistent volume %s: not found", pObj.Spec.VolumeName) } - newVolumeName = vObj.Name + newVolumeName = vName.Name } if newVolumeName != vObj.Spec.VolumeName { diff --git a/pkg/controllers/resources/persistentvolumeclaims/translate.go b/pkg/controllers/resources/persistentvolumeclaims/translate.go index 4b682f5476..43f9cfcebc 100644 --- a/pkg/controllers/resources/persistentvolumeclaims/translate.go +++ b/pkg/controllers/resources/persistentvolumeclaims/translate.go @@ -6,6 +6,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" "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" @@ -27,11 +28,24 @@ func (s *persistentVolumeClaimSyncer) translate(ctx *synccontext.SyncContext, vP if vPvc.Annotations[constants.SkipTranslationAnnotation] != "true" { if newPvc.Spec.DataSource != nil { - newPvc.Spec.DataSource.Name = translate.Default.PhysicalName(newPvc.Spec.DataSource.Name, vPvc.Namespace) + if newPvc.Spec.DataSource.Kind == "VolumeSnapshot" { + newPvc.Spec.DataSource.Name = mappings.VirtualToHostName(newPvc.Spec.DataSource.Name, vPvc.Namespace, mappings.VolumeSnapshots()) + } else if newPvc.Spec.DataSource.Kind == "PersistentVolumeClaim" { + newPvc.Spec.DataSource.Name = mappings.VirtualToHostName(newPvc.Spec.DataSource.Name, vPvc.Namespace, mappings.PersistentVolumeClaims()) + } } if newPvc.Spec.DataSourceRef != nil { - newPvc.Spec.DataSourceRef.Name = translate.Default.PhysicalName(newPvc.Spec.DataSourceRef.Name, vPvc.Namespace) + namespace := vPvc.Namespace + if newPvc.Spec.DataSourceRef.Namespace != nil { + namespace = *newPvc.Spec.DataSourceRef.Namespace + } + + if newPvc.Spec.DataSourceRef.Kind == "VolumeSnapshot" { + newPvc.Spec.DataSourceRef.Name = mappings.VirtualToHostName(newPvc.Spec.DataSourceRef.Name, namespace, mappings.VolumeSnapshots()) + } else if newPvc.Spec.DataSourceRef.Kind == "PersistentVolumeClaim" { + newPvc.Spec.DataSourceRef.Name = mappings.VirtualToHostName(newPvc.Spec.DataSourceRef.Name, namespace, mappings.PersistentVolumeClaims()) + } } } diff --git a/pkg/controllers/resources/persistentvolumes/syncer.go b/pkg/controllers/resources/persistentvolumes/syncer.go index db2c2d77ee..7cb88d7426 100644 --- a/pkg/controllers/resources/persistentvolumes/syncer.go +++ b/pkg/controllers/resources/persistentvolumes/syncer.go @@ -7,18 +7,16 @@ 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" syncertypes "github.com/loft-sh/vcluster/pkg/types" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/handler" - "github.com/loft-sh/vcluster/pkg/constants" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -32,7 +30,7 @@ const ( func NewSyncer(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &persistentVolumeSyncer{ - Translator: translator.NewClusterTranslator(ctx, "persistentvolume", &corev1.PersistentVolume{}, NewPersistentVolumeTranslator(), HostClusterPersistentVolumeAnnotation), + Translator: translator.NewClusterTranslator(ctx, "persistentvolume", &corev1.PersistentVolume{}, HostClusterPersistentVolumeAnnotation), virtualClient: ctx.VirtualManager.GetClient(), }, nil @@ -57,26 +55,12 @@ func mapPVCs(_ context.Context, obj client.Object) []reconcile.Request { return nil } -func NewPersistentVolumeTranslator() translate.PhysicalNameTranslator { - return func(vName string, vObj client.Object) string { - return translatePersistentVolumeName(vName, vObj) - } -} - type persistentVolumeSyncer struct { translator.Translator virtualClient client.Client } -var _ syncertypes.IndicesRegisterer = &persistentVolumeSyncer{} - -func (s *persistentVolumeSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.PersistentVolume{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translatePersistentVolumeName(rawObj.(*corev1.PersistentVolume).Name, rawObj)} - }) -} - var _ syncertypes.ControllerModifier = &persistentVolumeSyncer{} func (s *persistentVolumeSyncer) ModifyController(_ *synccontext.RegisterContext, builder *builder.Builder) (*builder.Builder, error) { @@ -250,8 +234,21 @@ func (s *persistentVolumeSyncer) shouldSync(ctx context.Context, pObj *corev1.Pe return false, nil, nil } + vName := mappings.PersistentVolumeClaims().HostToVirtual(ctx, types.NamespacedName{Name: pObj.Spec.ClaimRef.Name, Namespace: pObj.Spec.ClaimRef.Namespace}, nil) + if vName.Name == "" { + if translate.Default.IsManagedCluster(pObj) { + return true, nil, nil + } + + namespace, err := translate.Default.LegacyGetTargetNamespace() + if err != nil { + return false, nil, nil + } + return pObj.Spec.ClaimRef.Namespace == namespace && pObj.Spec.PersistentVolumeReclaimPolicy == corev1.PersistentVolumeReclaimRetain, nil, nil + } + vPvc := &corev1.PersistentVolumeClaim{} - err := clienthelper.GetByIndex(ctx, s.virtualClient, vPvc, constants.IndexByPhysicalName, pObj.Spec.ClaimRef.Namespace+"/"+pObj.Spec.ClaimRef.Name) + err := s.virtualClient.Get(ctx, vName, vPvc) if err != nil { if !kerrors.IsNotFound(err) { return false, nil, err @@ -282,43 +279,3 @@ func (s *persistentVolumeSyncer) IsManaged(ctx context.Context, pObj client.Obje return sync, nil } - -func (s *persistentVolumeSyncer) VirtualToHost(_ context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { - return types.NamespacedName{Name: translatePersistentVolumeName(req.Name, vObj)} -} - -func (s *persistentVolumeSyncer) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { - if pObj != nil { - pAnnotations := pObj.GetAnnotations() - if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { - return types.NamespacedName{ - Name: pAnnotations[translate.NameAnnotation], - } - } - } - - vObj := &corev1.PersistentVolume{} - err := clienthelper.GetByIndex(ctx, s.virtualClient, vObj, constants.IndexByPhysicalName, req.Name) - if err != nil { - if !kerrors.IsNotFound(err) { - return types.NamespacedName{} - } - - return types.NamespacedName{Name: req.Name} - } - - return types.NamespacedName{Name: vObj.GetName()} -} - -func translatePersistentVolumeName(name string, vObj runtime.Object) string { - if vObj == nil { - return name - } - - vPv, ok := vObj.(*corev1.PersistentVolume) - if !ok || vPv.Annotations == nil || vPv.Annotations[HostClusterPersistentVolumeAnnotation] == "" { - return translate.Default.PhysicalNameClusterScoped(name) - } - - return vPv.Annotations[HostClusterPersistentVolumeAnnotation] -} diff --git a/pkg/controllers/resources/persistentvolumes/translate.go b/pkg/controllers/resources/persistentvolumes/translate.go index 9be073efcb..e5081f3f67 100644 --- a/pkg/controllers/resources/persistentvolumes/translate.go +++ b/pkg/controllers/resources/persistentvolumes/translate.go @@ -4,28 +4,23 @@ 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" + "k8s.io/apimachinery/pkg/types" ) func (s *persistentVolumeSyncer) translate(ctx context.Context, vPv *corev1.PersistentVolume) *corev1.PersistentVolume { // translate the persistent volume pPV := s.TranslateMetadata(ctx, vPv).(*corev1.PersistentVolume) pPV.Spec.ClaimRef = nil - pPV.Spec.StorageClassName = translateStorageClass(vPv.Spec.StorageClassName) + pPV.Spec.StorageClassName = mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) // TODO: translate the storage secrets return pPV } -func translateStorageClass(vStorageClassName string) string { - if vStorageClassName == "" { - return "" - } - return translate.Default.PhysicalNameClusterScoped(vStorageClassName) -} - func (s *persistentVolumeSyncer) translateBackwards(pPv *corev1.PersistentVolume, vPvc *corev1.PersistentVolumeClaim) *corev1.PersistentVolume { // build virtual persistent volume vObj := pPv.DeepCopy() @@ -73,14 +68,19 @@ func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.Persistent // when the PVC gets deleted } else { // check if SC was created on virtual - storageClassPhysicalName := translateStorageClass(vPv.Spec.StorageClassName) + storageClassPhysicalName := mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) isStorageClassCreatedOnVirtual = equality.Semantic.DeepEqual(storageClassPhysicalName, translatedSpec.StorageClassName) // check if claim was created on virtual if vPv.Spec.ClaimRef != nil && translatedSpec.ClaimRef != nil { - claimRefPhysicalName := translate.Default.PhysicalName(vPv.Spec.ClaimRef.Name, vPv.Spec.ClaimRef.Namespace) - claimRefPhysicalNamespace := translate.Default.PhysicalNamespace(vPv.Spec.ClaimRef.Namespace) - isClaimRefCreatedOnVirtual = equality.Semantic.DeepEqual(claimRefPhysicalName, translatedSpec.ClaimRef.Name) && equality.Semantic.DeepEqual(claimRefPhysicalNamespace, translatedSpec.ClaimRef.Namespace) + var claimRef types.NamespacedName + if vPv.Spec.ClaimRef.Kind == "PersistentVolume" { + claimRef = mappings.VirtualToHost(vPv.Spec.ClaimRef.Name, vPv.Spec.ClaimRef.Namespace, mappings.PersistentVolumes()) + } else { + claimRef = mappings.VirtualToHost(vPv.Spec.ClaimRef.Name, vPv.Spec.ClaimRef.Namespace, mappings.PersistentVolumeClaims()) + } + + isClaimRefCreatedOnVirtual = claimRef.Name == translatedSpec.ClaimRef.Name && claimRef.Namespace == translatedSpec.ClaimRef.Namespace } } @@ -131,7 +131,7 @@ func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev updated.Spec.PersistentVolumeReclaimPolicy = vPv.Spec.PersistentVolumeReclaimPolicy } - translatedStorageClassName := translateStorageClass(vPv.Spec.StorageClassName) + translatedStorageClassName := mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) if !equality.Semantic.DeepEqual(pPv.Spec.StorageClassName, translatedStorageClassName) { updated = translator.NewIfNil(updated, pPv) updated.Spec.StorageClassName = translatedStorageClassName diff --git a/pkg/controllers/resources/pods/syncer.go b/pkg/controllers/resources/pods/syncer.go index 522d172e5d..7139c6c6b6 100644 --- a/pkg/controllers/resources/pods/syncer.go +++ b/pkg/controllers/resources/pods/syncer.go @@ -108,12 +108,6 @@ type podSyncer struct { podSecurityStandard string } -var _ syncer.IndicesRegisterer = &podSyncer{} - -func (s *podSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - return s.NamespacedTranslator.RegisterIndices(ctx) -} - var _ syncer.ControllerModifier = &podSyncer{} func (s *podSyncer) ModifyController(registerContext *synccontext.RegisterContext, builder *builder.Builder) (*builder.Builder, error) { diff --git a/pkg/controllers/resources/pods/translate.go b/pkg/controllers/resources/pods/translate.go index c10a1b24c9..b734432b7b 100644 --- a/pkg/controllers/resources/pods/translate.go +++ b/pkg/controllers/resources/pods/translate.go @@ -7,8 +7,8 @@ import ( podtranslate "github.com/loft-sh/vcluster/pkg/controllers/resources/pods/translate" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/specialservices" - "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -87,14 +87,13 @@ func (s *podSyncer) findKubernetesDNSIP(ctx *synccontext.SyncContext) (string, e return "", errors.New("specialservices default not initialized") } - pClient, namespace := specialservices.Default.DNSNamespace(ctx) - // 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, - translate.Default.PhysicalName(specialservices.DefaultKubeDNSServiceName, specialservices.DefaultKubeDNSServiceNamespace), + mappings.VirtualToHostName(specialservices.DefaultKubeDNSServiceName, specialservices.DefaultKubeDNSServiceNamespace, mappings.Services()), ) 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 4562f36d22..94636767a3 100644 --- a/pkg/controllers/resources/pods/translate/sa_token_secret.go +++ b/pkg/controllers/resources/pods/translate/sa_token_secret.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + "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/types" @@ -22,10 +23,10 @@ const ( var PodServiceAccountTokenSecretName string func SecretNameFromPodName(podName, namespace string) string { - return translate.Default.PhysicalName(fmt.Sprintf("%s-sa-token", podName), namespace) + return mappings.VirtualToHostName(fmt.Sprintf("%s-sa-token", podName), namespace, mappings.Secrets()) } -var ErrNotFound = errors.New("tanslate: not found") +var ErrNotFound = errors.New("translate: not found") func IgnoreAcceptableErrors(err error) error { if errors.Is(err, ErrNotFound) { diff --git a/pkg/controllers/resources/pods/translate/translator.go b/pkg/controllers/resources/pods/translate/translator.go index 4ef80f1819..29afc60e2e 100644 --- a/pkg/controllers/resources/pods/translate/translator.go +++ b/pkg/controllers/resources/pods/translate/translator.go @@ -11,8 +11,8 @@ import ( "strconv" "strings" - "github.com/loft-sh/vcluster/pkg/controllers/resources/priorityclasses" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/util/loghelper" "github.com/loft-sh/vcluster/pkg/util/random" "github.com/loft-sh/vcluster/pkg/util/translate" @@ -157,7 +157,11 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ } // convert to core object - pPod := translate.Default.ApplyMetadata(vPod, t.syncedLabels).(*corev1.Pod) + pPod := translate.Default.ApplyMetadata( + vPod, + mappings.Pods().VirtualToHost(ctx, mappings.NamespacedName(vPod), vPod), + t.syncedLabels, + ).(*corev1.Pod) // override pod fields pPod.Status = corev1.PodStatus{} @@ -169,7 +173,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ vPodServiceAccountName = vPod.Spec.ServiceAccountName } if vPodServiceAccountName != "" { - pPod.Spec.ServiceAccountName = translate.Default.PhysicalName(vPodServiceAccountName, vPod.Namespace) + pPod.Spec.ServiceAccountName = mappings.VirtualToHostName(vPodServiceAccountName, vPod.Namespace, mappings.ServiceAccounts()) } } @@ -181,7 +185,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ pPod.Spec.PriorityClassName = "" pPod.Spec.Priority = nil } else if pPod.Spec.PriorityClassName != "" { - pPod.Spec.PriorityClassName = priorityclasses.NewPriorityClassTranslator()(pPod.Spec.PriorityClassName, nil) + pPod.Spec.PriorityClassName = mappings.VirtualToHostName(pPod.Spec.PriorityClassName, "", mappings.PriorityClasses()) if pPod.Spec.Priority != nil && *pPod.Spec.Priority > maxPriority { pPod.Spec.Priority = &maxPriority } @@ -315,7 +319,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate image pull secrets for i := range pPod.Spec.ImagePullSecrets { - pPod.Spec.ImagePullSecrets[i].Name = translate.Default.PhysicalName(pPod.Spec.ImagePullSecrets[i].Name, vPod.Namespace) + pPod.Spec.ImagePullSecrets[i].Name = mappings.VirtualToHostName(pPod.Spec.ImagePullSecrets[i].Name, vPod.Namespace, mappings.Secrets()) } // translate volumes @@ -375,17 +379,13 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo for i := range pPod.Spec.Volumes { if pPod.Spec.Volumes[i].ConfigMap != nil { - if t.multiNamespaceMode && pPod.Spec.Volumes[i].ConfigMap.Name == "kube-root-ca.crt" { - pPod.Spec.Volumes[i].ConfigMap.Name = translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName) - } else { - pPod.Spec.Volumes[i].ConfigMap.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].ConfigMap.Name, vPod.Namespace) - } + pPod.Spec.Volumes[i].ConfigMap.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].ConfigMap.Name, vPod.Namespace, mappings.ConfigMaps()) } if pPod.Spec.Volumes[i].Secret != nil { - pPod.Spec.Volumes[i].Secret.SecretName = translate.Default.PhysicalName(pPod.Spec.Volumes[i].Secret.SecretName, vPod.Namespace) + pPod.Spec.Volumes[i].Secret.SecretName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].Secret.SecretName, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].PersistentVolumeClaim != nil { - pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName = translate.Default.PhysicalName(pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName, vPod.Namespace) + pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName, vPod.Namespace, mappings.PersistentVolumeClaims()) } if pPod.Spec.Volumes[i].Ephemeral != nil { // An ephemeral volume is created as a PVC by the "ephemeral_volume" K8s controller. @@ -396,7 +396,7 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo // the Pod, and that remains unchanged and thus the PVC will be removed by the kube // controllers of the vcluster, and syncer will then remove the PVC from the host. pPod.Spec.Volumes[i].PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: translate.Default.PhysicalName(ephemeral.VolumeClaimName(vPod, &vPod.Spec.Volumes[i]), vPod.Namespace), + ClaimName: mappings.VirtualToHostName(ephemeral.VolumeClaimName(vPod, &vPod.Spec.Volumes[i]), vPod.Namespace, mappings.PersistentVolumeClaims()), } pPod.Spec.Volumes[i].Ephemeral = nil } @@ -412,34 +412,34 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo } } if pPod.Spec.Volumes[i].ISCSI != nil && pPod.Spec.Volumes[i].ISCSI.SecretRef != nil { - pPod.Spec.Volumes[i].ISCSI.SecretRef.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].ISCSI.SecretRef.Name, vPod.Namespace) + pPod.Spec.Volumes[i].ISCSI.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].ISCSI.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].RBD != nil && pPod.Spec.Volumes[i].RBD.SecretRef != nil { - pPod.Spec.Volumes[i].RBD.SecretRef.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].RBD.SecretRef.Name, vPod.Namespace) + 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 = translate.Default.PhysicalName(pPod.Spec.Volumes[i].FlexVolume.SecretRef.Name, vPod.Namespace) + 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 { - pPod.Spec.Volumes[i].Cinder.SecretRef.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].Cinder.SecretRef.Name, vPod.Namespace) + pPod.Spec.Volumes[i].Cinder.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].Cinder.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].CephFS != nil && pPod.Spec.Volumes[i].CephFS.SecretRef != nil { - pPod.Spec.Volumes[i].CephFS.SecretRef.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].CephFS.SecretRef.Name, vPod.Namespace) + pPod.Spec.Volumes[i].CephFS.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].CephFS.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].AzureFile != nil && pPod.Spec.Volumes[i].AzureFile.SecretName != "" { - pPod.Spec.Volumes[i].AzureFile.SecretName = translate.Default.PhysicalName(pPod.Spec.Volumes[i].AzureFile.SecretName, vPod.Namespace) + pPod.Spec.Volumes[i].AzureFile.SecretName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].AzureFile.SecretName, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].ScaleIO != nil && pPod.Spec.Volumes[i].ScaleIO.SecretRef != nil { - pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name, vPod.Namespace) + pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].StorageOS != nil && pPod.Spec.Volumes[i].StorageOS.SecretRef != nil { - pPod.Spec.Volumes[i].StorageOS.SecretRef.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].StorageOS.SecretRef.Name, vPod.Namespace) + pPod.Spec.Volumes[i].StorageOS.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].StorageOS.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].CSI != nil && pPod.Spec.Volumes[i].CSI.NodePublishSecretRef != nil { - pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name = translate.Default.PhysicalName(pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name, vPod.Namespace) + pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].Glusterfs != nil && pPod.Spec.Volumes[i].Glusterfs.EndpointsName != "" { - pPod.Spec.Volumes[i].Glusterfs.EndpointsName = translate.Default.PhysicalName(pPod.Spec.Volumes[i].Glusterfs.EndpointsName, vPod.Namespace) + pPod.Spec.Volumes[i].Glusterfs.EndpointsName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].Glusterfs.EndpointsName, vPod.Namespace, mappings.Endpoints()) } } @@ -467,13 +467,10 @@ func (t *translator) translateProjectedVolume( ) error { for i := range projectedVolume.Sources { if projectedVolume.Sources[i].Secret != nil { - projectedVolume.Sources[i].Secret.Name = translate.Default.PhysicalName(projectedVolume.Sources[i].Secret.Name, vPod.Namespace) + projectedVolume.Sources[i].Secret.Name = mappings.VirtualToHostName(projectedVolume.Sources[i].Secret.Name, vPod.Namespace, mappings.Secrets()) } if projectedVolume.Sources[i].ConfigMap != nil { - projectedVolume.Sources[i].ConfigMap.Name = translate.Default.PhysicalName(projectedVolume.Sources[i].ConfigMap.Name, vPod.Namespace) - if projectedVolume.Sources[i].ConfigMap.Name == "kube-root-ca.crt" { - projectedVolume.Sources[i].ConfigMap.Name = translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName) - } + projectedVolume.Sources[i].ConfigMap.Name = mappings.VirtualToHostName(projectedVolume.Sources[i].ConfigMap.Name, vPod.Namespace, mappings.ConfigMaps()) } if projectedVolume.Sources[i].DownwardAPI != nil { for j := range projectedVolume.Sources[i].DownwardAPI.Items { @@ -607,24 +604,20 @@ func (t *translator) TranslateContainerEnv(envVar []corev1.EnvVar, envFrom []cor for j, env := range envVar { translateDownwardAPI(&envVar[j]) if env.ValueFrom != nil && env.ValueFrom.ConfigMapKeyRef != nil && env.ValueFrom.ConfigMapKeyRef.Name != "" { - envVar[j].ValueFrom.ConfigMapKeyRef.Name = translate.Default.PhysicalName(envVar[j].ValueFrom.ConfigMapKeyRef.Name, vPod.Namespace) + envVar[j].ValueFrom.ConfigMapKeyRef.Name = mappings.VirtualToHostName(envVar[j].ValueFrom.ConfigMapKeyRef.Name, vPod.Namespace, mappings.ConfigMaps()) } if env.ValueFrom != nil && env.ValueFrom.SecretKeyRef != nil && env.ValueFrom.SecretKeyRef.Name != "" { - envVar[j].ValueFrom.SecretKeyRef.Name = translate.Default.PhysicalName(envVar[j].ValueFrom.SecretKeyRef.Name, vPod.Namespace) + envVar[j].ValueFrom.SecretKeyRef.Name = mappings.VirtualToHostName(envVar[j].ValueFrom.SecretKeyRef.Name, vPod.Namespace, mappings.Secrets()) } envNameMap[env.Name] = struct{}{} } for j, from := range envFrom { if from.ConfigMapRef != nil && from.ConfigMapRef.Name != "" { - if t.multiNamespaceMode && envFrom[j].ConfigMapRef.Name == "kube-root-ca.crt" { - envFrom[j].ConfigMapRef.Name = translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName) - } else { - envFrom[j].ConfigMapRef.Name = translate.Default.PhysicalName(from.ConfigMapRef.Name, vPod.Namespace) - } + envFrom[j].ConfigMapRef.Name = mappings.VirtualToHostName(from.ConfigMapRef.Name, vPod.Namespace, mappings.ConfigMaps()) } if from.SecretRef != nil && from.SecretRef.Name != "" { - envFrom[j].SecretRef.Name = translate.Default.PhysicalName(from.SecretRef.Name, vPod.Namespace) + envFrom[j].SecretRef.Name = mappings.VirtualToHostName(from.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } } diff --git a/pkg/controllers/resources/priorityclasses/syncer.go b/pkg/controllers/resources/priorityclasses/syncer.go index 311d41e6c4..27947ffc8b 100644 --- a/pkg/controllers/resources/priorityclasses/syncer.go +++ b/pkg/controllers/resources/priorityclasses/syncer.go @@ -3,12 +3,10 @@ package priorityclasses import ( "fmt" - "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/patcher" syncer "github.com/loft-sh/vcluster/pkg/types" - "github.com/loft-sh/vcluster/pkg/util/translate" schedulingv1 "k8s.io/api/scheduling/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" ctrl "sigs.k8s.io/controller-runtime" @@ -17,7 +15,7 @@ import ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &priorityClassSyncer{ - Translator: translator.NewClusterTranslator(ctx, "priorityclass", &schedulingv1.PriorityClass{}, NewPriorityClassTranslator()), + Translator: translator.NewClusterTranslator(ctx, "priorityclass", &schedulingv1.PriorityClass{}), }, nil } @@ -25,14 +23,6 @@ type priorityClassSyncer struct { translator.Translator } -var _ syncer.IndicesRegisterer = &priorityClassSyncer{} - -func (s *priorityClassSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &schedulingv1.PriorityClass{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translatePriorityClassName(rawObj.GetName())} - }) -} - var _ syncer.Syncer = &priorityClassSyncer{} func (s *priorityClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { @@ -66,14 +56,3 @@ func (s *priorityClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Obj s.translateUpdate(ctx.Context, pPriorityClass, vPriorityClass, sourceObject, targetObject) return ctrl.Result{}, nil } - -func NewPriorityClassTranslator() translate.PhysicalNameTranslator { - return func(vName string, _ client.Object) string { - return translatePriorityClassName(vName) - } -} - -func translatePriorityClassName(name string) string { - // we have to prefix with vcluster as system is reserved - return translate.Default.PhysicalNameClusterScoped(name) -} diff --git a/pkg/controllers/resources/secrets/syncer.go b/pkg/controllers/resources/secrets/syncer.go index fee5bea038..a6f65b7d30 100644 --- a/pkg/controllers/resources/secrets/syncer.go +++ b/pkg/controllers/resources/secrets/syncer.go @@ -68,7 +68,8 @@ func (s *secretSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { if err != nil { return err } - return s.NamespacedTranslator.RegisterIndices(ctx) + + return nil } var _ syncer.ControllerModifier = &secretSyncer{} @@ -114,9 +115,12 @@ func (s *secretSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vO } defer func() { if err := patch.Patch(ctx, pObj, vObj); err != nil { - s.NamespacedTranslator.EventRecorder().Eventf(vObj, "Warning", "SyncError", "Error syncing: %v", err) retErr = utilerrors.NewAggregate([]error{retErr, err}) } + + if retErr != nil { + s.NamespacedTranslator.EventRecorder().Eventf(vObj, "Warning", "SyncError", "Error syncing: %v", retErr) + } }() // cast objects diff --git a/pkg/controllers/resources/storageclasses/syncer.go b/pkg/controllers/resources/storageclasses/syncer.go index 179d55c672..d7c95a2a12 100644 --- a/pkg/controllers/resources/storageclasses/syncer.go +++ b/pkg/controllers/resources/storageclasses/syncer.go @@ -1,11 +1,9 @@ package storageclasses 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" syncer "github.com/loft-sh/vcluster/pkg/types" - "github.com/loft-sh/vcluster/pkg/util/translate" storagev1 "k8s.io/api/storage/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -15,7 +13,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{}, NewStorageClassTranslator(), DefaultStorageClassAnnotation), + Translator: translator.NewClusterTranslator(ctx, "storageclass", &storagev1.StorageClass{}, DefaultStorageClassAnnotation), }, nil } @@ -23,14 +21,6 @@ type storageClassSyncer struct { translator.Translator } -var _ syncer.IndicesRegisterer = &storageClassSyncer{} - -func (s *storageClassSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &storagev1.StorageClass{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translateStorageClassName(rawObj.GetName())} - }) -} - var _ syncer.Syncer = &storageClassSyncer{} func (s *storageClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { @@ -59,14 +49,3 @@ func (s *storageClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj clien return ctrl.Result{}, nil } - -func NewStorageClassTranslator() translate.PhysicalNameTranslator { - return func(vName string, _ client.Object) string { - return translateStorageClassName(vName) - } -} - -func translateStorageClassName(name string) string { - // we have to prefix with vcluster as system is reserved - return translate.Default.PhysicalNameClusterScoped(name) -} diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go index 502eaad8cb..e1511cf54f 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go @@ -5,19 +5,17 @@ import ( "time" "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" + "k8s.io/apimachinery/pkg/types" volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" - "github.com/loft-sh/vcluster/pkg/constants" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/translate" "k8s.io/apimachinery/pkg/api/equality" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -29,7 +27,7 @@ const ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &volumeSnapshotContentSyncer{ - Translator: translator.NewClusterTranslator(ctx, "volume-snapshot-content", &volumesnapshotv1.VolumeSnapshotContent{}, NewVolumeSnapshotContentTranslator()), + Translator: translator.NewClusterTranslator(ctx, "volume-snapshot-content", &volumesnapshotv1.VolumeSnapshotContent{}), virtualClient: ctx.VirtualManager.GetClient(), }, nil @@ -47,24 +45,6 @@ func (s *volumeSnapshotContentSyncer) Init(registerContext *synccontext.Register return util.EnsureCRD(registerContext.Context, registerContext.VirtualManager.GetConfig(), []byte(volumeSnapshotContentsCRD), volumesnapshotv1.SchemeGroupVersion.WithKind("VolumeSnapshotContent")) } -func NewVolumeSnapshotContentTranslator() translate.PhysicalNameTranslator { - return func(vName string, vObj client.Object) string { - return translateVolumeSnapshotContentName(vName, vObj) - } -} - -var _ syncer.IndicesRegisterer = &volumeSnapshotContentSyncer{} - -func (s *volumeSnapshotContentSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &volumesnapshotv1.VolumeSnapshotContent{}, constants.IndexByPhysicalName, newIndexByVSCPhysicalName()) -} - -func newIndexByVSCPhysicalName() client.IndexerFunc { - return func(rawObj client.Object) []string { - return []string{translateVolumeSnapshotContentName(rawObj.GetName(), rawObj)} - } -} - var _ syncer.ToVirtualSyncer = &volumeSnapshotContentSyncer{} func (s *volumeSnapshotContentSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { @@ -213,8 +193,13 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl } func (s *volumeSnapshotContentSyncer) shouldSync(ctx context.Context, pObj *volumesnapshotv1.VolumeSnapshotContent) (bool, *volumesnapshotv1.VolumeSnapshot, error) { + vName := mappings.VolumeSnapshots().HostToVirtual(ctx, types.NamespacedName{Name: pObj.Spec.VolumeSnapshotRef.Name, Namespace: pObj.Spec.VolumeSnapshotRef.Namespace}, nil) + if vName.Name == "" { + return false, nil, nil + } + vVS := &volumesnapshotv1.VolumeSnapshot{} - err := clienthelper.GetByIndex(ctx, s.virtualClient, vVS, constants.IndexByPhysicalName, pObj.Spec.VolumeSnapshotRef.Namespace+"/"+pObj.Spec.VolumeSnapshotRef.Name) + err := s.virtualClient.Get(ctx, vName, vVS) if err != nil { if !kerrors.IsNotFound(err) { return false, nil, err @@ -240,43 +225,3 @@ func (s *volumeSnapshotContentSyncer) IsManaged(ctx context.Context, pObj client return sync, nil } - -func (s *volumeSnapshotContentSyncer) VirtualToHost(_ context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { - return types.NamespacedName{Name: translateVolumeSnapshotContentName(req.Name, vObj)} -} - -func (s *volumeSnapshotContentSyncer) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { - if pObj != nil { - pAnnotations := pObj.GetAnnotations() - if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { - return types.NamespacedName{ - Name: pAnnotations[translate.NameAnnotation], - } - } - } - - vObj := &volumesnapshotv1.VolumeSnapshotContent{} - err := clienthelper.GetByIndex(ctx, s.virtualClient, vObj, constants.IndexByPhysicalName, req.Name) - if err != nil { - if !kerrors.IsNotFound(err) { - return types.NamespacedName{} - } - - return types.NamespacedName{Name: req.Name} - } - - return types.NamespacedName{Name: vObj.GetName()} -} - -func translateVolumeSnapshotContentName(name string, vObj runtime.Object) string { - if vObj == nil { - return name - } - - vVSC, ok := vObj.(*volumesnapshotv1.VolumeSnapshotContent) - if !ok || vVSC.Annotations == nil || vVSC.Annotations[HostClusterVSCAnnotation] == "" { - return translate.Default.PhysicalNameClusterScoped(name) - } - - return vVSC.Annotations[HostClusterVSCAnnotation] -} diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go index c738fbcfdf..22f007b5e7 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go @@ -5,18 +5,17 @@ import ( "time" 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" volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" - "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" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -24,11 +23,9 @@ const ( ) func newFakeSyncer(t *testing.T, ctx *synccontext.RegisterContext) (*synccontext.SyncContext, *volumeSnapshotContentSyncer) { - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &volumesnapshotv1.VolumeSnapshotContent{}, constants.IndexByPhysicalName, newIndexByVSCPhysicalName()) + err := resources.RegisterVolumeSnapshotContentsMapper(ctx) assert.NilError(t, err) - err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &volumesnapshotv1.VolumeSnapshot{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { - return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translate.Default.PhysicalName(rawObj.GetName(), rawObj.GetNamespace())} - }) + err = resources.RegisterVolumeSnapshotsMapper(ctx) assert.NilError(t, err) syncContext, object := generictesting.FakeStartSyncer(t, ctx, New) diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go index 4238ec35ee..213007317a 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go @@ -5,7 +5,7 @@ import ( volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" - "github.com/loft-sh/vcluster/pkg/util/translate" + "github.com/loft-sh/vcluster/pkg/mappings" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -13,9 +13,10 @@ import ( func (s *volumeSnapshotContentSyncer) translate(ctx context.Context, vVSC *volumesnapshotv1.VolumeSnapshotContent) *volumesnapshotv1.VolumeSnapshotContent { pVSC := s.TranslateMetadata(ctx, vVSC).(*volumesnapshotv1.VolumeSnapshotContent) + pVolumeSnapshot := mappings.VirtualToHost(vVSC.Spec.VolumeSnapshotRef.Name, vVSC.Spec.VolumeSnapshotRef.Namespace, mappings.VolumeSnapshots()) pVSC.Spec.VolumeSnapshotRef = corev1.ObjectReference{ - Namespace: translate.Default.PhysicalNamespace(vVSC.Spec.VolumeSnapshotRef.Namespace), - Name: translate.Default.PhysicalName(vVSC.Spec.VolumeSnapshotRef.Name, vVSC.Spec.VolumeSnapshotRef.Namespace), + Namespace: pVolumeSnapshot.Namespace, + Name: pVolumeSnapshot.Name, } return pVSC } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go index bacba9ba59..e92ea18377 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go @@ -1,14 +1,11 @@ package volumesnapshots import ( - "github.com/loft-sh/vcluster/pkg/util/translate" - "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" syncer "github.com/loft-sh/vcluster/pkg/types" "github.com/loft-sh/vcluster/pkg/util" volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" - "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "k8s.io/apimachinery/pkg/api/equality" kerrors "k8s.io/apimachinery/pkg/api/errors" @@ -25,14 +22,12 @@ var ( func New(ctx *synccontext.RegisterContext) (syncer.Object, error) { return &volumeSnapshotSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "volume-snapshot", &volumesnapshotv1.VolumeSnapshot{}), - volumeSnapshotContentNameTranslator: volumesnapshotcontents.NewVolumeSnapshotContentTranslator(), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "volume-snapshot", &volumesnapshotv1.VolumeSnapshot{}), }, nil } type volumeSnapshotSyncer struct { translator.NamespacedTranslator - volumeSnapshotContentNameTranslator translate.PhysicalNameTranslator } var _ syncer.Initializer = &volumeSnapshotSyncer{} diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go b/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go index 56e1b9f7ca..6200a1bc01 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go @@ -8,8 +8,9 @@ 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/util/translate" + "github.com/loft-sh/vcluster/pkg/mappings" "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -19,7 +20,7 @@ func (s *volumeSnapshotSyncer) translate(ctx *synccontext.SyncContext, vVS *volu pVS.Spec.Source = vVS.Spec.Source } else { if vVS.Spec.Source.PersistentVolumeClaimName != nil { - pvcName := translate.Default.PhysicalName(*vVS.Spec.Source.PersistentVolumeClaimName, vVS.Namespace) + pvcName := mappings.VirtualToHostName(*vVS.Spec.Source.PersistentVolumeClaimName, vVS.Namespace, mappings.PersistentVolumeClaims()) pVS.Spec.Source.PersistentVolumeClaimName = &pvcName } if vVS.Spec.Source.VolumeSnapshotContentName != nil { @@ -28,7 +29,7 @@ func (s *volumeSnapshotSyncer) translate(ctx *synccontext.SyncContext, vVS *volu if err != nil { return nil, fmt.Errorf("failed to get virtual VolumeSnapshotContent resource referenced as source of the %s VolumeSnapshot: %w", vVS.Name, err) } - translatedName := s.volumeSnapshotContentNameTranslator(vVSC.Name, vVSC) + translatedName := mappings.VolumeSnapshotContents().VirtualToHost(ctx.Context, types.NamespacedName{Name: vVSC.Name}, vVSC).Name pVS.Spec.Source.VolumeSnapshotContentName = &translatedName } } diff --git a/pkg/controllers/syncer/syncer.go b/pkg/controllers/syncer/syncer.go index dbfd13a585..34178d899f 100644 --- a/pkg/controllers/syncer/syncer.go +++ b/pkg/controllers/syncer/syncer.go @@ -7,11 +7,15 @@ 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" @@ -28,15 +32,22 @@ import ( const hostObjectRequestPrefix = "host#" -func NewSyncController(ctx *synccontext.RegisterContext, syncer syncertypes.Syncer) *SyncController { +func NewSyncController(ctx *synccontext.RegisterContext, syncer syncertypes.Syncer) (*SyncController, error) { options := &syncertypes.Options{} optionsProvider, ok := syncer.(syncertypes.OptionsProvider) if ok { options = optionsProvider.WithOptions() } + gvk, err := apiutil.GVKForObject(syncer.Resource(), scheme.Scheme) + if err != nil { + return nil, err + } + return &SyncController{ - syncer: syncer, + syncer: syncer, + gvk: gvk, + log: loghelper.New(syncer.Name()), vEventRecorder: ctx.VirtualManager.GetEventRecorderFor(syncer.Name() + "-syncer"), physicalClient: ctx.PhysicalManager.GetClient(), @@ -48,15 +59,21 @@ func NewSyncController(ctx *synccontext.RegisterContext, syncer syncertypes.Sync options: options, locker: locker.New(), - } + }, nil } func RegisterSyncer(ctx *synccontext.RegisterContext, syncer syncertypes.Syncer) error { - return NewSyncController(ctx, syncer).Register(ctx) + controller, err := NewSyncController(ctx, syncer) + if err != nil { + return err + } + + return controller.Register(ctx) } type SyncController struct { syncer syncertypes.Syncer + gvk schema.GroupVersionKind log loghelper.Logger vEventRecorder record.EventRecorder @@ -181,7 +198,7 @@ func (r *SyncController) getObjectsFromPhysical(ctx *synccontext.SyncContext, re } // get virtual object - exclude, vObj, err = r.getVirtualObject(ctx.Context, r.syncer.HostToVirtual(ctx.Context, req.NamespacedName, pObj)) + exclude, vObj, err = r.getVirtualObject(ctx.Context, mappings.Default.ByGVK(r.gvk).HostToVirtual(ctx.Context, req.NamespacedName, pObj)) if err != nil { return nil, nil, err } else if exclude { @@ -201,7 +218,7 @@ func (r *SyncController) getObjectsFromVirtual(ctx *synccontext.SyncContext, req } // get physical object - exclude, pObj, err = r.getPhysicalObject(ctx.Context, r.syncer.VirtualToHost(ctx.Context, req.NamespacedName, vObj), vObj) + exclude, pObj, err = r.getPhysicalObject(ctx.Context, mappings.Default.ByGVK(r.gvk).VirtualToHost(ctx.Context, req.NamespacedName, vObj), vObj) if err != nil { return nil, nil, err } else if exclude { @@ -328,7 +345,7 @@ func (r *SyncController) extractRequest(ctx context.Context, req ctrl.Request) ( } // try to get virtual name from physical - req.NamespacedName = r.syncer.HostToVirtual(ctx, pReq.NamespacedName, pObj) + req.NamespacedName = mappings.Default.ByGVK(r.gvk).HostToVirtual(ctx, pReq.NamespacedName, pObj) } return req, pReq, nil @@ -341,7 +358,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 := r.syncer.VirtualToHost(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) + name := mappings.Default.ByGVK(r.gvk).VirtualToHost(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) if name.Name != "" { q.Add(toHostRequest(reconcile.Request{ NamespacedName: name, @@ -374,7 +391,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 := r.syncer.HostToVirtual(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj) + name := mappings.Default.ByGVK(r.gvk).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/translator/cluster_translator.go b/pkg/controllers/syncer/translator/cluster_translator.go index a6cfe006ef..3e94be70ed 100644 --- a/pkg/controllers/syncer/translator/cluster_translator.go +++ b/pkg/controllers/syncer/translator/cluster_translator.go @@ -2,32 +2,42 @@ package translator import ( context2 "context" + "fmt" - "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" + "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, nameTranslator translate.PhysicalNameTranslator, excludedAnnotations ...string) Translator { +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)) + } + return &clusterTranslator{ - name: name, + name: name, + gvk: gvk, + excludedAnnotations: excludedAnnotations, virtualClient: ctx.VirtualManager.GetClient(), obj: obj, - nameTranslator: nameTranslator, syncedLabels: ctx.Config.Experimental.SyncSettings.SyncLabels, } } type clusterTranslator struct { - name string + name string + gvk schema.GroupVersionKind + virtualClient client.Client obj client.Object - nameTranslator translate.PhysicalNameTranslator excludedAnnotations []string syncedLabels []string } @@ -44,37 +54,8 @@ func (n *clusterTranslator) IsManaged(_ context2.Context, pObj client.Object) (b return translate.Default.IsManagedCluster(pObj), nil } -func (n *clusterTranslator) VirtualToHost(_ context2.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { - return types.NamespacedName{ - Name: n.nameTranslator(req.Name, vObj), - } -} - -func (n *clusterTranslator) HostToVirtual(ctx context2.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { - if pObj != nil { - pAnnotations := pObj.GetAnnotations() - if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { - return types.NamespacedName{ - Namespace: pAnnotations[translate.NamespaceAnnotation], - Name: pAnnotations[translate.NameAnnotation], - } - } - } - - vObj := n.obj.DeepCopyObject().(client.Object) - err := clienthelper.GetByIndex(ctx, n.virtualClient, vObj, constants.IndexByPhysicalName, req.Name) - if err != nil { - return types.NamespacedName{} - } - - return types.NamespacedName{ - Namespace: vObj.GetNamespace(), - Name: vObj.GetName(), - } -} - -func (n *clusterTranslator) TranslateMetadata(_ context2.Context, vObj client.Object) client.Object { - pObj, err := translate.Default.SetupMetadataWithName(vObj, n.nameTranslator) +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)) 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 207445cf9f..9090384c42 100644 --- a/pkg/controllers/syncer/translator/mirror_name_translator.go +++ b/pkg/controllers/syncer/translator/mirror_name_translator.go @@ -4,7 +4,6 @@ import ( "context" "k8s.io/apimachinery/pkg/api/equality" - "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -46,11 +45,3 @@ func (n *mirrorPhysicalTranslator) TranslateMetadataUpdate(_ context.Context, vO func (n *mirrorPhysicalTranslator) IsManaged(context.Context, client.Object) (bool, error) { return true, nil } - -func (n *mirrorPhysicalTranslator) VirtualToHost(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { - return req -} - -func (n *mirrorPhysicalTranslator) HostToVirtual(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { - return req -} diff --git a/pkg/controllers/syncer/translator/namespaced_translator.go b/pkg/controllers/syncer/translator/namespaced_translator.go index 582dc52a66..48086aa925 100644 --- a/pkg/controllers/syncer/translator/namespaced_translator.go +++ b/pkg/controllers/syncer/translator/namespaced_translator.go @@ -2,33 +2,32 @@ package translator import ( context2 "context" + "fmt" "reflect" "time" - "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "github.com/loft-sh/vcluster/pkg/util/clienthelper" + "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/api/meta" + "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 { - return newNamespacedTranslator(ctx, name, obj, translate.Default.PhysicalName, excludedAnnotations...) -} - -func NewShortNamespacedTranslator(ctx *context.RegisterContext, name string, obj client.Object, excludedAnnotations ...string) NamespacedTranslator { - return newNamespacedTranslator(ctx, name, obj, translate.Default.PhysicalNameShort, excludedAnnotations...) -} + 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, translateName translate.PhysicalNameFunc, excludedAnnotations ...string) NamespacedTranslator { return &namespacedTranslator{ - name: name, - translateName: translateName, + name: name, + gvk: gvk, syncedLabels: ctx.Config.Experimental.SyncSettings.SyncLabels, excludedAnnotations: excludedAnnotations, @@ -42,6 +41,7 @@ func newNamespacedTranslator(ctx *context.RegisterContext, name string, obj clie type namespacedTranslator struct { name string + gvk schema.GroupVersionKind excludedAnnotations []string syncedLabels []string @@ -49,8 +49,6 @@ type namespacedTranslator struct { virtualClient client.Client obj client.Object - translateName translate.PhysicalNameFunc - eventRecorder record.EventRecorder } @@ -66,12 +64,6 @@ func (n *namespacedTranslator) Resource() client.Object { return n.obj.DeepCopyObject().(client.Object) } -func (n *namespacedTranslator) RegisterIndices(ctx *context.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 *namespacedTranslator) SyncToHostCreate(ctx *context.SyncContext, vObj, pObj client.Object) (ctrl.Result, error) { ctx.Log.Infof("create physical %s %s/%s", n.name, pObj.GetNamespace(), pObj.GetName()) err := ctx.PhysicalClient.Create(ctx.Context, pObj) @@ -106,58 +98,15 @@ func (n *namespacedTranslator) SyncToHostUpdate(ctx *context.SyncContext, vObj, } func (n *namespacedTranslator) IsManaged(_ context2.Context, pObj client.Object) (bool, error) { - return translate.Default.IsManaged(pObj, n.translateName), nil -} - -func (n *namespacedTranslator) VirtualToHost(_ context2.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { - return types.NamespacedName{ - Namespace: translate.Default.PhysicalNamespace(req.Namespace), - Name: n.translateName(req.Name, req.Namespace), - } -} - -func (n *namespacedTranslator) HostToVirtual(_ context2.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { - if pObj != nil { - pAnnotations := pObj.GetAnnotations() - if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { - return types.NamespacedName{ - Namespace: pAnnotations[translate.NamespaceAnnotation], - Name: pAnnotations[translate.NameAnnotation], - } - } - } - - vObj := n.obj.DeepCopyObject().(client.Object) - err := clienthelper.GetByIndex(context2.Background(), n.virtualClient, vObj, constants.IndexByPhysicalName, req.Namespace+"/"+req.Name) - if err != nil { - return types.NamespacedName{} - } - - return types.NamespacedName{ - Namespace: vObj.GetNamespace(), - Name: vObj.GetName(), - } + return translate.Default.IsManaged(pObj), nil } func (n *namespacedTranslator) TranslateMetadata(ctx context2.Context, vObj client.Object) client.Object { - pObj := vObj.DeepCopyObject().(client.Object) - m, err := meta.Accessor(pObj) + pObj, err := translate.Default.SetupMetadataWithName(vObj, mappings.Default.ByGVK(n.gvk).VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj)) if err != nil { return nil } - // reset metadata & translate name and namespace - translate.ResetObjectMetadata(m) - m.SetName(n.VirtualToHost(ctx, types.NamespacedName{Name: vObj.GetName(), Namespace: vObj.GetNamespace()}, vObj).Name) - if vObj.GetNamespace() != "" { - m.SetNamespace(translate.Default.PhysicalNamespace(vObj.GetNamespace())) - - // set owning stateful set if defined - if translate.Owner != nil { - m.SetOwnerReferences(translate.GetOwnerReference(vObj)) - } - } - pObj.SetAnnotations(translate.Default.ApplyAnnotations(vObj, nil, n.excludedAnnotations)) pObj.SetLabels(translate.Default.ApplyLabels(vObj, nil, n.syncedLabels)) return pObj diff --git a/pkg/controllers/syncer/translator/translator.go b/pkg/controllers/syncer/translator/translator.go index 0db6c0a8d4..1de797559b 100644 --- a/pkg/controllers/syncer/translator/translator.go +++ b/pkg/controllers/syncer/translator/translator.go @@ -4,7 +4,6 @@ import ( "context" syncercontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -14,20 +13,14 @@ import ( type Translator interface { Resource() client.Object Name() string - NameTranslator + ObjectManager MetadataTranslator } -// NameTranslator is used to convert virtual to physical names and vice versa -type NameTranslator interface { +// ObjectManager is used to convert virtual to physical names and vice versa +type ObjectManager interface { // IsManaged determines if a physical object is managed by the vcluster IsManaged(context.Context, client.Object) (bool, error) - - // VirtualToHost translates a virtual name to a physical name - VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName - - // HostToVirtual translates a physical name to a virtual name - HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName } // MetadataTranslator is used to convert metadata between virtual and physical objects and vice versa @@ -47,9 +40,6 @@ type NamespacedTranslator interface { // EventRecorder returns EventRecorder() record.EventRecorder - // RegisterIndices registers the default indices for the syncer - RegisterIndices(ctx *syncercontext.RegisterContext) error - // SyncToHostCreate creates the given pObj in the target namespace SyncToHostCreate(ctx *syncercontext.SyncContext, vObj, pObj client.Object) (ctrl.Result, error) diff --git a/pkg/integrations/metricsserver/metricsserver.go b/pkg/integrations/metricsserver/metricsserver.go index c369518dd6..cd328e7252 100644 --- a/pkg/integrations/metricsserver/metricsserver.go +++ b/pkg/integrations/metricsserver/metricsserver.go @@ -9,6 +9,7 @@ import ( "github.com/loft-sh/vcluster/pkg/apiservice" "github.com/loft-sh/vcluster/pkg/config" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/server/filters" "github.com/loft-sh/vcluster/pkg/server/handler" requestpkg "github.com/loft-sh/vcluster/pkg/util/request" @@ -169,13 +170,12 @@ func handleMetricsServerProxyRequest( // request is for get particular pod if info.Resource == PodResource && info.Verb == RequestVerbGet { - namespace := translate.Default.PhysicalNamespace(info.Namespace) - name := translate.Default.PhysicalName(info.Name, info.Namespace) + nameNamespace := mappings.VirtualToHost(info.Name, info.Namespace, mappings.Pods()) metricsServerProxy.resourceType = PodResource // replace the translated name and namespace - splitted[5] = namespace - splitted[7] = name + splitted[5] = nameNamespace.Namespace + splitted[7] = nameNamespace.Name req.URL.Path = strings.Join(splitted, "/") } @@ -390,12 +390,7 @@ func (p *serverProxy) rewritePodMetricsTableData(data []byte) { filteredTableRows := []metav1.TableRow{} for _, vPod := range p.podsInNamespace { - key := types.NamespacedName{ - Name: translate.Default.PhysicalName(vPod.Name, vPod.Namespace), - Namespace: translate.Default.PhysicalNamespace(vPod.Namespace), - } - - rowData, found := hostPodMap[key] + rowData, found := hostPodMap[mappings.VirtualToHost(vPod.Name, vPod.Namespace, mappings.Pods())] if found { // translate the data for the given index rowData.Cells[0] = vPod.Name @@ -449,12 +444,7 @@ func (p *serverProxy) rewritePodMetricsListData(data []byte) { } for _, vPod := range p.podsInNamespace { - key := types.NamespacedName{ - Name: translate.Default.PhysicalName(vPod.Name, vPod.Namespace), - Namespace: translate.Default.PhysicalNamespace(vPod.Namespace), - } - - podMetric, found := hostPodMap[key] + podMetric, found := hostPodMap[mappings.VirtualToHost(vPod.Name, vPod.Namespace, mappings.Pods())] if found { // translate back pod metric podMetric.Name = vPod.Name diff --git a/pkg/mappings/generic/cluster.go b/pkg/mappings/generic/cluster.go new file mode 100644 index 0000000000..951f0d291f --- /dev/null +++ b/pkg/mappings/generic/cluster.go @@ -0,0 +1,77 @@ +package generic + +import ( + context2 "context" + "fmt" + + "github.com/loft-sh/vcluster/pkg/constants" + synccontext "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/clienthelper" + "github.com/loft-sh/vcluster/pkg/util/translate" + "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) { + gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) + if err != nil { + return nil, fmt.Errorf("retrieve GVK for object failed: %w", err) + } + + return &clusterMapper{ + obj: obj, + gvk: gvk, + nameTranslator: nameTranslator, + virtualClient: ctx.VirtualManager.GetClient(), + }, nil +} + +type clusterMapper struct { + gvk schema.GroupVersionKind + obj client.Object + nameTranslator translate.PhysicalNameClusterFunc + virtualClient client.Client +} + +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), + } +} + +func (n *clusterMapper) HostToVirtual(ctx context2.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { + if pObj != nil { + pAnnotations := pObj.GetAnnotations() + if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { + return types.NamespacedName{ + Namespace: pAnnotations[translate.NamespaceAnnotation], + Name: pAnnotations[translate.NameAnnotation], + } + } + } + + vObj := n.obj.DeepCopyObject().(client.Object) + err := clienthelper.GetByIndex(ctx, n.virtualClient, vObj, constants.IndexByPhysicalName, req.Name) + if err != nil { + return types.NamespacedName{} + } + + return types.NamespacedName{ + Namespace: vObj.GetNamespace(), + Name: vObj.GetName(), + } +} diff --git a/pkg/mappings/generic/mirror.go b/pkg/mappings/generic/mirror.go new file mode 100644 index 0000000000..84fb145717 --- /dev/null +++ b/pkg/mappings/generic/mirror.go @@ -0,0 +1,45 @@ +package generic + +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" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/apiutil" +) + +func NewMirrorPhysicalMapper(obj client.Object) (mappings.Mapper, error) { + gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) + if err != nil { + return nil, fmt.Errorf("retrieve GVK for object failed: %w", err) + } + + return &mirrorPhysicalMapper{ + gvk: gvk, + }, nil +} + +type mirrorPhysicalMapper struct { + gvk schema.GroupVersionKind +} + +func (n *mirrorPhysicalMapper) Init(_ *synccontext.RegisterContext) error { + return nil +} + +func (n *mirrorPhysicalMapper) GroupVersionKind() schema.GroupVersionKind { + return n.gvk +} + +func (n *mirrorPhysicalMapper) VirtualToHost(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { + return req +} + +func (n *mirrorPhysicalMapper) HostToVirtual(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { + return req +} diff --git a/pkg/mappings/generic/namespaced.go b/pkg/mappings/generic/namespaced.go new file mode 100644 index 0000000000..e2ff790aa4 --- /dev/null +++ b/pkg/mappings/generic/namespaced.go @@ -0,0 +1,78 @@ +package generic + +import ( + context2 "context" + "fmt" + + "github.com/loft-sh/vcluster/pkg/constants" + synccontext "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/clienthelper" + "github.com/loft-sh/vcluster/pkg/util/translate" + "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) { + gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) + if err != nil { + return nil, fmt.Errorf("retrieve GVK for object failed: %w", err) + } + + return &namespacedMapper{ + translateName: translateName, + virtualClient: ctx.VirtualManager.GetClient(), + obj: obj, + gvk: gvk, + }, nil +} + +type namespacedMapper struct { + translateName translate.PhysicalNameFunc + virtualClient client.Client + obj client.Object + gvk schema.GroupVersionKind +} + +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), + Name: n.translateName(req.Name, req.Namespace), + } +} + +func (n *namespacedMapper) HostToVirtual(ctx context2.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { + if pObj != nil { + pAnnotations := pObj.GetAnnotations() + if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { + return types.NamespacedName{ + Namespace: pAnnotations[translate.NamespaceAnnotation], + Name: pAnnotations[translate.NameAnnotation], + } + } + } + + vObj := n.obj.DeepCopyObject().(client.Object) + err := clienthelper.GetByIndex(ctx, n.virtualClient, vObj, constants.IndexByPhysicalName, req.Namespace+"/"+req.Name) + if err != nil { + return types.NamespacedName{} + } + + return types.NamespacedName{ + Namespace: vObj.GetNamespace(), + Name: vObj.GetName(), + } +} diff --git a/pkg/mappings/mappings.go b/pkg/mappings/mappings.go new file mode 100644 index 0000000000..ab3313558c --- /dev/null +++ b/pkg/mappings/mappings.go @@ -0,0 +1,110 @@ +package mappings + +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" + schedulingv1 "k8s.io/api/scheduling/v1" + storagev1 "k8s.io/api/storage/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// Default is the global instance that holds all mappings +var Default = &Store{ + mappers: map[schema.GroupVersionKind]Mapper{}, +} + +// Mapper holds the mapping logic for an object +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 + + // HostToVirtual translates a physical name to a virtual name + HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName +} + +func Has(gvk schema.GroupVersionKind) bool { + return Default.Has(gvk) +} + +func ByGVK(gvk schema.GroupVersionKind) Mapper { + return Default.ByGVK(gvk) +} + +func CSIStorageCapacities() Mapper { + return Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("CSIStorageCapacity")) +} + +func VolumeSnapshotContents() Mapper { + return Default.ByGVK(volumesnapshotv1.SchemeGroupVersion.WithKind("VolumeSnapshotContent")) +} + +func VolumeSnapshots() Mapper { + return Default.ByGVK(volumesnapshotv1.SchemeGroupVersion.WithKind("VolumeSnapshot")) +} + +func Events() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Event")) +} + +func ConfigMaps() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("ConfigMap")) +} + +func Secrets() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Secret")) +} + +func Endpoints() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Endpoints")) +} + +func Services() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Service")) +} + +func ServiceAccounts() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("ServiceAccount")) +} + +func Pods() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("Pod")) +} + +func PersistentVolumes() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("PersistentVolume")) +} + +func StorageClasses() Mapper { + return Default.ByGVK(storagev1.SchemeGroupVersion.WithKind("StorageClass")) +} + +func PersistentVolumeClaims() Mapper { + return Default.ByGVK(corev1.SchemeGroupVersion.WithKind("PersistentVolumeClaim")) +} + +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 +} + +func VirtualToHost(vName, vNamespace string, mapper Mapper) types.NamespacedName { + return mapper.VirtualToHost(context.TODO(), types.NamespacedName{Name: vName, Namespace: vNamespace}, nil) +} diff --git a/pkg/mappings/registermappings/register.go b/pkg/mappings/registermappings/register.go new file mode 100644 index 0000000000..e961f225f6 --- /dev/null +++ b/pkg/mappings/registermappings/register.go @@ -0,0 +1,53 @@ +package registermappings + +import ( + "fmt" + + synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "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, +} + +func RegisterMappings(ctx *synccontext.RegisterContext) error { + for _, register := range mappings { + if register == nil { + continue + } + + err := register(ctx) + if err != nil { + return fmt.Errorf("register mapping: %w", err) + } + } + + return nil +} diff --git a/pkg/mappings/resources/configmaps.go b/pkg/mappings/resources/configmaps.go new file mode 100644 index 0000000000..d479001ee8 --- /dev/null +++ b/pkg/mappings/resources/configmaps.go @@ -0,0 +1,64 @@ +package resources + +import ( + "context" + + "github.com/loft-sh/vcluster/pkg/constants" + 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" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func RegisterConfigMapsMapper(ctx *synccontext.RegisterContext) error { + mapper, err := generic.NewNamespacedMapper(ctx, &corev1.ConfigMap{}, translate.Default.PhysicalName) + if err != nil { + return 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 { + 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())} + }) +} + +func (s *configMapsMapper) VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { + if !translate.Default.SingleNamespaceTarget() && req.Name == "kube-root-ca.crt" { + return types.NamespacedName{ + Name: translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName), + Namespace: s.Mapper.VirtualToHost(ctx, req, vObj).Namespace, + } + } + + return s.Mapper.VirtualToHost(ctx, req, vObj) +} + +func (s *configMapsMapper) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { + if !translate.Default.SingleNamespaceTarget() && req.Name == translate.SafeConcatName("vcluster", "kube-root-ca.crt", "x", translate.VClusterName) { + return types.NamespacedName{ + Name: "kube-root-ca.crt", + Namespace: s.Mapper.HostToVirtual(ctx, req, pObj).Namespace, + } + } else if !translate.Default.SingleNamespaceTarget() && req.Name == "kube-root-ca.crt" { + // ignore kube-root-ca.crt from host + return types.NamespacedName{} + } + + return s.Mapper.HostToVirtual(ctx, req, pObj) +} diff --git a/pkg/mappings/resources/csidrivers.go b/pkg/mappings/resources/csidrivers.go new file mode 100644 index 0000000000..2c61b6ad1d --- /dev/null +++ b/pkg/mappings/resources/csidrivers.go @@ -0,0 +1,17 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/csinodes.go b/pkg/mappings/resources/csinodes.go new file mode 100644 index 0000000000..2d7d039b36 --- /dev/null +++ b/pkg/mappings/resources/csinodes.go @@ -0,0 +1,17 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/csistoragecapacities.go b/pkg/mappings/resources/csistoragecapacities.go new file mode 100644 index 0000000000..e54215b658 --- /dev/null +++ b/pkg/mappings/resources/csistoragecapacities.go @@ -0,0 +1,66 @@ +package resources + +import ( + "context" + + "github.com/loft-sh/vcluster/pkg/constants" + synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "github.com/loft-sh/vcluster/pkg/mappings" + "github.com/loft-sh/vcluster/pkg/util/clienthelper" + "github.com/loft-sh/vcluster/pkg/util/translate" + storagev1 "k8s.io/api/storage/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var gvk = storagev1.SchemeGroupVersion.WithKind("CSIStorageCapacity") + +func RegisterCSIStorageCapacitiesMapper(ctx *synccontext.RegisterContext) error { + return mappings.Default.AddMapper(&csiStorageCapacitiesMapper{ + physicalClient: ctx.PhysicalManager.GetClient(), + }) +} + +type csiStorageCapacitiesMapper struct { + physicalClient client.Client +} + +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} + }) +} + +func (s *csiStorageCapacitiesMapper) HostToVirtual(_ context.Context, req types.NamespacedName, _ client.Object) types.NamespacedName { + return types.NamespacedName{Name: translate.SafeConcatName(req.Name, "x", req.Namespace), Namespace: "kube-system"} +} + +func (s *csiStorageCapacitiesMapper) VirtualToHost(ctx context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { + // if the virtual object is annotated with the physical name and namespace, return that + if vObj != nil { + vAnnotations := vObj.GetAnnotations() + if vAnnotations != nil && vAnnotations[translate.NameAnnotation] != "" { + return types.NamespacedName{ + Namespace: vAnnotations[translate.NamespaceAnnotation], + Name: vAnnotations[translate.NameAnnotation], + } + } + } + + sc := &storagev1.CSIStorageCapacity{} + pObj := sc.DeepCopyObject().(client.Object) + err := clienthelper.GetByIndex(ctx, s.physicalClient, pObj, constants.IndexByVirtualName, req.Name) + if err != nil { + return types.NamespacedName{} + } + + return types.NamespacedName{ + Namespace: pObj.GetNamespace(), + Name: pObj.GetName(), + } +} diff --git a/pkg/mappings/resources/endpoints.go b/pkg/mappings/resources/endpoints.go new file mode 100644 index 0000000000..3e047070ec --- /dev/null +++ b/pkg/mappings/resources/endpoints.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/events.go b/pkg/mappings/resources/events.go new file mode 100644 index 0000000000..d7e0c207a6 --- /dev/null +++ b/pkg/mappings/resources/events.go @@ -0,0 +1,151 @@ +package resources + +import ( + "context" + "errors" + "fmt" + "strings" + + synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" + "github.com/loft-sh/vcluster/pkg/mappings" + corev1 "k8s.io/api/core/v1" + kerrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var AcceptedKinds = map[schema.GroupVersionKind]bool{ + corev1.SchemeGroupVersion.WithKind("Pod"): true, + corev1.SchemeGroupVersion.WithKind("Service"): true, + corev1.SchemeGroupVersion.WithKind("Endpoint"): true, + corev1.SchemeGroupVersion.WithKind("Secret"): true, + corev1.SchemeGroupVersion.WithKind("ConfigMap"): true, +} + +func RegisterEventsMapper(ctx *synccontext.RegisterContext) error { + return mappings.Default.AddMapper(&eventMapper{ + virtualClient: ctx.VirtualManager.GetClient(), + }) +} + +type eventMapper struct { + virtualClient client.Client +} + +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{} +} + +func (s *eventMapper) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { + involvedObject, err := GetInvolvedObject(ctx, s.virtualClient, pObj) + if err != nil { + err = IgnoreAcceptableErrors(err) + if err != nil { + klog.Infof("Error retrieving involved object for %s/%s: %v", req.Namespace, req.Name, err) + } + + return types.NamespacedName{} + } else if involvedObject == nil { + return types.NamespacedName{} + } + + pEvent, ok := pObj.(*corev1.Event) + if !ok { + return types.NamespacedName{} + } + + return types.NamespacedName{ + Namespace: involvedObject.GetNamespace(), + Name: HostEventNameToVirtual(pEvent.GetName(), pEvent.InvolvedObject.Name, involvedObject.GetName()), + } +} + +func HostEventNameToVirtual(hostName string, hostInvolvedObjectName, virtualInvolvedObjectName string) string { + // replace name of object + if strings.HasPrefix(hostName, hostInvolvedObjectName) { + hostName = strings.Replace(hostName, hostInvolvedObjectName, virtualInvolvedObjectName, 1) + } + + return hostName +} + +var ( + ErrNilPhysicalObject = errors.New("events: nil pObject") + ErrKindNotAccepted = errors.New("events: kind not accpted") + ErrNotFound = errors.New("events: not found") +) + +func IgnoreAcceptableErrors(err error) error { + if errors.Is(err, ErrNilPhysicalObject) || + errors.Is(err, ErrKindNotAccepted) || + errors.Is(err, ErrNotFound) { + return nil + } + + return err +} + +// GetInvolvedObject returns the related object from the vCLuster. +// Alternatively returns a ErrNilPhysicalObject, ErrKindNotAccepted or ErrNotFound. +func GetInvolvedObject(ctx context.Context, virtualClient client.Client, pObj client.Object) (metav1.Object, error) { + if pObj == nil { + return nil, ErrNilPhysicalObject + } + + pEvent, ok := pObj.(*corev1.Event) + if !ok { + return nil, errors.New("object is not of type event") + } + + // check if the involved object is accepted + gvk := pEvent.InvolvedObject.GroupVersionKind() + if !AcceptedKinds[gvk] { + return nil, ErrKindNotAccepted + } + + // create new virtual object + vInvolvedObj, err := virtualClient.Scheme().New(gvk) + if err != nil { + return nil, err + } + + // get involved object + vName := mappings.Default.ByGVK(gvk).HostToVirtual(ctx, types.NamespacedName{ + Namespace: pEvent.Namespace, + Name: pEvent.InvolvedObject.Name, + }, nil) + if vName.Name == "" { + return nil, ErrNotFound + } + + // get virtual object + err = virtualClient.Get(ctx, vName, vInvolvedObj.(client.Object)) + if err != nil { + if !kerrors.IsNotFound(err) { + return nil, err + } + + return nil, fmt.Errorf("%w: %w", ErrNotFound, err) + } + + // we found the related object + m, err := meta.Accessor(vInvolvedObj) + if err != nil { + return nil, err + } + + return m, nil +} diff --git a/pkg/mappings/resources/generic.go b/pkg/mappings/resources/generic.go new file mode 100644 index 0000000000..b078621745 --- /dev/null +++ b/pkg/mappings/resources/generic.go @@ -0,0 +1,35 @@ +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 new file mode 100644 index 0000000000..26337a55c5 --- /dev/null +++ b/pkg/mappings/resources/ingressclasses.go @@ -0,0 +1,17 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/ingresses.go b/pkg/mappings/resources/ingresses.go new file mode 100644 index 0000000000..98aa20a323 --- /dev/null +++ b/pkg/mappings/resources/ingresses.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/ingresses_legacy.go b/pkg/mappings/resources/ingresses_legacy.go new file mode 100644 index 0000000000..0f4a5e385d --- /dev/null +++ b/pkg/mappings/resources/ingresses_legacy.go @@ -0,0 +1,18 @@ +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 new file mode 100644 index 0000000000..98887c7191 --- /dev/null +++ b/pkg/mappings/resources/namespaces.go @@ -0,0 +1,21 @@ +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" + corev1 "k8s.io/api/core/v1" + "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 { + 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 new file mode 100644 index 0000000000..b333d65d5f --- /dev/null +++ b/pkg/mappings/resources/networkpolicies.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/nodes.go b/pkg/mappings/resources/nodes.go new file mode 100644 index 0000000000..2ec31df28e --- /dev/null +++ b/pkg/mappings/resources/nodes.go @@ -0,0 +1,17 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/persistentvolumeclaims.go b/pkg/mappings/resources/persistentvolumeclaims.go new file mode 100644 index 0000000000..3ef0e1f81f --- /dev/null +++ b/pkg/mappings/resources/persistentvolumeclaims.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/persistentvolumes.go b/pkg/mappings/resources/persistentvolumes.go new file mode 100644 index 0000000000..5f4f7d3ee5 --- /dev/null +++ b/pkg/mappings/resources/persistentvolumes.go @@ -0,0 +1,76 @@ +package resources + +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" + "github.com/loft-sh/vcluster/pkg/util/clienthelper" + "github.com/loft-sh/vcluster/pkg/util/translate" + corev1 "k8s.io/api/core/v1" + kerrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func RegisterPersistentVolumesMapper(ctx *synccontext.RegisterContext) error { + mapper, err := generic.NewClusterMapper(ctx, &corev1.PersistentVolume{}, translatePersistentVolumeName) + if err != nil { + return err + } + + return mappings.Default.AddMapper(&persistentVolumeMapper{ + Mapper: mapper, + + virtualClient: ctx.VirtualManager.GetClient(), + }) +} + +type persistentVolumeMapper struct { + mappings.Mapper + + virtualClient client.Client +} + +func (s *persistentVolumeMapper) VirtualToHost(_ context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { + return types.NamespacedName{Name: translatePersistentVolumeName(req.Name, vObj)} +} + +func (s *persistentVolumeMapper) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { + if pObj != nil { + pAnnotations := pObj.GetAnnotations() + if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { + return types.NamespacedName{ + Name: pAnnotations[translate.NameAnnotation], + } + } + } + + vObj := &corev1.PersistentVolume{} + err := clienthelper.GetByIndex(ctx, s.virtualClient, vObj, constants.IndexByPhysicalName, req.Name) + if err != nil { + if !kerrors.IsNotFound(err) { + return types.NamespacedName{} + } + + return types.NamespacedName{Name: req.Name} + } + + return types.NamespacedName{Name: vObj.GetName()} +} + +func translatePersistentVolumeName(name string, vObj client.Object) string { + if vObj == nil { + return name + } + + vPv, ok := vObj.(*corev1.PersistentVolume) + if !ok || vPv.Annotations == nil || vPv.Annotations[persistentvolumes.HostClusterPersistentVolumeAnnotation] == "" { + return translate.Default.PhysicalNameClusterScoped(name) + } + + return vPv.Annotations[persistentvolumes.HostClusterPersistentVolumeAnnotation] +} diff --git a/pkg/mappings/resources/poddisruptionbudgets.go b/pkg/mappings/resources/poddisruptionbudgets.go new file mode 100644 index 0000000000..e166930b52 --- /dev/null +++ b/pkg/mappings/resources/poddisruptionbudgets.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/pods.go b/pkg/mappings/resources/pods.go new file mode 100644 index 0000000000..3acd13445f --- /dev/null +++ b/pkg/mappings/resources/pods.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/priorityclasses.go b/pkg/mappings/resources/priorityclasses.go new file mode 100644 index 0000000000..5ba7d70926 --- /dev/null +++ b/pkg/mappings/resources/priorityclasses.go @@ -0,0 +1,30 @@ +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" + schedulingv1 "k8s.io/api/scheduling/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func RegisterPriorityClassesMapper(ctx *synccontext.RegisterContext) error { + var ( + mapper mappings.Mapper + err 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 mappings.Default.AddMapper(mapper) +} diff --git a/pkg/mappings/resources/secrets.go b/pkg/mappings/resources/secrets.go new file mode 100644 index 0000000000..1b7dfe254e --- /dev/null +++ b/pkg/mappings/resources/secrets.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/serviceaccounts.go b/pkg/mappings/resources/serviceaccounts.go new file mode 100644 index 0000000000..37c04937b6 --- /dev/null +++ b/pkg/mappings/resources/serviceaccounts.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/services.go b/pkg/mappings/resources/services.go new file mode 100644 index 0000000000..4809213853 --- /dev/null +++ b/pkg/mappings/resources/services.go @@ -0,0 +1,18 @@ +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" + 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) +} diff --git a/pkg/mappings/resources/storageclasses.go b/pkg/mappings/resources/storageclasses.go new file mode 100644 index 0000000000..43f224bfea --- /dev/null +++ b/pkg/mappings/resources/storageclasses.go @@ -0,0 +1,29 @@ +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" + storagev1 "k8s.io/api/storage/v1" + "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 + } + + return mappings.Default.AddMapper(mapper) +} diff --git a/pkg/mappings/resources/volumesnapshotclasses.go b/pkg/mappings/resources/volumesnapshotclasses.go new file mode 100644 index 0000000000..779b5f867a --- /dev/null +++ b/pkg/mappings/resources/volumesnapshotclasses.go @@ -0,0 +1,17 @@ +package resources + +import ( + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" + 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" +) + +func RegisterVolumeSnapshotClassesMapper(_ *synccontext.RegisterContext) error { + mapper, err := generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshotClass{}) + if err != nil { + return err + } + + return mappings.Default.AddMapper(mapper) +} diff --git a/pkg/mappings/resources/volumesnapshotcontents.go b/pkg/mappings/resources/volumesnapshotcontents.go new file mode 100644 index 0000000000..3c2c156f6b --- /dev/null +++ b/pkg/mappings/resources/volumesnapshotcontents.go @@ -0,0 +1,85 @@ +package resources + +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/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" + "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/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func RegisterVolumeSnapshotContentsMapper(ctx *synccontext.RegisterContext) error { + if !ctx.Config.Sync.ToHost.VolumeSnapshots.Enabled { + mapper, err := generic.NewMirrorPhysicalMapper(&volumesnapshotv1.VolumeSnapshotContent{}) + if err != nil { + return err + } + + return mappings.Default.AddMapper(mapper) + } + + mapper, err := generic.NewClusterMapper(ctx, &volumesnapshotv1.VolumeSnapshotContent{}, translateVolumeSnapshotContentName) + if err != nil { + return err + } + + return mappings.Default.AddMapper(&volumeSnapshotContentMapper{ + Mapper: mapper, + + virtualClient: ctx.VirtualManager.GetClient(), + }) +} + +type volumeSnapshotContentMapper struct { + mappings.Mapper + + virtualClient client.Client +} + +func (s *volumeSnapshotContentMapper) VirtualToHost(_ context.Context, req types.NamespacedName, vObj client.Object) types.NamespacedName { + return types.NamespacedName{Name: translateVolumeSnapshotContentName(req.Name, vObj)} +} + +func (s *volumeSnapshotContentMapper) HostToVirtual(ctx context.Context, req types.NamespacedName, pObj client.Object) types.NamespacedName { + if pObj != nil { + pAnnotations := pObj.GetAnnotations() + if pAnnotations != nil && pAnnotations[translate.NameAnnotation] != "" { + return types.NamespacedName{ + Name: pAnnotations[translate.NameAnnotation], + } + } + } + + vObj := &volumesnapshotv1.VolumeSnapshotContent{} + err := clienthelper.GetByIndex(ctx, s.virtualClient, vObj, constants.IndexByPhysicalName, req.Name) + if err != nil { + if !kerrors.IsNotFound(err) { + return types.NamespacedName{} + } + + return types.NamespacedName{Name: req.Name} + } + + return types.NamespacedName{Name: vObj.GetName()} +} + +func translateVolumeSnapshotContentName(name string, vObj client.Object) string { + if vObj == nil { + return name + } + + vVSC, ok := vObj.(*volumesnapshotv1.VolumeSnapshotContent) + if !ok || vVSC.Annotations == nil || vVSC.Annotations[volumesnapshotcontents.HostClusterVSCAnnotation] == "" { + return translate.Default.PhysicalNameClusterScoped(name) + } + + return vVSC.Annotations[volumesnapshotcontents.HostClusterVSCAnnotation] +} diff --git a/pkg/mappings/resources/volumesnapshots.go b/pkg/mappings/resources/volumesnapshots.go new file mode 100644 index 0000000000..930d301a8e --- /dev/null +++ b/pkg/mappings/resources/volumesnapshots.go @@ -0,0 +1,26 @@ +package resources + +import ( + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" + 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" +) + +func RegisterVolumeSnapshotsMapper(ctx *synccontext.RegisterContext) error { + var ( + mapper mappings.Mapper + err 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 mappings.Default.AddMapper(mapper) +} diff --git a/pkg/mappings/store.go b/pkg/mappings/store.go new file mode 100644 index 0000000000..81733b1b21 --- /dev/null +++ b/pkg/mappings/store.go @@ -0,0 +1,54 @@ +package mappings + +import ( + "fmt" + "sync" + + "github.com/loft-sh/vcluster/pkg/scheme" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/apiutil" +) + +type Store struct { + mappers map[schema.GroupVersionKind]Mapper + + m sync.Mutex +} + +func (m *Store) AddMapper(mapper Mapper) error { + m.m.Lock() + defer m.m.Unlock() + + m.mappers[mapper.GroupVersionKind()] = mapper + return nil +} + +func (m *Store) ByObject(obj client.Object) Mapper { + gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) + if err != nil { + panic(fmt.Sprintf("Couldn't retrieve GVK from object: %v", err)) + } + + return m.ByGVK(gvk) +} + +func (m *Store) Has(gvk schema.GroupVersionKind) bool { + m.m.Lock() + defer m.m.Unlock() + + _, ok := m.mappers[gvk] + return ok +} + +func (m *Store) ByGVK(gvk schema.GroupVersionKind) Mapper { + m.m.Lock() + defer m.m.Unlock() + + mapper, ok := m.mappers[gvk] + if !ok { + panic(fmt.Sprintf("Mapper with GVK %s not found", gvk.String())) + } + + return mapper +} diff --git a/pkg/server/filters/redirect.go b/pkg/server/filters/redirect.go index 8ece3ce50c..b757ea076d 100644 --- a/pkg/server/filters/redirect.go +++ b/pkg/server/filters/redirect.go @@ -6,9 +6,9 @@ import ( "strings" "github.com/loft-sh/vcluster/pkg/authorization/delegatingauthorizer" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/server/handler" requestpkg "github.com/loft-sh/vcluster/pkg/util/request" - "github.com/loft-sh/vcluster/pkg/util/translate" corev1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -54,8 +54,9 @@ func WithRedirect(h http.Handler, localConfig *rest.Config, localScheme *runtime } // exchange namespace & name - splitted[4] = translate.Default.PhysicalNamespace(info.Namespace) - splitted[6] = translate.Default.PhysicalName(splitted[6], info.Namespace) + pName := mappings.VirtualToHost(splitted[6], info.Namespace, mappings.Pods()) + splitted[4] = pName.Namespace + splitted[6] = pName.Name req.URL.Path = strings.Join(splitted, "/") // we have to add a trailing slash here, because otherwise the diff --git a/pkg/server/filters/service.go b/pkg/server/filters/service.go index 337bc11471..54ac5b4ef9 100644 --- a/pkg/server/filters/service.go +++ b/pkg/server/filters/service.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/loft-sh/vcluster/pkg/controllers/resources/services" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/util/clienthelper" "github.com/loft-sh/vcluster/pkg/util/encoding" "github.com/loft-sh/vcluster/pkg/util/random" @@ -139,7 +140,8 @@ func updateService(req *http.Request, decoder encoding.Decoder, localClient clie // okay now we have to change the physical service pService := &corev1.Service{} - err = localClient.Get(ctx, client.ObjectKey{Namespace: translate.Default.PhysicalNamespace(oldVService.Namespace), Name: translate.Default.PhysicalName(oldVService.Name, oldVService.Namespace)}, pService) + pServiceName := mappings.VirtualToHost(oldVService.Name, oldVService.Namespace, mappings.Services()) + err = localClient.Get(ctx, client.ObjectKey{Namespace: pServiceName.Namespace, Name: pServiceName.Name}, pService) if err != nil { if kerrors.IsNotFound(err) { return nil, kerrors.NewNotFound(corev1.Resource("services"), oldVService.Name) @@ -206,7 +208,7 @@ func createService(req *http.Request, decoder encoding.Decoder, localClient clie vService.Name = vService.GenerateName + random.String(5) } - newService := translate.Default.ApplyMetadata(vService, syncedLabels).(*corev1.Service) + newService := translate.Default.ApplyMetadata(vService, mappings.Services().VirtualToHost(req.Context(), mappings.NamespacedName(vService), vService), syncedLabels).(*corev1.Service) if newService.Annotations == nil { newService.Annotations = map[string]string{} } diff --git a/pkg/setup/controller_context.go b/pkg/setup/controller_context.go index 6e40b936f0..833e461975 100644 --- a/pkg/setup/controller_context.go +++ b/pkg/setup/controller_context.go @@ -8,11 +8,13 @@ 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" @@ -98,6 +100,12 @@ 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/types/types.go b/pkg/types/types.go index c38a5e5b29..6abf59fde2 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -25,7 +25,7 @@ type Exporter interface { type Syncer interface { Object - translator.NameTranslator + translator.ObjectManager // SyncToHost is called when a virtual object was created and needs to be synced down to the physical cluster SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) diff --git a/pkg/util/translate/multi_namespace.go b/pkg/util/translate/multi_namespace.go index 1fa725e4eb..9e3c96f3bc 100644 --- a/pkg/util/translate/multi_namespace.go +++ b/pkg/util/translate/multi_namespace.go @@ -13,6 +13,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" ) @@ -63,7 +64,7 @@ func (s *multiNamespace) PhysicalNameClusterScoped(name string) string { return SafeConcatName("vcluster", name, "x", s.currentNamespace, "x", VClusterName) } -func (s *multiNamespace) IsManaged(obj runtime.Object, _ PhysicalNameFunc) bool { +func (s *multiNamespace) IsManaged(obj runtime.Object) bool { metaAccessor, err := meta.Accessor(obj) if err != nil { return false @@ -193,10 +194,8 @@ func (s *multiNamespace) LegacyGetTargetNamespace() (string, error) { return "", fmt.Errorf("unsupported feature in multi-namespace mode") } -func (s *multiNamespace) ApplyMetadata(vObj client.Object, syncedLabels []string, excludedAnnotations ...string) client.Object { - pObj, err := s.SetupMetadataWithName(vObj, func(_ string, vObj client.Object) string { - return s.objectPhysicalName(vObj) - }) +func (s *multiNamespace) ApplyMetadata(vObj client.Object, name types.NamespacedName, syncedLabels []string, excludedAnnotations ...string) client.Object { + pObj, err := s.SetupMetadataWithName(vObj, name) if err != nil { return nil } @@ -247,7 +246,7 @@ func (s *multiNamespace) TranslateLabels(fromLabels map[string]string, _ string, return fromLabels } -func (s *multiNamespace) SetupMetadataWithName(vObj client.Object, translator PhysicalNameTranslator) (client.Object, error) { +func (s *multiNamespace) SetupMetadataWithName(vObj client.Object, name types.NamespacedName) (client.Object, error) { target := vObj.DeepCopyObject().(client.Object) m, err := meta.Accessor(target) if err != nil { @@ -256,9 +255,9 @@ func (s *multiNamespace) SetupMetadataWithName(vObj client.Object, translator Ph // reset metadata & translate name and namespace ResetObjectMetadata(m) - m.SetName(translator(m.GetName(), vObj)) + m.SetName(name.Name) if vObj.GetNamespace() != "" { - m.SetNamespace(s.PhysicalNamespace(vObj.GetNamespace())) + m.SetNamespace(name.Namespace) } return target, nil diff --git a/pkg/util/translate/single_namespace.go b/pkg/util/translate/single_namespace.go index 50686a9c27..cc60aa10b3 100644 --- a/pkg/util/translate/single_namespace.go +++ b/pkg/util/translate/single_namespace.go @@ -1,17 +1,21 @@ package translate import ( + "context" "crypto/sha256" "encoding/hex" "regexp" "strings" + "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/scheme" "github.com/loft-sh/vcluster/pkg/util/base36" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" ) @@ -75,31 +79,38 @@ func (s *singleNamespace) PhysicalNameClusterScoped(name string) string { return SafeConcatName("vcluster", name, "x", s.targetNamespace, "x", VClusterName) } -func (s *singleNamespace) IsManaged(obj runtime.Object, physicalName PhysicalNameFunc) bool { +func (s *singleNamespace) IsManaged(obj runtime.Object) bool { metaAccessor, err := meta.Accessor(obj) if err != nil { return false } else if metaAccessor.GetNamespace() != "" && !s.IsTargetedNamespace(metaAccessor.GetNamespace()) { return false + } else if metaAccessor.GetLabels()[MarkerLabel] != VClusterName { + return false } // vcluster has not synced the object IF: // If object-name annotation is not set OR // If object-name annotation is different from actual name - if metaAccessor.GetAnnotations()[NameAnnotation] == "" || - metaAccessor.GetName() != physicalName(metaAccessor.GetAnnotations()[NameAnnotation], metaAccessor.GetAnnotations()[NamespaceAnnotation]) { - return false + gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) + if err == nil && mappings.Has(gvk) { + if metaAccessor.GetAnnotations()[NameAnnotation] == "" || metaAccessor.GetName() != mappings.VirtualToHostName(metaAccessor.GetAnnotations()[NameAnnotation], metaAccessor.GetAnnotations()[NamespaceAnnotation], mappings.ByGVK(gvk)) { + klog.FromContext(context.TODO()).V(1).Info("Host object doesn't match, because name annotations is wrong", + "object", metaAccessor.GetName(), + "existingName", metaAccessor.GetName(), + "expectedName", mappings.VirtualToHostName(metaAccessor.GetAnnotations()[NameAnnotation], metaAccessor.GetAnnotations()[NamespaceAnnotation], mappings.ByGVK(gvk))) + return false + } } // if kind doesn't match vCluster has probably not synced the object if metaAccessor.GetAnnotations()[KindAnnotation] != "" { - gvk, err := apiutil.GVKForObject(obj, scheme.Scheme) if err == nil && gvk.String() != metaAccessor.GetAnnotations()[KindAnnotation] { return false } } - return metaAccessor.GetLabels()[MarkerLabel] == VClusterName + return true } func (s *singleNamespace) IsManagedCluster(obj runtime.Object) bool { @@ -191,10 +202,8 @@ func (s *singleNamespace) LegacyGetTargetNamespace() (string, error) { return s.targetNamespace, nil } -func (s *singleNamespace) ApplyMetadata(vObj client.Object, syncedLabels []string, excludedAnnotations ...string) client.Object { - pObj, err := s.SetupMetadataWithName(vObj, func(_ string, vObj client.Object) string { - return s.objectPhysicalName(vObj) - }) +func (s *singleNamespace) ApplyMetadata(vObj client.Object, name types.NamespacedName, syncedLabels []string, excludedAnnotations ...string) client.Object { + pObj, err := s.SetupMetadataWithName(vObj, name) if err != nil { return nil } @@ -288,7 +297,7 @@ func (s *singleNamespace) TranslateLabels(fromLabels map[string]string, vNamespa return newLabels } -func (s *singleNamespace) SetupMetadataWithName(vObj client.Object, translator PhysicalNameTranslator) (client.Object, error) { +func (s *singleNamespace) SetupMetadataWithName(vObj client.Object, name types.NamespacedName) (client.Object, error) { target := vObj.DeepCopyObject().(client.Object) m, err := meta.Accessor(target) if err != nil { @@ -297,9 +306,9 @@ func (s *singleNamespace) SetupMetadataWithName(vObj client.Object, translator P // reset metadata & translate name and namespace ResetObjectMetadata(m) - m.SetName(translator(m.GetName(), vObj)) + m.SetName(name.Name) if vObj.GetNamespace() != "" { - m.SetNamespace(s.PhysicalNamespace(vObj.GetNamespace())) + m.SetNamespace(name.Namespace) // set owning stateful set if defined if Owner != nil { diff --git a/pkg/util/translate/types.go b/pkg/util/translate/types.go index 37f5651209..0b4e014be1 100644 --- a/pkg/util/translate/types.go +++ b/pkg/util/translate/types.go @@ -19,12 +19,15 @@ var Default Translator = &singleNamespace{} // PhysicalNameFunc is a definition to translate a name type PhysicalNameFunc func(vName, vNamespace string) string +// PhysicalNameClusterFunc is a definition to translate a cluster name +type PhysicalNameClusterFunc func(vName string, vObj client.Object) string + type Translator interface { // SingleNamespaceTarget signals if we sync all objects into a single namespace SingleNamespaceTarget() bool // IsManaged checks if the object is managed by vcluster - IsManaged(obj runtime.Object, physicalName PhysicalNameFunc) bool + IsManaged(obj runtime.Object) bool // IsManagedCluster checks if the cluster scoped object is managed by vcluster IsManagedCluster(obj runtime.Object) bool @@ -52,7 +55,7 @@ type Translator interface { TranslateLabelSelectorCluster(labelSelector *metav1.LabelSelector) *metav1.LabelSelector // ApplyMetadata translates the metadata including labels and annotations initially from virtual to physical - ApplyMetadata(vObj client.Object, syncedLabels []string, excludedAnnotations ...string) client.Object + ApplyMetadata(vObj client.Object, name types.NamespacedName, syncedLabels []string, excludedAnnotations ...string) client.Object // ApplyMetadataUpdate updates the physical objects metadata and signals if there were any changes ApplyMetadataUpdate(vObj client.Object, pObj client.Object, syncedLabels []string, excludedAnnotations ...string) (bool, map[string]string, map[string]string) @@ -70,7 +73,7 @@ type Translator interface { TranslateLabelSelector(labelSelector *metav1.LabelSelector) *metav1.LabelSelector // SetupMetadataWithName is similar to ApplyMetadata with a custom name translator and doesn't apply annotations and labels - SetupMetadataWithName(vObj client.Object, translator PhysicalNameTranslator) (client.Object, error) + SetupMetadataWithName(vObj client.Object, name types.NamespacedName) (client.Object, error) // LegacyGetTargetNamespace returns in the case of a single namespace the target namespace, but fails // if vcluster is syncing to multiple namespaces. @@ -79,8 +82,5 @@ type Translator interface { ConvertLabelKey(string) string } -// PhysicalNameTranslator transforms a virtual cluster name to a physical name -type PhysicalNameTranslator func(vName string, vObj client.Object) string - // PhysicalNamespacedNameTranslator transforms a virtual cluster name to a physical name type PhysicalNamespacedNameTranslator func(vNN types.NamespacedName, vObj client.Object) string From 0ca7e34e58b13c6953575ae4b541ffd490fe2052 Mon Sep 17 00:00:00 2001 From: Fabian Kramm Date: Mon, 15 Jul 2024 17:20:45 +0200 Subject: [PATCH 3/4] 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 } From 26e62df97d29a74dc36242d8995120f43eff5b9f Mon Sep 17 00:00:00 2001 From: Fabian Kramm Date: Thu, 18 Jul 2024 09:33:05 +0200 Subject: [PATCH 4/4] refactor: embedd context --- .../advanced-topics/plugins-development.mdx | 6 +- pkg/apiservice/generic.go | 10 ++-- pkg/config/controller_context.go | 2 +- pkg/controllers/deploy/start.go | 4 +- pkg/controllers/generic/export_syncer.go | 22 +++---- pkg/controllers/generic/import_syncer.go | 30 +++++----- pkg/controllers/register.go | 4 +- .../resources/configmaps/syncer.go | 10 ++-- .../resources/csidrivers/syncer.go | 8 +-- pkg/controllers/resources/csinodes/syncer.go | 14 ++--- .../resources/csistoragecapacities/syncer.go | 14 ++--- .../csistoragecapacities/translate.go | 6 +- pkg/controllers/resources/endpoints/syncer.go | 14 ++--- .../resources/endpoints/syncer_test.go | 2 +- .../resources/endpoints/translate.go | 10 ++-- pkg/controllers/resources/events/syncer.go | 10 ++-- .../resources/ingressclasses/syncer.go | 8 +-- pkg/controllers/resources/ingresses/syncer.go | 15 ++--- .../resources/ingresses/syncer_test.go | 16 ++--- .../resources/ingresses/translate.go | 16 ++--- .../resources/namespaces/syncer.go | 8 +-- .../resources/networkpolicies/syncer.go | 4 +- .../resources/nodes/fake_syncer.go | 10 ++-- .../resources/nodes/fake_syncer_test.go | 2 +- pkg/controllers/resources/nodes/syncer.go | 26 ++++---- .../resources/nodes/syncer_test.go | 6 +- pkg/controllers/resources/nodes/translate.go | 4 +- .../persistentvolumeclaims/syncer.go | 22 +++---- .../persistentvolumeclaims/syncer_test.go | 4 +- .../persistentvolumeclaims/translate.go | 12 ++-- .../persistentvolumes/fake_syncer.go | 12 ++-- .../persistentvolumes/fake_syncer_test.go | 2 +- .../resources/persistentvolumes/syncer.go | 34 +++++------ .../persistentvolumes/syncer_test.go | 8 +-- .../resources/persistentvolumes/translate.go | 16 ++--- .../resources/poddisruptionbudgets/syncer.go | 4 +- pkg/controllers/resources/pods/conditions.go | 2 +- .../resources/pods/ephemeral_containers.go | 6 +- pkg/controllers/resources/pods/syncer.go | 30 +++++----- pkg/controllers/resources/pods/translate.go | 10 ++-- .../pods/translate/sa_token_secret.go | 8 +-- .../resources/pods/translate/translator.go | 60 +++++++++---------- pkg/controllers/resources/pods/util.go | 10 ++-- .../resources/priorityclasses/syncer.go | 6 +- pkg/controllers/resources/register.go | 2 +- pkg/controllers/resources/secrets/syncer.go | 26 ++++---- .../resources/serviceaccounts/syncer.go | 4 +- pkg/controllers/resources/services/syncer.go | 12 ++-- .../resources/services/syncer_test.go | 8 +-- .../storageclasses/host_sc_syncer.go | 10 ++-- .../resources/storageclasses/syncer.go | 8 +-- .../volumesnapshotclasses/syncer.go | 10 ++-- .../volumesnapshotcontents/syncer.go | 30 +++++----- .../volumesnapshotcontents/translate.go | 2 +- .../volumesnapshots/volumesnapshots/syncer.go | 18 +++--- .../volumesnapshots/translate.go | 8 +-- pkg/controllers/syncer/context/context.go | 7 ++- pkg/controllers/syncer/syncer.go | 10 ++-- pkg/controllers/syncer/syncer_test.go | 4 +- .../translator/namespaced_translator.go | 4 +- .../metricsserver/metricsserver.go | 6 +- pkg/leaderelection/leaderelection.go | 4 +- pkg/mappings/generic/mapper.go | 2 +- pkg/mappings/resources/configmaps.go | 2 +- .../resources/csistoragecapacities.go | 4 +- pkg/mappings/types.go | 8 +-- pkg/patcher/patcher.go | 4 +- pkg/server/filters/redirect.go | 2 +- pkg/server/filters/service.go | 2 +- pkg/server/indicies.go | 4 +- pkg/server/server.go | 6 +- pkg/setup/controllers.go | 2 +- pkg/setup/managers.go | 12 ++-- pkg/setup/proxy.go | 2 +- pkg/specialservices/service_syncer.go | 10 ++-- pkg/util/context/converter.go | 2 +- pkg/util/translate/single_namespace.go | 4 +- 77 files changed, 384 insertions(+), 382 deletions(-) diff --git a/docs/pages/advanced-topics/plugins-development.mdx b/docs/pages/advanced-topics/plugins-development.mdx index 3f4a5613e0..aa31b09944 100644 --- a/docs/pages/advanced-topics/plugins-development.mdx +++ b/docs/pages/advanced-topics/plugins-development.mdx @@ -94,11 +94,11 @@ The `SyncDown` function mentioned above is called by the vCluster SDK when a giv ``` func (s *carSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostCreate(ctx, vObj, s.TranslateMetadata(ctx.Context, vObj).(*examplev1.Car)) + return s.SyncToHostCreate(ctx, vObj, s.TranslateMetadata(ctx, vObj).(*examplev1.Car)) } func (s *carSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostUpdate(ctx, vObj, s.translateUpdate(ctx.Context, pObj.(*examplev1.Car), vObj.(*examplev1.Car))) + return s.SyncToHostUpdate(ctx, vObj, s.translateUpdate(ctx, pObj.(*examplev1.Car), vObj.(*examplev1.Car))) } ``` The `TranslateMetadata` function used above produces a Car object that will be created in the host cluster. It is a deep copy of the Car from vCluster, but with certain metadata modifications - the name and labels are transformed, some vCluster labels and annotations are added, many metadata fields are stripped (uid, resourceVersion, etc.). @@ -109,7 +109,7 @@ Next, we need to implement code that will handle the updates of the Car. When a ``` func (s *carSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostUpdate(ctx, vObj, s.translateUpdate(ctx.Context, pObj.(*examplev1.Car), vObj.(*examplev1.Car))) + return s.SyncToHostUpdate(ctx, vObj, s.translateUpdate(ctx, pObj.(*examplev1.Car), vObj.(*examplev1.Car))) } func (s *carSyncer) translateUpdate(ctx context.Context, pObj, vObj *examplev1.Car) *examplev1.Car { diff --git a/pkg/apiservice/generic.go b/pkg/apiservice/generic.go index 35d2cd0395..3b5f427dfa 100644 --- a/pkg/apiservice/generic.go +++ b/pkg/apiservice/generic.go @@ -168,7 +168,7 @@ func StartAPIServiceProxy(ctx *config.ControllerContext, targetServiceName, targ Handler: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { // we only allow traffic to discovery paths if !isAPIServiceProxyPathAllowed(request.Method, request.URL.Path) { - klog.FromContext(ctx.Context).Info("Denied access to api service proxy at path", "path", request.URL.Path, "method", request.Method) + klog.FromContext(ctx).Info("Denied access to api service proxy at path", "path", request.URL.Path, "method", request.Method) responsewriters.ErrorNegotiated( kerrors.NewForbidden(metav1.SchemeGroupVersion.WithResource("proxy").GroupResource(), "proxy", fmt.Errorf("paths other than discovery paths are not allowed")), s, @@ -187,7 +187,7 @@ func StartAPIServiceProxy(ctx *config.ControllerContext, targetServiceName, targ klog.Infof("Listening apiservice proxy on localhost:%d...", hostPort) err = server.ListenAndServeTLS(tlsCertFile, tlsKeyFile) if err != nil { - klog.FromContext(ctx.Context).Error(err, "error listening for apiservice proxy and serve tls") + klog.FromContext(ctx).Error(err, "error listening for apiservice proxy and serve tls") os.Exit(1) } }() @@ -232,14 +232,14 @@ func isAPIServiceProxyPathAllowed(method, path string) bool { } func RegisterAPIService(ctx *config.ControllerContext, serviceName string, hostPort int, groupVersion schema.GroupVersion) error { - return applyOperation(ctx.Context, createOperation(ctx, serviceName, hostPort, groupVersion)) + return applyOperation(ctx, createOperation(ctx, serviceName, hostPort, groupVersion)) } func DeregisterAPIService(ctx *config.ControllerContext, groupVersion schema.GroupVersion) error { // check if the api service should get created - exists := checkExistingAPIService(ctx.Context, ctx.VirtualManager.GetClient(), groupVersion) + exists := checkExistingAPIService(ctx, ctx.VirtualManager.GetClient(), groupVersion) if exists { - return applyOperation(ctx.Context, deleteOperation(ctx, groupVersion)) + return applyOperation(ctx, deleteOperation(ctx, groupVersion)) } return nil diff --git a/pkg/config/controller_context.go b/pkg/config/controller_context.go index 5e1575fcce..4e40eca011 100644 --- a/pkg/config/controller_context.go +++ b/pkg/config/controller_context.go @@ -11,7 +11,7 @@ import ( ) type ControllerContext struct { - Context context.Context + context.Context LocalManager ctrl.Manager VirtualManager ctrl.Manager diff --git a/pkg/controllers/deploy/start.go b/pkg/controllers/deploy/start.go index 811e808a88..0728befd15 100644 --- a/pkg/controllers/deploy/start.go +++ b/pkg/controllers/deploy/start.go @@ -23,7 +23,7 @@ func RegisterInitManifestsController(controllerCtx *config.ControllerContext) er return err } - helmBinaryPath, err := helmdownloader.GetHelmBinaryPath(controllerCtx.Context, log.GetInstance()) + helmBinaryPath, err := helmdownloader.GetHelmBinaryPath(controllerCtx, log.GetInstance()) if err != nil { return err } @@ -37,7 +37,7 @@ func RegisterInitManifestsController(controllerCtx *config.ControllerContext) er go func() { for { - result, err := controller.Apply(controllerCtx.Context, controllerCtx.Config) + result, err := controller.Apply(controllerCtx, controllerCtx.Config) if err != nil { klog.Errorf("Error deploying manifests: %v", err) time.Sleep(time.Second * 10) diff --git a/pkg/controllers/generic/export_syncer.go b/pkg/controllers/generic/export_syncer.go index ddf9ba33ae..65d6d63e06 100644 --- a/pkg/controllers/generic/export_syncer.go +++ b/pkg/controllers/generic/export_syncer.go @@ -40,7 +40,7 @@ func CreateExporters(ctx *config.ControllerContext) error { for _, exportConfig := range exporterConfig.Exports { _, hasStatusSubresource, err := translate.EnsureCRDFromPhysicalCluster( - registerCtx.Context, + registerCtx, registerCtx.PhysicalManager.GetConfig(), registerCtx.VirtualManager.GetConfig(), schema.FromAPIVersionAndKind(exportConfig.APIVersion, exportConfig.Kind)) @@ -129,7 +129,7 @@ func BuildCustomExporter( replaceWhenInvalid bool, ) (syncertypes.Object, error) { _, hasStatusSubresource, err := translate.EnsureCRDFromPhysicalCluster( - registerCtx.Context, + registerCtx, registerCtx.PhysicalManager.GetConfig(), registerCtx.VirtualManager.GetConfig(), gvk) @@ -171,7 +171,7 @@ func (f *exporter) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) // apply object to physical cluster ctx.Log.Infof("Create physical %s %s/%s, since it is missing, but virtual object exists", f.gvk.Kind, vObj.GetNamespace(), vObj.GetName()) - pObj, err := f.patcher.ApplyPatches(ctx.Context, vObj, nil, f) + pObj, err := f.patcher.ApplyPatches(ctx, vObj, nil, f) if kerrors.IsConflict(err) { return ctrl.Result{Requeue: true}, nil } @@ -187,7 +187,7 @@ func (f *exporter) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) } // wait here for vObj to be created - err = wait.PollUntilContextTimeout(ctx.Context, time.Millisecond*10, time.Second, true, func(pollContext context.Context) (done bool, err error) { + err = wait.PollUntilContextTimeout(ctx, time.Millisecond*10, time.Second, true, func(pollContext context.Context) (done bool, err error) { err = ctx.PhysicalClient.Get(pollContext, types.NamespacedName{ Namespace: pObj.GetNamespace(), Name: pObj.GetName(), @@ -213,7 +213,7 @@ func (f *exporter) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c // check if virtual object is not matching anymore if !f.objectMatches(vObj) { ctx.Log.Infof("delete physical %s %s/%s, because it is not used anymore", f.gvk.Kind, pObj.GetNamespace(), pObj.GetName()) - err := ctx.PhysicalClient.Delete(ctx.Context, pObj, &client.DeleteOptions{ + err := ctx.PhysicalClient.Delete(ctx, pObj, &client.DeleteOptions{ GracePeriodSeconds: &[]int64{0}[0], }) if err != nil { @@ -228,12 +228,12 @@ func (f *exporter) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c if vObj.GetDeletionTimestamp() != nil || pObj.GetDeletionTimestamp() != nil { if pObj.GetDeletionTimestamp() == nil { ctx.Log.Infof("delete physical object %s/%s, because the virtual object is being deleted", pObj.GetNamespace(), pObj.GetName()) - if err := ctx.PhysicalClient.Delete(ctx.Context, pObj); err != nil { + if err := ctx.PhysicalClient.Delete(ctx, pObj); err != nil { return ctrl.Result{}, err } } else if vObj.GetDeletionTimestamp() == nil { ctx.Log.Infof("delete virtual object %s/%s, because physical object %s/%s is being deleted", vObj.GetNamespace(), vObj.GetName(), pObj.GetNamespace(), pObj.GetName()) - if err := ctx.VirtualClient.Delete(ctx.Context, vObj); err != nil { + if err := ctx.VirtualClient.Delete(ctx, vObj); err != nil { return ctrl.Result{}, nil } } @@ -242,7 +242,7 @@ func (f *exporter) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c } // apply reverse patches - result, err := f.patcher.ApplyReversePatches(ctx.Context, vObj, pObj, f) + result, err := f.patcher.ApplyReversePatches(ctx, vObj, pObj, f) if err != nil { if kerrors.IsConflict(err) { return ctrl.Result{Requeue: true}, nil @@ -263,14 +263,14 @@ func (f *exporter) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c } // apply patches - pObj, err = f.patcher.ApplyPatches(ctx.Context, vObj, pObj, f) + pObj, err = f.patcher.ApplyPatches(ctx, vObj, pObj, f) err = IgnoreAcceptableErrors(err) if err != nil { // when invalid, auto delete and recreate to recover if kerrors.IsInvalid(err) && f.replaceWhenInvalid { // Replace the object ctx.Log.Infof("Replace physical object, because apply failed: %v", err) - err = ctx.PhysicalClient.Delete(ctx.Context, pObj, &client.DeleteOptions{ + err = ctx.PhysicalClient.Delete(ctx, pObj, &client.DeleteOptions{ GracePeriodSeconds: &[]int64{0}[0], }) if err != nil { @@ -295,7 +295,7 @@ func (f *exporter) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c var _ syncertypes.ToVirtualSyncer = &exporter{} func (f *exporter) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { - isManaged, err := f.NamespacedTranslator.IsManaged(ctx.Context, pObj) + isManaged, err := f.NamespacedTranslator.IsManaged(ctx, pObj) if err != nil { return ctrl.Result{}, err } else if !isManaged { diff --git a/pkg/controllers/generic/import_syncer.go b/pkg/controllers/generic/import_syncer.go index b82b6eede9..e6ecb67a43 100644 --- a/pkg/controllers/generic/import_syncer.go +++ b/pkg/controllers/generic/import_syncer.go @@ -53,7 +53,7 @@ func CreateImporters(ctx *config.ControllerContext) error { // don't skip even if scheme.Recognizes(gvk) to ensure scope for builtin // cluster scoped resources is registered and set properly isClusterScoped, hasStatusSubresource, err := translate.EnsureCRDFromPhysicalCluster( - registerCtx.Context, + registerCtx, registerCtx.PhysicalManager.GetConfig(), registerCtx.VirtualManager.GetConfig(), gvk) @@ -117,7 +117,7 @@ func BuildCustomImporter( replaceWhenInvalid bool, ) (syncertypes.Object, error) { isClusterScoped, hasStatusSubresource, err := translate.EnsureCRDFromPhysicalCluster( - registerCtx.Context, + registerCtx, registerCtx.PhysicalManager.GetConfig(), registerCtx.VirtualManager.GetConfig(), gvk, @@ -187,7 +187,7 @@ func (s *importer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Objec pAnnotations := pObj.GetAnnotations() if pAnnotations != nil && pAnnotations[translate.ControllerLabel] == s.Name() && !s.syncerOptions.IsClusterScopedCRD { // only delete pObj if its not cluster scoped ctx.Log.Infof("Delete physical %s %s/%s, since virtual is missing, but physical object was already synced", s.gvk.Kind, pObj.GetNamespace(), pObj.GetName()) - err := ctx.PhysicalClient.Delete(ctx.Context, pObj) + err := ctx.PhysicalClient.Delete(ctx, pObj) if err != nil && !kerrors.IsNotFound(err) { return ctrl.Result{}, err } @@ -197,7 +197,7 @@ func (s *importer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Objec // apply object to virtual cluster ctx.Log.Infof("Create virtual %s, since it is missing, but physical object %s/%s exists", s.gvk.Kind, pObj.GetNamespace(), pObj.GetName()) - vObj, err := s.patcher.ApplyPatches(ctx.Context, pObj, nil, s) + vObj, err := s.patcher.ApplyPatches(ctx, pObj, nil, s) if err != nil { if err := IgnoreAcceptableErrors(err); err != nil { return ctrl.Result{}, nil @@ -217,7 +217,7 @@ func (s *importer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Objec } // wait here for vObj to be created - err = wait.PollUntilContextTimeout(ctx.Context, time.Millisecond*10, time.Second, true, func(syncContext context.Context) (done bool, err error) { + err = wait.PollUntilContextTimeout(ctx, time.Millisecond*10, time.Second, true, func(syncContext context.Context) (done bool, err error) { err = ctx.VirtualClient.Get(syncContext, types.NamespacedName{ Namespace: vObj.GetNamespace(), Name: vObj.GetName(), @@ -254,7 +254,7 @@ func (s *importer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) // should we delete the object? if vObj.GetDeletionTimestamp() == nil { ctx.Log.Infof("remove virtual %s %s/%s, because object should get deleted", s.gvk.Kind, vObj.GetNamespace(), vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } // remove finalizers if there are any @@ -262,11 +262,11 @@ func (s *importer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) // delete the finalizer here so that the object can be deleted vObj.SetFinalizers([]string{}) ctx.Log.Infof("remove virtual %s %s/%s finalizers, because object should get deleted", s.gvk.Kind, vObj.GetNamespace(), vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Update(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Update(ctx, vObj) } // force deletion - err := ctx.VirtualClient.Delete(ctx.Context, vObj, &client.DeleteOptions{ + err := ctx.VirtualClient.Delete(ctx, vObj, &client.DeleteOptions{ GracePeriodSeconds: &[]int64{0}[0], }) if kerrors.IsNotFound(err) { @@ -277,7 +277,7 @@ func (s *importer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) func (s *importer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { // check if physical object is managed by this import controller - managed, err := s.IsManaged(ctx.Context, pObj) + managed, err := s.IsManaged(ctx, pObj) if err != nil { return ctrl.Result{}, err } else if !managed { @@ -288,12 +288,12 @@ func (s *importer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c if vObj.GetDeletionTimestamp() != nil || pObj.GetDeletionTimestamp() != nil { if pObj.GetDeletionTimestamp() == nil && !s.syncerOptions.IsClusterScopedCRD { ctx.Log.Infof("delete physical object %s/%s, because the virtual object is being deleted", pObj.GetNamespace(), pObj.GetName()) - if err := ctx.PhysicalClient.Delete(ctx.Context, pObj); err != nil { + if err := ctx.PhysicalClient.Delete(ctx, pObj); err != nil { return ctrl.Result{}, err } } else if vObj.GetDeletionTimestamp() == nil { ctx.Log.Infof("delete virtual object %s/%s, because physical object is being deleted", vObj.GetNamespace(), vObj.GetName()) - if err := ctx.VirtualClient.Delete(ctx.Context, vObj); err != nil { + if err := ctx.VirtualClient.Delete(ctx, vObj); err != nil { return ctrl.Result{}, nil } } @@ -302,7 +302,7 @@ func (s *importer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c } // execute reverse patches - result, err := s.patcher.ApplyReversePatches(ctx.Context, pObj, vObj, s) + result, err := s.patcher.ApplyReversePatches(ctx, pObj, vObj, s) if err != nil { if kerrors.IsInvalid(err) { ctx.Log.Infof("Warning: this message could indicate a timing issue with no significant impact, or a bug. Please report this if your resource never reaches the expected state. Error message: failed to patch virtual %s %s/%s: %v", s.gvk.Kind, vObj.GetNamespace(), vObj.GetName(), err) @@ -319,14 +319,14 @@ func (s *importer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj c } // apply patches - vObj, err = s.patcher.ApplyPatches(ctx.Context, pObj, vObj, s) + vObj, err = s.patcher.ApplyPatches(ctx, pObj, vObj, s) err = IgnoreAcceptableErrors(err) if err != nil { // when invalid, auto delete and recreate to recover if kerrors.IsInvalid(err) && s.replaceWhenInvalid { // Replace the object ctx.Log.Infof("Replace virtual object, because of apply failed: %v", err) - err = ctx.VirtualClient.Delete(ctx.Context, vObj, &client.DeleteOptions{ + err = ctx.VirtualClient.Delete(ctx, vObj, &client.DeleteOptions{ GracePeriodSeconds: &[]int64{0}[0], }) if err != nil { @@ -508,5 +508,5 @@ func (s *importer) addAnnotationsToPhysicalObject(ctx *synccontext.SyncContext, } ctx.Log.Infof("Patch controlled-by annotation on %s %s/%s", s.gvk.Kind, pObj.GetNamespace(), pObj.GetName()) - return ctx.PhysicalClient.Patch(ctx.Context, pObj, patch) + return ctx.PhysicalClient.Patch(ctx, pObj, patch) } diff --git a/pkg/controllers/register.go b/pkg/controllers/register.go index 5279a37a56..e899a2ad98 100644 --- a/pkg/controllers/register.go +++ b/pkg/controllers/register.go @@ -147,14 +147,14 @@ func registerServiceSyncControllers(ctx *config.ControllerContext) error { // start the manager go func() { - err := globalLocalManager.Start(ctx.Context) + err := globalLocalManager.Start(ctx) if err != nil { panic(err) } }() // Wait for caches to be synced - globalLocalManager.GetCache().WaitForCacheSync(ctx.Context) + globalLocalManager.GetCache().WaitForCacheSync(ctx) // register controller controller := &servicesync.ServiceSyncer{ diff --git a/pkg/controllers/resources/configmaps/syncer.go b/pkg/controllers/resources/configmaps/syncer.go index 6035b72afd..a7b8170c35 100644 --- a/pkg/controllers/resources/configmaps/syncer.go +++ b/pkg/controllers/resources/configmaps/syncer.go @@ -39,7 +39,7 @@ var _ syncer.IndicesRegisterer = &configMapSyncer{} func (s *configMapSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { // index pods by their used config maps - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByConfigMap, func(rawObj client.Object) []string { + return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &corev1.Pod{}, constants.IndexByConfigMap, func(rawObj client.Object) []string { pod := rawObj.(*corev1.Pod) return configNamesFromPod(pod) }) @@ -59,7 +59,7 @@ func (s *configMapSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.O return ctrl.Result{}, nil } - return s.SyncToHostCreate(ctx, vObj, s.translate(ctx.Context, vObj.(*corev1.ConfigMap))) + return s.SyncToHostCreate(ctx, vObj, s.translate(ctx, vObj.(*corev1.ConfigMap))) } func (s *configMapSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { @@ -73,7 +73,7 @@ func (s *configMapSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, } ctx.Log.Infof("delete physical config map %s/%s, because it is not used anymore", pConfigMap.GetNamespace(), pConfigMap.GetName()) - err = ctx.PhysicalClient.Delete(ctx.Context, pObj) + err = ctx.PhysicalClient.Delete(ctx, pObj) if err != nil { ctx.Log.Infof("error deleting physical object %s/%s in physical cluster: %v", pConfigMap.GetNamespace(), pConfigMap.GetName(), err) return ctrl.Result{}, err @@ -82,7 +82,7 @@ func (s *configMapSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, return ctrl.Result{}, nil } - newConfigMap := s.translateUpdate(ctx.Context, pObj.(*corev1.ConfigMap), vObj.(*corev1.ConfigMap)) + newConfigMap := s.translateUpdate(ctx, pObj.(*corev1.ConfigMap), vObj.(*corev1.ConfigMap)) if newConfigMap != nil { translator.PrintChanges(pObj, newConfigMap, ctx.Log) } @@ -102,7 +102,7 @@ func (s *configMapSyncer) isConfigMapUsed(ctx *synccontext.SyncContext, vObj run } podList := &corev1.PodList{} - err := ctx.VirtualClient.List(ctx.Context, podList, client.MatchingFields{constants.IndexByConfigMap: configMap.Namespace + "/" + configMap.Name}) + err := ctx.VirtualClient.List(ctx, podList, client.MatchingFields{constants.IndexByConfigMap: configMap.Namespace + "/" + configMap.Name}) if err != nil { return false, err } diff --git a/pkg/controllers/resources/csidrivers/syncer.go b/pkg/controllers/resources/csidrivers/syncer.go index 684f84c6db..ab7a3dfadf 100644 --- a/pkg/controllers/resources/csidrivers/syncer.go +++ b/pkg/controllers/resources/csidrivers/syncer.go @@ -28,9 +28,9 @@ var _ syncer.ToVirtualSyncer = &csidriverSyncer{} var _ syncer.Syncer = &csidriverSyncer{} func (s *csidriverSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { - vObj := s.translateBackwards(ctx.Context, pObj.(*storagev1.CSIDriver)) + vObj := s.translateBackwards(ctx, pObj.(*storagev1.CSIDriver)) ctx.Log.Infof("create CSIDriver %s, because it does not exist in virtual cluster", vObj.Name) - return ctrl.Result{}, ctx.VirtualClient.Create(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (s *csidriverSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (_ ctrl.Result, retErr error) { @@ -44,12 +44,12 @@ func (s *csidriverSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, } }() // check if there is a change - s.translateUpdateBackwards(ctx.Context, pObj.(*storagev1.CSIDriver), vObj.(*storagev1.CSIDriver)) + s.translateUpdateBackwards(ctx, pObj.(*storagev1.CSIDriver), vObj.(*storagev1.CSIDriver)) return ctrl.Result{}, nil } func (s *csidriverSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { ctx.Log.Infof("delete virtual CSIDriver %s, because physical object is missing", vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } diff --git a/pkg/controllers/resources/csinodes/syncer.go b/pkg/controllers/resources/csinodes/syncer.go index 6af11bff58..e60088433c 100644 --- a/pkg/controllers/resources/csinodes/syncer.go +++ b/pkg/controllers/resources/csinodes/syncer.go @@ -35,15 +35,15 @@ var _ syncertypes.Syncer = &csinodeSyncer{} func (s *csinodeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { // look up matching node name, don't sync if not found node := &corev1.Node{} - err := s.virtualClient.Get(ctx.Context, types.NamespacedName{Name: pObj.GetName()}, node) + err := s.virtualClient.Get(ctx, types.NamespacedName{Name: pObj.GetName()}, node) if kerrors.IsNotFound(err) { return ctrl.Result{}, nil } else if err != nil { return ctrl.Result{}, err } - vObj := s.translateBackwards(ctx.Context, pObj.(*storagev1.CSINode)) + vObj := s.translateBackwards(ctx, pObj.(*storagev1.CSINode)) ctx.Log.Infof("create CSINode %s, because it does not exist in virtual cluster", vObj.Name) - return ctrl.Result{}, ctx.VirtualClient.Create(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (s *csinodeSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (_ ctrl.Result, retErr error) { @@ -63,21 +63,21 @@ func (s *csinodeSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, v }() node := &corev1.Node{} - err = s.virtualClient.Get(ctx.Context, types.NamespacedName{Name: pObj.GetName()}, node) + err = s.virtualClient.Get(ctx, types.NamespacedName{Name: pObj.GetName()}, node) if kerrors.IsNotFound(err) { ctx.Log.Infof("delete virtual CSINode %s, because corresponding node object is missing", vObj.GetName()) shouldPatch = false - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } else if err != nil { return ctrl.Result{}, err } // check if there is a change - s.translateUpdateBackwards(ctx.Context, pObj.(*storagev1.CSINode), vObj.(*storagev1.CSINode)) + s.translateUpdateBackwards(ctx, pObj.(*storagev1.CSINode), vObj.(*storagev1.CSINode)) return ctrl.Result{}, nil } func (s *csinodeSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { ctx.Log.Infof("delete virtual CSINode %s, because physical object is missing", vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } diff --git a/pkg/controllers/resources/csistoragecapacities/syncer.go b/pkg/controllers/resources/csistoragecapacities/syncer.go index b74eaa4075..f52fb8d275 100644 --- a/pkg/controllers/resources/csistoragecapacities/syncer.go +++ b/pkg/controllers/resources/csistoragecapacities/syncer.go @@ -52,7 +52,7 @@ func (s *csistoragecapacitySyncer) SyncToVirtual(ctx *synccontext.SyncContext, p } ctx.Log.Infof("create CSIStorageCapacity %s, because it does not exist in virtual cluster", vObj.Name) - return ctrl.Result{}, ctx.VirtualClient.Create(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (s *csistoragecapacitySyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (_ ctrl.Result, retErr error) { @@ -79,7 +79,7 @@ func (s *csistoragecapacitySyncer) Sync(ctx *synccontext.SyncContext, pObj clien } if shouldSkip { - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } return ctrl.Result{}, nil @@ -87,7 +87,7 @@ func (s *csistoragecapacitySyncer) Sync(ctx *synccontext.SyncContext, pObj clien func (s *csistoragecapacitySyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { ctx.Log.Infof("delete virtual CSIStorageCapacity %s, because physical object is missing", vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } func (s *csistoragecapacitySyncer) ModifyController(ctx *synccontext.RegisterContext, builder *builder.Builder) (*builder.Builder, error) { @@ -106,19 +106,19 @@ func (s *csistoragecapacitySyncer) ModifyController(ctx *synccontext.RegisterCon return builder.WatchesRawSource(source.Kind(allNSCache, s.Resource(), &handler.Funcs{ CreateFunc: func(_ context.Context, ce event.CreateEvent, rli workqueue.RateLimitingInterface) { obj := ce.Object - s.enqueuePhysical(ctx.Context, obj, rli) + s.enqueuePhysical(ctx, obj, rli) }, UpdateFunc: func(_ context.Context, ue event.UpdateEvent, rli workqueue.RateLimitingInterface) { obj := ue.ObjectNew - s.enqueuePhysical(ctx.Context, obj, rli) + s.enqueuePhysical(ctx, obj, rli) }, DeleteFunc: func(_ context.Context, de event.DeleteEvent, rli workqueue.RateLimitingInterface) { obj := de.Object - s.enqueuePhysical(ctx.Context, obj, rli) + s.enqueuePhysical(ctx, obj, rli) }, GenericFunc: func(_ context.Context, ge event.GenericEvent, rli workqueue.RateLimitingInterface) { obj := ge.Object - s.enqueuePhysical(ctx.Context, obj, rli) + s.enqueuePhysical(ctx, obj, rli) }, })), nil } diff --git a/pkg/controllers/resources/csistoragecapacities/translate.go b/pkg/controllers/resources/csistoragecapacities/translate.go index 1fc777e420..fad009d017 100644 --- a/pkg/controllers/resources/csistoragecapacities/translate.go +++ b/pkg/controllers/resources/csistoragecapacities/translate.go @@ -17,7 +17,7 @@ import ( func (s *csistoragecapacitySyncer) fetchVirtualStorageClass(ctx *synccontext.SyncContext, physName string) (string, bool, error) { if s.storageClassSyncEnabled { // the csistorage capacity being synced to the virtual cluster needs the name of the virtual storage cluster - vName := mappings.StorageClasses().HostToVirtual(ctx.Context, types.NamespacedName{Name: physName}, nil) + vName := mappings.StorageClasses().HostToVirtual(ctx, types.NamespacedName{Name: physName}, nil) if vName.Name == "" { return "", true, nil } @@ -36,7 +36,7 @@ func (s *csistoragecapacitySyncer) hasMatchingVirtualNodes(ctx *synccontext.Sync if err != nil { return false, err } - err = ctx.VirtualClient.List(ctx.Context, nodeList, client.MatchingLabelsSelector{Selector: selector}) + err = ctx.VirtualClient.List(ctx, nodeList, client.MatchingLabelsSelector{Selector: selector}) if err != nil { return false, err } @@ -56,7 +56,7 @@ func (s *csistoragecapacitySyncer) translateBackwards(ctx *synccontext.SyncConte return nil, shouldSkip, err } - translated, err := s.TranslateMetadata(ctx.Context, pObj.DeepCopy()) + translated, err := s.TranslateMetadata(ctx, pObj.DeepCopy()) if err != nil { return nil, false, fmt.Errorf("failed to translate metatdata backwards: %w", err) } diff --git a/pkg/controllers/resources/endpoints/syncer.go b/pkg/controllers/resources/endpoints/syncer.go index 627e18abf9..27d511ac1a 100644 --- a/pkg/controllers/resources/endpoints/syncer.go +++ b/pkg/controllers/resources/endpoints/syncer.go @@ -30,7 +30,7 @@ type endpointsSyncer struct { } func (s *endpointsSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostCreate(ctx, vObj, s.translate(ctx.Context, vObj)) + return s.SyncToHostCreate(ctx, vObj, s.translate(ctx, vObj)) } func (s *endpointsSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (_ ctrl.Result, retErr error) { @@ -48,7 +48,7 @@ func (s *endpointsSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, } }() - err = s.translateUpdate(ctx.Context, pObj.(*corev1.Endpoints), vObj.(*corev1.Endpoints)) + err = s.translateUpdate(ctx, pObj.(*corev1.Endpoints), vObj.(*corev1.Endpoints)) if err != nil { return ctrl.Result{}, err } @@ -69,7 +69,7 @@ func (s *endpointsSyncer) ReconcileStart(ctx *synccontext.SyncContext, req ctrl. } svc := &corev1.Service{} - err := ctx.VirtualClient.Get(ctx.Context, types.NamespacedName{ + err := ctx.VirtualClient.Get(ctx, types.NamespacedName{ Namespace: req.Namespace, Name: req.Name, }, svc) @@ -82,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, s.VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) + err = ctx.PhysicalClient.Get(ctx, s.VirtualToHost(ctx, req.NamespacedName, nil), endpoints) if err != nil { if !kerrors.IsNotFound(err) { klog.Infof("Error retrieving endpoints: %v", err) @@ -99,7 +99,7 @@ func (s *endpointsSyncer) ReconcileStart(ctx *synccontext.SyncContext, req ctrl. // to the same endpoints resulting in wrong DNS and cluster networking. Hence, deleting the previously // managed endpoints signals the Kubernetes controller to recreate the endpoints from the selector. klog.Infof("Refresh endpoints in physical cluster because they shouldn't be managed by vcluster anymore") - err = ctx.PhysicalClient.Delete(ctx.Context, endpoints) + err = ctx.PhysicalClient.Delete(ctx, endpoints) if err != nil { klog.Infof("Error deleting endpoints %s/%s: %v", endpoints.Namespace, endpoints.Name, err) return true, err @@ -111,10 +111,10 @@ 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, s.VirtualToHost(ctx.Context, req.NamespacedName, nil), endpoints) + err = ctx.PhysicalClient.Get(ctx, s.VirtualToHost(ctx, 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) + err = ctx.PhysicalClient.Delete(ctx, endpoints) if err != nil { klog.Infof("Error deleting endpoints %s/%s: %v", endpoints.Namespace, endpoints.Name, err) return true, err diff --git a/pkg/controllers/resources/endpoints/syncer_test.go b/pkg/controllers/resources/endpoints/syncer_test.go index 2c01273a6f..2b1b52e3a9 100644 --- a/pkg/controllers/resources/endpoints/syncer_test.go +++ b/pkg/controllers/resources/endpoints/syncer_test.go @@ -113,7 +113,7 @@ func TestExistingEndpoints(t *testing.T) { syncController, err := syncer.NewSyncController(ctx, fakeSyncer) assert.NilError(t, err) - _, err = syncController.Reconcile(ctx.Context, ctrl.Request{NamespacedName: types.NamespacedName{ + _, err = syncController.Reconcile(ctx, ctrl.Request{NamespacedName: types.NamespacedName{ Namespace: vEndpoints.Namespace, Name: vEndpoints.Name, }}) diff --git a/pkg/controllers/resources/endpoints/translate.go b/pkg/controllers/resources/endpoints/translate.go index 890a7e19c2..61d1bcd90e 100644 --- a/pkg/controllers/resources/endpoints/translate.go +++ b/pkg/controllers/resources/endpoints/translate.go @@ -11,7 +11,7 @@ import ( func (s *endpointsSyncer) translate(ctx context.Context, vObj client.Object) *corev1.Endpoints { endpoints := s.TranslateMetadata(ctx, vObj).(*corev1.Endpoints) - s.translateSpec(endpoints) + s.translateSpec(ctx, endpoints) // make sure we delete the control-plane.alpha.kubernetes.io/leader annotation // that will disable endpoint slice mirroring otherwise @@ -22,12 +22,12 @@ func (s *endpointsSyncer) translate(ctx context.Context, vObj client.Object) *co return endpoints } -func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) { +func (s *endpointsSyncer) translateSpec(ctx context.Context, endpoints *corev1.Endpoints) { // translate the addresses for i, subset := range endpoints.Subsets { for j, addr := range subset.Addresses { if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" { - nameNamespace := mappings.VirtualToHost(addr.TargetRef.Name, addr.TargetRef.Namespace, mappings.Pods()) + nameNamespace := mappings.VirtualToHost(ctx, addr.TargetRef.Name, addr.TargetRef.Namespace, mappings.Pods()) endpoints.Subsets[i].Addresses[j].TargetRef.Name = nameNamespace.Name endpoints.Subsets[i].Addresses[j].TargetRef.Namespace = nameNamespace.Namespace @@ -38,7 +38,7 @@ func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) { } for j, addr := range subset.NotReadyAddresses { if addr.TargetRef != nil && addr.TargetRef.Kind == "Pod" { - nameNamespace := mappings.VirtualToHost(addr.TargetRef.Name, addr.TargetRef.Namespace, mappings.Pods()) + nameNamespace := mappings.VirtualToHost(ctx, addr.TargetRef.Name, addr.TargetRef.Namespace, mappings.Pods()) endpoints.Subsets[i].NotReadyAddresses[j].TargetRef.Name = nameNamespace.Name endpoints.Subsets[i].NotReadyAddresses[j].TargetRef.Namespace = nameNamespace.Namespace @@ -53,7 +53,7 @@ func (s *endpointsSyncer) translateSpec(endpoints *corev1.Endpoints) { func (s *endpointsSyncer) translateUpdate(ctx context.Context, pObj, vObj *corev1.Endpoints) error { // check subsets translated := vObj.DeepCopy() - s.translateSpec(translated) + s.translateSpec(ctx, translated) if !equality.Semantic.DeepEqual(translated.Subsets, pObj.Subsets) { pObj.Subsets = translated.Subsets } diff --git a/pkg/controllers/resources/events/syncer.go b/pkg/controllers/resources/events/syncer.go index ed7c3e04a9..af7488531b 100644 --- a/pkg/controllers/resources/events/syncer.go +++ b/pkg/controllers/resources/events/syncer.go @@ -60,7 +60,7 @@ func (s *eventSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vOb // update event vOldEvent := vEvent.DeepCopy() - vEvent, err := s.buildVirtualEvent(ctx.Context, pEvent) + vEvent, err := s.buildVirtualEvent(ctx, pEvent) if err != nil { return ctrl.Result{}, resources.IgnoreAcceptableErrors(err) } @@ -77,7 +77,7 @@ func (s *eventSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vOb // check if updated ctx.Log.Infof("update virtual event %s/%s", vEvent.Namespace, vEvent.Name) translator.PrintChanges(vOldEvent, vEvent, ctx.Log) - err = ctx.VirtualClient.Update(ctx.Context, vEvent) + err = ctx.VirtualClient.Update(ctx, vEvent) if err != nil { return ctrl.Result{}, err } @@ -89,14 +89,14 @@ var _ syncer.ToVirtualSyncer = &eventSyncer{} func (s *eventSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { // build the virtual event - vObj, err := s.buildVirtualEvent(ctx.Context, pObj.(*corev1.Event)) + vObj, err := s.buildVirtualEvent(ctx, pObj.(*corev1.Event)) if err != nil { return ctrl.Result{}, resources.IgnoreAcceptableErrors(err) } // make sure namespace is not being deleted namespace := &corev1.Namespace{} - err = ctx.VirtualClient.Get(ctx.Context, client.ObjectKey{Name: vObj.Namespace}, namespace) + err = ctx.VirtualClient.Get(ctx, client.ObjectKey{Name: vObj.Namespace}, namespace) if err != nil { if kerrors.IsNotFound(err) { return ctrl.Result{}, nil @@ -110,7 +110,7 @@ func (s *eventSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Ob // try to create virtual event ctx.Log.Infof("create virtual event %s/%s", vObj.Namespace, vObj.Name) - err = ctx.VirtualClient.Create(ctx.Context, vObj) + err = ctx.VirtualClient.Create(ctx, vObj) if err != nil { return ctrl.Result{}, err } diff --git a/pkg/controllers/resources/ingressclasses/syncer.go b/pkg/controllers/resources/ingressclasses/syncer.go index 2fc38f3162..88b679772e 100644 --- a/pkg/controllers/resources/ingressclasses/syncer.go +++ b/pkg/controllers/resources/ingressclasses/syncer.go @@ -28,9 +28,9 @@ var _ syncer.ToVirtualSyncer = &ingressClassSyncer{} var _ syncer.Syncer = &ingressClassSyncer{} func (i *ingressClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { - vObj := i.createVirtual(ctx.Context, pObj.(*networkingv1.IngressClass)) + vObj := i.createVirtual(ctx, pObj.(*networkingv1.IngressClass)) ctx.Log.Infof("create ingress class %s, because it does not exist in virtual cluster", vObj.Name) - return ctrl.Result{}, ctx.VirtualClient.Create(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (i *ingressClassSyncer) Sync(ctx *synccontext.SyncContext, pObj, vObj client.Object) (_ ctrl.Result, retErr error) { @@ -48,11 +48,11 @@ func (i *ingressClassSyncer) Sync(ctx *synccontext.SyncContext, pObj, vObj clien // cast objects pIngressClass, vIngressClass, _, _ := synccontext.Cast[*networkingv1.IngressClass](ctx, pObj, vObj) - i.updateVirtual(ctx.Context, pIngressClass, vIngressClass) + i.updateVirtual(ctx, pIngressClass, vIngressClass) return ctrl.Result{}, nil } func (i *ingressClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { ctx.Log.Infof("delete virtual ingress class %s, because physical object is missing", vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } diff --git a/pkg/controllers/resources/ingresses/syncer.go b/pkg/controllers/resources/ingresses/syncer.go index 6827c0e083..78eac9ce1d 100644 --- a/pkg/controllers/resources/ingresses/syncer.go +++ b/pkg/controllers/resources/ingresses/syncer.go @@ -1,6 +1,7 @@ package ingresses import ( + "context" "fmt" "strings" @@ -33,7 +34,7 @@ type ingressSyncer struct { var _ syncertypes.Syncer = &ingressSyncer{} func (s *ingressSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - pObj, err := s.translate(ctx.Context, vObj.(*networkingv1.Ingress)) + pObj, err := s.translate(ctx, vObj.(*networkingv1.Ingress)) if err != nil { return ctrl.Result{}, err } @@ -59,7 +60,7 @@ 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) + err = s.translateUpdate(ctx, pIngress, vIngress) if err != nil { return ctrl.Result{}, err } @@ -67,9 +68,9 @@ func (s *ingressSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, v return ctrl.Result{}, nil } -func SecretNamesFromIngress(ingress *networkingv1.Ingress) []string { +func SecretNamesFromIngress(ctx context.Context, ingress *networkingv1.Ingress) []string { secrets := []string{} - _, extraSecrets := translateIngressAnnotations(ingress.Annotations, ingress.Namespace) + _, extraSecrets := translateIngressAnnotations(ctx, ingress.Annotations, ingress.Namespace) secrets = append(secrets, extraSecrets...) for _, tls := range ingress.Spec.TLS { if tls.SecretName != "" { @@ -85,7 +86,7 @@ var TranslateAnnotations = map[string]bool{ "nginx.ingress.kubernetes.io/proxy-ssl-secret": true, } -func translateIngressAnnotations(annotations map[string]string, ingressNamespace string) (map[string]string, []string) { +func translateIngressAnnotations(ctx context.Context, annotations map[string]string, ingressNamespace string) (map[string]string, []string) { foundSecrets := []string{} newAnnotations := map[string]string{} for k, v := range annotations { @@ -98,12 +99,12 @@ 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()) + newAnnotations[k] = mappings.VirtualToHostName(ctx, secret, ingressNamespace, mappings.Secrets()) } 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()) + pName := mappings.VirtualToHost(ctx, secret, namespace, mappings.Secrets()) newAnnotations[k] = pName.Namespace + "/" + pName.Name } else { newAnnotations[k] = v diff --git a/pkg/controllers/resources/ingresses/syncer_test.go b/pkg/controllers/resources/ingresses/syncer_test.go index f04610df7e..a3e4bd11bb 100644 --- a/pkg/controllers/resources/ingresses/syncer_test.go +++ b/pkg/controllers/resources/ingresses/syncer_test.go @@ -249,19 +249,19 @@ func TestSync(t *testing.T) { _, err := syncer.(*ingressSyncer).Sync(syncCtx, backwardUpdateIngress, vIngress) assert.NilError(t, err) - err = syncCtx.VirtualClient.Get(syncCtx.Context, types.NamespacedName{Namespace: vIngress.Namespace, Name: vIngress.Name}, vIngress) + err = syncCtx.VirtualClient.Get(syncCtx, types.NamespacedName{Namespace: vIngress.Namespace, Name: vIngress.Name}, vIngress) assert.NilError(t, err) - err = syncCtx.PhysicalClient.Get(syncCtx.Context, types.NamespacedName{Namespace: backwardUpdateIngress.Namespace, Name: backwardUpdateIngress.Name}, backwardUpdateIngress) + err = syncCtx.PhysicalClient.Get(syncCtx, types.NamespacedName{Namespace: backwardUpdateIngress.Namespace, Name: backwardUpdateIngress.Name}, backwardUpdateIngress) assert.NilError(t, err) _, err = syncer.(*ingressSyncer).Sync(syncCtx, backwardUpdateIngress, vIngress) assert.NilError(t, err) - err = syncCtx.VirtualClient.Get(syncCtx.Context, types.NamespacedName{Namespace: vIngress.Namespace, Name: vIngress.Name}, vIngress) + err = syncCtx.VirtualClient.Get(syncCtx, types.NamespacedName{Namespace: vIngress.Namespace, Name: vIngress.Name}, vIngress) assert.NilError(t, err) - err = syncCtx.PhysicalClient.Get(syncCtx.Context, types.NamespacedName{Namespace: backwardUpdateIngress.Namespace, Name: backwardUpdateIngress.Name}, backwardUpdateIngress) + err = syncCtx.PhysicalClient.Get(syncCtx, types.NamespacedName{Namespace: backwardUpdateIngress.Namespace, Name: backwardUpdateIngress.Name}, backwardUpdateIngress) assert.NilError(t, err) _, err = syncer.(*ingressSyncer).Sync(syncCtx, backwardUpdateIngress, vIngress) @@ -350,11 +350,11 @@ func TestSync(t *testing.T) { syncCtx, syncer := generictesting.FakeStartSyncer(t, registerContext, NewSyncer) vIngress := &networkingv1.Ingress{} - err := syncCtx.VirtualClient.Get(syncCtx.Context, types.NamespacedName{Name: baseIngress.Name, Namespace: baseIngress.Namespace}, vIngress) + err := syncCtx.VirtualClient.Get(syncCtx, types.NamespacedName{Name: baseIngress.Name, Namespace: baseIngress.Namespace}, vIngress) assert.NilError(t, err) pIngress := &networkingv1.Ingress{} - err = syncCtx.PhysicalClient.Get(syncCtx.Context, types.NamespacedName{Name: createdIngress.Name, Namespace: createdIngress.Namespace}, pIngress) + err = syncCtx.PhysicalClient.Get(syncCtx, types.NamespacedName{Name: createdIngress.Name, Namespace: createdIngress.Namespace}, pIngress) assert.NilError(t, err) _, err = syncer.(*ingressSyncer).Sync(syncCtx, pIngress, vIngress) @@ -427,11 +427,11 @@ func TestSync(t *testing.T) { syncCtx, syncer := generictesting.FakeStartSyncer(t, registerContext, NewSyncer) vIngress := &networkingv1.Ingress{} - err := syncCtx.VirtualClient.Get(syncCtx.Context, types.NamespacedName{Name: baseIngress.Name, Namespace: baseIngress.Namespace}, vIngress) + err := syncCtx.VirtualClient.Get(syncCtx, types.NamespacedName{Name: baseIngress.Name, Namespace: baseIngress.Namespace}, vIngress) assert.NilError(t, err) pIngress := &networkingv1.Ingress{} - err = syncCtx.PhysicalClient.Get(syncCtx.Context, types.NamespacedName{Name: createdIngress.Name, Namespace: createdIngress.Namespace}, pIngress) + err = syncCtx.PhysicalClient.Get(syncCtx, types.NamespacedName{Name: createdIngress.Name, Namespace: createdIngress.Namespace}, pIngress) assert.NilError(t, err) _, err = syncer.(*ingressSyncer).Sync(syncCtx, pIngress, vIngress) diff --git a/pkg/controllers/resources/ingresses/translate.go b/pkg/controllers/resources/ingresses/translate.go index 98cf816069..fc8eac41e3 100644 --- a/pkg/controllers/resources/ingresses/translate.go +++ b/pkg/controllers/resources/ingresses/translate.go @@ -21,13 +21,13 @@ const ( func (s *ingressSyncer) translate(ctx context.Context, vIngress *networkingv1.Ingress) (*networkingv1.Ingress, error) { newIngress := s.TranslateMetadata(ctx, vIngress).(*networkingv1.Ingress) - pSpec, err := translateSpec(vIngress.Namespace, &vIngress.Spec) + pSpec, err := translateSpec(ctx, vIngress.Namespace, &vIngress.Spec) if err != nil { return nil, err } newIngress.Spec = *pSpec - newIngress.Annotations, _ = translateIngressAnnotations(newIngress.Annotations, vIngress.Namespace) + newIngress.Annotations, _ = translateIngressAnnotations(ctx, newIngress.Annotations, vIngress.Namespace) return newIngress, nil } @@ -46,24 +46,24 @@ func (s *ingressSyncer) TranslateMetadataUpdate(ctx context.Context, vObj client } func (s *ingressSyncer) translateUpdate(ctx context.Context, pObj, vObj *networkingv1.Ingress) error { - pSpec, err := translateSpec(vObj.Namespace, &vObj.Spec) + pSpec, err := translateSpec(ctx, vObj.Namespace, &vObj.Spec) if err != nil { return err } pObj.Spec = *pSpec _, translatedAnnotations, translatedLabels := s.TranslateMetadataUpdate(ctx, vObj, pObj) - translatedAnnotations, _ = translateIngressAnnotations(translatedAnnotations, vObj.Namespace) + translatedAnnotations, _ = translateIngressAnnotations(ctx, translatedAnnotations, vObj.Namespace) pObj.Annotations = translatedAnnotations pObj.Labels = translatedLabels return nil } -func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) (*networkingv1.IngressSpec, error) { +func translateSpec(ctx context.Context, namespace string, vIngressSpec *networkingv1.IngressSpec) (*networkingv1.IngressSpec, error) { retSpec := vIngressSpec.DeepCopy() if retSpec.DefaultBackend != nil { if retSpec.DefaultBackend.Service != nil && retSpec.DefaultBackend.Service.Name != "" { - retSpec.DefaultBackend.Service.Name = mappings.VirtualToHostName(retSpec.DefaultBackend.Service.Name, namespace, mappings.Services()) + retSpec.DefaultBackend.Service.Name = mappings.VirtualToHostName(ctx, retSpec.DefaultBackend.Service.Name, namespace, mappings.Services()) } if retSpec.DefaultBackend.Resource != nil { retSpec.DefaultBackend.Resource.Name = translate.Default.PhysicalName(retSpec.DefaultBackend.Resource.Name, namespace) @@ -74,7 +74,7 @@ func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) (*n if rule.HTTP != nil { for j, path := range rule.HTTP.Paths { if path.Backend.Service != nil && path.Backend.Service.Name != "" { - retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name = mappings.VirtualToHostName(retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name, namespace, mappings.Services()) + retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name = mappings.VirtualToHostName(ctx, retSpec.Rules[i].HTTP.Paths[j].Backend.Service.Name, namespace, mappings.Services()) } if path.Backend.Resource != nil { retSpec.Rules[i].HTTP.Paths[j].Backend.Resource.Name = translate.Default.PhysicalName(retSpec.Rules[i].HTTP.Paths[j].Backend.Resource.Name, namespace) @@ -85,7 +85,7 @@ func translateSpec(namespace string, vIngressSpec *networkingv1.IngressSpec) (*n for i, tls := range retSpec.TLS { if tls.SecretName != "" { - retSpec.TLS[i].SecretName = mappings.VirtualToHostName(retSpec.TLS[i].SecretName, namespace, mappings.Secrets()) + retSpec.TLS[i].SecretName = mappings.VirtualToHostName(ctx, retSpec.TLS[i].SecretName, namespace, mappings.Secrets()) } } diff --git a/pkg/controllers/resources/namespaces/syncer.go b/pkg/controllers/resources/namespaces/syncer.go index c271aa5e2d..2c6c572e25 100644 --- a/pkg/controllers/resources/namespaces/syncer.go +++ b/pkg/controllers/resources/namespaces/syncer.go @@ -52,9 +52,9 @@ type namespaceSyncer struct { var _ syncertypes.Syncer = &namespaceSyncer{} func (s *namespaceSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - newNamespace := s.translate(ctx.Context, vObj.(*corev1.Namespace)) + newNamespace := s.translate(ctx, vObj.(*corev1.Namespace)) ctx.Log.Infof("create physical namespace %s", newNamespace.Name) - err := ctx.PhysicalClient.Create(ctx.Context, newNamespace) + err := ctx.PhysicalClient.Create(ctx, newNamespace) if err != nil { ctx.Log.Infof("error syncing %s to physical cluster: %v", vObj.GetName(), err) return ctrl.Result{}, err @@ -78,7 +78,7 @@ func (s *namespaceSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, // cast objects pNamespace, vNamespace, _, _ := synccontext.Cast[*corev1.Namespace](ctx, pObj, vObj) - s.translateUpdate(ctx.Context, pNamespace, vNamespace) + s.translateUpdate(ctx, pNamespace, vNamespace) return ctrl.Result{}, s.EnsureWorkloadServiceAccount(ctx, pNamespace.Name) } @@ -94,6 +94,6 @@ func (s *namespaceSyncer) EnsureWorkloadServiceAccount(ctx *synccontext.SyncCont Name: s.workloadServiceAccountName, }, } - _, err := controllerutil.CreateOrPatch(ctx.Context, ctx.PhysicalClient, svc, func() error { return nil }) + _, err := controllerutil.CreateOrPatch(ctx, ctx.PhysicalClient, svc, func() error { return nil }) return err } diff --git a/pkg/controllers/resources/networkpolicies/syncer.go b/pkg/controllers/resources/networkpolicies/syncer.go index 35bd7c2938..95033004f0 100644 --- a/pkg/controllers/resources/networkpolicies/syncer.go +++ b/pkg/controllers/resources/networkpolicies/syncer.go @@ -24,11 +24,11 @@ type networkPolicySyncer struct { var _ syncertypes.Syncer = &networkPolicySyncer{} func (s *networkPolicySyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostCreate(ctx, vObj, s.translate(ctx.Context, vObj.(*networkingv1.NetworkPolicy))) + return s.SyncToHostCreate(ctx, vObj, s.translate(ctx, vObj.(*networkingv1.NetworkPolicy))) } func (s *networkPolicySyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { - newNetworkPolicy := s.translateUpdate(ctx.Context, pObj.(*networkingv1.NetworkPolicy), vObj.(*networkingv1.NetworkPolicy)) + newNetworkPolicy := s.translateUpdate(ctx, pObj.(*networkingv1.NetworkPolicy), vObj.(*networkingv1.NetworkPolicy)) if newNetworkPolicy != nil { translator.PrintChanges(pObj, newNetworkPolicy, ctx.Log) } diff --git a/pkg/controllers/resources/nodes/fake_syncer.go b/pkg/controllers/resources/nodes/fake_syncer.go index 320be550b8..66e027ebff 100644 --- a/pkg/controllers/resources/nodes/fake_syncer.go +++ b/pkg/controllers/resources/nodes/fake_syncer.go @@ -76,7 +76,7 @@ func (r *fakeNodeSyncer) FakeSyncToVirtual(ctx *synccontext.SyncContext, name ty } ctx.Log.Infof("Create fake node %s", name.Name) - return ctrl.Result{}, createFakeNode(ctx.Context, r.fakeKubeletIPs, r.fakeKubeletHostnames, r.nodeServiceProvider, ctx.VirtualClient, name.Name) + return ctrl.Result{}, createFakeNode(ctx, r.fakeKubeletIPs, r.fakeKubeletHostnames, r.nodeServiceProvider, ctx.VirtualClient, name.Name) } func (r *fakeNodeSyncer) FakeSync(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { @@ -90,14 +90,14 @@ func (r *fakeNodeSyncer) FakeSync(ctx *synccontext.SyncContext, vObj client.Obje return ctrl.Result{}, err } else if !needed { ctx.Log.Infof("Delete fake node %s as it is not needed anymore", vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } // check if we need to update node ips updated := r.updateIfNeeded(ctx, node, node.Name) if updated != nil { ctx.Log.Infof("Update fake node %s", node.Name) - err := ctx.VirtualClient.Status().Update(ctx.Context, updated) + err := ctx.VirtualClient.Status().Update(ctx, updated) if err != nil { return ctrl.Result{}, errors.Wrap(err, "update node") } @@ -117,7 +117,7 @@ func (r *fakeNodeSyncer) updateIfNeeded(ctx *synccontext.SyncContext, node *core } if r.fakeKubeletIPs { - nodeIP, err := r.nodeServiceProvider.GetNodeIP(ctx.Context, name) + nodeIP, err := r.nodeServiceProvider.GetNodeIP(ctx, name) if err != nil { ctx.Log.Errorf("error getting fake node ip: %v", err) } @@ -137,7 +137,7 @@ func (r *fakeNodeSyncer) updateIfNeeded(ctx *synccontext.SyncContext, node *core } func (r *fakeNodeSyncer) nodeNeeded(ctx *synccontext.SyncContext, nodeName string) (bool, error) { - return isNodeNeededByPod(ctx.Context, ctx.VirtualClient, ctx.PhysicalClient, nodeName) + return isNodeNeededByPod(ctx, ctx.VirtualClient, ctx.PhysicalClient, nodeName) } // this is not a real guid, but it doesn't really matter because it should just look right and not be an actual guid diff --git a/pkg/controllers/resources/nodes/fake_syncer_test.go b/pkg/controllers/resources/nodes/fake_syncer_test.go index 9c00cb3ec7..a86aba7eee 100644 --- a/pkg/controllers/resources/nodes/fake_syncer_test.go +++ b/pkg/controllers/resources/nodes/fake_syncer_test.go @@ -24,7 +24,7 @@ import ( func newFakeFakeSyncer(t *testing.T, ctx *synccontext.RegisterContext) (*synccontext.SyncContext, *fakeNodeSyncer) { // we need that index here as well otherwise we wouldn't find the related pod - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { + err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { pod := rawObj.(*corev1.Pod) return []string{pod.Spec.NodeName} }) diff --git a/pkg/controllers/resources/nodes/syncer.go b/pkg/controllers/resources/nodes/syncer.go index 786382148f..30397f335a 100644 --- a/pkg/controllers/resources/nodes/syncer.go +++ b/pkg/controllers/resources/nodes/syncer.go @@ -113,7 +113,7 @@ func (s *nodeSyncer) ModifyController(ctx *synccontext.RegisterContext, bld *bui return nil, errors.Wrap(err, "create cache") } // add index for pod by node - err = podCache.IndexField(ctx.Context, &corev1.Pod{}, constants.IndexRunningNonVClusterPodsByNode, func(object client.Object) []string { + err = podCache.IndexField(ctx, &corev1.Pod{}, constants.IndexRunningNonVClusterPodsByNode, func(object client.Object) []string { pPod := object.(*corev1.Pod) // we ignore all non-running pods and the ones that are part of the current vcluster // to later calculate the status.allocatable part of the nodes correctly @@ -129,13 +129,13 @@ func (s *nodeSyncer) ModifyController(ctx *synccontext.RegisterContext, bld *bui return nil, errors.Wrap(err, "index pod by node") } go func() { - err := podCache.Start(ctx.Context) + err := podCache.Start(ctx) if err != nil { klog.Fatalf("error starting pod cache: %v", err) } }() - podCache.WaitForCacheSync(ctx.Context) + podCache.WaitForCacheSync(ctx) s.unmanagedPodCache = podCache // enqueues nodes based on pod phase changes if the scheduler is enabled @@ -189,7 +189,7 @@ func enqueueNonVClusterPod(old, new client.Object, q workqueue.RateLimitingInter // this is split out because it is shared with the fake syncer func modifyController(ctx *synccontext.RegisterContext, nodeServiceProvider nodeservice.Provider, bld *builder.Builder) (*builder.Builder, error) { go func() { - nodeServiceProvider.Start(ctx.Context) + nodeServiceProvider.Start(ctx) }() bld = bld.WatchesRawSource(source.Kind(ctx.PhysicalManager.GetCache(), &corev1.Pod{}, handler.TypedEnqueueRequestsFromMapFunc(func(_ context.Context, pod *corev1.Pod) []reconcile.Request { @@ -229,7 +229,7 @@ func (s *nodeSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { } func registerIndices(ctx *synccontext.RegisterContext) error { - err := ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { + err := ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { pod := rawObj.(*corev1.Pod) if !translate.Default.IsManaged(pod) || pod.Spec.NodeName == "" { return nil @@ -240,7 +240,7 @@ func registerIndices(ctx *synccontext.RegisterContext) error { return err } - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { + return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { pod := rawObj.(*corev1.Pod) if pod.Spec.NodeName == "" { return nil @@ -258,18 +258,18 @@ var _ syncertypes.Syncer = &nodeSyncer{} func (s *nodeSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { vNode := vObj.(*corev1.Node) ctx.Log.Infof("delete virtual node %s, because it is not needed anymore", vNode.Name) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } func (s *nodeSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { pNode := pObj.(*corev1.Node) vNode := vObj.(*corev1.Node) - shouldSync, err := s.shouldSync(ctx.Context, pNode) + shouldSync, err := s.shouldSync(ctx, pNode) if err != nil { return ctrl.Result{}, err } else if !shouldSync { ctx.Log.Infof("delete virtual node %s, because there is no virtual pod with that node", pNode.Name) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } updatedVNode, statusChanged, err := s.translateUpdateStatus(ctx, pNode, vNode) @@ -278,7 +278,7 @@ func (s *nodeSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj } else if statusChanged { ctx.Log.Infof("update virtual node %s, because status has changed", pNode.Name) translator.PrintChanges(vNode, updatedVNode, ctx.Log) - err := ctx.VirtualClient.Status().Update(ctx.Context, updatedVNode) + err := ctx.VirtualClient.Status().Update(ctx, updatedVNode) if err != nil { return ctrl.Result{}, err } @@ -290,7 +290,7 @@ func (s *nodeSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj if updated != nil { ctx.Log.Infof("update virtual node %s, because spec has changed", pNode.Name) translator.PrintChanges(vNode, updated, ctx.Log) - err = ctx.VirtualClient.Update(ctx.Context, updated) + err = ctx.VirtualClient.Update(ctx, updated) if err != nil { return ctrl.Result{}, err } @@ -303,7 +303,7 @@ var _ syncertypes.ToVirtualSyncer = &nodeSyncer{} func (s *nodeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { pNode := pObj.(*corev1.Node) - shouldSync, err := s.shouldSync(ctx.Context, pNode) + shouldSync, err := s.shouldSync(ctx, pNode) if err != nil { return ctrl.Result{}, err } else if !shouldSync { @@ -311,7 +311,7 @@ func (s *nodeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Obj } ctx.Log.Infof("create virtual node %s, because there is a virtual pod with that node", pNode.Name) - err = ctx.VirtualClient.Create(ctx.Context, &corev1.Node{ + err = ctx.VirtualClient.Create(ctx, &corev1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: pNode.Name, Labels: pNode.Labels, diff --git a/pkg/controllers/resources/nodes/syncer_test.go b/pkg/controllers/resources/nodes/syncer_test.go index 8e3f105655..4b4208bd23 100644 --- a/pkg/controllers/resources/nodes/syncer_test.go +++ b/pkg/controllers/resources/nodes/syncer_test.go @@ -22,7 +22,7 @@ import ( func newFakeSyncer(t *testing.T, ctx *synccontext.RegisterContext) (*synccontext.SyncContext, *nodeSyncer) { // we need that index here as well otherwise we wouldn't find the related pod - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { + err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &corev1.Pod{}, constants.IndexByAssigned, func(rawObj client.Object) []string { pod := rawObj.(*corev1.Pod) return []string{pod.Spec.NodeName} }) @@ -64,7 +64,7 @@ func TestNodeDeletion(t *testing.T) { syncController, err := syncer.NewSyncController(ctx, nodesSyncer) assert.NilError(t, err) - _, err = syncController.Reconcile(ctx.Context, controllerruntime.Request{NamespacedName: baseName}) + _, err = syncController.Reconcile(ctx, controllerruntime.Request{NamespacedName: baseName}) assert.NilError(t, err) }, }, @@ -183,7 +183,7 @@ func TestSync(t *testing.T) { _, err := syncer.Sync(syncCtx, editedNode, baseNode) assert.NilError(t, err) - err = ctx.VirtualManager.GetClient().Get(ctx.Context, types.NamespacedName{Name: baseNode.Name}, baseNode) + err = ctx.VirtualManager.GetClient().Get(ctx, types.NamespacedName{Name: baseNode.Name}, baseNode) assert.NilError(t, err) _, err = syncer.Sync(syncCtx, editedNode, baseNode) diff --git a/pkg/controllers/resources/nodes/translate.go b/pkg/controllers/resources/nodes/translate.go index 008edc37b7..6402aee86c 100644 --- a/pkg/controllers/resources/nodes/translate.go +++ b/pkg/controllers/resources/nodes/translate.go @@ -151,7 +151,7 @@ func (s *nodeSyncer) translateUpdateStatus(ctx *synccontext.SyncContext, pNode * if s.fakeKubeletIPs { // create new service for this node - nodeIP, err := s.nodeServiceProvider.GetNodeIP(ctx.Context, vNode.Name) + nodeIP, err := s.nodeServiceProvider.GetNodeIP(ctx, vNode.Name) if err != nil { return nil, false, fmt.Errorf("get vNode IP: %w", err) } @@ -183,7 +183,7 @@ func (s *nodeSyncer) translateUpdateStatus(ctx *synccontext.SyncContext, pNode * var nonVClusterPods int64 podList := &corev1.PodList{} - err := s.unmanagedPodCache.List(ctx.Context, podList, client.MatchingFields{constants.IndexRunningNonVClusterPodsByNode: pNode.Name}) + err := s.unmanagedPodCache.List(ctx, podList, client.MatchingFields{constants.IndexRunningNonVClusterPodsByNode: pNode.Name}) if err != nil { klog.Errorf("Error listing pods: %v", err) } else { diff --git a/pkg/controllers/resources/persistentvolumeclaims/syncer.go b/pkg/controllers/resources/persistentvolumeclaims/syncer.go index 791d8ef7f4..7414771851 100644 --- a/pkg/controllers/resources/persistentvolumeclaims/syncer.go +++ b/pkg/controllers/resources/persistentvolumeclaims/syncer.go @@ -67,7 +67,7 @@ func (s *persistentVolumeClaimSyncer) SyncToHost(ctx *synccontext.SyncContext, v if vPvc.DeletionTimestamp != nil { // delete pvc immediately ctx.Log.Infof("delete virtual persistent volume claim %s/%s immediately, because it is being deleted & there is no physical persistent volume claim", vPvc.Namespace, vPvc.Name) - err := ctx.VirtualClient.Delete(ctx.Context, vPvc, &client.DeleteOptions{ + err := ctx.VirtualClient.Delete(ctx, vPvc, &client.DeleteOptions{ GracePeriodSeconds: &zero, }) if kerrors.IsNotFound(err) { @@ -93,12 +93,12 @@ func (s *persistentVolumeClaimSyncer) Sync(ctx *synccontext.SyncContext, pObj cl if pPvc.DeletionTimestamp != nil { if vPvc.DeletionTimestamp == nil { ctx.Log.Infof("delete virtual persistent volume claim %s/%s, because the physical persistent volume claim is being deleted", vPvc.Namespace, vPvc.Name) - if err := ctx.VirtualClient.Delete(ctx.Context, vPvc, &client.DeleteOptions{GracePeriodSeconds: &minimumGracePeriodInSeconds}); err != nil { + if err := ctx.VirtualClient.Delete(ctx, vPvc, &client.DeleteOptions{GracePeriodSeconds: &minimumGracePeriodInSeconds}); err != nil { return ctrl.Result{}, err } } else if *vPvc.DeletionGracePeriodSeconds != *pPvc.DeletionGracePeriodSeconds { ctx.Log.Infof("delete virtual persistent volume claim %s/%s with grace period seconds %v", vPvc.Namespace, vPvc.Name, *pPvc.DeletionGracePeriodSeconds) - if err := ctx.VirtualClient.Delete(ctx.Context, vPvc, &client.DeleteOptions{GracePeriodSeconds: pPvc.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(vPvc.UID))}); err != nil { + if err := ctx.VirtualClient.Delete(ctx, vPvc, &client.DeleteOptions{GracePeriodSeconds: pPvc.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(vPvc.UID))}); err != nil { return ctrl.Result{}, err } } @@ -106,7 +106,7 @@ func (s *persistentVolumeClaimSyncer) Sync(ctx *synccontext.SyncContext, pObj cl return ctrl.Result{}, nil } else if vPvc.DeletionTimestamp != nil { ctx.Log.Infof("delete physical persistent volume claim %s/%s, because virtual persistent volume claim is being deleted", pPvc.Namespace, pPvc.Name) - err := ctx.PhysicalClient.Delete(ctx.Context, pPvc, &client.DeleteOptions{ + err := ctx.PhysicalClient.Delete(ctx, pPvc, &client.DeleteOptions{ GracePeriodSeconds: vPvc.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(pPvc.UID)), }) @@ -131,7 +131,7 @@ func (s *persistentVolumeClaimSyncer) Sync(ctx *synccontext.SyncContext, pObj cl if updated != nil { ctx.Log.Infof("update virtual persistent volume claim %s/%s, because the spec has changed", vPvc.Namespace, vPvc.Name) translator.PrintChanges(vPvc, updated, ctx.Log) - err := ctx.VirtualClient.Update(ctx.Context, updated) + err := ctx.VirtualClient.Update(ctx, updated) if err != nil { return ctrl.Result{}, err } @@ -146,7 +146,7 @@ func (s *persistentVolumeClaimSyncer) Sync(ctx *synccontext.SyncContext, pObj cl newPvc.Status = *pPvc.Status.DeepCopy() ctx.Log.Infof("update virtual persistent volume claim %s/%s, because the status has changed", vPvc.Namespace, vPvc.Name) translator.PrintChanges(vPvc, newPvc, ctx.Log) - err := ctx.VirtualClient.Status().Update(ctx.Context, newPvc) + err := ctx.VirtualClient.Status().Update(ctx, newPvc) if err != nil { return ctrl.Result{}, err } @@ -156,7 +156,7 @@ func (s *persistentVolumeClaimSyncer) Sync(ctx *synccontext.SyncContext, pObj cl } // forward update - newPvc, err := s.translateUpdate(ctx.Context, pPvc, vPvc) + newPvc, err := s.translateUpdate(ctx, pPvc, vPvc) if err != nil { return ctrl.Result{}, err } else if newPvc != nil { @@ -169,7 +169,7 @@ func (s *persistentVolumeClaimSyncer) Sync(ctx *synccontext.SyncContext, pObj cl func (s *persistentVolumeClaimSyncer) ensurePersistentVolume(ctx *synccontext.SyncContext, pObj *corev1.PersistentVolumeClaim, vObj *corev1.PersistentVolumeClaim, log loghelper.Logger) (bool, error) { // ensure the persistent volume is available in the virtual cluster vPV := &corev1.PersistentVolume{} - err := ctx.VirtualClient.Get(ctx.Context, types.NamespacedName{Name: pObj.Spec.VolumeName}, vPV) + err := ctx.VirtualClient.Get(ctx, types.NamespacedName{Name: pObj.Spec.VolumeName}, vPV) if err != nil { if !kerrors.IsNotFound(err) { log.Infof("error retrieving virtual pv %s: %v", pObj.Spec.VolumeName, err) @@ -180,7 +180,7 @@ func (s *persistentVolumeClaimSyncer) ensurePersistentVolume(ctx *synccontext.Sy if pObj.Spec.VolumeName != "" && vObj.Spec.VolumeName != pObj.Spec.VolumeName { newVolumeName := pObj.Spec.VolumeName if !s.useFakePersistentVolumes { - vName := mappings.PersistentVolumes().HostToVirtual(ctx.Context, types.NamespacedName{Name: pObj.Spec.VolumeName}, nil) + vName := mappings.PersistentVolumes().HostToVirtual(ctx, types.NamespacedName{Name: pObj.Spec.VolumeName}, nil) if vName.Name == "" { log.Infof("error retrieving virtual persistent volume %s: not found", pObj.Spec.VolumeName) return false, fmt.Errorf("error retrieving virtual persistent volume %s: not found", pObj.Spec.VolumeName) @@ -193,7 +193,7 @@ func (s *persistentVolumeClaimSyncer) ensurePersistentVolume(ctx *synccontext.Sy if vObj.Spec.VolumeName != "" { log.Infof("recreate persistent volume claim because volumeName differs between physical and virtual pvc: %s != %s", vObj.Spec.VolumeName, newVolumeName) s.EventRecorder().Eventf(vObj, corev1.EventTypeWarning, "VolumeNameDiffers", "recreate persistent volume claim because volumeName differs between physical and virtual pvc: %s != %s", vObj.Spec.VolumeName, newVolumeName) - _, err = recreatePersistentVolumeClaim(ctx.Context, ctx.VirtualClient, vPV, vObj, newVolumeName, log) + _, err = recreatePersistentVolumeClaim(ctx, ctx.VirtualClient, vPV, vObj, newVolumeName, log) if err != nil { log.Infof("error recreating virtual persistent volume claim: %v", err) return false, err @@ -204,7 +204,7 @@ func (s *persistentVolumeClaimSyncer) ensurePersistentVolume(ctx *synccontext.Sy log.Infof("update virtual pvc %s/%s volume name to %s", vObj.Namespace, vObj.Name, newVolumeName) vObj.Spec.VolumeName = newVolumeName - err = ctx.VirtualClient.Update(ctx.Context, vObj) + err = ctx.VirtualClient.Update(ctx, vObj) if err != nil { return false, err } diff --git a/pkg/controllers/resources/persistentvolumeclaims/syncer_test.go b/pkg/controllers/resources/persistentvolumeclaims/syncer_test.go index 6efe47430a..4be130fe49 100644 --- a/pkg/controllers/resources/persistentvolumeclaims/syncer_test.go +++ b/pkg/controllers/resources/persistentvolumeclaims/syncer_test.go @@ -294,14 +294,14 @@ func TestSync(t *testing.T) { syncer.(*persistentVolumeClaimSyncer).useFakePersistentVolumes = true vPVC := &corev1.PersistentVolumeClaim{} - err := syncCtx.VirtualClient.Get(syncCtx.Context, types.NamespacedName{ + err := syncCtx.VirtualClient.Get(syncCtx, types.NamespacedName{ Namespace: basePvc.Namespace, Name: basePvc.Name, }, vPVC) assert.NilError(t, err) pPVC := &corev1.PersistentVolumeClaim{} - err = syncCtx.PhysicalClient.Get(syncCtx.Context, types.NamespacedName{ + err = syncCtx.PhysicalClient.Get(syncCtx, types.NamespacedName{ Namespace: pObjectMeta.Namespace, Name: pObjectMeta.Name, }, pPVC) diff --git a/pkg/controllers/resources/persistentvolumeclaims/translate.go b/pkg/controllers/resources/persistentvolumeclaims/translate.go index 43f9cfcebc..a9f2c7121e 100644 --- a/pkg/controllers/resources/persistentvolumeclaims/translate.go +++ b/pkg/controllers/resources/persistentvolumeclaims/translate.go @@ -20,7 +20,7 @@ var ( ) func (s *persistentVolumeClaimSyncer) translate(ctx *synccontext.SyncContext, vPvc *corev1.PersistentVolumeClaim) (*corev1.PersistentVolumeClaim, error) { - newPvc := s.TranslateMetadata(ctx.Context, vPvc).(*corev1.PersistentVolumeClaim) + newPvc := s.TranslateMetadata(ctx, vPvc).(*corev1.PersistentVolumeClaim) newPvc, err := s.translateSelector(ctx, newPvc) if err != nil { return nil, err @@ -29,9 +29,9 @@ func (s *persistentVolumeClaimSyncer) translate(ctx *synccontext.SyncContext, vP if vPvc.Annotations[constants.SkipTranslationAnnotation] != "true" { if newPvc.Spec.DataSource != nil { if newPvc.Spec.DataSource.Kind == "VolumeSnapshot" { - newPvc.Spec.DataSource.Name = mappings.VirtualToHostName(newPvc.Spec.DataSource.Name, vPvc.Namespace, mappings.VolumeSnapshots()) + newPvc.Spec.DataSource.Name = mappings.VirtualToHostName(ctx, newPvc.Spec.DataSource.Name, vPvc.Namespace, mappings.VolumeSnapshots()) } else if newPvc.Spec.DataSource.Kind == "PersistentVolumeClaim" { - newPvc.Spec.DataSource.Name = mappings.VirtualToHostName(newPvc.Spec.DataSource.Name, vPvc.Namespace, mappings.PersistentVolumeClaims()) + newPvc.Spec.DataSource.Name = mappings.VirtualToHostName(ctx, newPvc.Spec.DataSource.Name, vPvc.Namespace, mappings.PersistentVolumeClaims()) } } @@ -42,9 +42,9 @@ func (s *persistentVolumeClaimSyncer) translate(ctx *synccontext.SyncContext, vP } if newPvc.Spec.DataSourceRef.Kind == "VolumeSnapshot" { - newPvc.Spec.DataSourceRef.Name = mappings.VirtualToHostName(newPvc.Spec.DataSourceRef.Name, namespace, mappings.VolumeSnapshots()) + newPvc.Spec.DataSourceRef.Name = mappings.VirtualToHostName(ctx, newPvc.Spec.DataSourceRef.Name, namespace, mappings.VolumeSnapshots()) } else if newPvc.Spec.DataSourceRef.Kind == "PersistentVolumeClaim" { - newPvc.Spec.DataSourceRef.Name = mappings.VirtualToHostName(newPvc.Spec.DataSourceRef.Name, namespace, mappings.PersistentVolumeClaims()) + newPvc.Spec.DataSourceRef.Name = mappings.VirtualToHostName(ctx, newPvc.Spec.DataSourceRef.Name, namespace, mappings.PersistentVolumeClaims()) } } } @@ -82,7 +82,7 @@ func (s *persistentVolumeClaimSyncer) translateSelector(ctx *synccontext.SyncCon if !s.storageClassesEnabled && storageClassName != "" { // Should the PVC be dynamically provisioned or not? if vPvc.Spec.Selector == nil && vPvc.Spec.VolumeName == "" { - err := ctx.PhysicalClient.Get(ctx.Context, types.NamespacedName{Name: storageClassName}, &storagev1.StorageClass{}) + err := ctx.PhysicalClient.Get(ctx, types.NamespacedName{Name: storageClassName}, &storagev1.StorageClass{}) if err != nil && kerrors.IsNotFound(err) { translated := translate.Default.PhysicalNameClusterScoped(storageClassName) delete(vPvc.Annotations, deprecatedStorageClassAnnotation) diff --git a/pkg/controllers/resources/persistentvolumes/fake_syncer.go b/pkg/controllers/resources/persistentvolumes/fake_syncer.go index 9ff42a8084..deb3bfcd53 100644 --- a/pkg/controllers/resources/persistentvolumes/fake_syncer.go +++ b/pkg/controllers/resources/persistentvolumes/fake_syncer.go @@ -36,7 +36,7 @@ func (r *fakePersistentVolumeSyncer) Name() string { var _ syncer.IndicesRegisterer = &fakePersistentVolumeSyncer{} func (r *fakePersistentVolumeSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { - return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.PersistentVolumeClaim{}, constants.IndexByAssigned, func(rawObj client.Object) []string { + return ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &corev1.PersistentVolumeClaim{}, constants.IndexByAssigned, func(rawObj client.Object) []string { pod := rawObj.(*corev1.PersistentVolumeClaim) return []string{pod.Spec.VolumeName} }) @@ -72,7 +72,7 @@ func (r *fakePersistentVolumeSyncer) FakeSyncToVirtual(ctx *synccontext.SyncCont } pvcList := &corev1.PersistentVolumeClaimList{} - err = ctx.VirtualClient.List(ctx.Context, pvcList, client.MatchingFields{constants.IndexByAssigned: req.Name}) + err = ctx.VirtualClient.List(ctx, pvcList, client.MatchingFields{constants.IndexByAssigned: req.Name}) if err != nil { return ctrl.Result{}, err } else if len(pvcList.Items) == 0 { @@ -80,7 +80,7 @@ func (r *fakePersistentVolumeSyncer) FakeSyncToVirtual(ctx *synccontext.SyncCont } ctx.Log.Infof("Create fake persistent volume for PVC %s/%s", pvcList.Items[0].Namespace, pvcList.Items[0].Name) - err = CreateFakePersistentVolume(ctx.Context, ctx.VirtualClient, req, &pvcList.Items[0]) + err = CreateFakePersistentVolume(ctx, ctx.VirtualClient, req, &pvcList.Items[0]) return ctrl.Result{}, err } @@ -98,7 +98,7 @@ func (r *fakePersistentVolumeSyncer) FakeSync(ctx *synccontext.SyncContext, vObj } ctx.Log.Infof("Delete fake persistent volume %s", vObj.GetName()) - err = ctx.VirtualClient.Delete(ctx.Context, vObj) + err = ctx.VirtualClient.Delete(ctx, vObj) if err != nil { if kerrors.IsNotFound(err) { return ctrl.Result{}, nil @@ -112,7 +112,7 @@ func (r *fakePersistentVolumeSyncer) FakeSync(ctx *synccontext.SyncContext, vObj if len(pv.Finalizers) > 0 { orig := pv.DeepCopy() pv.Finalizers = []string{} - err = ctx.VirtualClient.Patch(ctx.Context, pv, client.MergeFrom(orig)) + err = ctx.VirtualClient.Patch(ctx, pv, client.MergeFrom(orig)) if err != nil && !kerrors.IsNotFound(err) { return ctrl.Result{}, err } @@ -123,7 +123,7 @@ func (r *fakePersistentVolumeSyncer) FakeSync(ctx *synccontext.SyncContext, vObj func (r *fakePersistentVolumeSyncer) pvNeeded(ctx *synccontext.SyncContext, pvName string) (bool, error) { pvcList := &corev1.PersistentVolumeClaimList{} - err := ctx.VirtualClient.List(ctx.Context, pvcList, client.MatchingFields{constants.IndexByAssigned: pvName}) + err := ctx.VirtualClient.List(ctx, pvcList, client.MatchingFields{constants.IndexByAssigned: pvName}) if err != nil { return false, err } diff --git a/pkg/controllers/resources/persistentvolumes/fake_syncer_test.go b/pkg/controllers/resources/persistentvolumes/fake_syncer_test.go index dc5d3ef03f..ce9b2109ce 100644 --- a/pkg/controllers/resources/persistentvolumes/fake_syncer_test.go +++ b/pkg/controllers/resources/persistentvolumes/fake_syncer_test.go @@ -18,7 +18,7 @@ import ( ) func newFakeFakeSyncer(t *testing.T, ctx *synccontext.RegisterContext) (*synccontext.SyncContext, *fakePersistentVolumeSyncer) { - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.PersistentVolumeClaim{}, constants.IndexByAssigned, func(rawObj client.Object) []string { + err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &corev1.PersistentVolumeClaim{}, constants.IndexByAssigned, func(rawObj client.Object) []string { pod := rawObj.(*corev1.PersistentVolumeClaim) return []string{pod.Spec.VolumeName} }) diff --git a/pkg/controllers/resources/persistentvolumes/syncer.go b/pkg/controllers/resources/persistentvolumes/syncer.go index 21a13ac719..9a6ccea068 100644 --- a/pkg/controllers/resources/persistentvolumes/syncer.go +++ b/pkg/controllers/resources/persistentvolumes/syncer.go @@ -76,20 +76,20 @@ func (s *persistentVolumeSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj c // delete the finalizer here so that the object can be deleted vPv.Finalizers = []string{} ctx.Log.Infof("remove virtual persistent volume %s finalizers, because object should get deleted", vPv.Name) - return ctrl.Result{}, ctx.VirtualClient.Update(ctx.Context, vPv) + return ctrl.Result{}, ctx.VirtualClient.Update(ctx, vPv) } ctx.Log.Infof("remove virtual persistent volume %s, because object should get deleted", vPv.Name) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vPv) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vPv) } - pPv, err := s.translate(ctx.Context, vPv) + pPv, err := s.translate(ctx, 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, pPv) if err != nil { return ctrl.Result{}, err } @@ -119,7 +119,7 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. // check if the PV is dynamically provisioned and the reclaim policy is Delete if !(vPersistentVolume.Spec.ClaimRef != nil && vPersistentVolume.Spec.PersistentVolumeReclaimPolicy == corev1.PersistentVolumeReclaimDelete) { ctx.Log.Infof("delete physical persistent volume %s, because virtual persistent volume is deleted", pObj.GetName()) - err := ctx.PhysicalClient.Delete(ctx.Context, pObj) + err := ctx.PhysicalClient.Delete(ctx, pObj) if err != nil { return ctrl.Result{}, err } @@ -130,22 +130,22 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. } // check if the persistent volume should get synced - sync, vPvc, err := s.shouldSync(ctx.Context, pPersistentVolume) + sync, vPvc, err := s.shouldSync(ctx, pPersistentVolume) if err != nil { return ctrl.Result{}, err } else if !sync { ctx.Log.Infof("delete virtual persistent volume %s, because there is no virtual persistent volume claim with that volume", vPersistentVolume.Name) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } // check if there is a corresponding virtual pvc - updatedObj, err := s.translateUpdateBackwards(vPersistentVolume, pPersistentVolume, vPvc) + updatedObj, err := s.translateUpdateBackwards(ctx, 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) + err = ctx.VirtualClient.Update(ctx, updatedObj) if err != nil { return ctrl.Result{}, err } @@ -160,7 +160,7 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. updatedObj.Status = *pPersistentVolume.Status.DeepCopy() ctx.Log.Infof("update virtual persistent volume %s, because status has changed", vPersistentVolume.Name) translator.PrintChanges(vPersistentVolume, updatedObj, ctx.Log) - err = ctx.VirtualClient.Status().Update(ctx.Context, updatedObj) + err = ctx.VirtualClient.Status().Update(ctx, updatedObj) if err != nil { return ctrl.Result{}, err } @@ -177,7 +177,7 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. } ctx.Log.Infof("delete physical persistent volume %s, because virtual persistent volume is being deleted", pPersistentVolume.Name) - err := ctx.PhysicalClient.Delete(ctx.Context, pPersistentVolume, &client.DeleteOptions{ + err := ctx.PhysicalClient.Delete(ctx, pPersistentVolume, &client.DeleteOptions{ GracePeriodSeconds: vPersistentVolume.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(pPersistentVolume.UID)), }) @@ -187,13 +187,11 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, pObj client. return ctrl.Result{}, err } - updatedPv, err := s.translateUpdate(ctx.Context, vPersistentVolume, pPersistentVolume) - if err != nil { - return ctrl.Result{}, err - } else if updatedPv != nil { + updatedPv := s.translateUpdate(ctx, vPersistentVolume, pPersistentVolume) + 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) + err := ctx.PhysicalClient.Update(ctx, updatedPv) if err != nil { return ctrl.Result{}, err } @@ -213,7 +211,7 @@ var _ syncertypes.ToVirtualSyncer = &persistentVolumeSyncer{} func (s *persistentVolumeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { pPersistentVolume := pObj.(*corev1.PersistentVolume) - sync, vPvc, err := s.shouldSync(ctx.Context, pPersistentVolume) + sync, vPvc, err := s.shouldSync(ctx, pPersistentVolume) if err != nil { return ctrl.Result{}, err } else if translate.Default.IsManagedCluster(pObj) { @@ -226,7 +224,7 @@ func (s *persistentVolumeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pOb ctx.Log.Infof("create persistent volume %s, because it belongs to virtual pvc %s/%s and does not exist in virtual cluster", vObj.Name, vPvc.Namespace, vPvc.Name) } - return ctrl.Result{}, ctx.VirtualClient.Create(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } return ctrl.Result{}, nil diff --git a/pkg/controllers/resources/persistentvolumes/syncer_test.go b/pkg/controllers/resources/persistentvolumes/syncer_test.go index 15e6f91c90..d43a206430 100644 --- a/pkg/controllers/resources/persistentvolumes/syncer_test.go +++ b/pkg/controllers/resources/persistentvolumes/syncer_test.go @@ -258,10 +258,10 @@ func TestSync(t *testing.T) { _, err := syncer.Sync(syncContext, backwardUpdatePPv, baseVPv) assert.NilError(t, err) - err = syncContext.VirtualClient.Get(ctx.Context, types.NamespacedName{Name: baseVPv.Name}, baseVPv) + err = syncContext.VirtualClient.Get(ctx, types.NamespacedName{Name: baseVPv.Name}, baseVPv) assert.NilError(t, err) - err = syncContext.PhysicalClient.Get(ctx.Context, types.NamespacedName{Name: backwardUpdatePPv.Name}, backwardUpdatePPv) + err = syncContext.PhysicalClient.Get(ctx, types.NamespacedName{Name: backwardUpdatePPv.Name}, backwardUpdatePPv) assert.NilError(t, err) _, err = syncer.Sync(syncContext, backwardUpdatePPv, baseVPv) @@ -364,11 +364,11 @@ func TestSync(t *testing.T) { syncContext, syncer := newFakeSyncer(t, ctx) vPv := &corev1.PersistentVolume{} - err := syncContext.VirtualClient.Get(ctx.Context, types.NamespacedName{Name: baseVPv.Name}, vPv) + err := syncContext.VirtualClient.Get(ctx, types.NamespacedName{Name: baseVPv.Name}, vPv) assert.NilError(t, err) pPv := &corev1.PersistentVolume{} - err = syncContext.PhysicalClient.Get(ctx.Context, types.NamespacedName{Name: basePPv.Name}, pPv) + err = syncContext.PhysicalClient.Get(ctx, types.NamespacedName{Name: basePPv.Name}, pPv) assert.NilError(t, err) _, err = syncer.Sync(syncContext, pPv, vPv) diff --git a/pkg/controllers/resources/persistentvolumes/translate.go b/pkg/controllers/resources/persistentvolumes/translate.go index 96e1748454..c003a92413 100644 --- a/pkg/controllers/resources/persistentvolumes/translate.go +++ b/pkg/controllers/resources/persistentvolumes/translate.go @@ -18,7 +18,7 @@ func (s *persistentVolumeSyncer) translate(ctx context.Context, vPv *corev1.Pers pPV.Spec.ClaimRef = nil // TODO: translate the storage secrets - pPV.Spec.StorageClassName = mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) + pPV.Spec.StorageClassName = mappings.VirtualToHostName(ctx, vPv.Spec.StorageClassName, "", mappings.StorageClasses()) return pPV, nil } @@ -48,7 +48,7 @@ func (s *persistentVolumeSyncer) translateBackwards(pPv *corev1.PersistentVolume return vObj } -func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume, vPvc *corev1.PersistentVolumeClaim) (*corev1.PersistentVolume, error) { +func (s *persistentVolumeSyncer) translateUpdateBackwards(ctx context.Context, vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume, vPvc *corev1.PersistentVolumeClaim) (*corev1.PersistentVolume, error) { var updated *corev1.PersistentVolume // build virtual persistent volume @@ -69,15 +69,15 @@ func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.Persistent // when the PVC gets deleted } else { // check if SC was created on virtual - isStorageClassCreatedOnVirtual = vPv.Spec.StorageClassName != mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) + isStorageClassCreatedOnVirtual = vPv.Spec.StorageClassName != mappings.VirtualToHostName(ctx, vPv.Spec.StorageClassName, "", mappings.StorageClasses()) // check if claim was created on virtual if vPv.Spec.ClaimRef != nil && translatedSpec.ClaimRef != nil { var claimRef types.NamespacedName if vPv.Spec.ClaimRef.Kind == "PersistentVolume" { - claimRef = mappings.VirtualToHost(vPv.Spec.ClaimRef.Name, vPv.Spec.ClaimRef.Namespace, mappings.PersistentVolumes()) + claimRef = mappings.VirtualToHost(ctx, vPv.Spec.ClaimRef.Name, vPv.Spec.ClaimRef.Namespace, mappings.PersistentVolumes()) } else { - claimRef = mappings.VirtualToHost(vPv.Spec.ClaimRef.Name, vPv.Spec.ClaimRef.Namespace, mappings.PersistentVolumeClaims()) + claimRef = mappings.VirtualToHost(ctx, vPv.Spec.ClaimRef.Name, vPv.Spec.ClaimRef.Namespace, mappings.PersistentVolumeClaims()) } isClaimRefCreatedOnVirtual = claimRef.Name == translatedSpec.ClaimRef.Name && claimRef.Namespace == translatedSpec.ClaimRef.Namespace @@ -107,7 +107,7 @@ func (s *persistentVolumeSyncer) translateUpdateBackwards(vPv *corev1.Persistent return updated, nil } -func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume) (*corev1.PersistentVolume, error) { +func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev1.PersistentVolume, pPv *corev1.PersistentVolume) *corev1.PersistentVolume { var updated *corev1.PersistentVolume // TODO: translate the storage secrets @@ -131,7 +131,7 @@ func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev updated.Spec.PersistentVolumeReclaimPolicy = vPv.Spec.PersistentVolumeReclaimPolicy } - translatedStorageClassName := mappings.VirtualToHostName(vPv.Spec.StorageClassName, "", mappings.StorageClasses()) + translatedStorageClassName := mappings.VirtualToHostName(ctx, vPv.Spec.StorageClassName, "", mappings.StorageClasses()) if !equality.Semantic.DeepEqual(pPv.Spec.StorageClassName, translatedStorageClassName) { updated = translator.NewIfNil(updated, pPv) updated.Spec.StorageClassName = translatedStorageClassName @@ -160,5 +160,5 @@ func (s *persistentVolumeSyncer) translateUpdate(ctx context.Context, vPv *corev updated.Labels = updatedLabels } - return updated, nil + return updated } diff --git a/pkg/controllers/resources/poddisruptionbudgets/syncer.go b/pkg/controllers/resources/poddisruptionbudgets/syncer.go index 7dc3b7953f..82c2fc1741 100644 --- a/pkg/controllers/resources/poddisruptionbudgets/syncer.go +++ b/pkg/controllers/resources/poddisruptionbudgets/syncer.go @@ -21,13 +21,13 @@ type pdbSyncer struct { } func (pdb *pdbSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - return pdb.SyncToHostCreate(ctx, vObj, pdb.translate(ctx.Context, vObj.(*policyv1.PodDisruptionBudget))) + return pdb.SyncToHostCreate(ctx, vObj, pdb.translate(ctx, vObj.(*policyv1.PodDisruptionBudget))) } func (pdb *pdbSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { vPDB := vObj.(*policyv1.PodDisruptionBudget) pPDB := pObj.(*policyv1.PodDisruptionBudget) - newPDB := pdb.translateUpdate(ctx.Context, pPDB, vPDB) + newPDB := pdb.translateUpdate(ctx, pPDB, vPDB) if newPDB != nil { translator.PrintChanges(pObj, newPDB, ctx.Log) } diff --git a/pkg/controllers/resources/pods/conditions.go b/pkg/controllers/resources/pods/conditions.go index df54419968..e98b7da3c0 100644 --- a/pkg/controllers/resources/pods/conditions.go +++ b/pkg/controllers/resources/pods/conditions.go @@ -45,7 +45,7 @@ func UpdateConditions(ctx *synccontext.SyncContext, physicalPod *corev1.Pod, vir // update physical pod if updated { ctx.Log.Infof("update physical pod %s/%s, because custom pod conditions have changed", physicalPod.Namespace, physicalPod.Name) - err := ctx.PhysicalClient.Status().Update(ctx.Context, physicalPod) + err := ctx.PhysicalClient.Status().Update(ctx, physicalPod) if err != nil { return nil, err } diff --git a/pkg/controllers/resources/pods/ephemeral_containers.go b/pkg/controllers/resources/pods/ephemeral_containers.go index 457553f194..40ca491bbb 100644 --- a/pkg/controllers/resources/pods/ephemeral_containers.go +++ b/pkg/controllers/resources/pods/ephemeral_containers.go @@ -40,7 +40,7 @@ func AddEphemeralContainer(ctx *synccontext.SyncContext, physicalClusterClient k ctx.Log.Debugf("generated strategic merge patch for debug container: %s", patch) pods := physicalClusterClient.CoreV1().Pods(physicalPod.Namespace) - _, err = pods.Patch(ctx.Context, physicalPod.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}, "ephemeralcontainers") + _, err = pods.Patch(ctx, physicalPod.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{}, "ephemeralcontainers") if err != nil { // The apiserver will return a 404 when the EphemeralContainers feature is disabled because the `/ephemeralcontainers` subresource // is missing. Unlike the 404 returned by a missing physicalPod, the status details will be empty. @@ -81,12 +81,12 @@ func addEphemeralContainerLegacy(ctx *synccontext.SyncContext, physicalClusterCl Name(physicalPod.Name). SubResource("ephemeralcontainers"). Body(patch). - Do(ctx.Context) + Do(ctx) if err := result.Error(); err != nil { return err } - _, err = physicalClusterClient.CoreV1().Pods(physicalPod.Namespace).Get(ctx.Context, physicalPod.Name, metav1.GetOptions{}) + _, err = physicalClusterClient.CoreV1().Pods(physicalPod.Namespace).Get(ctx, physicalPod.Name, metav1.GetOptions{}) if err != nil { return err } diff --git a/pkg/controllers/resources/pods/syncer.go b/pkg/controllers/resources/pods/syncer.go index f2a49e9f26..41f8934349 100644 --- a/pkg/controllers/resources/pods/syncer.go +++ b/pkg/controllers/resources/pods/syncer.go @@ -150,7 +150,7 @@ func (s *podSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) if vPod.DeletionTimestamp != nil || vPod.Status.StartTime != nil { // delete pod immediately ctx.Log.Infof("delete pod %s/%s immediately, because it is being deleted & there is no physical pod", vPod.Namespace, vPod.Name) - err := ctx.VirtualClient.Delete(ctx.Context, vPod, &client.DeleteOptions{ + err := ctx.VirtualClient.Delete(ctx, vPod, &client.DeleteOptions{ GracePeriodSeconds: &zero, }) if kerrors.IsNotFound(err) { @@ -161,7 +161,7 @@ func (s *podSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) // validate virtual pod before syncing it to the host cluster if s.podSecurityStandard != "" { - valid, err := s.isPodSecurityStandardsValid(ctx.Context, vPod, ctx.Log) + valid, err := s.isPodSecurityStandardsValid(ctx, vPod, ctx.Log) if err != nil { return ctrl.Result{}, err } else if !valid { @@ -194,7 +194,7 @@ func (s *podSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) } } else { // make sure the node does exist in the virtual cluster - err = ctx.VirtualClient.Get(ctx.Context, types.NamespacedName{Name: pPod.Spec.NodeName}, &corev1.Node{}) + err = ctx.VirtualClient.Get(ctx, types.NamespacedName{Name: pPod.Spec.NodeName}, &corev1.Node{}) if err != nil { if !kerrors.IsNotFound(err) { return ctrl.Result{}, err @@ -227,12 +227,12 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj } ctx.Log.Infof("delete virtual pod %s/%s, because the physical pod is being deleted", vPod.Namespace, vPod.Name) - if err := ctx.VirtualClient.Delete(ctx.Context, vPod, &client.DeleteOptions{GracePeriodSeconds: &gracePeriod}); err != nil { + if err := ctx.VirtualClient.Delete(ctx, vPod, &client.DeleteOptions{GracePeriodSeconds: &gracePeriod}); err != nil { return ctrl.Result{}, err } } else if *vPod.DeletionGracePeriodSeconds != *pPod.DeletionGracePeriodSeconds { ctx.Log.Infof("delete virtual pPod %s/%s with grace period seconds %v", vPod.Namespace, vPod.Name, *pPod.DeletionGracePeriodSeconds) - if err := ctx.VirtualClient.Delete(ctx.Context, vPod, &client.DeleteOptions{GracePeriodSeconds: pPod.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(vPod.UID))}); err != nil { + if err := ctx.VirtualClient.Delete(ctx, vPod, &client.DeleteOptions{GracePeriodSeconds: pPod.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(vPod.UID))}); err != nil { return ctrl.Result{}, err } } @@ -240,7 +240,7 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj return ctrl.Result{}, nil } else if vPod.DeletionTimestamp != nil { ctx.Log.Infof("delete physical pod %s/%s, because virtual pod is being deleted", pPod.Namespace, pPod.Name) - err := ctx.PhysicalClient.Delete(ctx.Context, pPod, &client.DeleteOptions{ + err := ctx.PhysicalClient.Delete(ctx, pPod, &client.DeleteOptions{ GracePeriodSeconds: vPod.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(pPod.UID)), }) @@ -264,7 +264,7 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj } else if pPod.Spec.NodeName != "" && vPod.Spec.NodeName != "" && pPod.Spec.NodeName != vPod.Spec.NodeName { // if physical pod nodeName is different from virtual pod nodeName, we delete the virtual one ctx.Log.Infof("delete virtual pod %s/%s, because node name is different between the two", vPod.Namespace, vPod.Name) - err := ctx.VirtualClient.Delete(ctx.Context, vPod, &client.DeleteOptions{GracePeriodSeconds: &minimumGracePeriodInSeconds}) + err := ctx.VirtualClient.Delete(ctx, vPod, &client.DeleteOptions{GracePeriodSeconds: &minimumGracePeriodInSeconds}) if err != nil { return ctrl.Result{}, err } @@ -288,7 +288,7 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj newPod.Status = strippedPod.Status ctx.Log.Infof("update virtual pod %s/%s, because status has changed", vPod.Namespace, vPod.Name) translator.PrintChanges(vPod, newPod, ctx.Log) - err := ctx.VirtualClient.Status().Update(ctx.Context, newPod) + err := ctx.VirtualClient.Status().Update(ctx, newPod) if kerrors.IsConflict(err) { ctx.Log.Debugf("conflict updating virtual pod %s %s/%s", vPod.GetNamespace(), vPod.GetName()) return ctrl.Result{Requeue: true}, nil @@ -309,7 +309,7 @@ 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, err := s.podTranslator.TranslateContainerEnv(vPod.Spec.EphemeralContainers[i].Env, vPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := s.podTranslator.TranslateContainerEnv(ctx, 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) } @@ -326,7 +326,7 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj // validate virtual pod before syncing it to the host cluster if s.podSecurityStandard != "" { - valid, err := s.isPodSecurityStandardsValid(ctx.Context, vPod, ctx.Log) + valid, err := s.isPodSecurityStandardsValid(ctx, vPod, ctx.Log) if err != nil { return ctrl.Result{}, err } else if !valid { @@ -335,7 +335,7 @@ func (s *podSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj } // update the virtual pod if the spec has changed - updatedPod, err := s.translateUpdate(ctx.Context, ctx.PhysicalClient, pPod, vPod) + updatedPod, err := s.translateUpdate(ctx, ctx.PhysicalClient, pPod, vPod) if err != nil { return ctrl.Result{}, err } else if updatedPod != nil { @@ -367,7 +367,7 @@ func (s *podSyncer) ensureNode(ctx *synccontext.SyncContext, pObj *corev1.Pod, v if vObj.Spec.NodeName != pObj.Spec.NodeName && vObj.Spec.NodeName != "" { // node of virtual and physical pod are different, we delete the virtual pod to try to recover from this state ctx.Log.Infof("delete virtual pod %s/%s, because virtual and physical pods have different assigned nodes", vObj.Namespace, vObj.Name) - err := ctx.VirtualClient.Delete(ctx.Context, vObj) + err := ctx.VirtualClient.Delete(ctx, vObj) if err != nil { return false, err } @@ -378,7 +378,7 @@ func (s *podSyncer) ensureNode(ctx *synccontext.SyncContext, pObj *corev1.Pod, v // ensure the node is available in the virtual cluster, if not and we sync the pod to the virtual cluster, // it will get deleted automatically by kubernetes so we ensure the node is synced vNode := &corev1.Node{} - err := ctx.VirtualClient.Get(ctx.Context, types.NamespacedName{Name: pObj.Spec.NodeName}, vNode) + err := ctx.VirtualClient.Get(ctx, types.NamespacedName{Name: pObj.Spec.NodeName}, vNode) if err != nil { if !kerrors.IsNotFound(err) { ctx.Log.Infof("error retrieving virtual node %s: %v", pObj.Spec.NodeName, err) @@ -402,7 +402,7 @@ func (s *podSyncer) ensureNode(ctx *synccontext.SyncContext, pObj *corev1.Pod, v func (s *podSyncer) assignNodeToPod(ctx *synccontext.SyncContext, pObj *corev1.Pod, vObj *corev1.Pod) error { ctx.Log.Infof("bind virtual pod %s/%s to node %s, because node name between physical and virtual is different", vObj.Namespace, vObj.Name, pObj.Spec.NodeName) - err := s.virtualClusterClient.CoreV1().Pods(vObj.Namespace).Bind(ctx.Context, &corev1.Binding{ + err := s.virtualClusterClient.CoreV1().Pods(vObj.Namespace).Bind(ctx, &corev1.Binding{ ObjectMeta: metav1.ObjectMeta{ Name: vObj.Name, Namespace: vObj.Namespace, @@ -421,7 +421,7 @@ func (s *podSyncer) assignNodeToPod(ctx *synccontext.SyncContext, pObj *corev1.P } // wait until cache is updated - err = wait.PollUntilContextTimeout(ctx.Context, time.Millisecond*50, time.Second*2, true, func(syncContext context.Context) (done bool, err error) { + err = wait.PollUntilContextTimeout(ctx, time.Millisecond*50, time.Second*2, true, func(syncContext context.Context) (done bool, err error) { vPod := &corev1.Pod{} err = ctx.VirtualClient.Get(syncContext, types.NamespacedName{Namespace: vObj.Namespace, Name: vObj.Name}, vPod) if err != nil { diff --git a/pkg/controllers/resources/pods/translate.go b/pkg/controllers/resources/pods/translate.go index dc6a531068..5d78fda028 100644 --- a/pkg/controllers/resources/pods/translate.go +++ b/pkg/controllers/resources/pods/translate.go @@ -20,7 +20,7 @@ func (s *podSyncer) translate(ctx *synccontext.SyncContext, vPod *corev1.Pod) (* return nil, err } - pPod, err := s.podTranslator.Translate(ctx.Context, vPod, ptrServiceList, dnsIP, kubeIP) + pPod, err := s.podTranslator.Translate(ctx, vPod, ptrServiceList, dnsIP, kubeIP) if err != nil { return nil, err } @@ -41,7 +41,7 @@ func (s *podSyncer) getK8sIPDNSIPServiceList(ctx *synccontext.SyncContext, vPod // get services for pod serviceList := &corev1.ServiceList{} - err = ctx.VirtualClient.List(ctx.Context, serviceList, client.InNamespace(vPod.Namespace)) + err = ctx.VirtualClient.List(ctx, serviceList, client.InNamespace(vPod.Namespace)) if err != nil { return "", "", nil, err } @@ -71,7 +71,7 @@ func (s *podSyncer) translateUpdate(ctx context.Context, pClient client.Client, func (s *podSyncer) findKubernetesIP(ctx *synccontext.SyncContext) (string, error) { pService := &corev1.Service{} - err := ctx.CurrentNamespaceClient.Get(ctx.Context, types.NamespacedName{ + err := ctx.CurrentNamespaceClient.Get(ctx, types.NamespacedName{ Name: s.serviceName, Namespace: ctx.CurrentNamespace, }, pService) @@ -88,7 +88,7 @@ func (s *podSyncer) findKubernetesDNSIP(ctx *synccontext.SyncContext) (string, e } // translate service name - pService := mappings.VirtualToHostName(specialservices.DefaultKubeDNSServiceName, specialservices.DefaultKubeDNSServiceNamespace, mappings.Services()) + pService := mappings.VirtualToHostName(ctx, specialservices.DefaultKubeDNSServiceName, specialservices.DefaultKubeDNSServiceNamespace, mappings.Services()) // 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) @@ -107,7 +107,7 @@ func (s *podSyncer) findKubernetesDNSIP(ctx *synccontext.SyncContext) (string, e func (s *podSyncer) translateAndFindService(ctx *synccontext.SyncContext, kubeClient client.Client, namespace, name string) string { pService := &corev1.Service{} - err := kubeClient.Get(ctx.Context, types.NamespacedName{ + err := kubeClient.Get(ctx, types.NamespacedName{ Name: name, Namespace: namespace, }, pService) diff --git a/pkg/controllers/resources/pods/translate/sa_token_secret.go b/pkg/controllers/resources/pods/translate/sa_token_secret.go index c06d59358c..74a67619a8 100644 --- a/pkg/controllers/resources/pods/translate/sa_token_secret.go +++ b/pkg/controllers/resources/pods/translate/sa_token_secret.go @@ -22,8 +22,8 @@ const ( var PodServiceAccountTokenSecretName string -func SecretNameFromPodName(podName, namespace string) string { - return mappings.VirtualToHostName(fmt.Sprintf("%s-sa-token", podName), namespace, mappings.Secrets()) +func SecretNameFromPodName(ctx context.Context, podName, namespace string) string { + return mappings.VirtualToHostName(ctx, fmt.Sprintf("%s-sa-token", podName), namespace, mappings.Secrets()) } var ErrNotFound = errors.New("translate: not found") @@ -39,7 +39,7 @@ func IgnoreAcceptableErrors(err error) error { func GetSecretIfExists(ctx context.Context, pClient client.Client, vPodName, vNamespace string) (*corev1.Secret, error) { secret := &corev1.Secret{} err := pClient.Get(ctx, types.NamespacedName{ - Name: SecretNameFromPodName(vPodName, vNamespace), + Name: SecretNameFromPodName(ctx, vPodName, vNamespace), Namespace: translate.Default.PhysicalNamespace(vNamespace), }, secret) if err != nil { @@ -70,7 +70,7 @@ func SATokenSecret(ctx context.Context, pClient client.Client, vPod *corev1.Pod, // create to secret with the given token secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: SecretNameFromPodName(vPod.Name, vPod.Namespace), + Name: SecretNameFromPodName(ctx, vPod.Name, vPod.Namespace), Namespace: translate.Default.PhysicalNamespace(vPod.Namespace), Annotations: map[string]string{ diff --git a/pkg/controllers/resources/pods/translate/translator.go b/pkg/controllers/resources/pods/translate/translator.go index 0bc8ad02bc..7aa41fa74f 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, error) + TranslateContainerEnv(ctx context.Context, 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) { @@ -159,7 +159,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // convert to core object pPod := translate.Default.ApplyMetadata( vPod, - mappings.VirtualToHost(vPod.Name, vPod.Namespace, mappings.Pods()), + mappings.VirtualToHost(ctx, vPod.Name, vPod.Namespace, mappings.Pods()), t.syncedLabels, ).(*corev1.Pod) @@ -173,7 +173,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ vPodServiceAccountName = vPod.Spec.ServiceAccountName } if vPodServiceAccountName != "" { - pPod.Spec.ServiceAccountName = mappings.VirtualToHostName(vPodServiceAccountName, vPod.Namespace, mappings.ServiceAccounts()) + pPod.Spec.ServiceAccountName = mappings.VirtualToHostName(ctx, vPodServiceAccountName, vPod.Namespace, mappings.ServiceAccounts()) } } @@ -185,7 +185,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ pPod.Spec.PriorityClassName = "" pPod.Spec.Priority = nil } else if pPod.Spec.PriorityClassName != "" { - pPod.Spec.PriorityClassName = mappings.VirtualToHostName(pPod.Spec.PriorityClassName, "", mappings.PriorityClasses()) + pPod.Spec.PriorityClassName = mappings.VirtualToHostName(ctx, pPod.Spec.PriorityClassName, "", mappings.PriorityClasses()) if pPod.Spec.Priority != nil && *pPod.Spec.Priority > maxPriority { pPod.Spec.Priority = &maxPriority } @@ -295,7 +295,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate containers for i := range pPod.Spec.Containers { - envVar, envFrom, err := t.TranslateContainerEnv(pPod.Spec.Containers[i].Env, pPod.Spec.Containers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := t.TranslateContainerEnv(ctx, pPod.Spec.Containers[i].Env, pPod.Spec.Containers[i].EnvFrom, vPod, serviceEnv) if err != nil { return nil, err } @@ -306,7 +306,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate init containers for i := range pPod.Spec.InitContainers { - envVar, envFrom, err := t.TranslateContainerEnv(pPod.Spec.InitContainers[i].Env, pPod.Spec.InitContainers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := t.TranslateContainerEnv(ctx, pPod.Spec.InitContainers[i].Env, pPod.Spec.InitContainers[i].EnvFrom, vPod, serviceEnv) if err != nil { return nil, err } @@ -317,7 +317,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate ephemeral containers for i := range pPod.Spec.EphemeralContainers { - envVar, envFrom, err := t.TranslateContainerEnv(pPod.Spec.EphemeralContainers[i].Env, pPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv) + envVar, envFrom, err := t.TranslateContainerEnv(ctx, pPod.Spec.EphemeralContainers[i].Env, pPod.Spec.EphemeralContainers[i].EnvFrom, vPod, serviceEnv) if err != nil { return nil, err } @@ -328,7 +328,7 @@ func (t *translator) Translate(ctx context.Context, vPod *corev1.Pod, services [ // translate image pull secrets for i := range pPod.Spec.ImagePullSecrets { - pPod.Spec.ImagePullSecrets[i].Name = mappings.VirtualToHostName(pPod.Spec.ImagePullSecrets[i].Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.ImagePullSecrets[i].Name = mappings.VirtualToHostName(ctx, pPod.Spec.ImagePullSecrets[i].Name, vPod.Namespace, mappings.Secrets()) } // translate volumes @@ -388,13 +388,13 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo for i := range pPod.Spec.Volumes { if pPod.Spec.Volumes[i].ConfigMap != nil { - pPod.Spec.Volumes[i].ConfigMap.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].ConfigMap.Name, vPod.Namespace, mappings.ConfigMaps()) + pPod.Spec.Volumes[i].ConfigMap.Name = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].ConfigMap.Name, vPod.Namespace, mappings.ConfigMaps()) } if pPod.Spec.Volumes[i].Secret != nil { - pPod.Spec.Volumes[i].Secret.SecretName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].Secret.SecretName, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].Secret.SecretName = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].Secret.SecretName, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].PersistentVolumeClaim != nil { - pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName, vPod.Namespace, mappings.PersistentVolumeClaims()) + pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].PersistentVolumeClaim.ClaimName, vPod.Namespace, mappings.PersistentVolumeClaims()) } if pPod.Spec.Volumes[i].Ephemeral != nil { // An ephemeral volume is created as a PVC by the "ephemeral_volume" K8s controller. @@ -405,7 +405,7 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo // the Pod, and that remains unchanged and thus the PVC will be removed by the kube // controllers of the vcluster, and syncer will then remove the PVC from the host. pPod.Spec.Volumes[i].PersistentVolumeClaim = &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: mappings.VirtualToHostName(ephemeral.VolumeClaimName(vPod, &vPod.Spec.Volumes[i]), vPod.Namespace, mappings.PersistentVolumeClaims()), + ClaimName: mappings.VirtualToHostName(ctx, ephemeral.VolumeClaimName(vPod, &vPod.Spec.Volumes[i]), vPod.Namespace, mappings.PersistentVolumeClaims()), } pPod.Spec.Volumes[i].Ephemeral = nil } @@ -421,34 +421,34 @@ func (t *translator) translateVolumes(ctx context.Context, pPod *corev1.Pod, vPo } } if pPod.Spec.Volumes[i].ISCSI != nil && pPod.Spec.Volumes[i].ISCSI.SecretRef != nil { - pPod.Spec.Volumes[i].ISCSI.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].ISCSI.SecretRef.Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].ISCSI.SecretRef.Name = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].ISCSI.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].RBD != nil && pPod.Spec.Volumes[i].RBD.SecretRef != nil { - pPod.Spec.Volumes[i].RBD.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].RBD.SecretRef.Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].RBD.SecretRef.Name = mappings.VirtualToHostName(ctx, 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()) + pPod.Spec.Volumes[i].FlexVolume.SecretRef.Name = mappings.VirtualToHostName(ctx, 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 { - pPod.Spec.Volumes[i].Cinder.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].Cinder.SecretRef.Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].Cinder.SecretRef.Name = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].Cinder.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].CephFS != nil && pPod.Spec.Volumes[i].CephFS.SecretRef != nil { - pPod.Spec.Volumes[i].CephFS.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].CephFS.SecretRef.Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].CephFS.SecretRef.Name = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].CephFS.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].AzureFile != nil && pPod.Spec.Volumes[i].AzureFile.SecretName != "" { - pPod.Spec.Volumes[i].AzureFile.SecretName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].AzureFile.SecretName, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].AzureFile.SecretName = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].AzureFile.SecretName, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].ScaleIO != nil && pPod.Spec.Volumes[i].ScaleIO.SecretRef != nil { - pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].ScaleIO.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].StorageOS != nil && pPod.Spec.Volumes[i].StorageOS.SecretRef != nil { - pPod.Spec.Volumes[i].StorageOS.SecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].StorageOS.SecretRef.Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].StorageOS.SecretRef.Name = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].StorageOS.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].CSI != nil && pPod.Spec.Volumes[i].CSI.NodePublishSecretRef != nil { - pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name = mappings.VirtualToHostName(pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name, vPod.Namespace, mappings.Secrets()) + pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].CSI.NodePublishSecretRef.Name, vPod.Namespace, mappings.Secrets()) } if pPod.Spec.Volumes[i].Glusterfs != nil && pPod.Spec.Volumes[i].Glusterfs.EndpointsName != "" { - pPod.Spec.Volumes[i].Glusterfs.EndpointsName = mappings.VirtualToHostName(pPod.Spec.Volumes[i].Glusterfs.EndpointsName, vPod.Namespace, mappings.Endpoints()) + pPod.Spec.Volumes[i].Glusterfs.EndpointsName = mappings.VirtualToHostName(ctx, pPod.Spec.Volumes[i].Glusterfs.EndpointsName, vPod.Namespace, mappings.Endpoints()) } } @@ -476,10 +476,10 @@ func (t *translator) translateProjectedVolume( ) error { for i := range projectedVolume.Sources { if projectedVolume.Sources[i].Secret != nil { - projectedVolume.Sources[i].Secret.Name = mappings.VirtualToHostName(projectedVolume.Sources[i].Secret.Name, vPod.Namespace, mappings.Secrets()) + projectedVolume.Sources[i].Secret.Name = mappings.VirtualToHostName(ctx, projectedVolume.Sources[i].Secret.Name, vPod.Namespace, mappings.Secrets()) } if projectedVolume.Sources[i].ConfigMap != nil { - projectedVolume.Sources[i].ConfigMap.Name = mappings.VirtualToHostName(projectedVolume.Sources[i].ConfigMap.Name, vPod.Namespace, mappings.ConfigMaps()) + projectedVolume.Sources[i].ConfigMap.Name = mappings.VirtualToHostName(ctx, projectedVolume.Sources[i].ConfigMap.Name, vPod.Namespace, mappings.ConfigMaps()) } if projectedVolume.Sources[i].DownwardAPI != nil { for j := range projectedVolume.Sources[i].DownwardAPI.Items { @@ -534,7 +534,7 @@ func (t *translator) translateProjectedVolume( // rewrite projected volume to use sources as secret projectedVolume.Sources[i].Secret = &corev1.SecretProjection{ LocalObjectReference: corev1.LocalObjectReference{ - Name: SecretNameFromPodName(vPod.Name, vPod.Namespace), + Name: SecretNameFromPodName(ctx, vPod.Name, vPod.Namespace), }, Items: []corev1.KeyToPath{ { @@ -608,25 +608,25 @@ 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, error) { +func (t *translator) TranslateContainerEnv(ctx context.Context, 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]) if env.ValueFrom != nil && env.ValueFrom.ConfigMapKeyRef != nil && env.ValueFrom.ConfigMapKeyRef.Name != "" { - envVar[j].ValueFrom.ConfigMapKeyRef.Name = mappings.VirtualToHostName(envVar[j].ValueFrom.ConfigMapKeyRef.Name, vPod.Namespace, mappings.ConfigMaps()) + envVar[j].ValueFrom.ConfigMapKeyRef.Name = mappings.VirtualToHostName(ctx, envVar[j].ValueFrom.ConfigMapKeyRef.Name, vPod.Namespace, mappings.ConfigMaps()) } if env.ValueFrom != nil && env.ValueFrom.SecretKeyRef != nil && env.ValueFrom.SecretKeyRef.Name != "" { - envVar[j].ValueFrom.SecretKeyRef.Name = mappings.VirtualToHostName(envVar[j].ValueFrom.SecretKeyRef.Name, vPod.Namespace, mappings.Secrets()) + envVar[j].ValueFrom.SecretKeyRef.Name = mappings.VirtualToHostName(ctx, envVar[j].ValueFrom.SecretKeyRef.Name, vPod.Namespace, mappings.Secrets()) } envNameMap[env.Name] = struct{}{} } for j, from := range envFrom { if from.ConfigMapRef != nil && from.ConfigMapRef.Name != "" { - envFrom[j].ConfigMapRef.Name = mappings.VirtualToHostName(from.ConfigMapRef.Name, vPod.Namespace, mappings.ConfigMaps()) + envFrom[j].ConfigMapRef.Name = mappings.VirtualToHostName(ctx, from.ConfigMapRef.Name, vPod.Namespace, mappings.ConfigMaps()) } if from.SecretRef != nil && from.SecretRef.Name != "" { - envFrom[j].SecretRef.Name = mappings.VirtualToHostName(from.SecretRef.Name, vPod.Namespace, mappings.Secrets()) + envFrom[j].SecretRef.Name = mappings.VirtualToHostName(ctx, from.SecretRef.Name, vPod.Namespace, mappings.Secrets()) } } diff --git a/pkg/controllers/resources/pods/util.go b/pkg/controllers/resources/pods/util.go index b59325a0f5..d0da9bb27c 100644 --- a/pkg/controllers/resources/pods/util.go +++ b/pkg/controllers/resources/pods/util.go @@ -1,6 +1,8 @@ package pods import ( + "context" + "github.com/loft-sh/vcluster/pkg/util/translate" podtranslate "github.com/loft-sh/vcluster/pkg/controllers/resources/pods/translate" @@ -8,7 +10,7 @@ import ( corev1 "k8s.io/api/core/v1" ) -func SecretNamesFromPod(pod *corev1.Pod) []string { +func SecretNamesFromPod(ctx context.Context, pod *corev1.Pod) []string { secrets := []string{} for _, c := range pod.Spec.Containers { secrets = append(secrets, SecretNamesFromContainer(pod.Namespace, &c)...) @@ -22,11 +24,11 @@ func SecretNamesFromPod(pod *corev1.Pod) []string { for i := range pod.Spec.ImagePullSecrets { secrets = append(secrets, pod.Namespace+"/"+pod.Spec.ImagePullSecrets[i].Name) } - secrets = append(secrets, SecretNamesFromVolumes(pod)...) + secrets = append(secrets, SecretNamesFromVolumes(ctx, pod)...) return translate.UniqueSlice(secrets) } -func SecretNamesFromVolumes(pod *corev1.Pod) []string { +func SecretNamesFromVolumes(ctx context.Context, pod *corev1.Pod) []string { secrets := []string{} for i := range pod.Spec.Volumes { if pod.Spec.Volumes[i].Secret != nil { @@ -41,7 +43,7 @@ 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)) + secrets = append(secrets, pod.Namespace+"/"+podtranslate.SecretNameFromPodName(ctx, pod.Name, pod.Namespace)) } } } diff --git a/pkg/controllers/resources/priorityclasses/syncer.go b/pkg/controllers/resources/priorityclasses/syncer.go index 9e8ca80bc6..61c2b8b609 100644 --- a/pkg/controllers/resources/priorityclasses/syncer.go +++ b/pkg/controllers/resources/priorityclasses/syncer.go @@ -27,9 +27,9 @@ type priorityClassSyncer struct { var _ syncer.Syncer = &priorityClassSyncer{} func (s *priorityClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - newPriorityClass := s.translate(ctx.Context, vObj.(*schedulingv1.PriorityClass)) + newPriorityClass := s.translate(ctx, vObj.(*schedulingv1.PriorityClass)) ctx.Log.Infof("create physical priority class %s", newPriorityClass.Name) - err := ctx.PhysicalClient.Create(ctx.Context, newPriorityClass) + err := ctx.PhysicalClient.Create(ctx, newPriorityClass) if err != nil { ctx.Log.Infof("error syncing %s to physical cluster: %v", vObj.GetName(), err) return ctrl.Result{}, err @@ -54,6 +54,6 @@ func (s *priorityClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Obj pPriorityClass, vPriorityClass, sourceObject, targetObject := synccontext.Cast[*schedulingv1.PriorityClass](ctx, pObj, vObj) // did the priority class change? - s.translateUpdate(ctx.Context, pPriorityClass, vPriorityClass, sourceObject, targetObject) + s.translateUpdate(ctx, pPriorityClass, vPriorityClass, sourceObject, targetObject) return ctrl.Result{}, nil } diff --git a/pkg/controllers/resources/register.go b/pkg/controllers/resources/register.go index be594b90ca..d943155c37 100644 --- a/pkg/controllers/resources/register.go +++ b/pkg/controllers/resources/register.go @@ -94,7 +94,7 @@ func BuildSyncers(ctx *synccontext.RegisterContext) ([]syncertypes.Object, error // execute initializer initializer, ok := syncer.(syncertypes.Initializer) if ok { - klog.FromContext(ctx.Context).V(1).Info("Execute syncer init", "syncer", name) + klog.FromContext(ctx).V(1).Info("Execute syncer init", "syncer", name) err := initializer.Init(ctx) if err != nil { return nil, errors.Wrapf(err, "ensure prerequisites for %s syncer", name) diff --git a/pkg/controllers/resources/secrets/syncer.go b/pkg/controllers/resources/secrets/syncer.go index 32d6747acd..9ae0958a87 100644 --- a/pkg/controllers/resources/secrets/syncer.go +++ b/pkg/controllers/resources/secrets/syncer.go @@ -55,16 +55,16 @@ var _ syncer.IndicesRegisterer = &secretSyncer{} func (s *secretSyncer) RegisterIndices(ctx *synccontext.RegisterContext) error { if ctx.Config.Sync.ToHost.Ingresses.Enabled { - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &networkingv1.Ingress{}, constants.IndexByIngressSecret, func(rawObj client.Object) []string { - return ingresses.SecretNamesFromIngress(rawObj.(*networkingv1.Ingress)) + err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &networkingv1.Ingress{}, constants.IndexByIngressSecret, func(rawObj client.Object) []string { + return ingresses.SecretNamesFromIngress(ctx, rawObj.(*networkingv1.Ingress)) }) if err != nil { return err } } - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Pod{}, constants.IndexByPodSecret, func(rawObj client.Object) []string { - return pods.SecretNamesFromPod(rawObj.(*corev1.Pod)) + err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &corev1.Pod{}, constants.IndexByPodSecret, func(rawObj client.Object) []string { + return pods.SecretNamesFromPod(ctx, rawObj.(*corev1.Pod)) }) if err != nil { return err @@ -91,7 +91,7 @@ func (s *secretSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Obje return ctrl.Result{}, nil } - return s.SyncToHostCreate(ctx, vObj, s.create(ctx.Context, vObj.(*corev1.Secret))) + return s.SyncToHostCreate(ctx, vObj, s.create(ctx, vObj.(*corev1.Secret))) } func (s *secretSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (_ ctrl.Result, retErr error) { @@ -100,7 +100,7 @@ func (s *secretSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vO return ctrl.Result{}, err } else if !used { ctx.Log.Infof("delete physical secret %s/%s, because it is not used anymore", pObj.GetNamespace(), pObj.GetName()) - err = ctx.PhysicalClient.Delete(ctx.Context, pObj) + err = ctx.PhysicalClient.Delete(ctx, pObj) if err != nil { ctx.Log.Infof("error deleting physical object %s/%s in physical cluster: %v", pObj.GetNamespace(), pObj.GetName(), err) return ctrl.Result{}, err @@ -138,7 +138,7 @@ func (s *secretSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vO } // check annotations - changed, updatedAnnotations, updatedLabels := s.TranslateMetadataUpdate(ctx.Context, vObj, pObj) + changed, updatedAnnotations, updatedLabels := s.TranslateMetadataUpdate(ctx, vObj, pObj) if changed { pSecret.Annotations = updatedAnnotations pSecret.Labels = updatedLabels @@ -155,7 +155,7 @@ func (s *secretSyncer) isSecretUsed(ctx *synccontext.SyncContext, vObj runtime.O return true, nil } - isUsed, err := isSecretUsedByPods(ctx.Context, ctx.VirtualClient, secret.Namespace+"/"+secret.Name) + isUsed, err := isSecretUsedByPods(ctx, ctx.VirtualClient, secret.Namespace+"/"+secret.Name) if err != nil { return false, errors.Wrap(err, "is secret used by pods") } @@ -166,7 +166,7 @@ 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}) + err := ctx.VirtualClient.List(ctx, ingressesList, client.MatchingFields{constants.IndexByIngressSecret: secret.Namespace + "/" + secret.Name}) if err != nil { return false, err } @@ -184,14 +184,14 @@ func (s *secretSyncer) isSecretUsed(ctx *synccontext.SyncContext, vObj runtime.O return false, nil } -func mapIngresses(_ context.Context, obj client.Object) []reconcile.Request { +func mapIngresses(ctx context.Context, obj client.Object) []reconcile.Request { ingress, ok := obj.(*networkingv1.Ingress) if !ok { return nil } requests := []reconcile.Request{} - names := ingresses.SecretNamesFromIngress(ingress) + names := ingresses.SecretNamesFromIngress(ctx, ingress) for _, name := range names { splitted := strings.Split(name, "/") if len(splitted) == 2 { @@ -207,14 +207,14 @@ func mapIngresses(_ context.Context, obj client.Object) []reconcile.Request { return requests } -func mapPods(_ context.Context, obj client.Object) []reconcile.Request { +func mapPods(ctx context.Context, obj client.Object) []reconcile.Request { pod, ok := obj.(*corev1.Pod) if !ok { return nil } requests := []reconcile.Request{} - names := pods.SecretNamesFromPod(pod) + names := pods.SecretNamesFromPod(ctx, pod) for _, name := range names { splitted := strings.Split(name, "/") if len(splitted) == 2 { diff --git a/pkg/controllers/resources/serviceaccounts/syncer.go b/pkg/controllers/resources/serviceaccounts/syncer.go index 94065bee9f..d9cdddf389 100644 --- a/pkg/controllers/resources/serviceaccounts/syncer.go +++ b/pkg/controllers/resources/serviceaccounts/syncer.go @@ -22,12 +22,12 @@ type serviceAccountSyncer struct { } func (s *serviceAccountSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostCreate(ctx, vObj, s.translate(ctx.Context, vObj.(*corev1.ServiceAccount))) + return s.SyncToHostCreate(ctx, vObj, s.translate(ctx, vObj.(*corev1.ServiceAccount))) } func (s *serviceAccountSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { // did the service account change? - newServiceAccount := s.translateUpdate(ctx.Context, pObj.(*corev1.ServiceAccount), vObj.(*corev1.ServiceAccount)) + newServiceAccount := s.translateUpdate(ctx, pObj.(*corev1.ServiceAccount), vObj.(*corev1.ServiceAccount)) if newServiceAccount != nil { translator.PrintChanges(pObj, newServiceAccount, ctx.Log) } diff --git a/pkg/controllers/resources/services/syncer.go b/pkg/controllers/resources/services/syncer.go index 560a2985bd..0ba5f4aa94 100644 --- a/pkg/controllers/resources/services/syncer.go +++ b/pkg/controllers/resources/services/syncer.go @@ -46,7 +46,7 @@ func (s *serviceSyncer) WithOptions() *syncertypes.Options { } func (s *serviceSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - return s.SyncToHostCreate(ctx, vObj, s.translate(ctx.Context, vObj.(*corev1.Service))) + return s.SyncToHostCreate(ctx, vObj, s.translate(ctx, vObj.(*corev1.Service))) } func (s *serviceSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { @@ -66,7 +66,7 @@ func (s *serviceSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, v ctx.Log.Infof("recreating virtual service %s/%s, because cluster ip differs %s != %s", vService.Namespace, vService.Name, pService.Spec.ClusterIP, vService.Spec.ClusterIP) // recreate the new service with the correct cluster ip - _, err := recreateService(ctx.Context, ctx.VirtualClient, newService) + _, err := recreateService(ctx, ctx.VirtualClient, newService) if err != nil { ctx.Log.Errorf("error creating virtual service: %s/%s", vService.Namespace, vService.Name) return ctrl.Result{}, err @@ -74,7 +74,7 @@ func (s *serviceSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, v } else { // update with correct ports ctx.Log.Infof("update virtual service %s/%s, because spec is out of sync", vService.Namespace, vService.Name) - err := ctx.VirtualClient.Update(ctx.Context, newService) + err := ctx.VirtualClient.Update(ctx, newService) if err != nil { return ctrl.Result{}, err } @@ -90,7 +90,7 @@ func (s *serviceSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, v newService.Status = pService.Status ctx.Log.Infof("update virtual service %s/%s, because status is out of sync", vService.Namespace, vService.Name) translator.PrintChanges(vService, newService, ctx.Log) - err := ctx.VirtualClient.Status().Update(ctx.Context, newService) + err := ctx.VirtualClient.Status().Update(ctx, newService) if err != nil { return ctrl.Result{}, err } @@ -99,7 +99,7 @@ func (s *serviceSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, v } // forward update - newService = s.translateUpdate(ctx.Context, pService, vService) + newService = s.translateUpdate(ctx, pService, vService) if newService != nil { translator.PrintChanges(pService, newService, ctx.Log) } @@ -114,7 +114,7 @@ func isSwitchingFromExternalName(pService *corev1.Service, vService *corev1.Serv var _ syncertypes.ToVirtualSyncer = &serviceSyncer{} func (s *serviceSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { - isManaged, err := s.NamespacedTranslator.IsManaged(ctx.Context, pObj) + isManaged, err := s.NamespacedTranslator.IsManaged(ctx, pObj) if err != nil { return ctrl.Result{}, err } else if !isManaged { diff --git a/pkg/controllers/resources/services/syncer_test.go b/pkg/controllers/resources/services/syncer_test.go index 663c7359b1..26450e3822 100644 --- a/pkg/controllers/resources/services/syncer_test.go +++ b/pkg/controllers/resources/services/syncer_test.go @@ -401,10 +401,10 @@ func TestSync(t *testing.T) { _, err := syncer.(*serviceSyncer).Sync(syncCtx, updateBackwardSpecService, baseService) assert.NilError(t, err) - err = ctx.VirtualManager.GetClient().Get(ctx.Context, types.NamespacedName{Namespace: baseService.Namespace, Name: baseService.Name}, baseService) + err = ctx.VirtualManager.GetClient().Get(ctx, types.NamespacedName{Namespace: baseService.Namespace, Name: baseService.Name}, baseService) assert.NilError(t, err) - err = ctx.PhysicalManager.GetClient().Get(ctx.Context, types.NamespacedName{Namespace: updateBackwardSpecService.Namespace, Name: updateBackwardSpecService.Name}, updateBackwardSpecService) + err = ctx.PhysicalManager.GetClient().Get(ctx, types.NamespacedName{Namespace: updateBackwardSpecService.Namespace, Name: updateBackwardSpecService.Name}, updateBackwardSpecService) assert.NilError(t, err) baseService.Spec.ExternalName = updateBackwardSpecService.Spec.ExternalName @@ -429,10 +429,10 @@ func TestSync(t *testing.T) { _, err := syncer.(*serviceSyncer).Sync(syncCtx, updateBackwardSpecRecreateService, baseService) assert.NilError(t, err) - err = ctx.VirtualManager.GetClient().Get(ctx.Context, types.NamespacedName{Namespace: baseService.Namespace, Name: baseService.Name}, baseService) + err = ctx.VirtualManager.GetClient().Get(ctx, types.NamespacedName{Namespace: baseService.Namespace, Name: baseService.Name}, baseService) assert.NilError(t, err) - err = ctx.PhysicalManager.GetClient().Get(ctx.Context, types.NamespacedName{Namespace: updateBackwardSpecRecreateService.Namespace, Name: updateBackwardSpecRecreateService.Name}, updateBackwardSpecRecreateService) + err = ctx.PhysicalManager.GetClient().Get(ctx, types.NamespacedName{Namespace: updateBackwardSpecRecreateService.Namespace, Name: updateBackwardSpecRecreateService.Name}, updateBackwardSpecRecreateService) assert.NilError(t, err) baseService.Spec.ExternalName = updateBackwardSpecService.Spec.ExternalName diff --git a/pkg/controllers/resources/storageclasses/host_sc_syncer.go b/pkg/controllers/resources/storageclasses/host_sc_syncer.go index 42ee8d5923..ccf3b87093 100644 --- a/pkg/controllers/resources/storageclasses/host_sc_syncer.go +++ b/pkg/controllers/resources/storageclasses/host_sc_syncer.go @@ -23,20 +23,20 @@ type hostStorageClassSyncer struct { var _ syncer.ToVirtualSyncer = &hostStorageClassSyncer{} func (s *hostStorageClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { - vObj := s.translateBackwards(ctx.Context, pObj.(*storagev1.StorageClass)) + vObj := s.translateBackwards(ctx, pObj.(*storagev1.StorageClass)) ctx.Log.Infof("create storage class %s, because it does not exist in virtual cluster", vObj.Name) - return ctrl.Result{}, ctx.VirtualClient.Create(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } var _ syncer.Syncer = &hostStorageClassSyncer{} func (s *hostStorageClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { // check if there is a change - updated := s.translateUpdateBackwards(ctx.Context, pObj.(*storagev1.StorageClass), vObj.(*storagev1.StorageClass)) + updated := s.translateUpdateBackwards(ctx, pObj.(*storagev1.StorageClass), vObj.(*storagev1.StorageClass)) if updated != nil { ctx.Log.Infof("update storage class %s", vObj.GetName()) translator.PrintChanges(pObj, updated, ctx.Log) - return ctrl.Result{}, ctx.VirtualClient.Update(ctx.Context, updated) + return ctrl.Result{}, ctx.VirtualClient.Update(ctx, updated) } return ctrl.Result{}, nil @@ -44,5 +44,5 @@ func (s *hostStorageClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client. func (s *hostStorageClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { ctx.Log.Infof("delete virtual storage class %s, because physical object is missing", vObj.GetName()) - return ctrl.Result{}, ctx.VirtualClient.Delete(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, vObj) } diff --git a/pkg/controllers/resources/storageclasses/syncer.go b/pkg/controllers/resources/storageclasses/syncer.go index a9b159fc53..893d6099cd 100644 --- a/pkg/controllers/resources/storageclasses/syncer.go +++ b/pkg/controllers/resources/storageclasses/syncer.go @@ -26,11 +26,11 @@ var _ syncer.Syncer = &storageClassSyncer{} func (s *storageClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { // did the storage class change? - updated := s.translateUpdate(ctx.Context, pObj.(*storagev1.StorageClass), vObj.(*storagev1.StorageClass)) + updated := s.translateUpdate(ctx, pObj.(*storagev1.StorageClass), vObj.(*storagev1.StorageClass)) if updated != nil { ctx.Log.Infof("updating physical storage class %s, because virtual storage class has changed", updated.Name) translator.PrintChanges(pObj, updated, ctx.Log) - err := ctx.PhysicalClient.Update(ctx.Context, updated) + err := ctx.PhysicalClient.Update(ctx, updated) if err != nil { return ctrl.Result{}, err } @@ -40,9 +40,9 @@ func (s *storageClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Obje } func (s *storageClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj client.Object) (ctrl.Result, error) { - newStorageClass := s.translate(ctx.Context, vObj.(*storagev1.StorageClass)) + newStorageClass := s.translate(ctx, vObj.(*storagev1.StorageClass)) ctx.Log.Infof("create physical storage class %s", newStorageClass.Name) - err := ctx.PhysicalClient.Create(ctx.Context, newStorageClass) + err := ctx.PhysicalClient.Create(ctx, newStorageClass) if err != nil { ctx.Log.Infof("error syncing %s to physical cluster: %v", vObj.GetName(), err) return ctrl.Result{}, err diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go index ae028473cf..ac37fcfba7 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go @@ -32,9 +32,9 @@ var _ syncer.ToVirtualSyncer = &volumeSnapshotClassSyncer{} func (s *volumeSnapshotClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { pVolumeSnapshotClass := pObj.(*volumesnapshotv1.VolumeSnapshotClass) - vObj := s.translateBackwards(ctx.Context, pVolumeSnapshotClass) + vObj := s.translateBackwards(ctx, pVolumeSnapshotClass) ctx.Log.Infof("create VolumeSnapshotClass %s, because it does not exist in the virtual cluster", vObj.Name) - return ctrl.Result{}, ctx.VirtualClient.Create(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } var _ syncer.Syncer = &volumeSnapshotClassSyncer{} @@ -44,7 +44,7 @@ func (s *volumeSnapshotClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vOb // if this method is called it means that VolumeSnapshotClass was deleted in host or // a new VolumeSnapshotClass was created in vcluster, and it should be deleted to avoid confusion ctx.Log.Infof("delete VolumeSnapshotClass %s, because it does not exist in the host cluster", vObj.GetName()) - err := ctx.VirtualClient.Delete(ctx.Context, vObj) + err := ctx.VirtualClient.Delete(ctx, vObj) if err != nil { return ctrl.Result{}, err } @@ -52,11 +52,11 @@ func (s *volumeSnapshotClassSyncer) SyncToHost(ctx *synccontext.SyncContext, vOb } func (s *volumeSnapshotClassSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Object, vObj client.Object) (ctrl.Result, error) { - updated := s.translateUpdateBackwards(ctx.Context, pObj.(*volumesnapshotv1.VolumeSnapshotClass), vObj.(*volumesnapshotv1.VolumeSnapshotClass)) + updated := s.translateUpdateBackwards(ctx, pObj.(*volumesnapshotv1.VolumeSnapshotClass), vObj.(*volumesnapshotv1.VolumeSnapshotClass)) if updated != nil { ctx.Log.Infof("updating virtual VolumeSnapshotClass %s, because it differs from the physical one", updated.Name) translator.PrintChanges(vObj, updated, ctx.Log) - err := ctx.VirtualClient.Update(ctx.Context, updated) + err := ctx.VirtualClient.Update(ctx, updated) if err != nil { return ctrl.Result{}, err } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go index ffbf206f09..457bb32f3c 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go @@ -50,7 +50,7 @@ var _ syncer.ToVirtualSyncer = &volumeSnapshotContentSyncer{} func (s *volumeSnapshotContentSyncer) SyncToVirtual(ctx *synccontext.SyncContext, pObj client.Object) (ctrl.Result, error) { pVSC := pObj.(*volumesnapshotv1.VolumeSnapshotContent) // check if the VolumeSnapshotContent should get synced - sync, vVS, err := s.shouldSync(ctx.Context, pVSC) + sync, vVS, err := s.shouldSync(ctx, pVSC) if err != nil { return ctrl.Result{}, err } else if !sync { @@ -60,7 +60,7 @@ func (s *volumeSnapshotContentSyncer) SyncToVirtual(ctx *synccontext.SyncContext vVSC := s.translateBackwards(pVSC, vVS) ctx.Log.Infof("create VolumeSnapshotContent %s, because it does not exist in the virtual cluster", vVSC.Name) - return ctrl.Result{}, s.virtualClient.Create(ctx.Context, vVSC) + return ctrl.Result{}, s.virtualClient.Create(ctx, vVSC) } var _ syncer.Syncer = &volumeSnapshotContentSyncer{} @@ -72,16 +72,16 @@ func (s *volumeSnapshotContentSyncer) SyncToHost(ctx *synccontext.SyncContext, v // delete the finalizer here so that the object can be deleted vVSC.Finalizers = []string{} ctx.Log.Infof("remove virtual VolumeSnapshotContent %s finalizers, because object should get deleted", vVSC.Name) - return ctrl.Result{}, s.virtualClient.Update(ctx.Context, vVSC) + return ctrl.Result{}, s.virtualClient.Update(ctx, vVSC) } ctx.Log.Infof("remove virtual VolumeSnapshotContent %s, because object should get deleted", vVSC.Name) - return ctrl.Result{}, s.virtualClient.Delete(ctx.Context, vVSC) + return ctrl.Result{}, s.virtualClient.Delete(ctx, vVSC) } - pVSC := s.translate(ctx.Context, vVSC) + pVSC := s.translate(ctx, vVSC) ctx.Log.Infof("create physical VolumeSnapshotContent %s, because there is a virtual VolumeSnapshotContent", pVSC.Name) - err := ctx.PhysicalClient.Create(ctx.Context, pVSC) + err := ctx.PhysicalClient.Create(ctx, pVSC) if err != nil { return ctrl.Result{}, err } @@ -97,7 +97,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl if vObj.GetDeletionTimestamp() != nil { if pObj.GetDeletionTimestamp() == nil { ctx.Log.Infof("delete physical VolumeSnapshotContent %s, because virtual VolumeSnapshotContent is being deleted", pObj.GetName()) - err := ctx.PhysicalClient.Delete(ctx.Context, pObj) + err := ctx.PhysicalClient.Delete(ctx, pObj) if err != nil { return ctrl.Result{}, err } @@ -113,7 +113,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl updated.Finalizers = pVSC.Finalizers ctx.Log.Infof("update finalizers of the virtual VolumeSnapshotContent %s, because finalizers on the physical resource changed", vVSC.Name) translator.PrintChanges(vObj, updated, ctx.Log) - err := s.virtualClient.Update(ctx.Context, updated) + err := s.virtualClient.Update(ctx, updated) if kerrors.IsNotFound(err) { return ctrl.Result{RequeueAfter: time.Second}, nil } @@ -126,7 +126,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl updated.Status = pVSC.Status.DeepCopy() ctx.Log.Infof("update virtual VolumeSnapshotContent %s, because status has changed", vVSC.Name) translator.PrintChanges(vObj, updated, ctx.Log) - err := s.virtualClient.Status().Update(ctx.Context, updated) + err := s.virtualClient.Status().Update(ctx, updated) if err != nil && !kerrors.IsNotFound(err) { return ctrl.Result{}, err } @@ -135,7 +135,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl } // check if the VolumeSnapshotContent should get synced - sync, vVS, err := s.shouldSync(ctx.Context, pVSC) + sync, vVS, err := s.shouldSync(ctx, pVSC) if err != nil { return ctrl.Result{}, err } else if !sync { @@ -148,7 +148,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl if updatedObj != nil { ctx.Log.Infof("update virtual VolumeSnapshotContent %s, because spec or metadata(annotations or labels) have changed", vVSC.Name) translator.PrintChanges(vObj, updatedObj, ctx.Log) - return ctrl.Result{}, s.virtualClient.Update(ctx.Context, updatedObj) + return ctrl.Result{}, s.virtualClient.Update(ctx, updatedObj) } // update virtual status if it differs @@ -157,7 +157,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl newVSC.Status = pVSC.Status.DeepCopy() translator.PrintChanges(vObj, newVSC, ctx.Log) ctx.Log.Infof("update virtual VolumeSnapshotContent %s, because status has changed", vVSC.Name) - return ctrl.Result{}, s.virtualClient.Status().Update(ctx.Context, newVSC) + return ctrl.Result{}, s.virtualClient.Status().Update(ctx, newVSC) } // update the physical VolumeSnapshotContent if the virtual has changed @@ -168,7 +168,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl } ctx.Log.Infof("delete physical VolumeSnapshotContent %s, because virtual VolumeSnapshotContent is being deleted", pVSC.Name) - err := ctx.PhysicalClient.Delete(ctx.Context, pVSC, &client.DeleteOptions{ + err := ctx.PhysicalClient.Delete(ctx, pVSC, &client.DeleteOptions{ GracePeriodSeconds: vVSC.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(pVSC.UID)), }) @@ -178,11 +178,11 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, pObj cl return ctrl.Result{}, err } - updatedPv := s.translateUpdate(ctx.Context, vVSC, pVSC) + updatedPv := s.translateUpdate(ctx, vVSC, pVSC) if updatedPv != nil { ctx.Log.Infof("update physical VolumeSnapshotContent %s, because spec or annotations have changed", updatedPv.Name) translator.PrintChanges(pVSC, updatedPv, ctx.Log) - err := ctx.PhysicalClient.Update(ctx.Context, updatedPv) + err := ctx.PhysicalClient.Update(ctx, updatedPv) if err != nil { return ctrl.Result{}, err } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go index b5fc01e8d6..b663358e0b 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go @@ -14,7 +14,7 @@ import ( func (s *volumeSnapshotContentSyncer) translate(ctx context.Context, vVSC *volumesnapshotv1.VolumeSnapshotContent) *volumesnapshotv1.VolumeSnapshotContent { pVSC := s.TranslateMetadata(ctx, vVSC).(*volumesnapshotv1.VolumeSnapshotContent) - pVolumeSnapshot := mappings.VirtualToHost(vVSC.Spec.VolumeSnapshotRef.Name, vVSC.Spec.VolumeSnapshotRef.Namespace, mappings.VolumeSnapshots()) + pVolumeSnapshot := mappings.VirtualToHost(ctx, vVSC.Spec.VolumeSnapshotRef.Name, vVSC.Spec.VolumeSnapshotRef.Namespace, mappings.VolumeSnapshots()) pVSC.Spec.VolumeSnapshotRef = corev1.ObjectReference{ Namespace: pVolumeSnapshot.Namespace, Name: pVolumeSnapshot.Name, diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go b/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go index 21381830ba..4ee3a39377 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go @@ -46,7 +46,7 @@ func (s *volumeSnapshotSyncer) SyncToHost(ctx *synccontext.SyncContext, vObj cli if len(vObj.GetFinalizers()) > 0 || (vObj.GetDeletionGracePeriodSeconds() != nil && *vObj.GetDeletionGracePeriodSeconds() > 0) { vObj.SetFinalizers([]string{}) vObj.SetDeletionGracePeriodSeconds(&zero) - return ctrl.Result{}, ctx.VirtualClient.Update(ctx.Context, vObj) + return ctrl.Result{}, ctx.VirtualClient.Update(ctx, vObj) } return ctrl.Result{}, nil } @@ -66,13 +66,13 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Ob if pVS.DeletionTimestamp != nil { if vVS.DeletionTimestamp == nil { ctx.Log.Infof("delete virtual volume snapshot %s/%s, because the physical volume snapshot is being deleted", vVS.Namespace, vVS.Name) - err := ctx.VirtualClient.Delete(ctx.Context, vVS, &client.DeleteOptions{GracePeriodSeconds: &minimumGracePeriodInSeconds}) + err := ctx.VirtualClient.Delete(ctx, vVS, &client.DeleteOptions{GracePeriodSeconds: &minimumGracePeriodInSeconds}) if err != nil { return ctrl.Result{}, err } } else if *vVS.DeletionGracePeriodSeconds != *pVS.DeletionGracePeriodSeconds { ctx.Log.Infof("delete virtual volume snapshot %s/%s with grace period seconds %v", vVS.Namespace, vVS.Name, *pVS.DeletionGracePeriodSeconds) - err := ctx.VirtualClient.Delete(ctx.Context, vVS, &client.DeleteOptions{GracePeriodSeconds: pVS.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(vVS.UID))}) + err := ctx.VirtualClient.Delete(ctx, vVS, &client.DeleteOptions{GracePeriodSeconds: pVS.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(vVS.UID))}) if err != nil { return ctrl.Result{}, err } @@ -87,7 +87,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Ob updated.Finalizers = pVS.Finalizers ctx.Log.Infof("update finalizers of the virtual VolumeSnapshot %s, because finalizers on the physical resource changed", vVS.Name) translator.PrintChanges(vObj, updated, ctx.Log) - err := ctx.VirtualClient.Update(ctx.Context, updated) + err := ctx.VirtualClient.Update(ctx, updated) if kerrors.IsNotFound(err) { return ctrl.Result{}, nil } @@ -100,7 +100,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Ob updated.Status = pVS.Status.DeepCopy() ctx.Log.Infof("update virtual VolumeSnapshot %s, because status has changed", vVS.Name) translator.PrintChanges(vObj, updated, ctx.Log) - err := ctx.VirtualClient.Status().Update(ctx.Context, updated) + err := ctx.VirtualClient.Status().Update(ctx, updated) if err != nil && !kerrors.IsNotFound(err) { return ctrl.Result{}, err } @@ -109,7 +109,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Ob } else if vVS.DeletionTimestamp != nil { if pVS.DeletionTimestamp == nil { ctx.Log.Infof("delete physical volume snapshot %s/%s, because virtual volume snapshot is being deleted", pVS.Namespace, pVS.Name) - return ctrl.Result{}, ctx.PhysicalClient.Delete(ctx.Context, pVS, &client.DeleteOptions{ + return ctrl.Result{}, ctx.PhysicalClient.Delete(ctx, pVS, &client.DeleteOptions{ GracePeriodSeconds: vVS.DeletionGracePeriodSeconds, Preconditions: metav1.NewUIDPreconditions(string(pVS.UID)), }) @@ -122,7 +122,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Ob if updated != nil { ctx.Log.Infof("update virtual volume snapshot %s/%s, because the spec has changed", vVS.Namespace, vVS.Name) translator.PrintChanges(vObj, updated, ctx.Log) - err := ctx.VirtualClient.Update(ctx.Context, updated) + err := ctx.VirtualClient.Update(ctx, updated) if err != nil { return ctrl.Result{}, err } @@ -136,7 +136,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Ob updated.Status = pVS.Status.DeepCopy() ctx.Log.Infof("update virtual volume snapshot %s/%s, because the status has changed", vVS.Namespace, vVS.Name) translator.PrintChanges(vObj, updated, ctx.Log) - err := ctx.VirtualClient.Status().Update(ctx.Context, updated) + err := ctx.VirtualClient.Status().Update(ctx, updated) if err != nil { return ctrl.Result{}, err } @@ -144,7 +144,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, pObj client.Ob } // forward update - updated = s.translateUpdate(ctx.Context, pVS, vVS) + updated = s.translateUpdate(ctx, pVS, vVS) if updated != nil { translator.PrintChanges(pVS, updated, ctx.Log) } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go b/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go index 6200a1bc01..0bbcebaa98 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go +++ b/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go @@ -15,21 +15,21 @@ import ( ) func (s *volumeSnapshotSyncer) translate(ctx *synccontext.SyncContext, vVS *volumesnapshotv1.VolumeSnapshot) (*volumesnapshotv1.VolumeSnapshot, error) { - pVS := s.TranslateMetadata(ctx.Context, vVS).(*volumesnapshotv1.VolumeSnapshot) + pVS := s.TranslateMetadata(ctx, vVS).(*volumesnapshotv1.VolumeSnapshot) if vVS.Annotations != nil && vVS.Annotations[constants.SkipTranslationAnnotation] == "true" { pVS.Spec.Source = vVS.Spec.Source } else { if vVS.Spec.Source.PersistentVolumeClaimName != nil { - pvcName := mappings.VirtualToHostName(*vVS.Spec.Source.PersistentVolumeClaimName, vVS.Namespace, mappings.PersistentVolumeClaims()) + pvcName := mappings.VirtualToHostName(ctx, *vVS.Spec.Source.PersistentVolumeClaimName, vVS.Namespace, mappings.PersistentVolumeClaims()) pVS.Spec.Source.PersistentVolumeClaimName = &pvcName } if vVS.Spec.Source.VolumeSnapshotContentName != nil { vVSC := &volumesnapshotv1.VolumeSnapshotContent{} - err := ctx.VirtualClient.Get(ctx.Context, client.ObjectKey{Name: *vVS.Spec.Source.VolumeSnapshotContentName}, vVSC) + err := ctx.VirtualClient.Get(ctx, client.ObjectKey{Name: *vVS.Spec.Source.VolumeSnapshotContentName}, vVSC) if err != nil { return nil, fmt.Errorf("failed to get virtual VolumeSnapshotContent resource referenced as source of the %s VolumeSnapshot: %w", vVS.Name, err) } - translatedName := mappings.VolumeSnapshotContents().VirtualToHost(ctx.Context, types.NamespacedName{Name: vVSC.Name}, vVSC).Name + translatedName := mappings.VolumeSnapshotContents().VirtualToHost(ctx, types.NamespacedName{Name: vVSC.Name}, vVSC).Name pVS.Spec.Source.VolumeSnapshotContentName = &translatedName } } diff --git a/pkg/controllers/syncer/context/context.go b/pkg/controllers/syncer/context/context.go index 3640479efe..ab50840a0d 100644 --- a/pkg/controllers/syncer/context/context.go +++ b/pkg/controllers/syncer/context/context.go @@ -17,8 +17,9 @@ const ( ) type SyncContext struct { - Context context.Context - Log loghelper.Logger + context.Context + + Log loghelper.Logger PhysicalClient client.Client VirtualClient client.Client @@ -62,7 +63,7 @@ func (s *SyncContext) EventFromVirtual() bool { } type RegisterContext struct { - Context context.Context + context.Context Config *config.VirtualClusterConfig diff --git a/pkg/controllers/syncer/syncer.go b/pkg/controllers/syncer/syncer.go index 43d819d735..fe82f74a47 100644 --- a/pkg/controllers/syncer/syncer.go +++ b/pkg/controllers/syncer/syncer.go @@ -179,7 +179,7 @@ func (r *SyncController) getObjects(ctx *synccontext.SyncContext, vReq, pReq ctr func (r *SyncController) getObjectsFromPhysical(ctx *synccontext.SyncContext, req ctrl.Request) (vObj, pObj client.Object, err error) { // get physical object - exclude, pObj, err := r.getPhysicalObject(ctx.Context, req.NamespacedName, nil) + exclude, pObj, err := r.getPhysicalObject(ctx, req.NamespacedName, nil) if err != nil { return nil, nil, err } else if exclude { @@ -187,7 +187,7 @@ func (r *SyncController) getObjectsFromPhysical(ctx *synccontext.SyncContext, re } // get virtual object - exclude, vObj, err = r.getVirtualObject(ctx.Context, r.syncer.HostToVirtual(ctx.Context, req.NamespacedName, pObj)) + exclude, vObj, err = r.getVirtualObject(ctx, r.syncer.HostToVirtual(ctx, req.NamespacedName, pObj)) if err != nil { return nil, nil, err } else if exclude { @@ -199,7 +199,7 @@ func (r *SyncController) getObjectsFromPhysical(ctx *synccontext.SyncContext, re func (r *SyncController) getObjectsFromVirtual(ctx *synccontext.SyncContext, req ctrl.Request) (vObj, pObj client.Object, err error) { // get virtual object - exclude, vObj, err := r.getVirtualObject(ctx.Context, req.NamespacedName) + exclude, vObj, err := r.getVirtualObject(ctx, req.NamespacedName) if err != nil { return nil, nil, err } else if exclude { @@ -207,7 +207,7 @@ func (r *SyncController) getObjectsFromVirtual(ctx *synccontext.SyncContext, req } // get physical object - exclude, pObj, err = r.getPhysicalObject(ctx.Context, r.syncer.VirtualToHost(ctx.Context, req.NamespacedName, vObj), vObj) + exclude, pObj, err = r.getPhysicalObject(ctx, r.syncer.VirtualToHost(ctx, req.NamespacedName, vObj), vObj) if err != nil { return nil, nil, err } else if exclude { @@ -432,7 +432,7 @@ func DeleteObject(ctx *synccontext.SyncContext, pObj client.Object, reason strin } else { ctx.Log.Infof("delete physical %s, because %s", accessor.GetName(), reason) } - err = ctx.PhysicalClient.Delete(ctx.Context, pObj) + err = ctx.PhysicalClient.Delete(ctx, pObj) if err != nil { if kerrors.IsNotFound(err) { return ctrl.Result{}, nil diff --git a/pkg/controllers/syncer/syncer_test.go b/pkg/controllers/syncer/syncer_test.go index cfc92e466f..d35f308788 100644 --- a/pkg/controllers/syncer/syncer_test.go +++ b/pkg/controllers/syncer/syncer_test.go @@ -40,12 +40,12 @@ func NewMockSyncer(ctx *synccontext.RegisterContext) (syncertypes.Object, error) } func (s *mockSyncer) naiveTranslateCreate(ctx *synccontext.SyncContext, vObj client.Object) client.Object { - pObj := s.TranslateMetadata(ctx.Context, vObj) + pObj := s.TranslateMetadata(ctx, vObj) return pObj } func (s *mockSyncer) naiveTranslateUpdate(ctx *synccontext.SyncContext, vObj client.Object, pObj client.Object) client.Object { - _, updatedAnnotations, updatedLabels := s.TranslateMetadataUpdate(ctx.Context, vObj, pObj) + _, updatedAnnotations, updatedLabels := s.TranslateMetadataUpdate(ctx, vObj, pObj) newPObj := pObj.DeepCopyObject().(client.Object) newPObj.SetAnnotations(updatedAnnotations) newPObj.SetLabels(updatedLabels) diff --git a/pkg/controllers/syncer/translator/namespaced_translator.go b/pkg/controllers/syncer/translator/namespaced_translator.go index 5cee85a909..9dce4a5c91 100644 --- a/pkg/controllers/syncer/translator/namespaced_translator.go +++ b/pkg/controllers/syncer/translator/namespaced_translator.go @@ -59,7 +59,7 @@ func (n *namespacedTranslator) Resource() client.Object { func (n *namespacedTranslator) SyncToHostCreate(ctx *context.SyncContext, vObj, pObj client.Object) (ctrl.Result, error) { ctx.Log.Infof("create physical %s %s/%s", n.name, pObj.GetNamespace(), pObj.GetName()) - err := ctx.PhysicalClient.Create(ctx.Context, pObj) + err := ctx.PhysicalClient.Create(ctx, pObj) if err != nil { if kerrors.IsNotFound(err) { ctx.Log.Debugf("error syncing %s %s/%s to physical cluster: %v", n.name, vObj.GetNamespace(), vObj.GetName(), err) @@ -77,7 +77,7 @@ func (n *namespacedTranslator) SyncToHostUpdate(ctx *context.SyncContext, vObj, // this is needed because of interface nil check if !(pObj == nil || (reflect.ValueOf(pObj).Kind() == reflect.Ptr && reflect.ValueOf(pObj).IsNil())) { ctx.Log.Infof("updating physical %s/%s, because virtual %s have changed", pObj.GetNamespace(), pObj.GetName(), n.name) - err := ctx.PhysicalClient.Update(ctx.Context, pObj) + err := ctx.PhysicalClient.Update(ctx, pObj) if kerrors.IsConflict(err) { ctx.Log.Debugf("conflict syncing physical %s %s/%s", n.name, pObj.GetNamespace(), pObj.GetName()) return ctrl.Result{Requeue: true}, nil diff --git a/pkg/integrations/metricsserver/metricsserver.go b/pkg/integrations/metricsserver/metricsserver.go index 600a09a3de..e7942a28b5 100644 --- a/pkg/integrations/metricsserver/metricsserver.go +++ b/pkg/integrations/metricsserver/metricsserver.go @@ -163,7 +163,7 @@ func handleMetricsServerProxyRequest( // request is for get particular pod if info.Resource == PodResource && info.Verb == RequestVerbGet { - nameNamespace := mappings.VirtualToHost(info.Name, info.Namespace, mappings.Pods()) + nameNamespace := mappings.VirtualToHost(req.Context(), info.Name, info.Namespace, mappings.Pods()) metricsServerProxy.resourceType = PodResource // replace the translated name and namespace @@ -383,7 +383,7 @@ func (p *serverProxy) rewritePodMetricsTableData(data []byte) { filteredTableRows := []metav1.TableRow{} for _, vPod := range p.podsInNamespace { - rowData, found := hostPodMap[mappings.VirtualToHost(vPod.Name, vPod.Namespace, mappings.Pods())] + rowData, found := hostPodMap[mappings.VirtualToHost(p.request.Context(), vPod.Name, vPod.Namespace, mappings.Pods())] if found { // translate the data for the given index rowData.Cells[0] = vPod.Name @@ -437,7 +437,7 @@ func (p *serverProxy) rewritePodMetricsListData(data []byte) { } for _, vPod := range p.podsInNamespace { - podMetric, found := hostPodMap[mappings.VirtualToHost(vPod.Name, vPod.Namespace, mappings.Pods())] + podMetric, found := hostPodMap[mappings.VirtualToHost(p.request.Context(), vPod.Name, vPod.Namespace, mappings.Pods())] if found { // translate back pod metric podMetric.Name = vPod.Name diff --git a/pkg/leaderelection/leaderelection.go b/pkg/leaderelection/leaderelection.go index 2be4b11ce5..30ebee7651 100644 --- a/pkg/leaderelection/leaderelection.go +++ b/pkg/leaderelection/leaderelection.go @@ -63,7 +63,7 @@ func StartLeaderElection(ctx *config.ControllerContext, scheme *runtime.Scheme, } // try and become the leader and start controller manager loops - leaderelection.RunOrDie(ctx.Context, leaderelection.LeaderElectionConfig{ + leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{ Lock: rl, LeaseDuration: time.Duration(ctx.Config.ControlPlane.StatefulSet.HighAvailability.LeaseDuration) * time.Second, RenewDeadline: time.Duration(ctx.Config.ControlPlane.StatefulSet.HighAvailability.RenewDeadline) * time.Second, @@ -82,7 +82,7 @@ func StartLeaderElection(ctx *config.ControllerContext, scheme *runtime.Scheme, klog.Info("leader election lost") // vcluster_error - telemetry.CollectorControlPlane.RecordError(ctx.Context, ctx.Config, telemetry.WarningSeverity, fmt.Errorf("leader election lost")) + telemetry.CollectorControlPlane.RecordError(ctx, ctx.Config, telemetry.WarningSeverity, fmt.Errorf("leader election lost")) telemetry.CollectorControlPlane.Flush() os.Exit(1) diff --git a/pkg/mappings/generic/mapper.go b/pkg/mappings/generic/mapper.go index bdeb267cbd..7c2ede2f36 100644 --- a/pkg/mappings/generic/mapper.go +++ b/pkg/mappings/generic/mapper.go @@ -39,7 +39,7 @@ func NewMapperWithObject(ctx *synccontext.RegisterContext, obj client.Object, tr mapperOptions := getOptions(options...) if !mapperOptions.SkipIndex { - err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, obj.DeepCopyObject().(client.Object), constants.IndexByPhysicalName, func(rawObj client.Object) []string { + err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, obj.DeepCopyObject().(client.Object), constants.IndexByPhysicalName, func(rawObj client.Object) []string { if rawObj.GetNamespace() != "" { return []string{translate.Default.PhysicalNamespace(rawObj.GetNamespace()) + "/" + translateName(rawObj.GetName(), rawObj.GetNamespace(), rawObj)} } diff --git a/pkg/mappings/resources/configmaps.go b/pkg/mappings/resources/configmaps.go index fb5f39b974..d43e4a3f5b 100644 --- a/pkg/mappings/resources/configmaps.go +++ b/pkg/mappings/resources/configmaps.go @@ -19,7 +19,7 @@ func CreateConfigMapsMapper(ctx *synccontext.RegisterContext) (mappings.Mapper, return nil, err } - err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.ConfigMap{}, constants.IndexByPhysicalName, func(rawObj client.Object) []string { + err = ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &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)} } diff --git a/pkg/mappings/resources/csistoragecapacities.go b/pkg/mappings/resources/csistoragecapacities.go index 87b053496f..9ba7585f73 100644 --- a/pkg/mappings/resources/csistoragecapacities.go +++ b/pkg/mappings/resources/csistoragecapacities.go @@ -18,8 +18,8 @@ func CreateCSIStorageCapacitiesMapper(ctx *synccontext.RegisterContext) (mapping 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} + err := ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx, &storagev1.CSIStorageCapacity{}, constants.IndexByVirtualName, func(rawObj client.Object) []string { + return []string{s.HostToVirtual(ctx, types.NamespacedName{Name: rawObj.GetName(), Namespace: rawObj.GetNamespace()}, rawObj).Name} }) if err != nil { return nil, err diff --git a/pkg/mappings/types.go b/pkg/mappings/types.go index b510c1a380..1f532afcdf 100644 --- a/pkg/mappings/types.go +++ b/pkg/mappings/types.go @@ -131,10 +131,10 @@ func PriorityClasses() Mapper { return Default.ByGVK(schedulingv1.SchemeGroupVersion.WithKind("PriorityClass")) } -func VirtualToHostName(vName, vNamespace string, mapper Mapper) string { - return mapper.VirtualToHost(context.TODO(), types.NamespacedName{Name: vName, Namespace: vNamespace}, nil).Name +func VirtualToHostName(ctx context.Context, vName, vNamespace string, mapper Mapper) string { + return mapper.VirtualToHost(ctx, types.NamespacedName{Name: vName, Namespace: vNamespace}, nil).Name } -func VirtualToHost(vName, vNamespace string, mapper Mapper) types.NamespacedName { - return mapper.VirtualToHost(context.TODO(), types.NamespacedName{Name: vName, Namespace: vNamespace}, nil) +func VirtualToHost(ctx context.Context, vName, vNamespace string, mapper Mapper) types.NamespacedName { + return mapper.VirtualToHost(ctx, types.NamespacedName{Name: vName, Namespace: vNamespace}, nil) } diff --git a/pkg/patcher/patcher.go b/pkg/patcher/patcher.go index 9f3d164a0e..13f945c566 100644 --- a/pkg/patcher/patcher.go +++ b/pkg/patcher/patcher.go @@ -59,12 +59,12 @@ type SyncerPatcher struct { // Patch will attempt to patch the given object, including its status. func (h *SyncerPatcher) Patch(ctx *synccontext.SyncContext, pObj, vObj client.Object) error { - err := h.vPatcher.Patch(ctx.Context, vObj) + err := h.vPatcher.Patch(ctx, vObj) if err != nil { return fmt.Errorf("patch virtual object: %w", err) } - err = h.pPatcher.Patch(ctx.Context, pObj) + err = h.pPatcher.Patch(ctx, pObj) if err != nil { return fmt.Errorf("patch host object: %w", err) } diff --git a/pkg/server/filters/redirect.go b/pkg/server/filters/redirect.go index b757ea076d..3a9f8c20e2 100644 --- a/pkg/server/filters/redirect.go +++ b/pkg/server/filters/redirect.go @@ -54,7 +54,7 @@ func WithRedirect(h http.Handler, localConfig *rest.Config, localScheme *runtime } // exchange namespace & name - pName := mappings.VirtualToHost(splitted[6], info.Namespace, mappings.Pods()) + pName := mappings.VirtualToHost(req.Context(), splitted[6], info.Namespace, mappings.Pods()) splitted[4] = pName.Namespace splitted[6] = pName.Name req.URL.Path = strings.Join(splitted, "/") diff --git a/pkg/server/filters/service.go b/pkg/server/filters/service.go index a65fd97121..db4b9ac577 100644 --- a/pkg/server/filters/service.go +++ b/pkg/server/filters/service.go @@ -141,7 +141,7 @@ func updateService(req *http.Request, decoder encoding.Decoder, localClient clie // okay now we have to change the physical service pService := &corev1.Service{} - pServiceName := mappings.VirtualToHost(oldVService.Name, oldVService.Namespace, mappings.Services()) + pServiceName := mappings.VirtualToHost(req.Context(), oldVService.Name, oldVService.Namespace, mappings.Services()) err = localClient.Get(ctx, client.ObjectKey{Namespace: pServiceName.Namespace, Name: pServiceName.Name}, pService) if err != nil { if kerrors.IsNotFound(err) { diff --git a/pkg/server/indicies.go b/pkg/server/indicies.go index c4ca17c53d..55bc8f7e3e 100644 --- a/pkg/server/indicies.go +++ b/pkg/server/indicies.go @@ -14,7 +14,7 @@ import ( func RegisterIndices(ctx *synccontext.RegisterContext) error { // index services by ip if ctx.Config.Networking.Advanced.ProxyKubelets.ByIP { - err := ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Service{}, constants.IndexByClusterIP, func(object client.Object) []string { + err := ctx.PhysicalManager.GetFieldIndexer().IndexField(ctx, &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 @@ -27,7 +27,7 @@ func RegisterIndices(ctx *synccontext.RegisterContext) error { } } - err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx.Context, &corev1.Node{}, constants.IndexByHostName, func(rawObj client.Object) []string { + err := ctx.VirtualManager.GetFieldIndexer().IndexField(ctx, &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 { diff --git a/pkg/server/server.go b/pkg/server/server.go index 5f9e454376..2e6ba4ac9b 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -89,7 +89,7 @@ func NewServer(ctx *config.ControllerContext, requestHeaderCaFile, clientCaFile uncachedVirtualClient = pluginhookclient.WrapVirtualClient(uncachedVirtualClient) uncachedLocalClient = pluginhookclient.WrapPhysicalClient(uncachedLocalClient) - certSyncer, err := cert.NewSyncer(ctx.Context, ctx.Config.WorkloadNamespace, ctx.WorkloadNamespaceClient, ctx.Config) + certSyncer, err := cert.NewSyncer(ctx, ctx.Config.WorkloadNamespace, ctx.WorkloadNamespaceClient, ctx.Config) if err != nil { return nil, errors.Wrap(err, "create cert syncer") } @@ -137,7 +137,7 @@ func NewServer(ctx *config.ControllerContext, requestHeaderCaFile, clientCaFile } // init plugins - admissionHandler, err := initAdmission(ctx.Context, virtualConfig) + admissionHandler, err := initAdmission(ctx, virtualConfig) if err != nil { return nil, errors.Wrap(err, "init admission") } @@ -155,7 +155,7 @@ func NewServer(ctx *config.ControllerContext, requestHeaderCaFile, clientCaFile // 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.WithNodeChanges(ctx, h, uncachedLocalClient, uncachedVirtualClient, virtualConfig) } h = filters.WithFakeKubelet(h, localConfig, ctx.VirtualManager.GetClient()) h = filters.WithK3sConnect(h) diff --git a/pkg/setup/controllers.go b/pkg/setup/controllers.go index e7a7c6384d..80dbf4c248 100644 --- a/pkg/setup/controllers.go +++ b/pkg/setup/controllers.go @@ -166,7 +166,7 @@ func ApplyCoreDNS(controllerContext *config.ControllerContext) { func SyncKubernetesService(ctx *config.ControllerContext) error { err := specialservices.SyncKubernetesService( &synccontext.SyncContext{ - Context: ctx.Context, + Context: ctx, Log: loghelper.New("sync-kubernetes-service"), PhysicalClient: ctx.LocalManager.GetClient(), VirtualClient: ctx.VirtualManager.GetClient(), diff --git a/pkg/setup/managers.go b/pkg/setup/managers.go index ea21faeceb..32745a8597 100644 --- a/pkg/setup/managers.go +++ b/pkg/setup/managers.go @@ -32,7 +32,7 @@ func StartManagers(ctx *synccontext.RegisterContext) ([]syncertypes.Object, erro // start the local manager go func() { - err := ctx.PhysicalManager.Start(ctx.Context) + err := ctx.PhysicalManager.Start(ctx) if err != nil { panic(err) } @@ -40,17 +40,17 @@ func StartManagers(ctx *synccontext.RegisterContext) ([]syncertypes.Object, erro // start the virtual cluster manager go func() { - err := ctx.VirtualManager.Start(ctx.Context) + err := ctx.VirtualManager.Start(ctx) if err != nil { panic(err) } }() // Wait for caches to be synced - klog.Infof("Starting local & virtual managers...") - ctx.PhysicalManager.GetCache().WaitForCacheSync(ctx.Context) - ctx.VirtualManager.GetCache().WaitForCacheSync(ctx.Context) - klog.Infof("Successfully started local & virtual manager") + klog.FromContext(ctx).Info("Starting local & virtual managers...") + ctx.PhysicalManager.GetCache().WaitForCacheSync(ctx) + ctx.VirtualManager.GetCache().WaitForCacheSync(ctx) + klog.FromContext(ctx).Info("Successfully started local & virtual manager") return syncers, nil } diff --git a/pkg/setup/proxy.go b/pkg/setup/proxy.go index d0a73bbf9d..e516c5d400 100644 --- a/pkg/setup/proxy.go +++ b/pkg/setup/proxy.go @@ -10,7 +10,7 @@ import ( func StartProxy(ctx *config.ControllerContext) error { // add remote node port sans if ctx.Config.Experimental.IsolatedControlPlane.Enabled { - err := pro.AddRemoteNodePortSANs(ctx.Context, ctx.Config.ControlPlaneNamespace, ctx.Config.ControlPlaneService, ctx.Config.ControlPlaneClient) + err := pro.AddRemoteNodePortSANs(ctx, ctx.Config.ControlPlaneNamespace, ctx.Config.ControlPlaneService, ctx.Config.ControlPlaneClient) if err != nil { return err } diff --git a/pkg/specialservices/service_syncer.go b/pkg/specialservices/service_syncer.go index 6fba4cd617..7df50e2566 100644 --- a/pkg/specialservices/service_syncer.go +++ b/pkg/specialservices/service_syncer.go @@ -34,7 +34,7 @@ func SyncKubernetesService( ) error { // get physical service pObj := &corev1.Service{} - err := ctx.CurrentNamespaceClient.Get(ctx.Context, types.NamespacedName{ + err := ctx.CurrentNamespaceClient.Get(ctx, types.NamespacedName{ Namespace: svcNamespace, Name: svcName, }, pObj) @@ -47,7 +47,7 @@ func SyncKubernetesService( // get virtual service vObj := &corev1.Service{} - err = ctx.VirtualClient.Get(ctx.Context, vSvcToSync, vObj) + err = ctx.VirtualClient.Get(ctx, vSvcToSync, vObj) if err != nil { if kerrors.IsNotFound(err) { return nil @@ -68,7 +68,7 @@ func SyncKubernetesService( newService.Spec.Ports = translatedPorts if clusterIPsChanged { // delete & create with correct ClusterIP - err = ctx.VirtualClient.Delete(ctx.Context, vObj) + err = ctx.VirtualClient.Delete(ctx, vObj) if err != nil { return err } @@ -77,13 +77,13 @@ func SyncKubernetesService( newService.ResourceVersion = "" // create the new service with the correct cluster ip - err = ctx.VirtualClient.Create(ctx.Context, newService) + err = ctx.VirtualClient.Create(ctx, newService) if err != nil { return err } } else { // delete & create with correct ClusterIP - err = ctx.VirtualClient.Update(ctx.Context, newService) + err = ctx.VirtualClient.Update(ctx, newService) if err != nil { return err } diff --git a/pkg/util/context/converter.go b/pkg/util/context/converter.go index b7b3fed09e..92984851be 100644 --- a/pkg/util/context/converter.go +++ b/pkg/util/context/converter.go @@ -7,7 +7,7 @@ import ( func ToRegisterContext(ctx *config.ControllerContext) *synccontext.RegisterContext { return &synccontext.RegisterContext{ - Context: ctx.Context, + Context: ctx, Config: ctx.Config, diff --git a/pkg/util/translate/single_namespace.go b/pkg/util/translate/single_namespace.go index 949bbab430..bd5ec13309 100644 --- a/pkg/util/translate/single_namespace.go +++ b/pkg/util/translate/single_namespace.go @@ -83,11 +83,11 @@ func (s *singleNamespace) IsManaged(obj runtime.Object) bool { if err == nil { // check if the name annotation is correct if metaAccessor.GetAnnotations()[NameAnnotation] == "" || - (mappings.Has(gvk) && metaAccessor.GetName() != mappings.VirtualToHostName(metaAccessor.GetAnnotations()[NameAnnotation], metaAccessor.GetAnnotations()[NamespaceAnnotation], mappings.ByGVK(gvk))) { + (mappings.Has(gvk) && metaAccessor.GetName() != mappings.VirtualToHostName(context.TODO(), metaAccessor.GetAnnotations()[NameAnnotation], metaAccessor.GetAnnotations()[NamespaceAnnotation], mappings.ByGVK(gvk))) { klog.FromContext(context.TODO()).V(1).Info("Host object doesn't match, because name annotations is wrong", "object", metaAccessor.GetName(), "existingName", metaAccessor.GetName(), - "expectedName", mappings.VirtualToHostName(metaAccessor.GetAnnotations()[NameAnnotation], metaAccessor.GetAnnotations()[NamespaceAnnotation], mappings.ByGVK(gvk))) + "expectedName", mappings.VirtualToHostName(context.TODO(), metaAccessor.GetAnnotations()[NameAnnotation], metaAccessor.GetAnnotations()[NamespaceAnnotation], mappings.ByGVK(gvk))) return false }