diff --git a/chart/templates/_rbac.tpl b/chart/templates/_rbac.tpl index 04a9fd3b78..09ef5220b1 100644 --- a/chart/templates/_rbac.tpl +++ b/chart/templates/_rbac.tpl @@ -25,7 +25,8 @@ .Values.sync.toHost.persistentVolumes.enabled .Values.sync.toHost.priorityClasses.enabled .Values.sync.fromHost.priorityClasses.enabled - .Values.sync.toHost.volumeSnapshots.enabled + .Values.sync.toHost.volumeSnapshotContents.enabled + .Values.sync.fromHost.volumeSnapshotClasses.enabled .Values.controlPlane.advanced.virtualScheduler.enabled .Values.sync.fromHost.ingressClasses.enabled .Values.sync.fromHost.runtimeClasses.enabled diff --git a/chart/templates/clusterrole.yaml b/chart/templates/clusterrole.yaml index 9ba0ab7f2c..13ef709636 100644 --- a/chart/templates/clusterrole.yaml +++ b/chart/templates/clusterrole.yaml @@ -89,10 +89,12 @@ rules: resources: ["priorityclasses"] verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] {{- end }} - {{- if .Values.sync.toHost.volumeSnapshots.enabled }} + {{- if .Values.sync.fromHost.volumeSnapshotClasses.enabled }} - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotclasses"] verbs: ["get", "list", "watch"] + {{- end }} + {{- if .Values.sync.toHost.volumeSnapshotContents.enabled }} - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents"] verbs: ["create", "delete", "patch", "update", "get", "list", "watch"] diff --git a/chart/values.schema.json b/chart/values.schema.json index d19cee4447..9c248c588c 100755 --- a/chart/values.schema.json +++ b/chart/values.schema.json @@ -989,7 +989,7 @@ "additionalProperties": false, "type": "object" }, - "EnableAutoSwitch": { + "EnableAutoSwitchWithPatches": { "properties": { "enabled": { "oneOf": [ @@ -1001,6 +1001,13 @@ } ], "description": "Enabled defines if this option should be enabled." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." } }, "additionalProperties": false, @@ -2936,35 +2943,35 @@ "description": "Nodes defines if nodes should get synced from the host cluster to the virtual cluster, but not back." }, "events": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "Events defines if events should get synced from the host cluster to the virtual cluster, but not back." }, "ingressClasses": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "IngressClasses defines if ingress classes should get synced from the host cluster to the virtual cluster, but not back." }, "runtimeClasses": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "RuntimeClasses defines if runtime classes should get synced from the host cluster to the virtual cluster, but not back." }, "priorityClasses": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "PriorityClasses defines if priority classes classes should get synced from the host cluster to the virtual cluster, but not back." }, "storageClasses": { - "$ref": "#/$defs/EnableAutoSwitch", + "$ref": "#/$defs/EnableAutoSwitchWithPatches", "description": "StorageClasses defines if storage classes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." }, "csiNodes": { - "$ref": "#/$defs/EnableAutoSwitch", + "$ref": "#/$defs/EnableAutoSwitchWithPatches", "description": "CSINodes defines if csi nodes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." }, "csiDrivers": { - "$ref": "#/$defs/EnableAutoSwitch", + "$ref": "#/$defs/EnableAutoSwitchWithPatches", "description": "CSIDrivers defines if csi drivers should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." }, "csiStorageCapacities": { - "$ref": "#/$defs/EnableAutoSwitch", + "$ref": "#/$defs/EnableAutoSwitchWithPatches", "description": "CSIStorageCapacities defines if csi storage capacities should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled." }, "customResources": { @@ -2973,6 +2980,10 @@ }, "type": "object", "description": "CustomResources defines what custom resources should get synced read-only to the virtual cluster from the host cluster. vCluster will automatically add any required RBAC to the vCluster cluster role." + }, + "volumeSnapshotClasses": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "VolumeSnapshotClasses defines if volume snapshot classes created within the virtual cluster should get synced to the host cluster." } }, "additionalProperties": false, @@ -3029,6 +3040,13 @@ "selector": { "$ref": "#/$defs/SyncNodeSelector", "description": "Selector can be used to define more granular what nodes should get synced from the host cluster to the virtual cluster." + }, + "patches": { + "items": { + "$ref": "#/$defs/TranslatePatch" + }, + "type": "array", + "description": "Patches patch the resource according to the provided specification." } }, "additionalProperties": false, @@ -3124,11 +3142,11 @@ "description": "Services defines if services created within the virtual cluster should get synced to the host cluster." }, "endpoints": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "Endpoints defines if endpoints created within the virtual cluster should get synced to the host cluster." }, "networkPolicies": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "NetworkPolicies defines if network policies created within the virtual cluster should get synced to the host cluster." }, "persistentVolumeClaims": { @@ -3136,27 +3154,31 @@ "description": "PersistentVolumeClaims defines if persistent volume claims created within the virtual cluster should get synced to the host cluster." }, "persistentVolumes": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "PersistentVolumes defines if persistent volumes created within the virtual cluster should get synced to the host cluster." }, "volumeSnapshots": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "VolumeSnapshots defines if volume snapshots created within the virtual cluster should get synced to the host cluster." }, + "volumeSnapshotContents": { + "$ref": "#/$defs/EnableSwitchWithPatches", + "description": "VolumeSnapshotContents defines if volume snapshot contents created within the virtual cluster should get synced to the host cluster." + }, "storageClasses": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "StorageClasses defines if storage classes created within the virtual cluster should get synced to the host cluster." }, "serviceAccounts": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "ServiceAccounts defines if service accounts created within the virtual cluster should get synced to the host cluster." }, "podDisruptionBudgets": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "PodDisruptionBudgets defines if pod disruption budgets created within the virtual cluster should get synced to the host cluster." }, "priorityClasses": { - "$ref": "#/$defs/EnableSwitch", + "$ref": "#/$defs/EnableSwitchWithPatches", "description": "PriorityClasses defines if priority classes created within the virtual cluster should get synced to the host cluster." }, "customResources": { diff --git a/chart/values.yaml b/chart/values.yaml index 584de87108..37d595851d 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -8,6 +8,7 @@ sync: enabled: true # Endpoints defines if endpoints created within the virtual cluster should get synced to the host cluster. endpoints: + # Enabled defines if this option should be enabled. enabled: true # PersistentVolumeClaims defines if persistent volume claims created within the virtual cluster should get synced to the host cluster. persistentVolumeClaims: @@ -61,30 +62,42 @@ sync: enabled: false # PriorityClasses defines if priority classes created within the virtual cluster should get synced to the host cluster. priorityClasses: + # Enabled defines if this option should be enabled. enabled: false # NetworkPolicies defines if network policies created within the virtual cluster should get synced to the host cluster. networkPolicies: + # Enabled defines if this option should be enabled. enabled: false # VolumeSnapshots defines if volume snapshots created within the virtual cluster should get synced to the host cluster. volumeSnapshots: + # Enabled defines if this option should be enabled. + enabled: false + # VolumeSnapshotContents defines if volume snapshot contents created within the virtual cluster should get synced to the host cluster. + volumeSnapshotContents: + # Enabled defines if this option should be enabled. enabled: false # PodDisruptionBudgets defines if pod disruption budgets created within the virtual cluster should get synced to the host cluster. podDisruptionBudgets: + # Enabled defines if this option should be enabled. enabled: false # ServiceAccounts defines if service accounts created within the virtual cluster should get synced to the host cluster. serviceAccounts: + # Enabled defines if this option should be enabled. enabled: false # StorageClasses defines if storage classes created within the virtual cluster should get synced to the host cluster. storageClasses: + # Enabled defines if this option should be enabled. enabled: false # PersistentVolumes defines if persistent volumes created within the virtual cluster should get synced to the host cluster. persistentVolumes: + # Enabled defines if this option should be enabled. enabled: false # Configure what resources vCluster should sync from the host cluster to the virtual cluster. fromHost: # Events defines if events should get synced from the host cluster to the virtual cluster, but not back. events: + # Enabled defines if this option should be enabled. enabled: true # CSIDrivers defines if csi drivers should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. csiDrivers: @@ -104,12 +117,15 @@ sync: enabled: auto # IngressClasses defines if ingress classes should get synced from the host cluster to the virtual cluster, but not back. ingressClasses: + # Enabled defines if this option should be enabled. enabled: false # RuntimeClasses defines if runtime classes should get synced from the host cluster to the virtual cluster, but not back. runtimeClasses: + # Enabled defines if this option should be enabled. enabled: false # PriorityClasses defines if priority classes classes should get synced from the host cluster to the virtual cluster, but not back. priorityClasses: + # Enabled defines if this option should be enabled. enabled: false # Nodes defines if nodes should get synced from the host cluster to the virtual cluster, but not back. nodes: @@ -124,6 +140,10 @@ sync: # All specifies if all nodes should get synced by vCluster from the host to the virtual cluster or only the ones where pods are assigned to. all: false labels: {} + # VolumeSnapshotClasses defines if volume snapshot classes created within the virtual cluster should get synced to the host cluster. + volumeSnapshotClasses: + # Enabled defines if this option should be enabled. + enabled: false # Configure vCluster's control plane components and deployment. controlPlane: diff --git a/config/config.go b/config/config.go index 5736dde70f..ff9279f299 100644 --- a/config/config.go +++ b/config/config.go @@ -419,31 +419,34 @@ type SyncToHost struct { Services EnableSwitchWithPatches `json:"services,omitempty"` // Endpoints defines if endpoints created within the virtual cluster should get synced to the host cluster. - Endpoints EnableSwitch `json:"endpoints,omitempty"` + Endpoints EnableSwitchWithPatches `json:"endpoints,omitempty"` // NetworkPolicies defines if network policies created within the virtual cluster should get synced to the host cluster. - NetworkPolicies EnableSwitch `json:"networkPolicies,omitempty"` + NetworkPolicies EnableSwitchWithPatches `json:"networkPolicies,omitempty"` // PersistentVolumeClaims defines if persistent volume claims created within the virtual cluster should get synced to the host cluster. PersistentVolumeClaims EnableSwitchWithPatches `json:"persistentVolumeClaims,omitempty"` // PersistentVolumes defines if persistent volumes created within the virtual cluster should get synced to the host cluster. - PersistentVolumes EnableSwitch `json:"persistentVolumes,omitempty"` + PersistentVolumes EnableSwitchWithPatches `json:"persistentVolumes,omitempty"` // VolumeSnapshots defines if volume snapshots created within the virtual cluster should get synced to the host cluster. - VolumeSnapshots EnableSwitch `json:"volumeSnapshots,omitempty"` + VolumeSnapshots EnableSwitchWithPatches `json:"volumeSnapshots,omitempty"` + + // VolumeSnapshotContents defines if volume snapshot contents created within the virtual cluster should get synced to the host cluster. + VolumeSnapshotContents EnableSwitchWithPatches `json:"volumeSnapshotContents,omitempty"` // StorageClasses defines if storage classes created within the virtual cluster should get synced to the host cluster. - StorageClasses EnableSwitch `json:"storageClasses,omitempty"` + StorageClasses EnableSwitchWithPatches `json:"storageClasses,omitempty"` // ServiceAccounts defines if service accounts created within the virtual cluster should get synced to the host cluster. - ServiceAccounts EnableSwitch `json:"serviceAccounts,omitempty"` + ServiceAccounts EnableSwitchWithPatches `json:"serviceAccounts,omitempty"` // PodDisruptionBudgets defines if pod disruption budgets created within the virtual cluster should get synced to the host cluster. - PodDisruptionBudgets EnableSwitch `json:"podDisruptionBudgets,omitempty"` + PodDisruptionBudgets EnableSwitchWithPatches `json:"podDisruptionBudgets,omitempty"` // PriorityClasses defines if priority classes created within the virtual cluster should get synced to the host cluster. - PriorityClasses EnableSwitch `json:"priorityClasses,omitempty"` + PriorityClasses EnableSwitchWithPatches `json:"priorityClasses,omitempty"` // CustomResources defines what custom resources should get synced from the virtual cluster to the host cluster. vCluster will copy the definition automatically from host cluster to virtual cluster on startup. // vCluster will also automatically add any required RBAC permissions to the vCluster role for this to work. @@ -463,31 +466,34 @@ type SyncFromHost struct { Nodes SyncNodes `json:"nodes,omitempty"` // Events defines if events should get synced from the host cluster to the virtual cluster, but not back. - Events EnableSwitch `json:"events,omitempty"` + Events EnableSwitchWithPatches `json:"events,omitempty"` // IngressClasses defines if ingress classes should get synced from the host cluster to the virtual cluster, but not back. - IngressClasses EnableSwitch `json:"ingressClasses,omitempty"` + IngressClasses EnableSwitchWithPatches `json:"ingressClasses,omitempty"` // RuntimeClasses defines if runtime classes should get synced from the host cluster to the virtual cluster, but not back. - RuntimeClasses EnableSwitch `json:"runtimeClasses,omitempty"` + RuntimeClasses EnableSwitchWithPatches `json:"runtimeClasses,omitempty"` // PriorityClasses defines if priority classes classes should get synced from the host cluster to the virtual cluster, but not back. - PriorityClasses EnableSwitch `json:"priorityClasses,omitempty"` + PriorityClasses EnableSwitchWithPatches `json:"priorityClasses,omitempty"` // StorageClasses defines if storage classes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. - StorageClasses EnableAutoSwitch `json:"storageClasses,omitempty"` + StorageClasses EnableAutoSwitchWithPatches `json:"storageClasses,omitempty"` // CSINodes defines if csi nodes should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. - CSINodes EnableAutoSwitch `json:"csiNodes,omitempty"` + CSINodes EnableAutoSwitchWithPatches `json:"csiNodes,omitempty"` // CSIDrivers defines if csi drivers should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. - CSIDrivers EnableAutoSwitch `json:"csiDrivers,omitempty"` + CSIDrivers EnableAutoSwitchWithPatches `json:"csiDrivers,omitempty"` // CSIStorageCapacities defines if csi storage capacities should get synced from the host cluster to the virtual cluster, but not back. If auto, is automatically enabled when the virtual scheduler is enabled. - CSIStorageCapacities EnableAutoSwitch `json:"csiStorageCapacities,omitempty"` + CSIStorageCapacities EnableAutoSwitchWithPatches `json:"csiStorageCapacities,omitempty"` // CustomResources defines what custom resources should get synced read-only to the virtual cluster from the host cluster. vCluster will automatically add any required RBAC to the vCluster cluster role. CustomResources map[string]SyncFromHostCustomResource `json:"customResources,omitempty"` + + // VolumeSnapshotClasses defines if volume snapshot classes created within the virtual cluster should get synced to the host cluster. + VolumeSnapshotClasses EnableSwitchWithPatches `json:"volumeSnapshotClasses,omitempty"` } type SyncToHostCustomResource struct { @@ -561,6 +567,14 @@ type EnableAutoSwitch struct { Enabled StrBool `json:"enabled,omitempty" jsonschema:"oneof_type=string;boolean"` } +type EnableAutoSwitchWithPatches struct { + // Enabled defines if this option should be enabled. + Enabled StrBool `json:"enabled,omitempty" jsonschema:"oneof_type=string;boolean"` + + // Patches patch the resource according to the provided specification. + Patches []TranslatePatch `json:"patches,omitempty"` +} + type EnableSwitch struct { // Enabled defines if this option should be enabled. Enabled bool `json:"enabled,omitempty"` @@ -629,6 +643,9 @@ type SyncNodes struct { // Selector can be used to define more granular what nodes should get synced from the host cluster to the virtual cluster. Selector SyncNodeSelector `json:"selector,omitempty"` + + // Patches patch the resource according to the provided specification. + Patches []TranslatePatch `json:"patches,omitempty"` } type SyncNodeSelector struct { diff --git a/config/values.yaml b/config/values.yaml index bbd6e92042..f3c9929165 100644 --- a/config/values.yaml +++ b/config/values.yaml @@ -39,6 +39,8 @@ sync: enabled: false volumeSnapshots: enabled: false + volumeSnapshotContents: + enabled: false podDisruptionBudgets: enabled: false serviceAccounts: @@ -72,6 +74,8 @@ sync: selector: all: false labels: {} + volumeSnapshotClasses: + enabled: false controlPlane: distro: @@ -204,7 +208,7 @@ controlPlane: retentionPolicy: Retain size: 5Gi storageClass: "" - accessModes: [ "ReadWriteOnce" ] + accessModes: ["ReadWriteOnce"] volumeClaimTemplates: [] addVolumes: [] addVolumeMounts: [] @@ -237,8 +241,8 @@ controlPlane: image: "" replicas: 1 pods: - labels: {} - annotations: {} + labels: {} + annotations: {} nodeSelector: {} affinity: {} tolerations: [] @@ -250,12 +254,12 @@ controlPlane: cpu: 20m memory: 64Mi topologySpreadConstraints: - - maxSkew: 1 - topologyKey: kubernetes.io/hostname - whenUnsatisfiable: DoNotSchedule - labelSelector: - matchLabels: - k8s-app: kube-dns + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + k8s-app: kube-dns service: enabled: true @@ -324,14 +328,14 @@ controlPlane: retentionPolicy: Retain size: 5Gi storageClass: "" - accessModes: [ "ReadWriteOnce" ] + accessModes: ["ReadWriteOnce"] volumeClaimTemplates: [] addVolumeMounts: [] addVolumes: [] dataVolume: [] binariesVolume: - - name: binaries - emptyDir: {} + - name: binaries + emptyDir: {} enableServiceLinks: true diff --git a/pkg/controllers/resources/configmaps/syncer.go b/pkg/controllers/resources/configmaps/syncer.go index 183e937fa0..57a2427c2b 100644 --- a/pkg/controllers/resources/configmaps/syncer.go +++ b/pkg/controllers/resources/configmaps/syncer.go @@ -48,7 +48,7 @@ type configMapSyncer struct { var _ syncertypes.Syncer = &configMapSyncer{} func (s *configMapSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.ConfigMap](s) + return syncer.ToGenericSyncer(s) } var _ syncertypes.ControllerModifier = &configMapSyncer{} diff --git a/pkg/controllers/resources/csidrivers/syncer.go b/pkg/controllers/resources/csidrivers/syncer.go index 825683f2ac..a1a449d200 100644 --- a/pkg/controllers/resources/csidrivers/syncer.go +++ b/pkg/controllers/resources/csidrivers/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings/generic" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -42,17 +43,24 @@ func (s *csidriverSyncer) Resource() client.Object { var _ syncertypes.Syncer = &csidriverSyncer{} func (s *csidriverSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*storagev1.CSIDriver](s) + return syncer.ToGenericSyncer(s) } func (s *csidriverSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*storagev1.CSIDriver]) (ctrl.Result, error) { vObj := translate.CopyObjectWithName(event.Host, types.NamespacedName{Name: event.Host.Name, Namespace: event.Host.Namespace}, false) + + // Apply pro patches + err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.CSIDrivers.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + ctx.Log.Infof("create CSIDriver %s, because it does not exist in virtual cluster", vObj.Name) return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (s *csidriverSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*storagev1.CSIDriver]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.CSIDrivers.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/csinodes/syncer.go b/pkg/controllers/resources/csinodes/syncer.go index f47fa1d42b..28e30801a0 100644 --- a/pkg/controllers/resources/csinodes/syncer.go +++ b/pkg/controllers/resources/csinodes/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings/generic" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -25,8 +26,7 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { } return &csinodeSyncer{ - Mapper: mapper, - + Mapper: mapper, virtualClient: ctx.VirtualManager.GetClient(), }, nil } @@ -47,7 +47,7 @@ func (s *csinodeSyncer) Resource() client.Object { var _ syncertypes.Syncer = &csinodeSyncer{} func (s *csinodeSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*storagev1.CSINode](s) + return syncer.ToGenericSyncer(s) } func (s *csinodeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*storagev1.CSINode]) (ctrl.Result, error) { @@ -61,6 +61,13 @@ func (s *csinodeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *syncc } vObj := translate.CopyObjectWithName(event.Host, types.NamespacedName{Name: event.Host.Name, Namespace: event.Host.Namespace}, false) + + // Apply pro patches + err = pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.CSINodes.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + ctx.Log.Infof("create CSINode %s, because it does not exist in virtual cluster", vObj.Name) return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } @@ -76,7 +83,7 @@ func (s *csinodeSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.Sy } // look up matching node name, delete csinode if not found - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.CSINodes.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/csistoragecapacities/syncer.go b/pkg/controllers/resources/csistoragecapacities/syncer.go index de387f8372..fb786dcc40 100644 --- a/pkg/controllers/resources/csistoragecapacities/syncer.go +++ b/pkg/controllers/resources/csistoragecapacities/syncer.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -39,10 +40,9 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { type csistoragecapacitySyncer struct { synccontext.Mapper - + physicalClient client.Client storageClassSyncEnabled bool hostStorageClassSyncEnabled bool - physicalClient client.Client } var _ syncertypes.Syncer = &csistoragecapacitySyncer{} @@ -56,7 +56,7 @@ func (s *csistoragecapacitySyncer) Resource() client.Object { } func (s *csistoragecapacitySyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*storagev1.CSIStorageCapacity](s) + return syncer.ToGenericSyncer(s) } func (s *csistoragecapacitySyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*storagev1.CSIStorageCapacity]) (ctrl.Result, error) { @@ -65,12 +65,18 @@ func (s *csistoragecapacitySyncer) SyncToVirtual(ctx *synccontext.SyncContext, e return ctrl.Result{}, err } + // Apply pro patches + err = pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.CSIStorageCapacities.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + ctx.Log.Infof("create CSIStorageCapacity %s, because it does not exist in virtual cluster", vObj.Name) return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (s *csistoragecapacitySyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*storagev1.CSIStorageCapacity]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.CSIStorageCapacities.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/endpoints/syncer.go b/pkg/controllers/resources/endpoints/syncer.go index d67cdfa8ad..904cf0e96e 100644 --- a/pkg/controllers/resources/endpoints/syncer.go +++ b/pkg/controllers/resources/endpoints/syncer.go @@ -6,6 +6,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/specialservices" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" @@ -44,7 +45,7 @@ type endpointsSyncer struct { var _ syncertypes.Syncer = &endpointsSyncer{} func (s *endpointsSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.Endpoints](s) + return syncer.ToGenericSyncer(s) } func (s *endpointsSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*corev1.Endpoints]) (ctrl.Result, error) { @@ -52,11 +53,17 @@ func (s *endpointsSyncer) SyncToHost(ctx *synccontext.SyncContext, event *syncco return syncer.DeleteVirtualObject(ctx, event.Virtual, "host object was deleted") } - return syncer.CreateHostObject(ctx, event.Virtual, s.translate(ctx, event.Virtual), s.EventRecorder()) + pObj := s.translate(ctx, event.Virtual) + err := pro.ApplyPatchesHostObject(ctx, nil, pObj, event.Virtual, ctx.Config.Sync.ToHost.Endpoints.Patches) + if err != nil { + return ctrl.Result{}, err + } + + return syncer.CreateHostObject(ctx, event.Virtual, pObj, s.EventRecorder()) } func (s *endpointsSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*corev1.Endpoints]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.Endpoints.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/events/syncer.go b/pkg/controllers/resources/events/syncer.go index 3d83e646ee..9672c86ce4 100644 --- a/pkg/controllers/resources/events/syncer.go +++ b/pkg/controllers/resources/events/syncer.go @@ -6,6 +6,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/mappings/resources" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -47,7 +48,7 @@ func (s *eventSyncer) Name() string { var _ syncertypes.Syncer = &eventSyncer{} func (s *eventSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.Event](s) + return syncer.ToGenericSyncer(s) } var _ syncertypes.OptionsProvider = &eventSyncer{} @@ -69,7 +70,7 @@ func (s *eventSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontex } func (s *eventSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*corev1.Event]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.Events.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } @@ -97,6 +98,12 @@ func (s *eventSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccon return ctrl.Result{}, resources.IgnoreAcceptableErrors(err) } + // Apply pro patches + err = pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.Events.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + // make sure namespace is not being deleted namespace := &corev1.Namespace{} err = ctx.VirtualClient.Get(ctx, client.ObjectKey{Name: vObj.Namespace}, namespace) diff --git a/pkg/controllers/resources/ingressclasses/syncer.go b/pkg/controllers/resources/ingressclasses/syncer.go index 7e57382bb7..f78bcbaccb 100644 --- a/pkg/controllers/resources/ingressclasses/syncer.go +++ b/pkg/controllers/resources/ingressclasses/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings/generic" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -42,17 +43,24 @@ func (i *ingressClassSyncer) Resource() client.Object { var _ syncertypes.Syncer = &ingressClassSyncer{} func (i *ingressClassSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*networkingv1.IngressClass](i) + return syncer.ToGenericSyncer(i) } func (i *ingressClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*networkingv1.IngressClass]) (ctrl.Result, error) { vObj := translate.CopyObjectWithName(event.Host, types.NamespacedName{Name: event.Host.Name, Namespace: event.Host.Namespace}, false) + + // Apply pro patches + err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.IngressClasses.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + ctx.Log.Infof("create ingress class %s, because it does not exist in virtual cluster", vObj.Name) return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (i *ingressClassSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*networkingv1.IngressClass]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.IngressClasses.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/ingresses/syncer.go b/pkg/controllers/resources/ingresses/syncer.go index 568994922a..256d91c80d 100644 --- a/pkg/controllers/resources/ingresses/syncer.go +++ b/pkg/controllers/resources/ingresses/syncer.go @@ -42,7 +42,7 @@ type ingressSyncer struct { var _ syncertypes.Syncer = &ingressSyncer{} func (s *ingressSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*networkingv1.Ingress](s) + return syncer.ToGenericSyncer(s) } func (s *ingressSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*networkingv1.Ingress]) (ctrl.Result, error) { diff --git a/pkg/controllers/resources/namespaces/syncer.go b/pkg/controllers/resources/namespaces/syncer.go index 7f561c1fb4..81acdae13e 100644 --- a/pkg/controllers/resources/namespaces/syncer.go +++ b/pkg/controllers/resources/namespaces/syncer.go @@ -54,11 +54,10 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { type namespaceSyncer struct { syncertypes.GenericTranslator - workloadServiceAccountName string - - excludedAnnotations []string - namespaceLabels map[string]string + namespaceLabels map[string]string + workloadServiceAccountName string + excludedAnnotations []string } var _ syncertypes.Syncer = &namespaceSyncer{} diff --git a/pkg/controllers/resources/networkpolicies/syncer.go b/pkg/controllers/resources/networkpolicies/syncer.go index e49d09dbd8..0d98ba60e0 100644 --- a/pkg/controllers/resources/networkpolicies/syncer.go +++ b/pkg/controllers/resources/networkpolicies/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings/generic" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" "github.com/loft-sh/vcluster/pkg/syncer/translator" @@ -34,7 +35,7 @@ type networkPolicySyncer struct { var _ syncertypes.Syncer = &networkPolicySyncer{} func (s *networkPolicySyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*networkingv1.NetworkPolicy](s) + return syncer.ToGenericSyncer(s) } func (s *networkPolicySyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*networkingv1.NetworkPolicy]) (ctrl.Result, error) { @@ -42,11 +43,17 @@ func (s *networkPolicySyncer) SyncToHost(ctx *synccontext.SyncContext, event *sy return syncer.DeleteVirtualObject(ctx, event.Virtual, "host object was deleted") } - return syncer.CreateHostObject(ctx, event.Virtual, s.translate(ctx, event.Virtual), s.EventRecorder()) + pObj := s.translate(ctx, event.Virtual) + err := pro.ApplyPatchesHostObject(ctx, nil, pObj, event.Virtual, ctx.Config.Sync.ToHost.NetworkPolicies.Patches) + if err != nil { + return ctrl.Result{}, err + } + + return syncer.CreateHostObject(ctx, event.Virtual, pObj, s.EventRecorder()) } func (s *networkPolicySyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*networkingv1.NetworkPolicy]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.NetworkPolicies.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/nodes/syncer.go b/pkg/controllers/resources/nodes/syncer.go index 3780941a39..9994979ce0 100644 --- a/pkg/controllers/resources/nodes/syncer.go +++ b/pkg/controllers/resources/nodes/syncer.go @@ -6,6 +6,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -103,7 +104,7 @@ func (s *nodeSyncer) Name() string { var _ syncertypes.Syncer = &nodeSyncer{} func (s *nodeSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.Node](s) + return syncer.ToGenericSyncer(s) } var _ syncertypes.ControllerModifier = &nodeSyncer{} @@ -284,7 +285,7 @@ func (s *nodeSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncE return ctrl.Result{}, ctx.VirtualClient.Delete(ctx, event.Virtual) } - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.Nodes.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } @@ -312,13 +313,21 @@ func (s *nodeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccont } ctx.Log.Infof("create virtual node %s, because there is a virtual pod with that node", event.Host.Name) - err = ctx.VirtualClient.Create(ctx, &corev1.Node{ + virtualNode := &corev1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: event.Host.Name, Labels: event.Host.Labels, Annotations: event.Host.Annotations, }, - }) + } + + // Apply pro patches + err = pro.ApplyPatchesVirtualObject(ctx, nil, virtualNode, event.Host, ctx.Config.Sync.FromHost.Nodes.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + + err = ctx.VirtualClient.Create(ctx, virtualNode) if err != nil { return ctrl.Result{}, err } diff --git a/pkg/controllers/resources/persistentvolumeclaims/syncer.go b/pkg/controllers/resources/persistentvolumeclaims/syncer.go index a2ac63e5f5..1fce293737 100644 --- a/pkg/controllers/resources/persistentvolumeclaims/syncer.go +++ b/pkg/controllers/resources/persistentvolumeclaims/syncer.go @@ -79,7 +79,7 @@ func (s *persistentVolumeClaimSyncer) Options() *syncertypes.Options { var _ syncertypes.Syncer = &persistentVolumeClaimSyncer{} func (s *persistentVolumeClaimSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.PersistentVolumeClaim](s) + return syncer.ToGenericSyncer(s) } func (s *persistentVolumeClaimSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*corev1.PersistentVolumeClaim]) (ctrl.Result, error) { diff --git a/pkg/controllers/resources/persistentvolumes/syncer.go b/pkg/controllers/resources/persistentvolumes/syncer.go index 407f168031..f87b72a11c 100644 --- a/pkg/controllers/resources/persistentvolumes/syncer.go +++ b/pkg/controllers/resources/persistentvolumes/syncer.go @@ -8,6 +8,7 @@ import ( "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" "github.com/loft-sh/vcluster/pkg/syncer/translator" @@ -68,10 +69,8 @@ func mapPVCs(_ context.Context, obj client.Object) []reconcile.Request { type persistentVolumeSyncer struct { syncertypes.GenericTranslator - + virtualClient client.Client excludedAnnotations []string - - virtualClient client.Client } var _ syncertypes.ControllerModifier = &persistentVolumeSyncer{} @@ -89,7 +88,7 @@ func (s *persistentVolumeSyncer) Options() *syncertypes.Options { var _ syncertypes.Syncer = &persistentVolumeSyncer{} func (s *persistentVolumeSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.PersistentVolume](s) + return syncer.ToGenericSyncer(s) } func (s *persistentVolumeSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*corev1.PersistentVolume]) (ctrl.Result, error) { @@ -110,6 +109,12 @@ func (s *persistentVolumeSyncer) SyncToHost(ctx *synccontext.SyncContext, event return ctrl.Result{}, err } + // Apply pro patches + err = pro.ApplyPatchesHostObject(ctx, nil, pPv, event.Virtual, ctx.Config.Sync.ToHost.PersistentVolumes.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + ctx.Log.Infof("create physical persistent volume %s, because there is a virtual persistent volume", pPv.Name) err = ctx.PhysicalClient.Create(ctx, pPv) if err != nil { @@ -175,7 +180,7 @@ func (s *persistentVolumeSyncer) Sync(ctx *synccontext.SyncContext, event *syncc } // patch objects - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.PersistentVolumes.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } @@ -224,6 +229,11 @@ func (s *persistentVolumeSyncer) SyncToVirtual(ctx *synccontext.SyncContext, eve } else if sync { // create the persistent volume vObj := s.translateBackwards(event.Host, vPvc) + err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.ToHost.PersistentVolumes.Patches) + if err != nil { + return ctrl.Result{}, err + } + if vPvc != nil { 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) } diff --git a/pkg/controllers/resources/poddisruptionbudgets/syncer.go b/pkg/controllers/resources/poddisruptionbudgets/syncer.go index 7828eac55d..12431af916 100644 --- a/pkg/controllers/resources/poddisruptionbudgets/syncer.go +++ b/pkg/controllers/resources/poddisruptionbudgets/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings/generic" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" "github.com/loft-sh/vcluster/pkg/syncer/translator" @@ -34,7 +35,7 @@ type pdbSyncer struct { var _ syncertypes.Syncer = &pdbSyncer{} func (s *pdbSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*policyv1.PodDisruptionBudget](s) + return syncer.ToGenericSyncer(s) } func (s *pdbSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*policyv1.PodDisruptionBudget]) (ctrl.Result, error) { @@ -42,11 +43,18 @@ func (s *pdbSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext. return syncer.DeleteVirtualObject(ctx, event.Virtual, "host object was deleted") } - return syncer.CreateHostObject(ctx, event.Virtual, s.translate(ctx, event.Virtual), s.EventRecorder()) + newPDB := s.translate(ctx, event.Virtual) + + err := pro.ApplyPatchesHostObject(ctx, nil, newPDB, event.Virtual, ctx.Config.Sync.ToHost.PodDisruptionBudgets.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("apply patches: %w", err) + } + + return syncer.CreateHostObject(ctx, event.Virtual, newPDB, s.EventRecorder()) } func (s *pdbSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*policyv1.PodDisruptionBudget]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.PodDisruptionBudgets.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/priorityclasses/syncer.go b/pkg/controllers/resources/priorityclasses/syncer.go index 21449ed6df..005f6e8cc4 100644 --- a/pkg/controllers/resources/priorityclasses/syncer.go +++ b/pkg/controllers/resources/priorityclasses/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" "github.com/loft-sh/vcluster/pkg/syncer/translator" @@ -13,6 +14,7 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/reconcile" ) func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { @@ -46,8 +48,14 @@ func (s *priorityClassSyncer) SyncToHost(ctx *synccontext.SyncContext, event *sy } newPriorityClass := s.translate(ctx, event.Virtual) + + err := pro.ApplyPatchesHostObject(ctx, nil, newPriorityClass, event.Virtual, ctx.Config.Sync.ToHost.PriorityClasses.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("apply patches: %w", err) + } + ctx.Log.Infof("create physical priority class %s", newPriorityClass.Name) - err := ctx.PhysicalClient.Create(ctx, newPriorityClass) + err = ctx.PhysicalClient.Create(ctx, newPriorityClass) if err != nil { ctx.Log.Infof("error syncing %s to physical cluster: %v", event.Virtual.Name, err) return ctrl.Result{}, err @@ -62,6 +70,20 @@ func (s *priorityClassSyncer) Sync(ctx *synccontext.SyncContext, event *synccont if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } + + if s.fromHost && event.Source == synccontext.SyncEventSourceHost { + patch, err = patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.PriorityClasses.Patches)) + if err != nil { + return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) + } + } + if s.toHost && event.Source == synccontext.SyncEventSourceVirtual { + patch, err = patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.PriorityClasses.Patches)) + if err != nil { + return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) + } + } + defer func() { if err := patch.Patch(ctx, event.Host, event.Virtual); err != nil { retErr = utilerrors.NewAggregate([]error{retErr, err}) @@ -83,8 +105,13 @@ func (s *priorityClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event } newVirtualPC := s.translateFromHost(ctx, event.Host) + err := pro.ApplyPatchesVirtualObject(ctx, nil, newVirtualPC, event.Host, ctx.Config.Sync.FromHost.PriorityClasses.Patches) + if err != nil { + return reconcile.Result{}, err + } + ctx.Log.Infof("create virtual priority class %s from host priority class", newVirtualPC.Name) - err := ctx.VirtualClient.Create(ctx, newVirtualPC) + err = ctx.VirtualClient.Create(ctx, newVirtualPC) if err != nil { ctx.Log.Infof("error syncing %s to virtual cluster: %v", event.Host.Name, err) return ctrl.Result{}, err diff --git a/pkg/controllers/resources/register.go b/pkg/controllers/resources/register.go index 7a176b08cf..b8fd59e67e 100644 --- a/pkg/controllers/resources/register.go +++ b/pkg/controllers/resources/register.go @@ -24,9 +24,9 @@ import ( "github.com/loft-sh/vcluster/pkg/controllers/resources/serviceaccounts" "github.com/loft-sh/vcluster/pkg/controllers/resources/services" "github.com/loft-sh/vcluster/pkg/controllers/resources/storageclasses" - "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses" - "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents" - "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshots/volumesnapshots" + "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshotclasses" + "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshotcontents" + "github.com/loft-sh/vcluster/pkg/controllers/resources/volumesnapshots" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" "github.com/loft-sh/vcluster/pkg/util/loghelper" @@ -57,13 +57,13 @@ func getSyncers(ctx *synccontext.RegisterContext) []BuildController { isEnabled(ctx.Config.Sync.ToHost.PriorityClasses.Enabled || ctx.Config.Sync.FromHost.PriorityClasses.Enabled, priorityclasses.New), isEnabled(ctx.Config.Sync.ToHost.PodDisruptionBudgets.Enabled, poddisruptionbudgets.New), isEnabled(ctx.Config.Sync.ToHost.NetworkPolicies.Enabled, networkpolicies.New), - isEnabled(ctx.Config.Sync.ToHost.VolumeSnapshots.Enabled, volumesnapshotclasses.New), isEnabled(ctx.Config.Sync.ToHost.VolumeSnapshots.Enabled, volumesnapshots.New), - isEnabled(ctx.Config.Sync.ToHost.VolumeSnapshots.Enabled, volumesnapshotcontents.New), + isEnabled(ctx.Config.Sync.ToHost.VolumeSnapshotContents.Enabled, volumesnapshotcontents.New), isEnabled(ctx.Config.Sync.ToHost.ServiceAccounts.Enabled, serviceaccounts.New), isEnabled(ctx.Config.Sync.FromHost.CSINodes.Enabled == "true", csinodes.New), isEnabled(ctx.Config.Sync.FromHost.CSIDrivers.Enabled == "true", csidrivers.New), isEnabled(ctx.Config.Sync.FromHost.CSIStorageCapacities.Enabled == "true", csistoragecapacities.New), + isEnabled(ctx.Config.Sync.FromHost.VolumeSnapshotClasses.Enabled, volumesnapshotclasses.New), isEnabled(ctx.Config.Experimental.MultiNamespaceMode.Enabled, namespaces.New), persistentvolumes.New, nodes.New, diff --git a/pkg/controllers/resources/runtimeclasses/syncer.go b/pkg/controllers/resources/runtimeclasses/syncer.go index 516005e40c..db1c7548f6 100644 --- a/pkg/controllers/resources/runtimeclasses/syncer.go +++ b/pkg/controllers/resources/runtimeclasses/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings/generic" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -42,17 +43,24 @@ func (i *runtimeClassSyncer) Resource() client.Object { var _ syncertypes.Syncer = &runtimeClassSyncer{} func (i *runtimeClassSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*nodev1.RuntimeClass](i) + return syncer.ToGenericSyncer(i) } func (i *runtimeClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*nodev1.RuntimeClass]) (ctrl.Result, error) { vObj := translate.CopyObjectWithName(event.Host, types.NamespacedName{Name: event.Host.Name, Namespace: event.Host.Namespace}, false) + + // Apply pro patches + err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.RuntimeClasses.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + ctx.Log.Infof("create runtime class %s, because it does not exist in virtual cluster", vObj.Name) return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (i *runtimeClassSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*nodev1.RuntimeClass]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.RuntimeClasses.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/serviceaccounts/syncer.go b/pkg/controllers/resources/serviceaccounts/syncer.go index 2ce9ba934c..29867dc8f8 100644 --- a/pkg/controllers/resources/serviceaccounts/syncer.go +++ b/pkg/controllers/resources/serviceaccounts/syncer.go @@ -13,6 +13,7 @@ import ( "github.com/loft-sh/vcluster/pkg/util/translate" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/reconcile" corev1 "k8s.io/api/core/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -39,7 +40,7 @@ type serviceAccountSyncer struct { var _ syncertypes.Syncer = &serviceAccountSyncer{} func (s *serviceAccountSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.ServiceAccount](s) + return syncer.ToGenericSyncer(s) } func (s *serviceAccountSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*corev1.ServiceAccount]) (ctrl.Result, error) { @@ -53,11 +54,17 @@ func (s *serviceAccountSyncer) SyncToHost(ctx *synccontext.SyncContext, event *s pObj.Secrets = nil pObj.AutomountServiceAccountToken = &[]bool{false}[0] pObj.ImagePullSecrets = nil + + err := pro.ApplyPatchesHostObject(ctx, nil, pObj, event.Virtual, ctx.Config.Sync.ToHost.ServiceAccounts.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("apply patches: %w", err) + } + return syncer.CreateHostObject(ctx, event.Virtual, pObj, s.EventRecorder()) } func (s *serviceAccountSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*corev1.ServiceAccount]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.ServiceAccounts.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } @@ -87,5 +94,10 @@ func (s *serviceAccountSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event } vObj := translate.VirtualMetadata(event.Host, s.HostToVirtual(ctx, types.NamespacedName{Name: event.Host.Name, Namespace: event.Host.Namespace}, event.Host)) + err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.ToHost.ServiceAccounts.Patches) + if err != nil { + return reconcile.Result{}, err + } + return syncer.CreateVirtualObject(ctx, event.Host, vObj, s.EventRecorder()) } diff --git a/pkg/controllers/resources/services/syncer.go b/pkg/controllers/resources/services/syncer.go index 800d9e4dfc..4ad987e931 100644 --- a/pkg/controllers/resources/services/syncer.go +++ b/pkg/controllers/resources/services/syncer.go @@ -49,10 +49,8 @@ func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { type serviceSyncer struct { syncertypes.GenericTranslator syncertypes.Importer - + serviceName string excludedAnnotations []string - - serviceName string } var _ syncertypes.OptionsProvider = &serviceSyncer{} @@ -66,7 +64,7 @@ func (s *serviceSyncer) Options() *syncertypes.Options { var _ syncertypes.Syncer = &serviceSyncer{} func (s *serviceSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*corev1.Service](s) + return syncer.ToGenericSyncer(s) } func (s *serviceSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*corev1.Service]) (ctrl.Result, error) { diff --git a/pkg/controllers/resources/storageclasses/host_syncer.go b/pkg/controllers/resources/storageclasses/host_syncer.go index 4fc5728a64..44f4160c5a 100644 --- a/pkg/controllers/resources/storageclasses/host_syncer.go +++ b/pkg/controllers/resources/storageclasses/host_syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -42,17 +43,24 @@ func (s *hostStorageClassSyncer) Resource() client.Object { var _ syncertypes.Syncer = &hostStorageClassSyncer{} func (s *hostStorageClassSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*storagev1.StorageClass](s) + return syncer.ToGenericSyncer(s) } func (s *hostStorageClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*storagev1.StorageClass]) (ctrl.Result, error) { vObj := translate.CopyObjectWithName(event.Host, types.NamespacedName{Name: event.Host.Name}, false) + + // Apply pro patches + err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.StorageClasses.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying patches: %w", err) + } + ctx.Log.Infof("create storage class %s, because it does not exist in virtual cluster", vObj.Name) return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } func (s *hostStorageClassSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*storagev1.StorageClass]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.StorageClasses.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/storageclasses/syncer.go b/pkg/controllers/resources/storageclasses/syncer.go index 33c981c488..3d30f7640b 100644 --- a/pkg/controllers/resources/storageclasses/syncer.go +++ b/pkg/controllers/resources/storageclasses/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" "github.com/loft-sh/vcluster/pkg/syncer/translator" @@ -43,7 +44,7 @@ type storageClassSyncer struct { var _ syncertypes.Syncer = &storageClassSyncer{} func (s *storageClassSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*storagev1.StorageClass](s) + return syncer.ToGenericSyncer(s) } func (s *storageClassSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*storagev1.StorageClass]) (ctrl.Result, error) { @@ -52,8 +53,14 @@ func (s *storageClassSyncer) SyncToHost(ctx *synccontext.SyncContext, event *syn } newStorageClass := translate.HostMetadata(event.Virtual, s.VirtualToHost(ctx, types.NamespacedName{Name: event.Virtual.Name}, event.Virtual), s.excludedAnnotations...) + + err := pro.ApplyPatchesHostObject(ctx, nil, newStorageClass, event.Virtual, ctx.Config.Sync.ToHost.StorageClasses.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("apply patches: %w", err) + } + ctx.Log.Infof("create physical storage class %s", newStorageClass.Name) - err := ctx.PhysicalClient.Create(ctx, newStorageClass) + err = ctx.PhysicalClient.Create(ctx, newStorageClass) if err != nil { ctx.Log.Infof("error syncing %s to physical cluster: %v", event.Virtual.Name, err) return ctrl.Result{}, err @@ -63,7 +70,7 @@ func (s *storageClassSyncer) SyncToHost(ctx *synccontext.SyncContext, event *syn } func (s *storageClassSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*storagev1.StorageClass]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.StorageClasses.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go b/pkg/controllers/resources/volumesnapshotclasses/syncer.go similarity index 88% rename from pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go rename to pkg/controllers/resources/volumesnapshotclasses/syncer.go index 2a19711a88..41133205bd 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer.go +++ b/pkg/controllers/resources/volumesnapshotclasses/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" syncertypes "github.com/loft-sh/vcluster/pkg/syncer/types" @@ -43,11 +44,18 @@ func (s *volumeSnapshotClassSyncer) Resource() client.Object { var _ syncertypes.Syncer = &volumeSnapshotClassSyncer{} func (s *volumeSnapshotClassSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*volumesnapshotv1.VolumeSnapshotClass](s) + return syncer.ToGenericSyncer(s) } func (s *volumeSnapshotClassSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*volumesnapshotv1.VolumeSnapshotClass]) (ctrl.Result, error) { vObj := translate.CopyObjectWithName(event.Host, types.NamespacedName{Name: event.Host.Name}, false) + + // Apply pro patches + err := pro.ApplyPatchesVirtualObject(ctx, nil, vObj, event.Host, ctx.Config.Sync.FromHost.VolumeSnapshotClasses.Patches) + if err != nil { + return ctrl.Result{}, fmt.Errorf("error applying pro patches: %w", err) + } + ctx.Log.Infof("create VolumeSnapshotClass %s, because it does not exist in the virtual cluster", vObj.Name) return ctrl.Result{}, ctx.VirtualClient.Create(ctx, vObj) } @@ -65,7 +73,7 @@ func (s *volumeSnapshotClassSyncer) SyncToHost(ctx *synccontext.SyncContext, eve } func (s *volumeSnapshotClassSyncer) Sync(ctx *synccontext.SyncContext, event *synccontext.SyncEvent[*volumesnapshotv1.VolumeSnapshotClass]) (_ ctrl.Result, retErr error) { - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.FromHost.VolumeSnapshotClasses.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer_test.go b/pkg/controllers/resources/volumesnapshotclasses/syncer_test.go similarity index 100% rename from pkg/controllers/resources/volumesnapshots/volumesnapshotclasses/syncer_test.go rename to pkg/controllers/resources/volumesnapshotclasses/syncer_test.go diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go b/pkg/controllers/resources/volumesnapshotcontents/syncer.go similarity index 93% rename from pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go rename to pkg/controllers/resources/volumesnapshotcontents/syncer.go index 6518be79c2..26f950012c 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer.go +++ b/pkg/controllers/resources/volumesnapshotcontents/syncer.go @@ -7,6 +7,7 @@ import ( "github.com/loft-sh/vcluster/pkg/constants" "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" translator2 "github.com/loft-sh/vcluster/pkg/syncer/translator" @@ -48,7 +49,7 @@ type volumeSnapshotContentSyncer struct { var _ syncertypes.Syncer = &volumeSnapshotContentSyncer{} func (s *volumeSnapshotContentSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*volumesnapshotv1.VolumeSnapshotContent](s) + return syncer.ToGenericSyncer(s) } func (s *volumeSnapshotContentSyncer) SyncToVirtual(ctx *synccontext.SyncContext, event *synccontext.SyncToVirtualEvent[*volumesnapshotv1.VolumeSnapshotContent]) (ctrl.Result, error) { @@ -62,6 +63,11 @@ func (s *volumeSnapshotContentSyncer) SyncToVirtual(ctx *synccontext.SyncContext } vVSC := s.translateBackwards(event.Host, vVS) + err = pro.ApplyPatchesVirtualObject(ctx, nil, vVSC, event.Host, ctx.Config.Sync.ToHost.VolumeSnapshotContents.Patches) + if err != nil { + return ctrl.Result{}, err + } + ctx.Log.Infof("create VolumeSnapshotContent %s, because it does not exist in the virtual cluster", vVSC.Name) return ctrl.Result{}, s.virtualClient.Create(ctx, vVSC) } @@ -80,8 +86,13 @@ func (s *volumeSnapshotContentSyncer) SyncToHost(ctx *synccontext.SyncContext, e } pVSC := s.translate(ctx, event.Virtual) + err := pro.ApplyPatchesHostObject(ctx, nil, pVSC, event.Virtual, ctx.Config.Sync.ToHost.VolumeSnapshotContents.Patches) + if err != nil { + return ctrl.Result{}, err + } + ctx.Log.Infof("create host VolumeSnapshotContent %s, because there is a virtual VolumeSnapshotContent", pVSC.Name) - err := ctx.PhysicalClient.Create(ctx, pVSC) + err = ctx.PhysicalClient.Create(ctx, pVSC) if err != nil { return ctrl.Result{}, err } @@ -157,7 +168,7 @@ func (s *volumeSnapshotContentSyncer) Sync(ctx *synccontext.SyncContext, event * } // patch objects - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.VolumeSnapshotContents.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go b/pkg/controllers/resources/volumesnapshotcontents/syncer_test.go similarity index 100% rename from pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/syncer_test.go rename to pkg/controllers/resources/volumesnapshotcontents/syncer_test.go diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go b/pkg/controllers/resources/volumesnapshotcontents/translate.go similarity index 100% rename from pkg/controllers/resources/volumesnapshots/volumesnapshotcontents/translate.go rename to pkg/controllers/resources/volumesnapshotcontents/translate.go diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go b/pkg/controllers/resources/volumesnapshots/syncer.go similarity index 94% rename from pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go rename to pkg/controllers/resources/volumesnapshots/syncer.go index de64099b1e..42d9ae7c72 100644 --- a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer.go +++ b/pkg/controllers/resources/volumesnapshots/syncer.go @@ -5,6 +5,7 @@ import ( "github.com/loft-sh/vcluster/pkg/mappings" "github.com/loft-sh/vcluster/pkg/patcher" + "github.com/loft-sh/vcluster/pkg/pro" "github.com/loft-sh/vcluster/pkg/syncer" "github.com/loft-sh/vcluster/pkg/syncer/synccontext" translator2 "github.com/loft-sh/vcluster/pkg/syncer/translator" @@ -44,7 +45,7 @@ type volumeSnapshotSyncer struct { var _ syncertypes.Syncer = &volumeSnapshotSyncer{} func (s *volumeSnapshotSyncer) Syncer() syncertypes.Sync[client.Object] { - return syncer.ToGenericSyncer[*volumesnapshotv1.VolumeSnapshot](s) + return syncer.ToGenericSyncer(s) } func (s *volumeSnapshotSyncer) SyncToHost(ctx *synccontext.SyncContext, event *synccontext.SyncToHostEvent[*volumesnapshotv1.VolumeSnapshot]) (ctrl.Result, error) { @@ -63,6 +64,11 @@ func (s *volumeSnapshotSyncer) SyncToHost(ctx *synccontext.SyncContext, event *s return ctrl.Result{}, err } + err = pro.ApplyPatchesHostObject(ctx, nil, pObj, event.Virtual, ctx.Config.Sync.ToHost.VolumeSnapshots.Patches) + if err != nil { + return ctrl.Result{}, err + } + return syncer.CreateHostObject(ctx, event.Virtual, pObj, s.EventRecorder()) } @@ -83,7 +89,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, event *synccon } // sync finalizers and status to allow tracking of the deletion progress - //TODO: refactor finalizer syncing and handling + // TODO: refactor finalizer syncing and handling // we can not add new finalizers from physical to virtual once it has deletionTimestamp, we can only remove finalizers if !equality.Semantic.DeepEqual(event.Virtual.Finalizers, event.Host.Finalizers) { @@ -120,7 +126,7 @@ func (s *volumeSnapshotSyncer) Sync(ctx *synccontext.SyncContext, event *synccon } // patch objects - patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual) + patch, err := patcher.NewSyncerPatcher(ctx, event.Host, event.Virtual, patcher.TranslatePatches(ctx.Config.Sync.ToHost.VolumeSnapshots.Patches)) if err != nil { return ctrl.Result{}, fmt.Errorf("new syncer patcher: %w", err) } diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer_test.go b/pkg/controllers/resources/volumesnapshots/syncer_test.go similarity index 100% rename from pkg/controllers/resources/volumesnapshots/volumesnapshots/syncer_test.go rename to pkg/controllers/resources/volumesnapshots/syncer_test.go diff --git a/pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go b/pkg/controllers/resources/volumesnapshots/translate.go similarity index 100% rename from pkg/controllers/resources/volumesnapshots/volumesnapshots/translate.go rename to pkg/controllers/resources/volumesnapshots/translate.go