From c91600a782853e8dadf27aa17c7cf13bb4408ed8 Mon Sep 17 00:00:00 2001 From: Tesshu Flower Date: Fri, 19 Jan 2024 23:20:09 -0500 Subject: [PATCH 1/2] resourceReqs and podLabels for mover job/deploy Resolves: https://github.com/backube/volsync/issues/707 Signed-off-by: Tesshu Flower --- api/v1alpha1/common_types.go | 27 ++ api/v1alpha1/replicationdestination_types.go | 33 +- api/v1alpha1/replicationsource_types.go | 44 +-- api/v1alpha1/rsync_tls_types.go | 22 +- api/v1alpha1/zz_generated.deepcopy.go | 138 ++++---- ...lsync.backube_replicationdestinations.yaml | 242 +++++++++++++- .../volsync.backube_replicationsources.yaml | 303 +++++++++++++++++- .../volsync.clusterserviceversion.yaml | 2 +- ...lsync.backube_replicationdestinations.yaml | 242 +++++++++++++- .../volsync.backube_replicationsources.yaml | 303 +++++++++++++++++- controllers/mover/rclone/builder.go | 68 ++-- controllers/mover/rclone/mover.go | 38 +-- controllers/mover/rclone/rclone_test.go | 45 +++ controllers/mover/restic/builder.go | 4 +- controllers/mover/restic/mover.go | 7 +- controllers/mover/restic/restic_test.go | 44 +++ controllers/mover/rsync/builder.go | 11 + controllers/mover/rsync/mover.go | 5 + controllers/mover/rsync/rsync_test.go | 44 +++ controllers/mover/rsynctls/builder.go | 76 ++--- controllers/mover/rsynctls/mover.go | 45 +-- controllers/mover/rsynctls/rsync_test.go | 44 +++ controllers/mover/syncthing/builder.go | 36 +-- controllers/mover/syncthing/mover.go | 42 +-- controllers/mover/syncthing/syncthing_test.go | 70 ++++ controllers/utils/utils.go | 31 ++ controllers/utils/utils_test.go | 256 +++++++++++++++ ...lsync.backube_replicationdestinations.yaml | 174 +++++++++- .../volsync.backube_replicationsources.yaml | 218 ++++++++++++- 29 files changed, 2305 insertions(+), 309 deletions(-) diff --git a/api/v1alpha1/common_types.go b/api/v1alpha1/common_types.go index d9a305f4f..14fa34a75 100644 --- a/api/v1alpha1/common_types.go +++ b/api/v1alpha1/common_types.go @@ -33,6 +33,10 @@ limitations under the License. package v1alpha1 +import ( + corev1 "k8s.io/api/core/v1" +) + // CopyMethodType defines the methods for creating point-in-time copies of // volumes. // +kubebuilder:validation:Enum=Direct;None;Clone;Snapshot @@ -116,3 +120,26 @@ type CustomCASpec struct { // The key within the Secret or ConfigMap containing the CA certificate Key string `json:"key,omitempty"` } + +type MoverConfig struct { + // MoverSecurityContext allows specifying the PodSecurityContext that will + // be used by the data mover + MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` + // MoverServiceAccount allows specifying the name of the service account + // that will be used by the data mover. This should only be used by advanced + // users who want to override the service account normally used by the mover. + // The service account needs to exist in the same namespace as this CR. + //+optional + MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + // Labels that should be added to data mover pods + // These will be in addition to any labels that VolSync may add + // +optional + MoverPodLabels map[string]string `json:"moverPodLabels,omitempty"` + // Resources represents compute resources required by the data mover container. + // Immutable. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + // This should only be used by advanced users as this can result in a mover + // pod being unschedulable or crashing due to limited resources. + // +optional + MoverResources *corev1.ResourceRequirements `json:"moverResources,omitempty"` +} diff --git a/api/v1alpha1/replicationdestination_types.go b/api/v1alpha1/replicationdestination_types.go index bd5fdb1c2..765d5ecaf 100644 --- a/api/v1alpha1/replicationdestination_types.go +++ b/api/v1alpha1/replicationdestination_types.go @@ -121,6 +121,17 @@ type ReplicationDestinationRsyncSpec struct { // The service account needs to exist in the same namespace as the ReplicationDestination. //+optional MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + // Labels that should be added to data mover pods + // These will be in addition to any labels that VolSync may add + // +optional + MoverPodLabels map[string]string `json:"moverPodLabels,omitempty"` + // Resources represents compute resources required by the data mover container. + // Immutable. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + // This should only be used by advanced users as this can result in a mover + // pod being unschedulable or crashing due to limited resources. + // +optional + MoverResources *corev1.ResourceRequirements `json:"moverResources,omitempty"` } // ReplicationDestinationRcloneSpec defines the field for rclone in replicationDestination. @@ -134,15 +145,8 @@ type ReplicationDestinationRcloneSpec struct { RcloneConfig *string `json:"rcloneConfig,omitempty"` // customCA is a custom CA that will be used to verify the remote CustomCA CustomCASpec `json:"customCA,omitempty"` - // MoverSecurityContext allows specifying the PodSecurityContext that will - // be used by the data mover - MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` - // MoverServiceAccount allows specifying the name of the service account - // that will be used by the data mover. This should only be used by advanced - // users who want to override the service account normally used by the mover. - // The service account needs to exist in the same namespace as the ReplicationDestination. - //+optional - MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + + MoverConfig `json:",inline"` } // ReplicationDestinationExternalSpec defines the configuration when using an @@ -228,15 +232,8 @@ type ReplicationDestinationResticSpec struct { // +kubebuilder:validation:Format="date-time" //+optional RestoreAsOf *string `json:"restoreAsOf,omitempty"` - // MoverSecurityContext allows specifying the PodSecurityContext that will - // be used by the data mover - MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` - // MoverServiceAccount allows specifying the name of the service account - // that will be used by the data mover. This should only be used by advanced - // users who want to override the service account normally used by the mover. - // The service account needs to exist in the same namespace as the ReplicationDestination. - //+optional - MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + + MoverConfig `json:",inline"` } // ReplicationDestinationStatus defines the observed state of ReplicationDestination diff --git a/api/v1alpha1/replicationsource_types.go b/api/v1alpha1/replicationsource_types.go index a0292fb06..1725cf71c 100644 --- a/api/v1alpha1/replicationsource_types.go +++ b/api/v1alpha1/replicationsource_types.go @@ -123,6 +123,17 @@ type ReplicationSourceRsyncSpec struct { // The service account needs to exist in the same namespace as the ReplicationSource. //+optional MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + // Labels that should be added to data mover pods + // These will be in addition to any labels that VolSync may add + // +optional + MoverPodLabels map[string]string `json:"moverPodLabels,omitempty"` + // Resources represents compute resources required by the data mover container. + // Immutable. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + // This should only be used by advanced users as this can result in a mover + // pod being unschedulable or crashing due to limited resources. + // +optional + MoverResources *corev1.ResourceRequirements `json:"moverResources,omitempty"` } // ReplicationSourceRcloneSpec defines the field for rclone in replicationSource. @@ -136,15 +147,8 @@ type ReplicationSourceRcloneSpec struct { RcloneConfig *string `json:"rcloneConfig,omitempty"` // customCA is a custom CA that will be used to verify the remote CustomCA CustomCASpec `json:"customCA,omitempty"` - // MoverSecurityContext allows specifying the PodSecurityContext that will - // be used by the data mover - MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` - // MoverServiceAccount allows specifying the name of the service account - // that will be used by the data mover. This should only be used by advanced - // users who want to override the service account normally used by the mover. - // The service account needs to exist in the same namespace as the ReplicationSource. - //+optional - MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + + MoverConfig `json:",inline"` } // ResticRetainPolicy defines the feilds for Restic backup @@ -205,15 +209,8 @@ type ReplicationSourceResticSpec struct { // then ran a backup. // Unlock will not be run again unless spec.restic.unlock is set to a different value. Unlock string `json:"unlock,omitempty"` - // MoverSecurityContext allows specifying the PodSecurityContext that will - // be used by the data mover - MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` - // MoverServiceAccount allows specifying the name of the service account - // that will be used by the data mover. This should only be used by advanced - // users who want to override the service account normally used by the mover. - // The service account needs to exist in the same namespace as the ReplicationSource. - //+optional - MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + + MoverConfig `json:",inline"` } // ReplicationSourceResticStatus defines the field for ReplicationSourceStatus in ReplicationSourceStatus @@ -243,15 +240,8 @@ type ReplicationSourceSyncthingSpec struct { // Used to set the accessModes of Syncthing config volume. //+optional ConfigAccessModes []corev1.PersistentVolumeAccessMode `json:"configAccessModes,omitempty"` - // MoverSecurityContext allows specifying the PodSecurityContext that will - // be used by the data mover - MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` - // MoverServiceAccount allows specifying the name of the service account - // that will be used by the data mover. This should only be used by advanced - // users who want to override the service account normally used by the mover. - // The service account needs to exist in the same namespace as the ReplicationSource. - //+optional - MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + + MoverConfig `json:",inline"` } // ReplicationSourceSpec defines the desired state of ReplicationSource diff --git a/api/v1alpha1/rsync_tls_types.go b/api/v1alpha1/rsync_tls_types.go index b57c61b3c..f051e8512 100644 --- a/api/v1alpha1/rsync_tls_types.go +++ b/api/v1alpha1/rsync_tls_types.go @@ -54,15 +54,8 @@ type ReplicationSourceRsyncTLSSpec struct { //+kubebuilder:validation:Maximum=65535 //+optional Port *int32 `json:"port,omitempty"` - // MoverSecurityContext allows specifying the PodSecurityContext that will - // be used by the data mover - MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` - // MoverServiceAccount allows specifying the name of the service account - // that will be used by the data mover. This should only be used by advanced - // users who want to override the service account normally used by the mover. - // The service account needs to exist in the same namespace as the ReplicationSource. - //+optional - MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + + MoverConfig `json:",inline"` } type ReplicationSourceRsyncTLSStatus struct { @@ -92,15 +85,8 @@ type ReplicationDestinationRsyncTLSSpec struct { // will be used instead of any VolSync default values. //+optional ServiceAnnotations *map[string]string `json:"serviceAnnotations,omitempty"` - // MoverSecurityContext allows specifying the PodSecurityContext that will - // be used by the data mover - MoverSecurityContext *corev1.PodSecurityContext `json:"moverSecurityContext,omitempty"` - // MoverServiceAccount allows specifying the name of the service account - // that will be used by the data mover. This should only be used by advanced - // users who want to override the service account normally used by the mover. - // The service account needs to exist in the same namespace as the ReplicationDestination. - //+optional - MoverServiceAccount *string `json:"moverServiceAccount,omitempty"` + + MoverConfig `json:",inline"` } type ReplicationDestinationRsyncTLSStatus struct { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index a99f89660..079ddce27 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -58,6 +58,43 @@ func (in *CustomCASpec) DeepCopy() *CustomCASpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MoverConfig) DeepCopyInto(out *MoverConfig) { + *out = *in + if in.MoverSecurityContext != nil { + in, out := &in.MoverSecurityContext, &out.MoverSecurityContext + *out = new(v1.PodSecurityContext) + (*in).DeepCopyInto(*out) + } + if in.MoverServiceAccount != nil { + in, out := &in.MoverServiceAccount, &out.MoverServiceAccount + *out = new(string) + **out = **in + } + if in.MoverPodLabels != nil { + in, out := &in.MoverPodLabels, &out.MoverPodLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.MoverResources != nil { + in, out := &in.MoverResources, &out.MoverResources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MoverConfig. +func (in *MoverConfig) DeepCopy() *MoverConfig { + if in == nil { + return nil + } + out := new(MoverConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MoverStatus) DeepCopyInto(out *MoverStatus) { *out = *in @@ -178,16 +215,7 @@ func (in *ReplicationDestinationRcloneSpec) DeepCopyInto(out *ReplicationDestina **out = **in } out.CustomCA = in.CustomCA - if in.MoverSecurityContext != nil { - in, out := &in.MoverSecurityContext, &out.MoverSecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.MoverServiceAccount != nil { - in, out := &in.MoverServiceAccount, &out.MoverServiceAccount - *out = new(string) - **out = **in - } + in.MoverConfig.DeepCopyInto(&out.MoverConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationDestinationRcloneSpec. @@ -245,16 +273,7 @@ func (in *ReplicationDestinationResticSpec) DeepCopyInto(out *ReplicationDestina *out = new(string) **out = **in } - if in.MoverSecurityContext != nil { - in, out := &in.MoverSecurityContext, &out.MoverSecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.MoverServiceAccount != nil { - in, out := &in.MoverServiceAccount, &out.MoverServiceAccount - *out = new(string) - **out = **in - } + in.MoverConfig.DeepCopyInto(&out.MoverConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationDestinationResticSpec. @@ -317,6 +336,18 @@ func (in *ReplicationDestinationRsyncSpec) DeepCopyInto(out *ReplicationDestinat *out = new(string) **out = **in } + if in.MoverPodLabels != nil { + in, out := &in.MoverPodLabels, &out.MoverPodLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.MoverResources != nil { + in, out := &in.MoverResources, &out.MoverResources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationDestinationRsyncSpec. @@ -384,16 +415,7 @@ func (in *ReplicationDestinationRsyncTLSSpec) DeepCopyInto(out *ReplicationDesti } } } - if in.MoverSecurityContext != nil { - in, out := &in.MoverSecurityContext, &out.MoverSecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.MoverServiceAccount != nil { - in, out := &in.MoverServiceAccount, &out.MoverServiceAccount - *out = new(string) - **out = **in - } + in.MoverConfig.DeepCopyInto(&out.MoverConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationDestinationRsyncTLSSpec. @@ -712,16 +734,7 @@ func (in *ReplicationSourceRcloneSpec) DeepCopyInto(out *ReplicationSourceRclone **out = **in } out.CustomCA = in.CustomCA - if in.MoverSecurityContext != nil { - in, out := &in.MoverSecurityContext, &out.MoverSecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.MoverServiceAccount != nil { - in, out := &in.MoverServiceAccount, &out.MoverServiceAccount - *out = new(string) - **out = **in - } + in.MoverConfig.DeepCopyInto(&out.MoverConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationSourceRcloneSpec. @@ -779,16 +792,7 @@ func (in *ReplicationSourceResticSpec) DeepCopyInto(out *ReplicationSourceRestic *out = make([]v1.PersistentVolumeAccessMode, len(*in)) copy(*out, *in) } - if in.MoverSecurityContext != nil { - in, out := &in.MoverSecurityContext, &out.MoverSecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.MoverServiceAccount != nil { - in, out := &in.MoverServiceAccount, &out.MoverServiceAccount - *out = new(string) - **out = **in - } + in.MoverConfig.DeepCopyInto(&out.MoverConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationSourceResticSpec. @@ -859,6 +863,18 @@ func (in *ReplicationSourceRsyncSpec) DeepCopyInto(out *ReplicationSourceRsyncSp *out = new(string) **out = **in } + if in.MoverPodLabels != nil { + in, out := &in.MoverPodLabels, &out.MoverPodLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.MoverResources != nil { + in, out := &in.MoverResources, &out.MoverResources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationSourceRsyncSpec. @@ -920,16 +936,7 @@ func (in *ReplicationSourceRsyncTLSSpec) DeepCopyInto(out *ReplicationSourceRsyn *out = new(int32) **out = **in } - if in.MoverSecurityContext != nil { - in, out := &in.MoverSecurityContext, &out.MoverSecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.MoverServiceAccount != nil { - in, out := &in.MoverServiceAccount, &out.MoverServiceAccount - *out = new(string) - **out = **in - } + in.MoverConfig.DeepCopyInto(&out.MoverConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationSourceRsyncTLSSpec. @@ -1111,16 +1118,7 @@ func (in *ReplicationSourceSyncthingSpec) DeepCopyInto(out *ReplicationSourceSyn *out = make([]v1.PersistentVolumeAccessMode, len(*in)) copy(*out, *in) } - if in.MoverSecurityContext != nil { - in, out := &in.MoverSecurityContext, &out.MoverSecurityContext - *out = new(v1.PodSecurityContext) - (*in).DeepCopyInto(*out) - } - if in.MoverServiceAccount != nil { - in, out := &in.MoverServiceAccount, &out.MoverServiceAccount - *out = new(string) - **out = **in - } + in.MoverConfig.DeepCopyInto(&out.MoverConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicationSourceSyncthingSpec. diff --git a/bundle/manifests/volsync.backube_replicationdestinations.yaml b/bundle/manifests/volsync.backube_replicationdestinations.yaml index cf67e4bf9..93dbc14c8 100644 --- a/bundle/manifests/volsync.backube_replicationdestinations.yaml +++ b/bundle/manifests/volsync.backube_replicationdestinations.yaml @@ -120,6 +120,65 @@ spec: instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -298,7 +357,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationDestination. + needs to exist in the same namespace as this CR. type: string rcloneConfig: description: RcloneConfig is the rclone secret name @@ -391,6 +450,65 @@ spec: instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -569,7 +687,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationDestination. + needs to exist in the same namespace as this CR. type: string previous: description: Previous specifies the number of image to skip before @@ -632,6 +750,65 @@ spec: instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverServiceAccount: description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This @@ -720,6 +897,65 @@ spec: TLS pre-shared key to be used for authentication. If not provided, the key will be generated. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -898,7 +1134,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationDestination. + needs to exist in the same namespace as this CR. type: string serviceAnnotations: additionalProperties: diff --git a/bundle/manifests/volsync.backube_replicationsources.yaml b/bundle/manifests/volsync.backube_replicationsources.yaml index 2c8b4f5c3..5c83c8017 100644 --- a/bundle/manifests/volsync.backube_replicationsources.yaml +++ b/bundle/manifests/volsync.backube_replicationsources.yaml @@ -117,6 +117,65 @@ spec: should not be set type: string type: object + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -295,7 +354,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string rcloneConfig: description: RcloneConfig is the rclone secret name @@ -382,6 +441,65 @@ spec: should not be set type: string type: object + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -560,7 +678,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string pruneIntervalDays: description: PruneIntervalDays define how often to prune the repository @@ -658,6 +776,65 @@ spec: - Clone - Snapshot type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverServiceAccount: description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This @@ -735,6 +912,65 @@ spec: TLS pre-shared key to be used for authentication. If not provided, the key will be generated. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -913,7 +1149,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string port: description: port is the port to connect to for replication. Defaults @@ -956,6 +1192,65 @@ spec: description: Used to set the StorageClass of the Syncthing config volume. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -1134,7 +1429,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string peers: description: List of Syncthing peers to be connected for syncing diff --git a/bundle/manifests/volsync.clusterserviceversion.yaml b/bundle/manifests/volsync.clusterserviceversion.yaml index 878f15901..21c121e6d 100644 --- a/bundle/manifests/volsync.clusterserviceversion.yaml +++ b/bundle/manifests/volsync.clusterserviceversion.yaml @@ -55,7 +55,7 @@ metadata: } ] capabilities: Basic Install - createdAt: "2023-10-20T15:36:26Z" + createdAt: "2024-01-23T21:58:58Z" olm.skipRange: '>=0.4.0 <0.8.0' operators.operatorframework.io/builder: operator-sdk-v1.31.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 diff --git a/config/crd/bases/volsync.backube_replicationdestinations.yaml b/config/crd/bases/volsync.backube_replicationdestinations.yaml index d853d5b23..c0f57da01 100644 --- a/config/crd/bases/volsync.backube_replicationdestinations.yaml +++ b/config/crd/bases/volsync.backube_replicationdestinations.yaml @@ -120,6 +120,65 @@ spec: instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -298,7 +357,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationDestination. + needs to exist in the same namespace as this CR. type: string rcloneConfig: description: RcloneConfig is the rclone secret name @@ -391,6 +450,65 @@ spec: instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -569,7 +687,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationDestination. + needs to exist in the same namespace as this CR. type: string previous: description: Previous specifies the number of image to skip before @@ -632,6 +750,65 @@ spec: instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverServiceAccount: description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This @@ -720,6 +897,65 @@ spec: TLS pre-shared key to be used for authentication. If not provided, the key will be generated. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -898,7 +1134,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationDestination. + needs to exist in the same namespace as this CR. type: string serviceAnnotations: additionalProperties: diff --git a/config/crd/bases/volsync.backube_replicationsources.yaml b/config/crd/bases/volsync.backube_replicationsources.yaml index 13db950ab..59d836059 100644 --- a/config/crd/bases/volsync.backube_replicationsources.yaml +++ b/config/crd/bases/volsync.backube_replicationsources.yaml @@ -117,6 +117,65 @@ spec: should not be set type: string type: object + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -295,7 +354,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string rcloneConfig: description: RcloneConfig is the rclone secret name @@ -382,6 +441,65 @@ spec: should not be set type: string type: object + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -560,7 +678,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string pruneIntervalDays: description: PruneIntervalDays define how often to prune the repository @@ -658,6 +776,65 @@ spec: - Clone - Snapshot type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverServiceAccount: description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This @@ -735,6 +912,65 @@ spec: TLS pre-shared key to be used for authentication. If not provided, the key will be generated. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -913,7 +1149,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string port: description: port is the port to connect to for replication. Defaults @@ -956,6 +1192,65 @@ spec: description: Used to set the StorageClass of the Syncthing config volume. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These + will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required + by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + This should only be used by advanced users as this can result + in a mover pod being unschedulable or crashing due to limited + resources.' + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover @@ -1134,7 +1429,7 @@ spec: the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account - needs to exist in the same namespace as the ReplicationSource. + needs to exist in the same namespace as this CR. type: string peers: description: List of Syncthing peers to be connected for syncing diff --git a/controllers/mover/rclone/builder.go b/controllers/mover/rclone/builder.go index 82681785f..2741832cf 100644 --- a/controllers/mover/rclone/builder.go +++ b/controllers/mover/rclone/builder.go @@ -115,23 +115,23 @@ func (rb *Builder) FromSource(client client.Client, logger logr.Logger, source.Spec.Rclone.MoverServiceAccount) return &Mover{ - client: client, - logger: logger.WithValues("method", "Rclone"), - eventRecorder: eventRecorder, - owner: source, - vh: vh, - saHandler: saHandler, - containerImage: rb.getRcloneContainerImage(), - rcloneConfigSection: source.Spec.Rclone.RcloneConfigSection, - rcloneDestPath: source.Spec.Rclone.RcloneDestPath, - rcloneConfig: source.Spec.Rclone.RcloneConfig, - isSource: isSource, - paused: source.Spec.Paused, - mainPVCName: &source.Spec.SourcePVC, - customCASpec: source.Spec.Rclone.CustomCA, - privileged: privileged, - moverSecurityContext: source.Spec.Rclone.MoverSecurityContext, - latestMoverStatus: source.Status.LatestMoverStatus, + client: client, + logger: logger.WithValues("method", "Rclone"), + eventRecorder: eventRecorder, + owner: source, + vh: vh, + saHandler: saHandler, + containerImage: rb.getRcloneContainerImage(), + rcloneConfigSection: source.Spec.Rclone.RcloneConfigSection, + rcloneDestPath: source.Spec.Rclone.RcloneDestPath, + rcloneConfig: source.Spec.Rclone.RcloneConfig, + isSource: isSource, + paused: source.Spec.Paused, + mainPVCName: &source.Spec.SourcePVC, + customCASpec: source.Spec.Rclone.CustomCA, + privileged: privileged, + latestMoverStatus: source.Status.LatestMoverStatus, + moverConfig: source.Spec.Rclone.MoverConfig, }, nil } @@ -163,22 +163,22 @@ func (rb *Builder) FromDestination(client client.Client, logger logr.Logger, destination.Spec.Rclone.MoverServiceAccount) return &Mover{ - client: client, - logger: logger.WithValues("method", "Rclone"), - eventRecorder: eventRecorder, - owner: destination, - vh: vh, - saHandler: saHandler, - containerImage: rb.getRcloneContainerImage(), - rcloneConfigSection: destination.Spec.Rclone.RcloneConfigSection, - rcloneDestPath: destination.Spec.Rclone.RcloneDestPath, - rcloneConfig: destination.Spec.Rclone.RcloneConfig, - isSource: isSource, - paused: destination.Spec.Paused, - mainPVCName: destination.Spec.Rclone.DestinationPVC, - customCASpec: destination.Spec.Rclone.CustomCA, - privileged: privileged, - moverSecurityContext: destination.Spec.Rclone.MoverSecurityContext, - latestMoverStatus: destination.Status.LatestMoverStatus, + client: client, + logger: logger.WithValues("method", "Rclone"), + eventRecorder: eventRecorder, + owner: destination, + vh: vh, + saHandler: saHandler, + containerImage: rb.getRcloneContainerImage(), + rcloneConfigSection: destination.Spec.Rclone.RcloneConfigSection, + rcloneDestPath: destination.Spec.Rclone.RcloneDestPath, + rcloneConfig: destination.Spec.Rclone.RcloneConfig, + isSource: isSource, + paused: destination.Spec.Paused, + mainPVCName: destination.Spec.Rclone.DestinationPVC, + customCASpec: destination.Spec.Rclone.CustomCA, + privileged: privileged, + latestMoverStatus: destination.Status.LatestMoverStatus, + moverConfig: destination.Spec.Rclone.MoverConfig, }, nil } diff --git a/controllers/mover/rclone/mover.go b/controllers/mover/rclone/mover.go index 326d942ab..222a79890 100644 --- a/controllers/mover/rclone/mover.go +++ b/controllers/mover/rclone/mover.go @@ -48,23 +48,23 @@ const ( // Mover is the reconciliation logic for the Rclone-based data mover. type Mover struct { - client client.Client - logger logr.Logger - eventRecorder events.EventRecorder - owner client.Object - vh *volumehandler.VolumeHandler - saHandler utils.SAHandler - containerImage string - rcloneConfigSection *string - rcloneDestPath *string - rcloneConfig *string - isSource bool - paused bool - mainPVCName *string - customCASpec volsyncv1alpha1.CustomCASpec - privileged bool // true if the mover should have elevated privileges - moverSecurityContext *corev1.PodSecurityContext - latestMoverStatus *volsyncv1alpha1.MoverStatus + client client.Client + logger logr.Logger + eventRecorder events.EventRecorder + owner client.Object + vh *volumehandler.VolumeHandler + saHandler utils.SAHandler + containerImage string + rcloneConfigSection *string + rcloneDestPath *string + rcloneConfig *string + isSource bool + paused bool + mainPVCName *string + customCASpec volsyncv1alpha1.CustomCASpec + privileged bool // true if the mover should have elevated privileges + latestMoverStatus *volsyncv1alpha1.MoverStatus + moverConfig volsyncv1alpha1.MoverConfig } var _ mover.Mover = &Mover{} @@ -265,7 +265,6 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC }} job.Spec.Template.Spec.RestartPolicy = corev1.RestartPolicyNever job.Spec.Template.Spec.ServiceAccountName = sa.Name - job.Spec.Template.Spec.SecurityContext = m.moverSecurityContext job.Spec.Template.Spec.Volumes = []corev1.Volume{ {Name: dataVolumeName, VolumeSource: corev1.VolumeSource{ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ @@ -316,6 +315,9 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC }) } + // Update the job securityContext, podLabels and resourceRequirements from moverConfig (if specified) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + // Adjust the Job based on whether the mover should be running as privileged logger.Info("mover permissions", "privileged-mover", m.privileged) if m.privileged { diff --git a/controllers/mover/rclone/rclone_test.go b/controllers/mover/rclone/rclone_test.go index 13b7b56f2..f21d5ab1f 100644 --- a/controllers/mover/rclone/rclone_test.go +++ b/controllers/mover/rclone/rclone_test.go @@ -647,6 +647,51 @@ var _ = Describe("Rclone as a source", func() { validateJobEnvVars(job.Spec.Template.Spec.Containers[0].Env, true) }) + It("Should not have container resourceRequirements set by default", func() { + j, e := mover.ensureJob(ctx, sPVC, sa, rcloneConfigSecret, nil) // Using sPVC as dataPVC (i.e. direct) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be the empty/default value + Expect(job.Spec.Template.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{})) + }) + + When("moverResources (resource requirements) are provided", func() { + BeforeEach(func() { + rs.Spec.Rclone.MoverResources = &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + } + }) + It("Should use them in the mover job container", func() { + j, e := mover.ensureJob(ctx, sPVC, sa, rcloneConfigSecret, nil) // Using sPVC as dataPVC (i.e. direct) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be set + resourceReqs := job.Spec.Template.Spec.Containers[0].Resources + Expect(resourceReqs.Limits).To(BeNil()) // No limits were set + Expect(resourceReqs.Requests).NotTo(BeNil()) + + cpuRequest := resourceReqs.Requests[corev1.ResourceCPU] + Expect(cpuRequest).NotTo(BeNil()) + Expect(cpuRequest).To(Equal(resource.MustParse("50m"))) + memRequest := resourceReqs.Requests[corev1.ResourceMemory] + Expect(memRequest).NotTo(BeNil()) + Expect(memRequest).To(Equal(resource.MustParse("128Mi"))) + }) + }) + When("a custom CA is not supplied", func() { It("Should not attempt to update the podspec in the mover job", func() { var customCA volsyncv1alpha1.CustomCASpec // No CustomCA, not initializing w any values diff --git a/controllers/mover/restic/builder.go b/controllers/mover/restic/builder.go index 73d18ed1f..fd0207b4c 100644 --- a/controllers/mover/restic/builder.go +++ b/controllers/mover/restic/builder.go @@ -136,12 +136,12 @@ func (rb *Builder) FromSource(client client.Client, logger logr.Logger, mainPVCName: &source.Spec.SourcePVC, customCASpec: volsyncv1alpha1.CustomCASpec(source.Spec.Restic.CustomCA), privileged: privileged, - moverSecurityContext: source.Spec.Restic.MoverSecurityContext, pruneInterval: source.Spec.Restic.PruneIntervalDays, retainPolicy: source.Spec.Restic.Retain, unlock: source.Spec.Restic.Unlock, sourceStatus: source.Status.Restic, latestMoverStatus: source.Status.LatestMoverStatus, + moverConfig: source.Spec.Restic.MoverConfig, }, nil } @@ -189,9 +189,9 @@ func (rb *Builder) FromDestination(client client.Client, logger logr.Logger, mainPVCName: destination.Spec.Restic.DestinationPVC, customCASpec: volsyncv1alpha1.CustomCASpec(destination.Spec.Restic.CustomCA), privileged: privileged, - moverSecurityContext: destination.Spec.Restic.MoverSecurityContext, restoreAsOf: destination.Spec.Restic.RestoreAsOf, previous: destination.Spec.Restic.Previous, latestMoverStatus: destination.Status.LatestMoverStatus, + moverConfig: destination.Spec.Restic.MoverConfig, }, nil } diff --git a/controllers/mover/restic/mover.go b/controllers/mover/restic/mover.go index 6d6ce7a45..931dd6544 100644 --- a/controllers/mover/restic/mover.go +++ b/controllers/mover/restic/mover.go @@ -72,8 +72,8 @@ type Mover struct { mainPVCName *string customCASpec volsyncv1alpha1.CustomCASpec privileged bool - moverSecurityContext *corev1.PodSecurityContext latestMoverStatus *volsyncv1alpha1.MoverStatus + moverConfig volsyncv1alpha1.MoverConfig // Source-only fields pruneInterval *int32 unlock string @@ -411,7 +411,6 @@ func (m *Mover) ensureJob(ctx context.Context, cachePVC *corev1.PersistentVolume }} podSpec.RestartPolicy = corev1.RestartPolicyNever podSpec.ServiceAccountName = sa.Name - podSpec.SecurityContext = m.moverSecurityContext podSpec.Volumes = []corev1.Volume{ {Name: dataVolumeName, VolumeSource: corev1.VolumeSource{ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ @@ -487,6 +486,10 @@ func (m *Mover) ensureJob(ctx context.Context, cachePVC *corev1.PersistentVolume }, }) } + + // Update the job securityContext, podLabels and resourceRequirements from moverConfig (if specified) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + if m.privileged { podSpec.Containers[0].Env = append(podSpec.Containers[0].Env, corev1.EnvVar{ Name: "PRIVILEGED_MOVER", diff --git a/controllers/mover/restic/restic_test.go b/controllers/mover/restic/restic_test.go index b913cbaea..f53261875 100644 --- a/controllers/mover/restic/restic_test.go +++ b/controllers/mover/restic/restic_test.go @@ -803,6 +803,50 @@ var _ = Describe("Restic as a source", func() { }) }) + It("Should not have container resourceRequirements set by default", func() { + j, e := mover.ensureJob(ctx, cache, sPVC, sa, repo, nil) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be the empty/default value + Expect(job.Spec.Template.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{})) + }) + When("moverResources (resource requirements) are provided", func() { + BeforeEach(func() { + rs.Spec.Restic.MoverResources = &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + } + }) + It("Should use them in the mover job container", func() { + j, e := mover.ensureJob(ctx, cache, sPVC, sa, repo, nil) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be set + resourceReqs := job.Spec.Template.Spec.Containers[0].Resources + Expect(resourceReqs.Limits).To(BeNil()) // No limits were set + Expect(resourceReqs.Requests).NotTo(BeNil()) + + cpuRequest := resourceReqs.Requests[corev1.ResourceCPU] + Expect(cpuRequest).NotTo(BeNil()) + Expect(cpuRequest).To(Equal(resource.MustParse("50m"))) + memRequest := resourceReqs.Requests[corev1.ResourceMemory] + Expect(memRequest).NotTo(BeNil()) + Expect(memRequest).To(Equal(resource.MustParse("128Mi"))) + }) + }) + When("The NS allows privileged movers", func() { // Already the case in this block It("Should start a privileged mover", func() { j, e := mover.ensureJob(ctx, cache, sPVC, sa, repo, nil) diff --git a/controllers/mover/rsync/builder.go b/controllers/mover/rsync/builder.go index 61ddf3a58..35f0b0ae8 100644 --- a/controllers/mover/rsync/builder.go +++ b/controllers/mover/rsync/builder.go @@ -137,9 +137,15 @@ func (rb *Builder) FromSource(client client.Client, logger logr.Logger, mainPVCName: &source.Spec.SourcePVC, sourceStatus: source.Status.Rsync, latestMoverStatus: source.Status.LatestMoverStatus, + moverConfig: volsyncv1alpha1.MoverConfig{ + MoverSecurityContext: nil, // Not supported for rsync ssh + MoverPodLabels: source.Spec.Rsync.MoverPodLabels, + MoverResources: source.Spec.Rsync.MoverResources, + }, }, nil } +//nolint:funlen func (rb *Builder) FromDestination(client client.Client, logger logr.Logger, eventRecorder events.EventRecorder, destination *volsyncv1alpha1.ReplicationDestination, _ bool) (mover.Mover, error) { @@ -198,5 +204,10 @@ func (rb *Builder) FromDestination(client client.Client, logger logr.Logger, mainPVCName: destination.Spec.Rsync.DestinationPVC, destStatus: destination.Status.Rsync, latestMoverStatus: destination.Status.LatestMoverStatus, + moverConfig: volsyncv1alpha1.MoverConfig{ + MoverSecurityContext: nil, // Not supported for rsync ssh + MoverPodLabels: destination.Spec.Rsync.MoverPodLabels, + MoverResources: destination.Spec.Rsync.MoverResources, + }, }, nil } diff --git a/controllers/mover/rsync/mover.go b/controllers/mover/rsync/mover.go index a0f0981f2..176c9d58f 100644 --- a/controllers/mover/rsync/mover.go +++ b/controllers/mover/rsync/mover.go @@ -68,6 +68,7 @@ type Mover struct { sourceStatus *volsyncv1alpha1.ReplicationSourceRsyncStatus destStatus *volsyncv1alpha1.ReplicationDestinationRsyncStatus latestMoverStatus *volsyncv1alpha1.MoverStatus + moverConfig volsyncv1alpha1.MoverConfig } var _ mover.Mover = &Mover{} @@ -454,6 +455,10 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC job.Spec.Template.Spec.NodeSelector = affinity.NodeSelector job.Spec.Template.Spec.Tolerations = affinity.Tolerations } + + // Update the job podLabels and resourceRequirements (if specified) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + logger.V(1).Info("Job has PVC", "PVC", dataPVC, "DS", dataPVC.Spec.DataSource) return nil }) diff --git a/controllers/mover/rsync/rsync_test.go b/controllers/mover/rsync/rsync_test.go index 06d582e4f..f1cec14d8 100644 --- a/controllers/mover/rsync/rsync_test.go +++ b/controllers/mover/rsync/rsync_test.go @@ -724,6 +724,50 @@ var _ = Describe("Rsync as a source", func() { Expect(job.Spec.Template.Spec.ServiceAccountName).To(Equal(sa.Name)) }) + It("Should not have container resourceRequirements set by default", func() { + j, e := mover.ensureJob(ctx, sPVC, sa, sshKeysSecret.GetName()) // Using sPVC as dataPVC (i.e. direct) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be the empty/default value + Expect(job.Spec.Template.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{})) + }) + When("moverResources (resource requirements) are provided", func() { + BeforeEach(func() { + rs.Spec.Rsync.MoverResources = &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + } + }) + It("Should use them in the mover job container", func() { + j, e := mover.ensureJob(ctx, sPVC, sa, sshKeysSecret.GetName()) // Using sPVC as dataPVC (i.e. direct) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be set + resourceReqs := job.Spec.Template.Spec.Containers[0].Resources + Expect(resourceReqs.Limits).To(BeNil()) // No limits were set + Expect(resourceReqs.Requests).NotTo(BeNil()) + + cpuRequest := resourceReqs.Requests[corev1.ResourceCPU] + Expect(cpuRequest).NotTo(BeNil()) + Expect(cpuRequest).To(Equal(resource.MustParse("50m"))) + memRequest := resourceReqs.Requests[corev1.ResourceMemory] + Expect(memRequest).NotTo(BeNil()) + Expect(memRequest).To(Equal(resource.MustParse("128Mi"))) + }) + }) + It("Should have correct volume mounts", func() { j, e := mover.ensureJob(ctx, sPVC, sa, sshKeysSecret.GetName()) // Using sPVC as dataPVC (i.e. direct) Expect(e).NotTo(HaveOccurred()) diff --git a/controllers/mover/rsynctls/builder.go b/controllers/mover/rsynctls/builder.go index e97f2a645..2a35835ca 100644 --- a/controllers/mover/rsynctls/builder.go +++ b/controllers/mover/rsynctls/builder.go @@ -120,25 +120,25 @@ func (rb *Builder) FromSource(client client.Client, logger logr.Logger, source.Spec.RsyncTLS.MoverServiceAccount) return &Mover{ - client: client, - logger: logger.WithValues("method", "RsyncTLS"), - eventRecorder: eventRecorder, - owner: source, - vh: vh, - saHandler: saHandler, - containerImage: rb.getRsyncTLSContainerImage(), - key: source.Spec.RsyncTLS.KeySecret, - serviceType: nil, - serviceAnnotations: nil, - address: source.Spec.RsyncTLS.Address, - port: source.Spec.RsyncTLS.Port, - isSource: isSource, - paused: source.Spec.Paused, - mainPVCName: &source.Spec.SourcePVC, - privileged: privileged, - moverSecurityContext: source.Spec.RsyncTLS.MoverSecurityContext, - sourceStatus: source.Status.RsyncTLS, - latestMoverStatus: source.Status.LatestMoverStatus, + client: client, + logger: logger.WithValues("method", "RsyncTLS"), + eventRecorder: eventRecorder, + owner: source, + vh: vh, + saHandler: saHandler, + containerImage: rb.getRsyncTLSContainerImage(), + key: source.Spec.RsyncTLS.KeySecret, + serviceType: nil, + serviceAnnotations: nil, + address: source.Spec.RsyncTLS.Address, + port: source.Spec.RsyncTLS.Port, + isSource: isSource, + paused: source.Spec.Paused, + mainPVCName: &source.Spec.SourcePVC, + privileged: privileged, + sourceStatus: source.Status.RsyncTLS, + latestMoverStatus: source.Status.LatestMoverStatus, + moverConfig: source.Spec.RsyncTLS.MoverConfig, }, nil } @@ -183,24 +183,24 @@ func (rb *Builder) FromDestination(client client.Client, logger logr.Logger, } return &Mover{ - client: client, - logger: logger.WithValues("method", "RsyncTLS"), - eventRecorder: eventRecorder, - owner: destination, - vh: vh, - saHandler: saHandler, - containerImage: rb.getRsyncTLSContainerImage(), - key: destination.Spec.RsyncTLS.KeySecret, - serviceType: destination.Spec.RsyncTLS.ServiceType, - serviceAnnotations: svcAnnotations, - address: nil, - port: nil, - isSource: isSource, - paused: destination.Spec.Paused, - mainPVCName: destination.Spec.RsyncTLS.DestinationPVC, - privileged: privileged, - moverSecurityContext: destination.Spec.RsyncTLS.MoverSecurityContext, - destStatus: destination.Status.RsyncTLS, - latestMoverStatus: destination.Status.LatestMoverStatus, + client: client, + logger: logger.WithValues("method", "RsyncTLS"), + eventRecorder: eventRecorder, + owner: destination, + vh: vh, + saHandler: saHandler, + containerImage: rb.getRsyncTLSContainerImage(), + key: destination.Spec.RsyncTLS.KeySecret, + serviceType: destination.Spec.RsyncTLS.ServiceType, + serviceAnnotations: svcAnnotations, + address: nil, + port: nil, + isSource: isSource, + paused: destination.Spec.Paused, + mainPVCName: destination.Spec.RsyncTLS.DestinationPVC, + privileged: privileged, + destStatus: destination.Status.RsyncTLS, + latestMoverStatus: destination.Status.LatestMoverStatus, + moverConfig: destination.Spec.RsyncTLS.MoverConfig, }, nil } diff --git a/controllers/mover/rsynctls/mover.go b/controllers/mover/rsynctls/mover.go index 4c29d19cb..eb89b63c8 100644 --- a/controllers/mover/rsynctls/mover.go +++ b/controllers/mover/rsynctls/mover.go @@ -53,26 +53,26 @@ const ( // Mover is the reconciliation logic for the Rsync-based data mover. type Mover struct { - client client.Client - logger logr.Logger - eventRecorder events.EventRecorder - owner client.Object - vh *volumehandler.VolumeHandler - saHandler utils.SAHandler - containerImage string - key *string - serviceType *corev1.ServiceType - serviceAnnotations map[string]string - address *string - port *int32 - isSource bool - paused bool - mainPVCName *string - privileged bool - moverSecurityContext *corev1.PodSecurityContext - sourceStatus *volsyncv1alpha1.ReplicationSourceRsyncTLSStatus - destStatus *volsyncv1alpha1.ReplicationDestinationRsyncTLSStatus - latestMoverStatus *volsyncv1alpha1.MoverStatus + client client.Client + logger logr.Logger + eventRecorder events.EventRecorder + owner client.Object + vh *volumehandler.VolumeHandler + saHandler utils.SAHandler + containerImage string + key *string + serviceType *corev1.ServiceType + serviceAnnotations map[string]string + address *string + port *int32 + isSource bool + paused bool + mainPVCName *string + privileged bool + sourceStatus *volsyncv1alpha1.ReplicationSourceRsyncTLSStatus + destStatus *volsyncv1alpha1.ReplicationDestinationRsyncTLSStatus + latestMoverStatus *volsyncv1alpha1.MoverStatus + moverConfig volsyncv1alpha1.MoverConfig } var _ mover.Mover = &Mover{} @@ -416,7 +416,6 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC } } podSpec.RestartPolicy = corev1.RestartPolicyNever - podSpec.SecurityContext = m.moverSecurityContext podSpec.ServiceAccountName = sa.Name podSpec.Volumes = []corev1.Volume{ {Name: dataVolumeName, VolumeSource: corev1.VolumeSource{ @@ -446,6 +445,10 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC podSpec.NodeSelector = affinity.NodeSelector podSpec.Tolerations = affinity.Tolerations } + + // Update the job securityContext, podLabels and resourceRequirements from moverConfig (if specified) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + if m.privileged { podSpec.Containers[0].Env = append(podSpec.Containers[0].Env, corev1.EnvVar{ Name: "PRIVILEGED_MOVER", diff --git a/controllers/mover/rsynctls/rsync_test.go b/controllers/mover/rsynctls/rsync_test.go index 77c501d68..df3d12525 100644 --- a/controllers/mover/rsynctls/rsync_test.go +++ b/controllers/mover/rsynctls/rsync_test.go @@ -844,6 +844,50 @@ var _ = Describe("RsyncTLS as a source", func() { Expect(job.Labels).To(HaveKey("volsync.backube/cleanup")) }) + It("Should not have container resourceRequirements set by default", func() { + j, e := mover.ensureJob(ctx, sPVC, sa, tlsKeySecret.GetName()) // Using sPVC as dataPVC (i.e. direct) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be the empty/default value + Expect(job.Spec.Template.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{})) + }) + When("moverResources (resource requirements) are provided", func() { + BeforeEach(func() { + rs.Spec.RsyncTLS.MoverResources = &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + } + }) + It("Should use them in the mover job container", func() { + j, e := mover.ensureJob(ctx, sPVC, sa, tlsKeySecret.GetName()) // Using sPVC as dataPVC (i.e. direct) + Expect(e).NotTo(HaveOccurred()) + Expect(j).To(BeNil()) // hasn't completed + nsn := types.NamespacedName{Name: jobName, Namespace: ns.Name} + job = &batchv1.Job{} + Expect(k8sClient.Get(ctx, nsn, job)).To(Succeed()) + + Expect(len(job.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be set + resourceReqs := job.Spec.Template.Spec.Containers[0].Resources + Expect(resourceReqs.Limits).To(BeNil()) // No limits were set + Expect(resourceReqs.Requests).NotTo(BeNil()) + + cpuRequest := resourceReqs.Requests[corev1.ResourceCPU] + Expect(cpuRequest).NotTo(BeNil()) + Expect(cpuRequest).To(Equal(resource.MustParse("50m"))) + memRequest := resourceReqs.Requests[corev1.ResourceMemory] + Expect(memRequest).NotTo(BeNil()) + Expect(memRequest).To(Equal(resource.MustParse("128Mi"))) + }) + }) + It("should support pausing", func() { j, e := mover.ensureJob(ctx, sPVC, sa, tlsKeySecret.GetName()) // Using sPVC as dataPVC (i.e. direct) Expect(e).NotTo(HaveOccurred()) diff --git a/controllers/mover/syncthing/builder.go b/controllers/mover/syncthing/builder.go index 260bf4798..b0c670fee 100644 --- a/controllers/mover/syncthing/builder.go +++ b/controllers/mover/syncthing/builder.go @@ -117,24 +117,24 @@ func (rb *Builder) FromSource(client client.Client, logger logr.Logger, syncthingLogger := logger.WithValues("method", "Syncthing") return &Mover{ - client: client, - logger: syncthingLogger, - owner: source, - saHandler: saHandler, - eventRecorder: eventRecorder, - configCapacity: source.Spec.Syncthing.ConfigCapacity, - configStorageClass: source.Spec.Syncthing.ConfigStorageClassName, - configAccessModes: source.Spec.Syncthing.ConfigAccessModes, - containerImage: rb.getSyncthingContainerImage(), - peerList: source.Spec.Syncthing.Peers, - paused: source.Spec.Paused, - dataPVCName: &source.Spec.SourcePVC, - status: source.Status.Syncthing, - serviceType: serviceType, - syncthingConnection: nil, - apiConfig: api.APIConfig{}, - privileged: privileged, - moverSecurityContext: source.Spec.Syncthing.MoverSecurityContext, + client: client, + logger: syncthingLogger, + owner: source, + saHandler: saHandler, + eventRecorder: eventRecorder, + configCapacity: source.Spec.Syncthing.ConfigCapacity, + configStorageClass: source.Spec.Syncthing.ConfigStorageClassName, + configAccessModes: source.Spec.Syncthing.ConfigAccessModes, + containerImage: rb.getSyncthingContainerImage(), + peerList: source.Spec.Syncthing.Peers, + paused: source.Spec.Paused, + dataPVCName: &source.Spec.SourcePVC, + status: source.Status.Syncthing, + serviceType: serviceType, + syncthingConnection: nil, + apiConfig: api.APIConfig{}, + privileged: privileged, + moverConfig: source.Spec.Syncthing.MoverConfig, // defer setting the VolumeHandler }, nil } diff --git a/controllers/mover/syncthing/mover.go b/controllers/mover/syncthing/mover.go index 955197aee..2d883da99 100644 --- a/controllers/mover/syncthing/mover.go +++ b/controllers/mover/syncthing/mover.go @@ -99,24 +99,24 @@ const ( // Mover is the reconciliation logic for the Restic-based data mover. type Mover struct { - client client.Client - logger logr.Logger - owner client.Object - saHandler utils.SAHandler - eventRecorder events.EventRecorder - configCapacity *resource.Quantity - configStorageClass *string - configAccessModes []corev1.PersistentVolumeAccessMode - containerImage string - paused bool - dataPVCName *string - peerList []volsyncv1alpha1.SyncthingPeer - status *volsyncv1alpha1.ReplicationSourceSyncthingStatus - serviceType corev1.ServiceType - syncthingConnection api.SyncthingConnection - apiConfig api.APIConfig - privileged bool - moverSecurityContext *corev1.PodSecurityContext + client client.Client + logger logr.Logger + owner client.Object + saHandler utils.SAHandler + eventRecorder events.EventRecorder + configCapacity *resource.Quantity + configStorageClass *string + configAccessModes []corev1.PersistentVolumeAccessMode + containerImage string + paused bool + dataPVCName *string + peerList []volsyncv1alpha1.SyncthingPeer + status *volsyncv1alpha1.ReplicationSourceSyncthingStatus + serviceType corev1.ServiceType + syncthingConnection api.SyncthingConnection + apiConfig api.APIConfig + privileged bool + moverConfig volsyncv1alpha1.MoverConfig } var _ mover.Mover = &Mover{} @@ -476,9 +476,6 @@ func (m *Mover) ensureDeployment(ctx context.Context, dataPVC *corev1.Persistent }, } - // security context - podSpec.SecurityContext = m.moverSecurityContext - // configure volumes podSpec.Volumes = []corev1.Volume{ { @@ -513,6 +510,9 @@ func (m *Mover) ensureDeployment(ctx context.Context, dataPVC *corev1.Persistent }, } + // Update the deployment securityContext, podLabels and resourceRequirements from moverConfig (if specified) + utils.UpdatePodTemplateSpecFromMoverConfig(&deployment.Spec.Template, m.moverConfig) + if m.privileged { podSpec.Containers[0].Env = append(podSpec.Containers[0].Env, corev1.EnvVar{ Name: "PRIVILEGED_MOVER", diff --git a/controllers/mover/syncthing/syncthing_test.go b/controllers/mover/syncthing/syncthing_test.go index 3305ed111..c4f1a44a5 100644 --- a/controllers/mover/syncthing/syncthing_test.go +++ b/controllers/mover/syncthing/syncthing_test.go @@ -1301,6 +1301,76 @@ var _ = Describe("When an RS specifies Syncthing", func() { }) }) }) + + Context("Mover resourceRequirements and podLabels", func() { + When("No mover resourceRequirements or podLables are set", func() { + It("Should have default container resourceRequirements set", func() { + deployment, err := mover.ensureDeployment(ctx, srcPVC, configPVC, sa, apiSecret) + Expect(err).NotTo(HaveOccurred()) + Expect(deployment).NotTo(BeNil()) + + Expect(len(deployment.Spec.Template.Spec.Containers)).To(Equal(1)) + // Restic mover sets a default memory limit of 1Gi + Expect(deployment.Spec.Template.Spec.Containers[0].Resources).To(Equal( + corev1.ResourceRequirements{ + Limits: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("1Gi")}, + }, + )) + }) + }) + When("mover podLabels are set", func() { + BeforeEach(func() { + rs.Spec.Syncthing.MoverPodLabels = map[string]string{ + "mountain": "Aconcagua", + "range": "Andes", + } + }) + It("Should set the mover podLabels on the deployment pod", func() { + deployment, err := mover.ensureDeployment(ctx, srcPVC, configPVC, sa, apiSecret) + Expect(err).NotTo(HaveOccurred()) + Expect(deployment).NotTo(BeNil()) + + Expect(len(deployment.Spec.Template.Spec.Containers)).To(Equal(1)) + Expect(deployment.Spec.Template.Labels["mountain"]).To(Equal("Aconcagua")) + Expect(deployment.Spec.Template.Labels["range"]).To(Equal("Andes")) + }) + }) + When("moverResources (resource requirements) are provided", func() { + BeforeEach(func() { + rs.Spec.Syncthing.MoverResources = &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("2Gi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("20m"), + }, + } + }) + It("Should use them in the mover deployment container", func() { + deployment, err := mover.ensureDeployment(ctx, srcPVC, configPVC, sa, apiSecret) + Expect(err).NotTo(HaveOccurred()) + Expect(deployment).NotTo(BeNil()) + + Expect(len(deployment.Spec.Template.Spec.Containers)).To(Equal(1)) + // ResourceRequirements should be set + resourceReqs := deployment.Spec.Template.Spec.Containers[0].Resources + Expect(resourceReqs.Limits).NotTo(BeNil()) // No limits were set + Expect(resourceReqs.Requests).NotTo(BeNil()) + // Limits + cpuLimit := resourceReqs.Limits[corev1.ResourceCPU] + Expect(cpuLimit).NotTo(BeNil()) + Expect(cpuLimit).To(Equal(resource.MustParse("500m"))) + memLimit := resourceReqs.Limits[corev1.ResourceMemory] + Expect(memLimit).NotTo(BeNil()) + Expect(memLimit).To(Equal(resource.MustParse("2Gi"))) + // Requests + cpuRequest := resourceReqs.Requests[corev1.ResourceCPU] + Expect(cpuRequest).NotTo(BeNil()) + Expect(cpuRequest).To(Equal(resource.MustParse("20m"))) + }) + }) + }) }) When("Deployment already exists", func() { diff --git a/controllers/utils/utils.go b/controllers/utils/utils.go index d805dcc2f..ff14726d4 100644 --- a/controllers/utils/utils.go +++ b/controllers/utils/utils.go @@ -30,6 +30,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/reference" "sigs.k8s.io/controller-runtime/pkg/client" + + volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" ) //+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch @@ -184,3 +186,32 @@ func AppendEnvVarsForClusterWideProxy(envVars []corev1.EnvVar) []corev1.EnvVar { return envVars } + +// Updates to set the securityContext, podLabels on mover pod in the spec and resourceRequirements on the mover +// containers based on what is set in the MoverConfig +func UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec *corev1.PodTemplateSpec, + moverConfig volsyncv1alpha1.MoverConfig) { + if podTemplateSpec == nil { + return + } + + // Security context + if moverConfig.MoverSecurityContext != nil { + podTemplateSpec.Spec.SecurityContext = moverConfig.MoverSecurityContext + } + + // Adjust the job/deploy containers resourceRequirements based on resourceRequirements from the moverConfig + if moverConfig.MoverResources != nil { + for i := range podTemplateSpec.Spec.Containers { + podTemplateSpec.Spec.Containers[i].Resources = *moverConfig.MoverResources + } + } + + // Set custom labels on the job pod if specified in the moverConfig + if podTemplateSpec.Labels == nil { + podTemplateSpec.Labels = map[string]string{} + } + for label, value := range moverConfig.MoverPodLabels { + podTemplateSpec.Labels[label] = value + } +} diff --git a/controllers/utils/utils_test.go b/controllers/utils/utils_test.go index 5a32a255e..62aeb0ce8 100644 --- a/controllers/utils/utils_test.go +++ b/controllers/utils/utils_test.go @@ -18,11 +18,17 @@ along with this program. If not, see . package utils_test import ( + "os" + "github.com/backube/volsync/controllers/utils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + + volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1" ) var _ = Describe("utils tests", func() { @@ -96,4 +102,254 @@ var _ = Describe("utils tests", func() { }) }) }) + + Describe("PvcIsBlockMode", func() { + var pvc *corev1.PersistentVolumeClaim + + storageClassName := "mytest-storage-class" + + BeforeEach(func() { + pvc = &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pvc-1", + Namespace: "test-pvc-1-namespace", + }, + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: &storageClassName, + AccessModes: []corev1.PersistentVolumeAccessMode{ + corev1.ReadWriteOnce, + }, + }, + } + }) + + When("The PVC does not have VolumeMode set", func() { + It("Should not be blockmode", func() { + Expect(utils.PvcIsBlockMode(pvc)).To(BeFalse()) + }) + }) + When("The PVC has volumemode filesystem", func() { + It("Should not be blockmode", func() { + volumeMode := corev1.PersistentVolumeFilesystem + pvc.Spec.VolumeMode = &volumeMode + Expect(utils.PvcIsBlockMode(pvc)).To(BeFalse()) + }) + }) + When("The PVC has volumemode block", func() { + It("Should be blockmode", func() { + volumeMode := corev1.PersistentVolumeBlock + pvc.Spec.VolumeMode = &volumeMode + Expect(utils.PvcIsBlockMode(pvc)).To(BeTrue()) + }) + }) + }) + + Describe("AppendEnvVarsForClusterWideProxy", func() { + envVarsOrig := []corev1.EnvVar{ + { + Name: "existingvar1", + Value: "value1", + }, + { + Name: "EXISTINGVAR2", + Value: "VALUE2", + }, + } + + var envVars []corev1.EnvVar + + BeforeEach(func() { + // Reset envVars back to initial starting value for test + envVars = make([]corev1.EnvVar, len(envVarsOrig)) + copy(envVars, envVarsOrig) + }) + + AfterEach(func() { + os.Unsetenv("HTTP_PROXY") + os.Unsetenv("HTTPS_PROXY") + os.Unsetenv("NO_PROXY") + }) + + When("no proxy env vars are set", func() { + It("Should not modify the existing env vars", func() { + envVars = utils.AppendEnvVarsForClusterWideProxy(envVars) + Expect(envVars).To(Equal(envVarsOrig)) + }) + }) + + When("proxy env vars are set", func() { + httpProxyValue := "http://myproxy.com" + httpsProxyValue := "https://myproxy-secure.com" + noProxyValue := "myinternal.network.acmewidgets.com,testing.acmewidgets.com" + + BeforeEach(func() { + os.Setenv("HTTP_PROXY", httpProxyValue) + os.Setenv("HTTPS_PROXY", httpsProxyValue) + os.Setenv("NO_PROXY", noProxyValue) + }) + + It("Should set the appropriate env vars", func() { + envVars = utils.AppendEnvVarsForClusterWideProxy(envVars) + for i := range envVarsOrig { + // Original env vars should still be set + origVar := envVarsOrig[i] + Expect(envVars).To(ContainElements(origVar)) + } + + // Proxy env vars should be set + Expect(envVars).To(ContainElement(corev1.EnvVar{ + Name: "HTTP_PROXY", + Value: httpProxyValue, + })) + Expect(envVars).To(ContainElement(corev1.EnvVar{ + Name: "http_proxy", + Value: httpProxyValue, + })) + Expect(envVars).To(ContainElement(corev1.EnvVar{ + Name: "HTTPS_PROXY", + Value: httpsProxyValue, + })) + Expect(envVars).To(ContainElement(corev1.EnvVar{ + Name: "https_proxy", + Value: httpsProxyValue, + })) + Expect(envVars).To(ContainElement(corev1.EnvVar{ + Name: "NO_PROXY", + Value: noProxyValue, + })) + Expect(envVars).To(ContainElement(corev1.EnvVar{ + Name: "no_proxy", + Value: noProxyValue, + })) + }) + }) + }) + + Describe("UpdatePodTemplateSpecFromMoverConfig", func() { + When("no pod template spec", func() { + It("should not fail", func() { + utils.UpdatePodTemplateSpecFromMoverConfig(nil, volsyncv1alpha1.MoverConfig{}) + }) + }) + + var podTemplateSpec *corev1.PodTemplateSpec + existingLabelsOrig := map[string]string{ + "existingl": "12345", + } + + BeforeEach(func() { + // Copy the orig map so we keep orig unchanged to compare later + existingLabels := map[string]string{} + for k, v := range existingLabelsOrig { + existingLabels[k] = v + } + + podTemplateSpec = &corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-podtemplatespec", + Namespace: "test-ns", + Labels: existingLabels, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + // 1 container for this test - all movers currently using + // only 1 container + { + Name: "testcontainer0", + Image: "quay.io/testtesttest/test:test", + Command: []string{"takeovertheworld.sh", "now"}, + }, + }, + }, + } + }) + + When("moverConfig does not have any moverResource requirements or pod labels", func() { + JustBeforeEach(func() { + moverConfig := volsyncv1alpha1.MoverConfig{} + utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig) + + // Pod template spec should essentially be unchanged + Expect(podTemplateSpec.Spec.SecurityContext).To(BeNil()) + // ResourceRequirements should be default (empty value) + Expect(podTemplateSpec.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{})) + }) + When("podTemplateSpec has podLabels", func() { + It("Should not update the podTemplateSpec and labels should be retained", func() { + Expect(podTemplateSpec.Labels).To(Equal(existingLabelsOrig)) + }) + }) + When("podlabels are nil", func() { + BeforeEach(func() { + podTemplateSpec.Labels = nil + }) + It("Should not fail, podLabels should be empty in the podtemplatespec", func() { + Expect(podTemplateSpec.Labels).To(Equal(map[string]string{})) + }) + }) + }) + + When("moverConfig has a securityContext set", func() { + var moverConfig volsyncv1alpha1.MoverConfig + var customMoverSecurityContext *corev1.PodSecurityContext + + BeforeEach(func() { + customMoverSecurityContext = &corev1.PodSecurityContext{ + RunAsUser: ptr.To[int64](20), + FSGroup: ptr.To[int64](40), + } + + moverConfig = volsyncv1alpha1.MoverConfig{ + MoverSecurityContext: customMoverSecurityContext, + } + }) + + It("Should update the securityContext in the podTemplateSpec", func() { + utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig) + Expect(podTemplateSpec.Spec.SecurityContext).To(Equal(customMoverSecurityContext)) + }) + }) + + When("moverConfig has resourceRequirements and pod labels", func() { + var moverConfig volsyncv1alpha1.MoverConfig + var customLabels map[string]string + var customResources *corev1.ResourceRequirements + + BeforeEach(func() { + customLabels = map[string]string{ + "customCondimentLabel1": "pickles", + "customCondimentLabel2": "mustard", + } + + customResources = &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("512Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("5m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + } + + moverConfig = volsyncv1alpha1.MoverConfig{ + MoverPodLabels: customLabels, + MoverResources: customResources, + } + }) + + It("Should update the podTemplateSpec", func() { + utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig) + + for k, v := range existingLabelsOrig { + Expect(podTemplateSpec.Labels[k]).To(Equal(v)) + } + for k, v := range customLabels { + Expect(podTemplateSpec.Labels[k]).To(Equal(v)) + } + Expect(podTemplateSpec.Spec.Containers[0].Resources.Limits).To(Equal(customResources.Limits)) + Expect(podTemplateSpec.Spec.Containers[0].Resources.Requests).To(Equal(customResources.Requests)) + }) + }) + }) }) diff --git a/helm/volsync/templates/volsync.backube_replicationdestinations.yaml b/helm/volsync/templates/volsync.backube_replicationdestinations.yaml index d2eb9cfe2..3f433add6 100644 --- a/helm/volsync/templates/volsync.backube_replicationdestinations.yaml +++ b/helm/volsync/templates/volsync.backube_replicationdestinations.yaml @@ -99,6 +99,48 @@ spec: destinationPVC: description: destinationPVC is a PVC to use as the transfer destination instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover properties: @@ -188,7 +230,7 @@ spec: type: object type: object moverServiceAccount: - description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationDestination. + description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as this CR. type: string rcloneConfig: description: RcloneConfig is the rclone secret name @@ -261,6 +303,48 @@ spec: destinationPVC: description: destinationPVC is a PVC to use as the transfer destination instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover properties: @@ -350,7 +434,7 @@ spec: type: object type: object moverServiceAccount: - description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationDestination. + description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as this CR. type: string previous: description: Previous specifies the number of image to skip before selecting one to restore from @@ -400,6 +484,48 @@ spec: destinationPVC: description: destinationPVC is a PVC to use as the transfer destination instead of automatically provisioning one. Either this field or both capacity and accessModes must be specified. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverServiceAccount: description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationDestination. type: string @@ -463,6 +589,48 @@ spec: keySecret: description: keySecret is the name of a Secret that contains the TLS pre-shared key to be used for authentication. If not provided, the key will be generated. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover properties: @@ -552,7 +720,7 @@ spec: type: object type: object moverServiceAccount: - description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationDestination. + description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as this CR. type: string serviceAnnotations: additionalProperties: diff --git a/helm/volsync/templates/volsync.backube_replicationsources.yaml b/helm/volsync/templates/volsync.backube_replicationsources.yaml index de4e6f073..3cf24890b 100644 --- a/helm/volsync/templates/volsync.backube_replicationsources.yaml +++ b/helm/volsync/templates/volsync.backube_replicationsources.yaml @@ -99,6 +99,48 @@ spec: description: The name of a Secret that contains the custom CA certificate If SecretName is used then ConfigMapName should not be set type: string type: object + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover properties: @@ -188,7 +230,7 @@ spec: type: object type: object moverServiceAccount: - description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationSource. + description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as this CR. type: string rcloneConfig: description: RcloneConfig is the rclone secret name @@ -258,6 +300,48 @@ spec: description: The name of a Secret that contains the custom CA certificate If SecretName is used then ConfigMapName should not be set type: string type: object + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover properties: @@ -347,7 +431,7 @@ spec: type: object type: object moverServiceAccount: - description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationSource. + description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as this CR. type: string pruneIntervalDays: description: PruneIntervalDays define how often to prune the repository @@ -423,6 +507,48 @@ spec: - Clone - Snapshot type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverServiceAccount: description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationSource. type: string @@ -481,6 +607,48 @@ spec: keySecret: description: keySecret is the name of a Secret that contains the TLS pre-shared key to be used for authentication. If not provided, the key will be generated. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover properties: @@ -570,7 +738,7 @@ spec: type: object type: object moverServiceAccount: - description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationSource. + description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as this CR. type: string port: description: port is the port to connect to for replication. Defaults to 8000. @@ -606,6 +774,48 @@ spec: configStorageClassName: description: Used to set the StorageClass of the Syncthing config volume. type: string + moverPodLabels: + additionalProperties: + type: string + description: Labels that should be added to data mover pods These will be in addition to any labels that VolSync may add + type: object + moverResources: + description: 'Resources represents compute resources required by the data mover container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ This should only be used by advanced users as this can result in a mover pod being unschedulable or crashing due to limited resources.' + properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object moverSecurityContext: description: MoverSecurityContext allows specifying the PodSecurityContext that will be used by the data mover properties: @@ -695,7 +905,7 @@ spec: type: object type: object moverServiceAccount: - description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as the ReplicationSource. + description: MoverServiceAccount allows specifying the name of the service account that will be used by the data mover. This should only be used by advanced users who want to override the service account normally used by the mover. The service account needs to exist in the same namespace as this CR. type: string peers: description: List of Syncthing peers to be connected for syncing From 86c6a22eaebe8e27604a4acfb537a44c74fa72c0 Mon Sep 17 00:00:00 2001 From: Tesshu Flower Date: Wed, 24 Jan 2024 23:13:59 -0500 Subject: [PATCH 2/2] update securityConfig/resourcerequirements - in cases where user has set securityReqs/ resourceRequirements, and then unsets in the spec, we would not update the spec - in this case make sure the job/deploy template gets updated properly back to the default/empty values Signed-off-by: Tesshu Flower --- controllers/mover/rclone/mover.go | 2 +- controllers/mover/restic/mover.go | 2 +- controllers/mover/rsync/mover.go | 2 +- controllers/mover/rsynctls/mover.go | 2 +- controllers/mover/syncthing/mover.go | 9 +++--- controllers/utils/utils.go | 16 +++++----- controllers/utils/utils_test.go | 45 +++++++++++++++++++++++++--- 7 files changed, 58 insertions(+), 20 deletions(-) diff --git a/controllers/mover/rclone/mover.go b/controllers/mover/rclone/mover.go index 222a79890..a0c6b8fee 100644 --- a/controllers/mover/rclone/mover.go +++ b/controllers/mover/rclone/mover.go @@ -316,7 +316,7 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC } // Update the job securityContext, podLabels and resourceRequirements from moverConfig (if specified) - utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig, corev1.ResourceRequirements{}) // Adjust the Job based on whether the mover should be running as privileged logger.Info("mover permissions", "privileged-mover", m.privileged) diff --git a/controllers/mover/restic/mover.go b/controllers/mover/restic/mover.go index 931dd6544..a668799b6 100644 --- a/controllers/mover/restic/mover.go +++ b/controllers/mover/restic/mover.go @@ -488,7 +488,7 @@ func (m *Mover) ensureJob(ctx context.Context, cachePVC *corev1.PersistentVolume } // Update the job securityContext, podLabels and resourceRequirements from moverConfig (if specified) - utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig, corev1.ResourceRequirements{}) if m.privileged { podSpec.Containers[0].Env = append(podSpec.Containers[0].Env, corev1.EnvVar{ diff --git a/controllers/mover/rsync/mover.go b/controllers/mover/rsync/mover.go index 176c9d58f..aa77ab5d0 100644 --- a/controllers/mover/rsync/mover.go +++ b/controllers/mover/rsync/mover.go @@ -457,7 +457,7 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC } // Update the job podLabels and resourceRequirements (if specified) - utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig, corev1.ResourceRequirements{}) logger.V(1).Info("Job has PVC", "PVC", dataPVC, "DS", dataPVC.Spec.DataSource) return nil diff --git a/controllers/mover/rsynctls/mover.go b/controllers/mover/rsynctls/mover.go index eb89b63c8..71b771d30 100644 --- a/controllers/mover/rsynctls/mover.go +++ b/controllers/mover/rsynctls/mover.go @@ -447,7 +447,7 @@ func (m *Mover) ensureJob(ctx context.Context, dataPVC *corev1.PersistentVolumeC } // Update the job securityContext, podLabels and resourceRequirements from moverConfig (if specified) - utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(&job.Spec.Template, m.moverConfig, corev1.ResourceRequirements{}) if m.privileged { podSpec.Containers[0].Env = append(podSpec.Containers[0].Env, corev1.EnvVar{ diff --git a/controllers/mover/syncthing/mover.go b/controllers/mover/syncthing/mover.go index 2d883da99..270af95ea 100644 --- a/controllers/mover/syncthing/mover.go +++ b/controllers/mover/syncthing/mover.go @@ -462,9 +462,6 @@ func (m *Mover) ensureDeployment(ctx context.Context, dataPVC *corev1.Persistent {Name: dataVolumeName, MountPath: dataDirMountPath}, {Name: certVolumeName, MountPath: certDirMountPath}, }, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("1Gi")}, - }, SecurityContext: &corev1.SecurityContext{ AllowPrivilegeEscalation: ptr.To(false), Capabilities: &corev1.Capabilities{ @@ -510,8 +507,12 @@ func (m *Mover) ensureDeployment(ctx context.Context, dataPVC *corev1.Persistent }, } + defaultMoverResources := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("1Gi")}, + } + // Update the deployment securityContext, podLabels and resourceRequirements from moverConfig (if specified) - utils.UpdatePodTemplateSpecFromMoverConfig(&deployment.Spec.Template, m.moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(&deployment.Spec.Template, m.moverConfig, defaultMoverResources) if m.privileged { podSpec.Containers[0].Env = append(podSpec.Containers[0].Env, corev1.EnvVar{ diff --git a/controllers/utils/utils.go b/controllers/utils/utils.go index ff14726d4..38c01dbc9 100644 --- a/controllers/utils/utils.go +++ b/controllers/utils/utils.go @@ -190,21 +190,21 @@ func AppendEnvVarsForClusterWideProxy(envVars []corev1.EnvVar) []corev1.EnvVar { // Updates to set the securityContext, podLabels on mover pod in the spec and resourceRequirements on the mover // containers based on what is set in the MoverConfig func UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec *corev1.PodTemplateSpec, - moverConfig volsyncv1alpha1.MoverConfig) { + moverConfig volsyncv1alpha1.MoverConfig, defaultMoverResources corev1.ResourceRequirements) { if podTemplateSpec == nil { return } - // Security context - if moverConfig.MoverSecurityContext != nil { - podTemplateSpec.Spec.SecurityContext = moverConfig.MoverSecurityContext - } + // Security context (nil by default) + podTemplateSpec.Spec.SecurityContext = moverConfig.MoverSecurityContext // Adjust the job/deploy containers resourceRequirements based on resourceRequirements from the moverConfig + moverResources := defaultMoverResources if moverConfig.MoverResources != nil { - for i := range podTemplateSpec.Spec.Containers { - podTemplateSpec.Spec.Containers[i].Resources = *moverConfig.MoverResources - } + moverResources = *moverConfig.MoverResources + } + for i := range podTemplateSpec.Spec.Containers { + podTemplateSpec.Spec.Containers[i].Resources = moverResources } // Set custom labels on the job pod if specified in the moverConfig diff --git a/controllers/utils/utils_test.go b/controllers/utils/utils_test.go index 62aeb0ce8..257fe836d 100644 --- a/controllers/utils/utils_test.go +++ b/controllers/utils/utils_test.go @@ -228,7 +228,7 @@ var _ = Describe("utils tests", func() { Describe("UpdatePodTemplateSpecFromMoverConfig", func() { When("no pod template spec", func() { It("should not fail", func() { - utils.UpdatePodTemplateSpecFromMoverConfig(nil, volsyncv1alpha1.MoverConfig{}) + utils.UpdatePodTemplateSpecFromMoverConfig(nil, volsyncv1alpha1.MoverConfig{}, corev1.ResourceRequirements{}) }) }) @@ -265,15 +265,36 @@ var _ = Describe("utils tests", func() { }) When("moverConfig does not have any moverResource requirements or pod labels", func() { + var defaultResourceRequirements corev1.ResourceRequirements + + BeforeEach(func() { + defaultResourceRequirements = corev1.ResourceRequirements{} + }) + JustBeforeEach(func() { moverConfig := volsyncv1alpha1.MoverConfig{} - utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig, defaultResourceRequirements) // Pod template spec should essentially be unchanged Expect(podTemplateSpec.Spec.SecurityContext).To(BeNil()) + }) + It("Should have empty resource requirements set", func() { // ResourceRequirements should be default (empty value) Expect(podTemplateSpec.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{})) }) + + When("Default resourceRequirements with limits are used", func() { + BeforeEach(func() { + defaultResourceRequirements = corev1.ResourceRequirements{ + Limits: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("1Gi")}, + } + }) + It("Should use the limits from the default requirements", func() { + Expect(podTemplateSpec.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("1Gi")}, + })) + }) + }) When("podTemplateSpec has podLabels", func() { It("Should not update the podTemplateSpec and labels should be retained", func() { Expect(podTemplateSpec.Labels).To(Equal(existingLabelsOrig)) @@ -305,7 +326,7 @@ var _ = Describe("utils tests", func() { }) It("Should update the securityContext in the podTemplateSpec", func() { - utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig, corev1.ResourceRequirements{}) Expect(podTemplateSpec.Spec.SecurityContext).To(Equal(customMoverSecurityContext)) }) }) @@ -339,7 +360,7 @@ var _ = Describe("utils tests", func() { }) It("Should update the podTemplateSpec", func() { - utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig) + utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig, corev1.ResourceRequirements{}) for k, v := range existingLabelsOrig { Expect(podTemplateSpec.Labels[k]).To(Equal(v)) @@ -350,6 +371,22 @@ var _ = Describe("utils tests", func() { Expect(podTemplateSpec.Spec.Containers[0].Resources.Limits).To(Equal(customResources.Limits)) Expect(podTemplateSpec.Spec.Containers[0].Resources.Requests).To(Equal(customResources.Requests)) }) + + When("the default resource requirements are set", func() { + It("Should still use the user-supplied resourceRequirements", func() { + defaultRequirements := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("20Mi"), + }, + } + utils.UpdatePodTemplateSpecFromMoverConfig(podTemplateSpec, moverConfig, defaultRequirements) + Expect(podTemplateSpec.Spec.Containers[0].Resources.Limits).To(Equal(customResources.Limits)) + Expect(podTemplateSpec.Spec.Containers[0].Resources.Requests).To(Equal(customResources.Requests)) + }) + }) }) }) })