diff --git a/api/v1alpha1/oadp_types.go b/api/v1alpha1/oadp_types.go index e629ef1c47..4bb50409bf 100644 --- a/api/v1alpha1/oadp_types.go +++ b/api/v1alpha1/oadp_types.go @@ -131,7 +131,7 @@ type PodConfig struct { // tolerations defines the list of tolerations to be applied to daemonset // +optional Tolerations []corev1.Toleration `json:"tolerations,omitempty"` - // resourceAllocations defines the CPU and Memory resource allocations for the Pod + // resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod // +optional // +nullable ResourceAllocations corev1.ResourceRequirements `json:"resourceAllocations,omitempty"` diff --git a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml index b61c9d4d7a..afce4e36d0 100644 --- a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml +++ b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml @@ -305,7 +305,7 @@ spec: description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object resourceAllocations: - description: resourceAllocations defines the CPU and Memory resource allocations for the Pod + description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true properties: claims: @@ -546,7 +546,7 @@ spec: description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object resourceAllocations: - description: resourceAllocations defines the CPU and Memory resource allocations for the Pod + description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true properties: claims: @@ -980,7 +980,7 @@ spec: description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object resourceAllocations: - description: resourceAllocations defines the CPU and Memory resource allocations for the Pod + description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true properties: claims: diff --git a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml index c86b4f5ab2..446bc22429 100644 --- a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml +++ b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml @@ -305,7 +305,7 @@ spec: description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object resourceAllocations: - description: resourceAllocations defines the CPU and Memory resource allocations for the Pod + description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true properties: claims: @@ -546,7 +546,7 @@ spec: description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object resourceAllocations: - description: resourceAllocations defines the CPU and Memory resource allocations for the Pod + description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true properties: claims: @@ -980,7 +980,7 @@ spec: description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object resourceAllocations: - description: resourceAllocations defines the CPU and Memory resource allocations for the Pod + description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true properties: claims: diff --git a/controllers/nodeagent.go b/controllers/nodeagent.go index 7ae172e575..0992410535 100644 --- a/controllers/nodeagent.go +++ b/controllers/nodeagent.go @@ -42,9 +42,6 @@ const ( ) var ( - fsPvHostPath = getFsPvHostPath("") - pluginsHostPath = getPluginsHostPath("") - // v1.MountPropagationHostToContainer is a const. Const cannot be pointed to. // we need to declare mountPropagationToHostContainer so that we have an address to point to // for ds.Spec.Template.Spec.Volumes[].Containers[].VolumeMounts[].MountPropagation diff --git a/controllers/nodeagent_test.go b/controllers/nodeagent_test.go index c0747e1eb3..12648b1033 100644 --- a/controllers/nodeagent_test.go +++ b/controllers/nodeagent_test.go @@ -2,7 +2,6 @@ package controllers import ( "context" - "fmt" "os" "reflect" "slices" @@ -29,6 +28,21 @@ import ( "github.com/openshift/oadp-operator/pkg/common" ) +var ( + testNodeAgentDaemonSet = &appsv1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.NodeAgent, + Namespace: testNamespaceName, + Labels: nodeAgentMatchLabels, + }, + } + testGenericInfrastructure = &configv1.Infrastructure{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster", + }, + } +) + type ReconcileNodeAgentControllerScenario struct { namespace string dpaName string @@ -214,3040 +228,919 @@ var _ = ginkgo.Describe("Test ReconcileNodeAgentDaemonSet function", func() { ) }) -func TestDPAReconciler_buildNodeAgentDaemonset(t *testing.T) { - type args struct { - dpa *oadpv1alpha1.DataProtectionApplication - ds *appsv1.DaemonSet - } - r := &DPAReconciler{} - dpa := oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{}, - }, - UploaderType: "", - }, - }, - }, - } - tests := []struct { - name string - args args - want *appsv1.DaemonSet - wantErr bool - clientObjects []client.Object - }{ - { - name: "dpa is nil", - args: args{ - nil, &appsv1.DaemonSet{}, - }, - wantErr: true, - want: nil, +type TestBuiltNodeAgentDaemonSetOptions struct { + args []string + labels map[string]string + annotations map[string]string + volumes []corev1.Volume + volumeMounts []corev1.VolumeMount + env []corev1.EnvVar + dnsPolicy corev1.DNSPolicy + dnsConfig *corev1.PodDNSConfig + resourceLimits corev1.ResourceList + resourceRequests corev1.ResourceList + toleration []corev1.Toleration + nodeSelector map[string]string +} + +func createTestBuiltNodeAgentDaemonSet(options TestBuiltNodeAgentDaemonSetOptions) *appsv1.DaemonSet { + testBuiltNodeAgentDaemonSet := &appsv1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.NodeAgent, + Namespace: testNamespaceName, + Labels: nodeAgentMatchLabels, }, - { - name: "DaemonSet is nil", - args: args{ - &oadpv1alpha1.DataProtectionApplication{}, nil, - }, - wantErr: true, - want: nil, + TypeMeta: metav1.TypeMeta{ + Kind: "DaemonSet", + APIVersion: appsv1.SchemeGroupVersion.String(), }, - { - name: "Valid velero and daemonset", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - }, - }, + Spec: appsv1.DaemonSetSpec{ + Selector: nodeAgentLabelSelector, + UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ + Type: appsv1.RollingUpdateDaemonSetStrategyType, + RollingUpdate: &appsv1.RollingUpdateDaemonSet{ + MaxUnavailable: &intstr.IntOrString{ + Type: intstr.Int, + IntVal: 1, }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", + MaxSurge: &intstr.IntOrString{ + Type: intstr.Int, + IntVal: 0, }, }, }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), + RevisionHistoryLimit: ptr.To(int32(10)), + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "component": common.Velero, + "name": common.NodeAgent, + }, }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, + ServiceAccountName: common.Velero, + TerminationGracePeriodSeconds: ptr.To(int64(30)), + DNSPolicy: corev1.DNSClusterFirst, + DeprecatedServiceAccount: common.Velero, + SecurityContext: &corev1.PodSecurityContext{ + RunAsUser: ptr.To(int64(0)), }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, + SchedulerName: "default-scheduler", + Containers: []corev1.Container{ + { + Name: common.NodeAgent, + Image: common.VeleroImage, + ImagePullPolicy: corev1.PullAlways, + TerminationMessagePath: "/dev/termination-log", + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + SecurityContext: &corev1.SecurityContext{Privileged: ptr.To(true)}, + Ports: []corev1.ContainerPort{ + { + Name: "metrics", + ContainerPort: 8085, + Protocol: "TCP", + }, }, - }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below + Command: []string{"/velero"}, + Args: append([]string{common.NodeAgent, "server"}, options.args...), + VolumeMounts: []corev1.VolumeMount{ { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, + Name: HostPods, + MountPath: "/host_pods", + MountPropagation: &mountPropagationToHostContainer, }, { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, + Name: HostPlugins, + MountPath: "/var/lib/kubelet/plugins", + MountPropagation: &mountPropagationToHostContainer, }, { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + Name: "scratch", + MountPath: "/scratch", }, { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, + Name: "certs", + MountPath: "/etc/ssl/certs", }, }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ + Env: []corev1.EnvVar{ { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", + Name: "NODE_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "spec.nodeName", }, }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", + }, + { + Name: "VELERO_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.namespace", }, }, }, + {Name: common.VeleroScratchDirEnvKey, Value: "/scratch"}, }, }, }, - }, - }, - }, - { - name: "Valid velero with Env PodConfig and daemonset", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - Env: []corev1.EnvVar{ - { - Name: "TEST_ENV", - Value: "TEST_VALUE", - }, - }, - }, + Volumes: []corev1.Volume{ + { + Name: HostPods, + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: "/var/lib/kubelet/pods", + Type: ptr.To(corev1.HostPathUnset), + }, + }, + }, + { + Name: HostPlugins, + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: "/var/lib/kubelet/plugins", + Type: ptr.To(corev1.HostPathUnset), }, - UploaderType: "", }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, + }, + { + Name: "scratch", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + { + Name: "certs", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, }, }, }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), }, }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", + }, + } + + if options.labels != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Labels = common.AppendTTMapAsCopy(testBuiltNodeAgentDaemonSet.Spec.Template.Labels, options.labels) + } + + if options.annotations != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Annotations = common.AppendTTMapAsCopy(testBuiltNodeAgentDaemonSet.Spec.Template.Annotations, options.annotations) + } + + if options.env != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].Env = append(testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].Env, options.env...) + } + + if options.volumes != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Volumes = append(testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Volumes, options.volumes...) + } + + if options.volumeMounts != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].VolumeMounts = append(testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].VolumeMounts, options.volumeMounts...) + } + + if options.nodeSelector != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.NodeSelector = options.nodeSelector + } + + if options.resourceLimits != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].Resources.Limits = options.resourceLimits + } + + if options.resourceRequests != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].Resources.Requests = options.resourceRequests + } + + if options.toleration != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Tolerations = options.toleration + } + + if len(options.dnsPolicy) > 0 { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.DNSPolicy = options.dnsPolicy + } + + if options.dnsConfig != nil { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.DNSConfig = options.dnsConfig + } + + return testBuiltNodeAgentDaemonSet +} + +func TestDPAReconciler_buildNodeAgentDaemonset(t *testing.T) { + tests := []struct { + name string + dpa *oadpv1alpha1.DataProtectionApplication + testProxy bool + clientObjects []client.Object + nodeAgentDaemonSet *appsv1.DaemonSet + wantNodeAgentDaemonSet *appsv1.DaemonSet + errorMessage string + }{ + { + name: "DPA CR is nil, error is returned", + errorMessage: "dpa cannot be nil", + }, + { + name: "NodeAgent DaemonSet is nil, error is returned", + dpa: &oadpv1alpha1.DataProtectionApplication{}, + errorMessage: "ds cannot be nil", + }, + { + name: "valid DPA CR, NodeAgent DaemonSet is built", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, }, }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - "node-agent", - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{}), + }, + { + name: "valid DPA CR with PodConfig Env, NodeAgent DaemonSet is built with Container Env", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: "TEST_ENV", - Value: "TEST_VALUE", - }, + {Name: "TEST_ENV", Value: "TEST_VALUE"}, }, }, }, + UploaderType: "kopia", }, }, }, - }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + env: []corev1.EnvVar{{Name: "TEST_ENV", Value: "TEST_VALUE"}}, + }), }, { - name: "podConfig label for velero and NodeAgent", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - Labels: map[string]string{ - "nodeAgentLabel": "this is a label", - }, + name: "valid DPA CR with PodConfig label, NodeAgent DaemonSet is built with template labels", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + Labels: map[string]string{ + "nodeAgentLabel": "this is a label", }, }, - UploaderType: "", }, - Velero: &oadpv1alpha1.VeleroConfig{ + UploaderType: "kopia", + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + labels: map[string]string{"nodeAgentLabel": "this is a label"}, + }), + }, + { + name: "invalid DPA CR with podConfig label, error is returned", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ PodConfig: &oadpv1alpha1.PodConfig{ Labels: map[string]string{ - "veleroLabel": "this is a label", + "name": "not-node-agent", // this label is already defined by https://github.com/openshift/velero/blob/8b2f7dbdb510434b9c05180bae7a3fb2a8081e2f/pkg/install/daemonset.go#L71 }, }, }, + UploaderType: "kopia", }, }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), }, - }, - wantErr: false, + ), + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + errorMessage: "NodeAgent daemonset template custom label: conflicting key name with value not-node-agent may not override node-agent", + }, + { + name: "valid DPA CR with Pod annotations, NodeAgent DaemonSet is built with template annotations", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, + }, + PodAnnotations: map[string]string{ + "test-annotation": "awesome annotation", + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + annotations: map[string]string{"test-annotation": "awesome annotation"}, + }), + }, + { + name: "valid DPA CR with Unsupported NodeAgent Server Args, NodeAgent DaemonSet is built with Unsupported NodeAgent Server Args", + dpa: createTestDpaWith( + map[string]string{common.UnsupportedNodeAgentServerArgsAnnotation: "unsupported-node-agent-server-args-cm"}, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, + }, + }, + ), clientObjects: []client.Object{ - &configv1.Infrastructure{ + &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", + Name: "unsupported-node-agent-server-args-cm", + Namespace: testNamespaceName, + }, + Data: map[string]string{ + "unsupported-arg": "value1", + "unsupported-bool-arg": "True", }, }, + testGenericInfrastructure, }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + args: []string{ + "--unsupported-arg=value1", + "--unsupported-bool-arg=true", }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, + }), + }, + { + name: "valid DPA CR with Empty String Unsupported NodeAgent Server Args, NodeAgent DaemonSet is built", + dpa: createTestDpaWith( + map[string]string{common.UnsupportedNodeAgentServerArgsAnnotation: ""}, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - "nodeAgentLabel": "this is a label", - }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{}), + }, + { + name: "valid DPA CR with Unsupported NodeAgent Server Args and missing ConfigMap, error is returned", + dpa: createTestDpaWith( + map[string]string{common.UnsupportedNodeAgentServerArgsAnnotation: "missing-unsupported-node-agent-server-args-cm"}, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + errorMessage: "configmaps \"missing-unsupported-node-agent-server-args-cm\" not found", + }, + { + name: "valid DPA CR with NodeAgent resource allocations, NodeAgent DaemonSet is built with resource allocations", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("400Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, }, }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "Invalid podConfig label for velero and NodeAgent", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - Labels: map[string]string{ - "name": "not-node-agent", // this label is already defined by https://github.com/openshift/velero/blob/8b2f7dbdb510434b9c05180bae7a3fb2a8081e2f/pkg/install/daemonset.go#L71 - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{ - Labels: map[string]string{ - "veleroLabel": "this is a label", - }, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: true, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: nil, - }, - { - name: "test NodeAgent nodeselector customization via dpa", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, }, + UploaderType: "kopia", }, }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("400Mi"), }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, - }, + }), }, { - name: "test NodeAgent resource reqs customization via dpa", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "test NodeAgent resource reqs only NodeAgent cpu limit customization via dpa", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - }, - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ + name: "valid DPA CR with NodeAgent cpu limit, NodeAgent DaemonSet is built with cpu limit", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("2"), }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "test NodeAgent resource reqs only NodeAgent cpu request customization via dpa", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ResourceAllocations: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - }, - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "test NodeAgent resource reqs only NodeAgent memory limit customization via dpa", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "test NodeAgent resource reqs only NodeAgent memory request customization via dpa", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ResourceAllocations: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: map[string]string{ - "foo": "bar", - }, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "test NodeAgent tolerations customization via dpa", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{ - Tolerations: []corev1.Toleration{ - { - Key: "key1", - Operator: "Equal", - Value: "value1", - Effect: "NoSchedule", - }, - }, - }, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: []corev1.Toleration{ - { - Key: "key1", - Operator: "Equal", - Value: "value1", - Effect: "NoSchedule", - }, - }, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "Valid DPA CR with Unsupported NodeAgent Args, appropriate NodeAgent DaemonSet is built", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "sample-dpa", - Namespace: "sample-ns", - Annotations: map[string]string{ - common.UnsupportedNodeAgentServerArgsAnnotation: "unsupported-node-agent-server-args-cm", - }, - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{}, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - clientObjects: []client.Object{ - &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "unsupported-node-agent-server-args-cm", - Namespace: "sample-ns", - }, - Data: map[string]string{ - "unsupported-arg": "value1", - "unsupported-bool-arg": "True", - }, - }, - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - wantErr: false, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - "--unsupported-arg=value1", - "--unsupported-bool-arg=true", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "Valid DPA CR with empty value for Unsupported NodeAgent Args cm annotation, appropriate NodeAgent DaemonSet is built", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "sample-dpa", - Namespace: "sample-ns", - Annotations: map[string]string{ - common.UnsupportedNodeAgentServerArgsAnnotation: "", - }, - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{}, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - clientObjects: []client.Object{ - &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "unsupported-node-agent-server-args-cm", - Namespace: "sample-ns", - }, - Data: map[string]string{ - "unsupported-arg": "value1", - "unsupported-bool-arg": "True", - }, - }, - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - wantErr: false, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - name: "Valid DPA CR with Unsupported NodeAgent Args cm missing, DPA error case", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "sample-dpa", - Namespace: "sample-ns", - Annotations: map[string]string{ - common.UnsupportedNodeAgentServerArgsAnnotation: "unsupported-node-agent-server-args-cm", - }, - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{}, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: true, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: nil, - }, - { - name: "Valid velero and daemon set for aws as bsl", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - NodeAgent: &oadpv1alpha1.NodeAgentConfig{ - NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ - PodConfig: &oadpv1alpha1.PodConfig{}, - }, - UploaderType: "", - }, - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{}, - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", - }, - }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, }, }, }, + UploaderType: "kopia", }, }, }, - }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + }), }, { - name: "Valid velero with annotation and daemonset for aws as bsl with default secret name", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, + name: "valid DPA CR with NodeAgent cpu request, NodeAgent DaemonSet is built with cpu request", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + }, }, }, - NodeAgent: &oadpv1alpha1.NodeAgentConfig{}, + UploaderType: "kopia", }, - BackupLocations: []oadpv1alpha1.BackupLocation{ - { - Velero: &velerov1.BackupStorageLocationSpec{ - Provider: AWSProvider, - StorageType: velerov1.StorageType{ - ObjectStorage: &velerov1.ObjectStorageLocation{ - Bucket: "aws-bucket", - }, - }, - Config: map[string]string{ - Region: "aws-region", - S3URL: "https://sr-url-aws-domain.com", - InsecureSkipTLSVerify: "false", - }, - Credential: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "cloud-credentials", + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }), + }, + { + name: "valid DPA CR with NodeAgent memory limit, NodeAgent DaemonSet is built with memory limit", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, }, }, + UploaderType: "kopia", }, - PodAnnotations: map[string]string{ - "test-annotation": "awesome annotation", - }, - }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - }, - }, - wantErr: false, - clientObjects: []client.Object{ - &configv1.Infrastructure{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", }, }, - }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("256Mi"), }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - Annotations: map[string]string{ - "test-annotation": "awesome annotation", - }, - }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, + }), + }, + { + name: "valid DPA CR with NodeAgent memory request, NodeAgent DaemonSet is built with memory request", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, + }, + UploaderType: "kopia", + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + }, + }), + }, + { + name: "valid DPA CR with NodeAgent ephemeral-storage limit, NodeAgent DaemonSet is built with ephemeral-storage limit", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, }, }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Resources: corev1.ResourceRequirements{ + UploaderType: "kopia", + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), + }, + }), + }, + { + name: "valid DPA CR with NodeAgent ephemeral-storage request, NodeAgent DaemonSet is built with ephemeral-storage request", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, + }, + }, + UploaderType: "kopia", + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), + }, + }), + }, + { + name: "valid DPA CR with NodeAgent tolerations, NodeAgent DaemonSet is built with tolerations", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + Tolerations: []corev1.Toleration{ { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", + Key: "key1", + Operator: "Equal", + Value: "value1", + Effect: "NoSchedule", }, }, }, }, + UploaderType: "kopia", }, }, }, - }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + toleration: []corev1.Toleration{ + { + Key: "key1", + Operator: "Equal", + Value: "value1", + Effect: "NoSchedule", + }, + }, + }), }, { - name: "Valid velero with DNS Policy/Config with annotation and daemonset for aws as bsl with default secret name not specified", - args: args{ - &oadpv1alpha1.DataProtectionApplication{ - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, + name: "valid DPA CR with NodeAgent nodeselector, NodeAgent DaemonSet is built with nodeselector", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + NodeSelector: map[string]string{"foo": "bar"}, }, }, - NodeAgent: &oadpv1alpha1.NodeAgentConfig{}, + UploaderType: "kopia", }, - BackupLocations: []oadpv1alpha1.BackupLocation{ - { - Velero: &velerov1.BackupStorageLocationSpec{ - Provider: AWSProvider, - StorageType: velerov1.StorageType{ - ObjectStorage: &velerov1.ObjectStorageLocation{ - Bucket: "aws-bucket", - }, - }, - Config: map[string]string{ - Region: "aws-region", - S3URL: "https://sr-url-aws-domain.com", - InsecureSkipTLSVerify: "false", - }, - }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + nodeSelector: map[string]string{"foo": "bar"}, + }), + }, + { + name: "valid DPA CR with aws plugin, NodeAgent DaemonSet is built", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, + }, + }, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + volumes: []corev1.Volume{deploymentVolumeSecret("cloud-credentials")}, + volumeMounts: []corev1.VolumeMount{ + {Name: "cloud-credentials", MountPath: "/credentials"}, + }, + env: []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }, + }), + }, + { + name: "valid DPA CR with aws and kubevirt plugin, NodeAgent DaemonSet is built", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, + oadpv1alpha1.DefaultPluginKubeVirt, }, }, - PodAnnotations: map[string]string{ - "test-annotation": "awesome annotation", + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", }, - PodDnsPolicy: "None", - PodDnsConfig: corev1.PodDNSConfig{ - Nameservers: []string{ - "1.1.1.1", - "8.8.8.8", + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + volumes: []corev1.Volume{deploymentVolumeSecret("cloud-credentials")}, + volumeMounts: []corev1.VolumeMount{ + {Name: "cloud-credentials", MountPath: "/credentials"}, + }, + env: []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }, + }), + }, + { + name: "valid DPA CR with aws plugin from CloudStorage, NodeAgent DaemonSet is built", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, }, - Options: []corev1.PodDNSConfigOption{ - { - Name: "ndots", - Value: ptr.To("2"), + }, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, + }, + BackupLocations: []oadpv1alpha1.BackupLocation{ + { + CloudStorage: &oadpv1alpha1.CloudStorageLocation{ + CloudStorageRef: corev1.LocalObjectReference{ + Name: "bucket-123", }, - { - Name: "edns0", + Config: nil, + Credential: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "cloud-credentials", + }, + Key: "creds", }, + Default: false, + BackupSyncPeriod: &metav1.Duration{}, }, }, }, - }, &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), }, - }, - wantErr: false, + ), clientObjects: []client.Object{ - &configv1.Infrastructure{ + &oadpv1alpha1.CloudStorage{ ObjectMeta: metav1.ObjectMeta{ - Name: "cluster", + Name: "bucket-123", + Namespace: testNamespaceName, + }, + Spec: oadpv1alpha1.CloudStorageSpec{ + EnableSharedConfig: ptr.To(true), }, }, + testGenericInfrastructure, }, - want: &appsv1.DaemonSet{ - ObjectMeta: getNodeAgentObjectMeta(r), - TypeMeta: metav1.TypeMeta{ - Kind: "DaemonSet", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DaemonSetSpec{ - UpdateStrategy: appsv1.DaemonSetUpdateStrategy{ - Type: appsv1.RollingUpdateDaemonSetStrategyType, - }, - Selector: nodeAgentLabelSelector, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "component": common.Velero, - "name": common.NodeAgent, - }, - Annotations: map[string]string{ - "test-annotation": "awesome annotation", + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{}), + }, + { + name: "valid DPA CR with aws plugin and BSL, NodeAgent DaemonSet is built", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, }, }, - Spec: corev1.PodSpec{ - NodeSelector: dpa.Spec.Configuration.NodeAgent.PodConfig.NodeSelector, - ServiceAccountName: common.Velero, - SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: ptr.To(int64(0)), - SupplementalGroups: dpa.Spec.Configuration.NodeAgent.SupplementalGroups, - }, - DNSPolicy: "None", - DNSConfig: &corev1.PodDNSConfig{ - Nameservers: []string{ - "1.1.1.1", - "8.8.8.8", - }, - Options: []corev1.PodDNSConfigOption{ - { - Name: "ndots", - Value: ptr.To("2"), - }, - { - Name: "edns0", - }, - }, - }, - Volumes: []corev1.Volume{ - // Cloud Provider volumes are dynamically added in the for loop below - { - Name: HostPods, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: fsPvHostPath, - }, - }, - }, - { - Name: HostPlugins, - VolumeSource: corev1.VolumeSource{ - HostPath: &corev1.HostPathVolumeSource{ - Path: pluginsHostPath, - }, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, + }, + BackupLocations: []oadpv1alpha1.BackupLocation{ + { + Velero: &velerov1.BackupStorageLocationSpec{ + Provider: AWSProvider, + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + Bucket: "aws-bucket", }, }, - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, + Config: map[string]string{ + Region: "aws-region", + S3URL: "https://sr-url-aws-domain.com", + InsecureSkipTLSVerify: "false", }, - }, - Tolerations: dpa.Spec.Configuration.NodeAgent.PodConfig.Tolerations, - Containers: []corev1.Container{ - { - Name: common.NodeAgent, - SecurityContext: &corev1.SecurityContext{ - Privileged: ptr.To(true), - }, - Image: getVeleroImage(&dpa), - ImagePullPolicy: corev1.PullAlways, - Command: []string{ - "/velero", - }, - Args: []string{ - common.NodeAgent, - "server", - }, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - Protocol: "TCP", - }, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: HostPods, - MountPath: "/host_pods", - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: HostPlugins, - MountPath: pluginsHostPath, - MountPropagation: &mountPropagationToHostContainer, - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - { - Name: "cloud-credentials", - MountPath: "/credentials", - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Env: []corev1.EnvVar{ - { - Name: "NODE_NAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "spec.nodeName", - }, - }, - }, - { - Name: "VELERO_NAMESPACE", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: "VELERO_SCRATCH_DIR", - Value: "/scratch", - }, - { - Name: common.AWSSharedCredentialsFileEnvKey, - Value: "/credentials/cloud", - }, + Credential: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "cloud-credentials", }, }, }, }, }, }, - }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{}), + }, + { + name: "valid DPA CR with PodDNS Policy/Config, NodeAgent DaemonSet is built with DNS Policy/Config", + dpa: createTestDpaWith( + map[string]string{common.UnsupportedNodeAgentServerArgsAnnotation: ""}, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{}, + UploaderType: "kopia", + }, + }, + PodDnsPolicy: "None", + PodDnsConfig: corev1.PodDNSConfig{ + Nameservers: []string{"1.1.1.1", "8.8.8.8"}, + Options: []corev1.PodDNSConfigOption{ + {Name: "ndots", Value: ptr.To("2")}, + {Name: "edns0"}, + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + dnsPolicy: corev1.DNSNone, + dnsConfig: &corev1.PodDNSConfig{ + Nameservers: []string{"1.1.1.1", "8.8.8.8"}, + Options: []corev1.PodDNSConfigOption{ + {Name: "ndots", Value: ptr.To("2")}, + {Name: "edns0"}, + }, + }, + }), }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - fakeClient, err := getFakeClientFromObjects(tt.clientObjects...) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + fakeClient, err := getFakeClientFromObjects(test.clientObjects...) if err != nil { t.Errorf("error in creating fake client, likely programmer error") } - r := &DPAReconciler{ - Client: fakeClient, - } - got, err := r.buildNodeAgentDaemonset(tt.args.dpa, tt.args.ds) - if (err != nil) != tt.wantErr { - t.Errorf("DPAReconciler.buildNodeAgentDaemonset() error = %v, wantErr %v", err, tt.wantErr) - return - } - if tt.args.dpa != nil && tt.want != nil { - setPodTemplateSpecDefaults(&tt.want.Spec.Template) - if len(tt.want.Spec.Template.Spec.Containers) > 0 { - setContainerDefaults(&tt.want.Spec.Template.Spec.Containers[0]) - } - if tt.want.Spec.UpdateStrategy.Type == appsv1.RollingUpdateDaemonSetStrategyType { - tt.want.Spec.UpdateStrategy.RollingUpdate = &appsv1.RollingUpdateDaemonSet{ - MaxUnavailable: &intstr.IntOrString{ - Type: intstr.Int, - IntVal: 1, - }, - MaxSurge: &intstr.IntOrString{ - Type: intstr.Int, - IntVal: 0, - }, - } + r := &DPAReconciler{Client: fakeClient} + if result, err := r.buildNodeAgentDaemonset(test.dpa, test.nodeAgentDaemonSet); err != nil { + if test.errorMessage != err.Error() { + t.Errorf("buildNodeAgentDaemonset() error = %v, errorMessage %v", err, test.errorMessage) } - if tt.want.Spec.RevisionHistoryLimit == nil { - tt.want.Spec.RevisionHistoryLimit = ptr.To(int32(10)) + } else { + if !reflect.DeepEqual(test.wantNodeAgentDaemonSet, result) { + t.Errorf("expected NodeAgent DaemonSet diffs.\nDIFF:%v", cmp.Diff(test.wantNodeAgentDaemonSet, result)) } } - if !reflect.DeepEqual(got, tt.want) { - fmt.Printf(cmp.Diff(got, tt.want)) - t.Errorf("DPAReconciler.buildNodeAgentDaemonset() got = %v, want %v", got, tt.want) - } }) } } diff --git a/controllers/validator.go b/controllers/validator.go index fd1b285ee1..7135d99bac 100644 --- a/controllers/validator.go +++ b/controllers/validator.go @@ -61,13 +61,17 @@ func (r *DPAReconciler) ValidateDataProtectionCR(log logr.Logger) (bool, error) return false, err } + // TODO refactor to call functions only once + // they are called here to check error, and then after to get value if _, err := r.getVeleroResourceReqs(&dpa); err != nil { return false, err } - if _, err := getResticResourceReqs(&dpa); err != nil { return false, err } + if _, err := getNodeAgentResourceReqs(&dpa); err != nil { + return false, err + } // validate non-admin enable and tech-preview-ack if r.checkNonAdminEnabled(&dpa) { diff --git a/controllers/velero.go b/controllers/velero.go index d31c1a2424..d48cd8f044 100644 --- a/controllers/velero.go +++ b/controllers/velero.go @@ -61,6 +61,12 @@ var ( "app.kubernetes.io/component": Server, oadpv1alpha1.OadpOperatorLabel: "True", } + defaultContainerResourceRequirements = corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + } ) func (r *DPAReconciler) ReconcileVeleroDeployment(log logr.Logger) (bool, error) { @@ -671,174 +677,80 @@ func getAppLabels(instanceName string) map[string]string { return labels } -// Get Velero Resource Requirements -func (r *DPAReconciler) getVeleroResourceReqs(dpa *oadpv1alpha1.DataProtectionApplication) (corev1.ResourceRequirements, error) { - - // Set default values - ResourcesReqs := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - } - - if dpa != nil && dpa.Spec.Configuration != nil && dpa.Spec.Configuration.Velero != nil && dpa.Spec.Configuration.Velero.PodConfig != nil { - // Set custom limits and requests values if defined on VELERO Spec - if dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Requests.Cpu() != nil && dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Requests.Cpu().Value() != 0 { - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Requests.Cpu().String()) - ResourcesReqs.Requests[corev1.ResourceCPU] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } - } - - if dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Requests.Memory() != nil && dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Requests.Memory().Value() != 0 { - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Requests.Memory().String()) - ResourcesReqs.Requests[corev1.ResourceMemory] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } +// getResourceListFrom get the values of cpu, memory and ephemeral-storage from +// input into defaultResourceList. +func getResourceListFrom(input corev1.ResourceList, defaultResourceList corev1.ResourceList) (*corev1.ResourceList, error) { + if input.Cpu() != nil && input.Cpu().Value() != 0 { + parsedQuantity, err := resource.ParseQuantity(input.Cpu().String()) + if err != nil { + return nil, err } - - if dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Limits.Cpu() != nil && dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Limits.Cpu().Value() != 0 { - if ResourcesReqs.Limits == nil { - ResourcesReqs.Limits = corev1.ResourceList{} - } - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Limits.Cpu().String()) - ResourcesReqs.Limits[corev1.ResourceCPU] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } + defaultResourceList[corev1.ResourceCPU] = parsedQuantity + } + if input.Memory() != nil && input.Memory().Value() != 0 { + parsedQuantity, err := resource.ParseQuantity(input.Memory().String()) + if err != nil { + return nil, err } - - if dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Limits.Memory() != nil && dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Limits.Memory().Value() != 0 { - if ResourcesReqs.Limits == nil { - ResourcesReqs.Limits = corev1.ResourceList{} - } - parsedQuantiy, err := resource.ParseQuantity(dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations.Limits.Memory().String()) - ResourcesReqs.Limits[corev1.ResourceMemory] = parsedQuantiy - if err != nil { - return ResourcesReqs, err - } + defaultResourceList[corev1.ResourceMemory] = parsedQuantity + } + if input.StorageEphemeral() != nil && input.StorageEphemeral().Value() != 0 { + parsedQuantity, err := resource.ParseQuantity(input.StorageEphemeral().String()) + if err != nil { + return nil, err } - + defaultResourceList[corev1.ResourceEphemeralStorage] = parsedQuantity } - return ResourcesReqs, nil + return &defaultResourceList, nil } -// Get Restic Resource Requirements -func getResticResourceReqs(dpa *oadpv1alpha1.DataProtectionApplication) (corev1.ResourceRequirements, error) { - - // Set default values - ResourcesReqs := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - } - - if dpa != nil && dpa.Spec.Configuration != nil && dpa.Spec.Configuration.Restic != nil && dpa.Spec.Configuration.Restic.PodConfig != nil { - // Set custom limits and requests values if defined on Restic Spec - if dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Requests.Cpu() != nil && dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Requests.Cpu().Value() != 0 { - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Requests.Cpu().String()) - ResourcesReqs.Requests[corev1.ResourceCPU] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } - } +func getResourceReqs(dpa *corev1.ResourceRequirements) (corev1.ResourceRequirements, error) { + resourcesReqs := *defaultContainerResourceRequirements.DeepCopy() - if dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Requests.Memory() != nil && dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Requests.Memory().Value() != 0 { - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Requests.Memory().String()) - ResourcesReqs.Requests[corev1.ResourceMemory] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } + if dpa.Requests != nil { + requests, err := getResourceListFrom(dpa.Requests, resourcesReqs.Requests) + if err != nil { + return resourcesReqs, err } + resourcesReqs.Requests = *requests + } - if dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Limits.Cpu() != nil && dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Limits.Cpu().Value() != 0 { - if ResourcesReqs.Limits == nil { - ResourcesReqs.Limits = corev1.ResourceList{} - } - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Limits.Cpu().String()) - ResourcesReqs.Limits[corev1.ResourceCPU] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } + if dpa.Limits != nil { + limits, err := getResourceListFrom(dpa.Limits, corev1.ResourceList{}) + if err != nil { + return resourcesReqs, err } + resourcesReqs.Limits = *limits + } - if dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Limits.Memory() != nil && dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Limits.Memory().Value() != 0 { - if ResourcesReqs.Limits == nil { - ResourcesReqs.Limits = corev1.ResourceList{} - } - parsedQuantiy, err := resource.ParseQuantity(dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations.Limits.Memory().String()) - ResourcesReqs.Limits[corev1.ResourceMemory] = parsedQuantiy - if err != nil { - return ResourcesReqs, err - } - } + return resourcesReqs, nil +} +// Get Velero Resource Requirements +func (r *DPAReconciler) getVeleroResourceReqs(dpa *oadpv1alpha1.DataProtectionApplication) (corev1.ResourceRequirements, error) { + if dpa.Spec.Configuration.Velero != nil && dpa.Spec.Configuration.Velero.PodConfig != nil { + return getResourceReqs(&dpa.Spec.Configuration.Velero.PodConfig.ResourceAllocations) } + return *defaultContainerResourceRequirements.DeepCopy(), nil +} - return ResourcesReqs, nil +// Get Restic Resource Requirements +func getResticResourceReqs(dpa *oadpv1alpha1.DataProtectionApplication) (corev1.ResourceRequirements, error) { + if dpa.Spec.Configuration.Restic != nil && dpa.Spec.Configuration.Restic.PodConfig != nil { + return getResourceReqs(&dpa.Spec.Configuration.Restic.PodConfig.ResourceAllocations) + } + return *defaultContainerResourceRequirements.DeepCopy(), nil } // Get NodeAgent Resource Requirements // Separate function to getResticResourceReqs, so once Restic config is removed in the future // It will be easier to delete obsolete getResticResourceReqs func getNodeAgentResourceReqs(dpa *oadpv1alpha1.DataProtectionApplication) (corev1.ResourceRequirements, error) { - - // Set default values - ResourcesReqs := corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, + if dpa.Spec.Configuration.NodeAgent != nil && dpa.Spec.Configuration.NodeAgent.PodConfig != nil { + return getResourceReqs(&dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations) } - - if dpa != nil && dpa.Spec.Configuration != nil && dpa.Spec.Configuration.NodeAgent != nil && dpa.Spec.Configuration.NodeAgent.PodConfig != nil { - // Set custom limits and requests values if defined on NodeAgent Spec - if dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Requests.Cpu() != nil && dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Requests.Cpu().Value() != 0 { - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Requests.Cpu().String()) - ResourcesReqs.Requests[corev1.ResourceCPU] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } - } - - if dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Requests.Memory() != nil && dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Requests.Memory().Value() != 0 { - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Requests.Memory().String()) - ResourcesReqs.Requests[corev1.ResourceMemory] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } - } - - if dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Limits.Cpu() != nil && dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Limits.Cpu().Value() != 0 { - if ResourcesReqs.Limits == nil { - ResourcesReqs.Limits = corev1.ResourceList{} - } - parsedQuantity, err := resource.ParseQuantity(dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Limits.Cpu().String()) - ResourcesReqs.Limits[corev1.ResourceCPU] = parsedQuantity - if err != nil { - return ResourcesReqs, err - } - } - - if dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Limits.Memory() != nil && dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Limits.Memory().Value() != 0 { - if ResourcesReqs.Limits == nil { - ResourcesReqs.Limits = corev1.ResourceList{} - } - parsedQuantiy, err := resource.ParseQuantity(dpa.Spec.Configuration.NodeAgent.PodConfig.ResourceAllocations.Limits.Memory().String()) - ResourcesReqs.Limits[corev1.ResourceMemory] = parsedQuantiy - if err != nil { - return ResourcesReqs, err - } - } - - } - - return ResourcesReqs, nil + return *defaultContainerResourceRequirements.DeepCopy(), nil } // noDefaultCredentials determines if a provider needs the default credentials. diff --git a/controllers/velero_test.go b/controllers/velero_test.go index 9c06850c8e..6869d3a8bc 100644 --- a/controllers/velero_test.go +++ b/controllers/velero_test.go @@ -2,6 +2,7 @@ package controllers import ( "context" + "fmt" "os" "reflect" "slices" @@ -16,11 +17,11 @@ import ( "github.com/onsi/gomega" "github.com/operator-framework/operator-lib/proxy" "github.com/sirupsen/logrus" + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/tools/record" @@ -34,18 +35,22 @@ import ( ) const ( - proxyEnvKey = "HTTP_PROXY" - proxyEnvValue = "http://proxy.example.com:8080" - argsMetricsPortTest int32 = 69420 - defaultFileSystemBackupTimeout = "--fs-backup-timeout=4h" - defaultRestoreResourcePriorities = "--restore-resource-priorities=securitycontextconstraints,customresourcedefinitions,klusterletconfigs.config.open-cluster-management.io,managedcluster.cluster.open-cluster-management.io,namespaces,roles,rolebindings,clusterrolebindings,klusterletaddonconfig.agent.open-cluster-management.io,managedclusteraddon.addon.open-cluster-management.io,storageclasses,volumesnapshotclass.snapshot.storage.k8s.io,volumesnapshotcontents.snapshot.storage.k8s.io,volumesnapshots.snapshot.storage.k8s.io,datauploads.velero.io,persistentvolumes,persistentvolumeclaims,serviceaccounts,secrets,configmaps,limitranges,pods,replicasets.apps,clusterclasses.cluster.x-k8s.io,endpoints,services,-,clusterbootstraps.run.tanzu.vmware.com,clusters.cluster.x-k8s.io,clusterresourcesets.addons.cluster.x-k8s.io" - defaultDisableInformerCache = "--disable-informer-cache=false" + proxyEnvKey = "HTTP_PROXY" + proxyEnvValue = "http://proxy.example.com:8080" + argsMetricsPortTest = 69420 + defaultFileSystemBackupTimeout = "--fs-backup-timeout=4h" + defaultRestoreResourcePriorities = "--restore-resource-priorities=securitycontextconstraints,customresourcedefinitions,klusterletconfigs.config.open-cluster-management.io,managedcluster.cluster.open-cluster-management.io,namespaces,roles,rolebindings,clusterrolebindings,klusterletaddonconfig.agent.open-cluster-management.io,managedclusteraddon.addon.open-cluster-management.io,storageclasses,volumesnapshotclass.snapshot.storage.k8s.io,volumesnapshotcontents.snapshot.storage.k8s.io,volumesnapshots.snapshot.storage.k8s.io,datauploads.velero.io,persistentvolumes,persistentvolumeclaims,serviceaccounts,secrets,configmaps,limitranges,pods,replicasets.apps,clusterclasses.cluster.x-k8s.io,endpoints,services,-,clusterbootstraps.run.tanzu.vmware.com,clusters.cluster.x-k8s.io,clusterresourcesets.addons.cluster.x-k8s.io" + defaultDisableInformerCache = "--disable-informer-cache=false" + + testNamespaceName = "test-ns" + testDpaName = "test-DPA-CR" + testVeleroDeploymentName = "test-velero-deployment" ) var ( veleroDeploymentLabel = map[string]string{ "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", + "app.kubernetes.io/instance": testDpaName, "app.kubernetes.io/managed-by": common.OADPOperator, "app.kubernetes.io/component": Server, "component": "velero", @@ -62,12 +67,27 @@ var ( Labels: veleroDeploymentMatchLabels, Annotations: veleroPodAnnotations, } + + baseObjectMeta = metav1.ObjectMeta{ + Name: testVeleroDeploymentName, + Namespace: testNamespaceName, + Labels: veleroDeploymentLabel, + } + + baseTypeMeta = metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + } + baseEnvVars = []corev1.EnvVar{ {Name: common.VeleroScratchDirEnvKey, Value: "/scratch"}, { Name: common.VeleroNamespaceEnvKey, ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + FieldRef: &corev1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.namespace", + }, }, }, {Name: common.LDLibraryPathEnvKey, Value: "/plugins"}, @@ -110,6 +130,22 @@ var ( {MountPath: "/target", Name: "plugins"}, }, } + + allDefaultPluginsList = []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, + oadpv1alpha1.DefaultPluginGCP, + oadpv1alpha1.DefaultPluginMicrosoftAzure, + oadpv1alpha1.DefaultPluginKubeVirt, + oadpv1alpha1.DefaultPluginOpenShift, + oadpv1alpha1.DefaultPluginCSI, + } + + testVeleroDeployment = &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: testVeleroDeploymentName, + Namespace: testNamespaceName, + }, + } ) type ReconcileVeleroControllerScenario struct { @@ -273,140 +309,238 @@ func pluginContainer(name, image string) corev1.Container { return container } -func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { - type fields struct { - Client client.Client - Scheme *runtime.Scheme - Log logr.Logger - Context context.Context - NamespacedName types.NamespacedName - EventRecorder record.EventRecorder +func deploymentVolumeSecret(name string) corev1.Volume { + return corev1.Volume{ + Name: name, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: name, + DefaultMode: ptr.To(int32(420)), + }, + }, + } +} + +func createTestDpaWith( + dpaAnnotations map[string]string, + dpaSpec oadpv1alpha1.DataProtectionApplicationSpec, +) *oadpv1alpha1.DataProtectionApplication { + return &oadpv1alpha1.DataProtectionApplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: testDpaName, + Namespace: testNamespaceName, + Annotations: dpaAnnotations, + }, + Spec: dpaSpec, + } +} + +type TestBuiltVeleroDeploymentOptions struct { + args []string + customLabels map[string]string + labels map[string]string + annotations map[string]string + metricsPort int + initContainers []corev1.Container + volumes []corev1.Volume + volumeMounts []corev1.VolumeMount + env []corev1.EnvVar + dnsPolicy corev1.DNSPolicy + dnsConfig *corev1.PodDNSConfig + resourceLimits corev1.ResourceList + resourceRequests corev1.ResourceList + toleration []corev1.Toleration + nodeSelector map[string]string +} + +func createTestBuiltVeleroDeployment(options TestBuiltVeleroDeploymentOptions) *appsv1.Deployment { + testBuiltVeleroDeployment := &appsv1.Deployment{ + ObjectMeta: baseObjectMeta, + TypeMeta: baseTypeMeta, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + Replicas: ptr.To(int32(1)), + Strategy: appsv1.DeploymentStrategy{ + Type: appsv1.RollingUpdateDeploymentStrategyType, + RollingUpdate: &appsv1.RollingUpdateDeployment{ + MaxUnavailable: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, + MaxSurge: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, + }, + }, + RevisionHistoryLimit: ptr.To(int32(10)), + ProgressDeadlineSeconds: ptr.To(int32(600)), + Template: corev1.PodTemplateSpec{ + ObjectMeta: veleroPodObjectMeta, + Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, + ServiceAccountName: common.Velero, + TerminationGracePeriodSeconds: ptr.To(int64(30)), + DNSPolicy: corev1.DNSClusterFirst, + DeprecatedServiceAccount: common.Velero, + SecurityContext: &corev1.PodSecurityContext{}, + SchedulerName: "default-scheduler", + Containers: []corev1.Container{ + { + Name: common.Velero, + Image: common.VeleroImage, + ImagePullPolicy: corev1.PullAlways, + TerminationMessagePath: "/dev/termination-log", + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + Ports: []corev1.ContainerPort{{ + Name: "metrics", + ContainerPort: 8085, + Protocol: corev1.ProtocolTCP, + }}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + Command: []string{"/velero"}, + Args: append([]string{"server"}, options.args...), + VolumeMounts: baseVolumeMounts, + Env: baseEnvVars, + }, + }, + Volumes: baseVolumes, + InitContainers: []corev1.Container{}, + }, + }, + }, + } + + if options.customLabels != nil { + testBuiltVeleroDeployment.Labels = common.AppendTTMapAsCopy(testBuiltVeleroDeployment.Labels, options.customLabels) + testBuiltVeleroDeployment.Spec.Selector.MatchLabels = common.AppendTTMapAsCopy(testBuiltVeleroDeployment.Spec.Selector.MatchLabels, options.customLabels) + testBuiltVeleroDeployment.Spec.Template.Labels = common.AppendTTMapAsCopy(testBuiltVeleroDeployment.Spec.Template.Labels, options.customLabels) + } + + if options.labels != nil { + testBuiltVeleroDeployment.Spec.Template.Labels = common.AppendTTMapAsCopy(testBuiltVeleroDeployment.Spec.Template.Labels, options.labels) + } + + if options.annotations != nil { + testBuiltVeleroDeployment.Spec.Template.Annotations = common.AppendTTMapAsCopy(testBuiltVeleroDeployment.Spec.Template.Annotations, options.annotations) + } + + if options.initContainers != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.InitContainers = options.initContainers + } + + if options.volumes != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.Volumes = append(baseVolumes, options.volumes...) + } + + if options.volumeMounts != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.Containers[0].VolumeMounts = append(baseVolumeMounts, options.volumeMounts...) + } + + if options.env != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.Containers[0].Env = options.env + } + + if options.resourceLimits != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.Containers[0].Resources.Limits = options.resourceLimits + } + + if options.resourceRequests != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.Containers[0].Resources.Requests = options.resourceRequests + } + + if options.toleration != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.Tolerations = options.toleration + } + + if options.nodeSelector != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.NodeSelector = options.nodeSelector + } + + if options.metricsPort != 0 { + testBuiltVeleroDeployment.Spec.Template.Annotations = common.AppendTTMapAsCopy(testBuiltVeleroDeployment.Spec.Template.Annotations, map[string]string{"prometheus.io/port": strconv.Itoa(options.metricsPort)}) + testBuiltVeleroDeployment.Spec.Template.Spec.Containers[0].Ports[0].ContainerPort = int32(options.metricsPort) + } + + if len(options.dnsPolicy) > 0 { + testBuiltVeleroDeployment.Spec.Template.Spec.DNSPolicy = options.dnsPolicy + } + + if options.dnsConfig != nil { + testBuiltVeleroDeployment.Spec.Template.Spec.DNSConfig = options.dnsConfig } - trueVal := true + return testBuiltVeleroDeployment +} + +func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { tests := []struct { name string - fields fields - veleroDeployment *appsv1.Deployment dpa *oadpv1alpha1.DataProtectionApplication - wantErr bool - wantVeleroDeployment *appsv1.Deployment - clientObjects []client.Object testProxy bool + clientObjects []client.Object + veleroDeployment *appsv1.Deployment + wantVeleroDeployment *appsv1.Deployment + errorMessage string }{ { - name: "DPA CR is nil", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: veleroLabelSelector, - }, - }, - dpa: nil, - wantErr: true, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: veleroLabelSelector, - }, - }, + name: "DPA CR is nil, error is returned", + errorMessage: "DPA CR cannot be nil", }, { - name: "Velero Deployment is nil", - veleroDeployment: nil, - dpa: &oadpv1alpha1.DataProtectionApplication{}, - wantErr: true, - wantVeleroDeployment: nil, + name: "Velero Deployment is nil, error is returned", + dpa: &oadpv1alpha1.DataProtectionApplication{}, + errorMessage: "velero deployment cannot be nil", }, { - name: "given valid DPA CR, appropriate Velero Deployment is built", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR, Velero Deployment is built with default args", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{}, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR with PodConfig Env, appropriate Velero Deployment is built", + name: "valid DPA CR, Velero Deployment is built with custom labels", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + }, + ), veleroDeployment: &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + Name: testVeleroDeploymentName, + Namespace: testNamespaceName, + Labels: map[string]string{"foo": "bar"}, }, }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + customLabels: map[string]string{"foo": "bar"}, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with PodConfig Env, Velero Deployment is built with Container Env", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ @@ -417,366 +551,172 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: []corev1.EnvVar{ - {Name: common.VeleroScratchDirEnvKey, Value: "/scratch"}, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - {Name: common.LDLibraryPathEnvKey, Value: "/plugins"}, - {Name: "TEST_ENV", Value: "TEST_VALUE"}, - {Name: "OPENSHIFT_IMAGESTREAM_BACKUP", Value: "true"}, - }, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + env: slices.Insert(baseEnvVars, 3, []corev1.EnvVar{{Name: "TEST_ENV", Value: "TEST_VALUE"}}...), + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR, noDefaultBackupLocation, unsupportedOverrides operatorType MTC, vel deployment has secret volumes", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with proxy Env, Velero Deployment is built with Container Env", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - NoDefaultBackupLocation: true, - DefaultPlugins: allDefaultPluginsList, - }, - }, - UnsupportedOverrides: map[oadpv1alpha1.UnsupportedImageKey]string{ - oadpv1alpha1.OperatorTypeKey: oadpv1alpha1.OperatorTypeMTC, + Velero: &oadpv1alpha1.VeleroConfig{}, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--features=EnableCSI", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: append(baseVolumeMounts, []corev1.VolumeMount{ - {Name: "cloud-credentials", MountPath: "/credentials"}, - {Name: "cloud-credentials-gcp", MountPath: "/credentials-gcp"}, - {Name: "cloud-credentials-azure", MountPath: "/credentials-azure"}, - }...), - Env: append(baseEnvVars, []corev1.EnvVar{ - {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, - {Name: common.GCPCredentialsEnvKey, Value: "/credentials-gcp/cloud"}, - {Name: common.AzureCredentialsFileEnvKey, Value: "/credentials-azure/cloud"}, - }...), - }, - }, - Volumes: append(baseVolumes, []corev1.Volume{ - { - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }, - { - Name: "cloud-credentials-gcp", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials-gcp", - }, - }, - }, - { - Name: "cloud-credentials-azure", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials-azure", - }, - }, - }, - }...), - InitContainers: []corev1.Container{ - pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), - pluginContainer(common.VeleroPluginForGCP, common.GCPPluginImage), - pluginContainer(common.VeleroPluginForAzure, common.AzurePluginImage), - pluginContainer(common.KubeVirtPlugin, common.KubeVirtPluginImage), - pluginContainer(common.VeleroPluginForOpenshift, common.OpenshiftPluginImage), - }, - }, - }, + ), + testProxy: true, + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + env: slices.Insert(baseEnvVars, 3, []corev1.EnvVar{ + {Name: proxyEnvKey, Value: proxyEnvValue}, + {Name: strings.ToLower(proxyEnvKey), Value: proxyEnvValue}, + }...), + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR with proxy env var, appropriate Velero Deployment is built", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - testProxy: true, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with PodConfig label, Velero Deployment is built with template labels", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{}, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - - Env: []corev1.EnvVar{ - {Name: common.VeleroScratchDirEnvKey, Value: "/scratch"}, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - {Name: common.LDLibraryPathEnvKey, Value: "/plugins"}, - {Name: proxyEnvKey, Value: proxyEnvValue}, - {Name: strings.ToLower(proxyEnvKey), Value: proxyEnvValue}, - {Name: "OPENSHIFT_IMAGESTREAM_BACKUP", Value: "true"}, - }, + Velero: &oadpv1alpha1.VeleroConfig{ + PodConfig: &oadpv1alpha1.PodConfig{ + Labels: map[string]string{ + "thisIsVelero": "yes", }, }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, }, }, }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + labels: map[string]string{"thisIsVelero": "yes"}, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), }, { - name: "given valid DPA CR with podConfig label, appropriate Velero Deployment has template labels", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "invalid DPA CR with podConfig label, error is returned", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ Labels: map[string]string{ - "thisIsVelero": "yes", - }, - }, - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: common.AppendTTMapAsCopy(veleroDeploymentMatchLabels, - map[string]string{ - "thisIsVelero": "yes", - }), - Annotations: veleroPodAnnotations, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, + "component": common.NodeAgent, }, }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, }, }, }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + errorMessage: "velero deployment template custom label: conflicting key component with value node-agent may not override velero", }, { - name: "given valid DPA CR with Unsupported Server Args, appropriate Velero Deployment is built", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", + name: "valid DPA CR with Pod annotations, Velero Deployment is built with template annotations", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + PodAnnotations: map[string]string{ + "test-annotation": "awesome annotation", + }, }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + annotations: map[string]string{"test-annotation": "awesome annotation"}, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - Annotations: map[string]string{ - "oadp.openshift.io/unsupported-velero-server-args": "unsupported-server-args-cm", + }), + }, + { + name: "valid DPA CR with noDefaultBackupLocation, all default plugins and unsupportedOverrides operatorType MTC, Velero Deployment is built with secret volumes", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + NoDefaultBackupLocation: true, + DefaultPlugins: allDefaultPluginsList, + }, + }, + UnsupportedOverrides: map[oadpv1alpha1.UnsupportedImageKey]string{ + oadpv1alpha1.OperatorTypeKey: oadpv1alpha1.OperatorTypeMTC, }, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + initContainers: []corev1.Container{ + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), + pluginContainer(common.VeleroPluginForGCP, common.GCPPluginImage), + pluginContainer(common.VeleroPluginForAzure, common.AzurePluginImage), + pluginContainer(common.KubeVirtPlugin, common.KubeVirtPluginImage), + pluginContainer(common.VeleroPluginForOpenshift, common.OpenshiftPluginImage), + }, + volumes: []corev1.Volume{ + deploymentVolumeSecret("cloud-credentials"), + deploymentVolumeSecret("cloud-credentials-gcp"), + deploymentVolumeSecret("cloud-credentials-azure"), + }, + volumeMounts: []corev1.VolumeMount{ + {Name: "cloud-credentials", MountPath: "/credentials"}, + {Name: "cloud-credentials-gcp", MountPath: "/credentials-gcp"}, + {Name: "cloud-credentials-azure", MountPath: "/credentials-azure"}, + }, + env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + {Name: common.GCPCredentialsEnvKey, Value: "/credentials-gcp/cloud"}, + {Name: common.AzureCredentialsFileEnvKey, Value: "/credentials-azure/cloud"}, + }...), + args: []string{ + "--features=EnableCSI", + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), + }, + { + name: "valid DPA CR with Unsupported Server Args, Velero Deployment is built with Unsupported Server Args", + dpa: createTestDpaWith( + map[string]string{common.UnsupportedVeleroServerArgsAnnotation: "unsupported-server-args-cm"}, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{}, }, }, - }, + ), clientObjects: []client.Object{ &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "unsupported-server-args-cm", - Namespace: "test-ns", + Namespace: testNamespaceName, }, Data: map[string]string{ "unsupported-arg": "value1", @@ -784,82 +724,52 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: veleroPodAnnotations, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--unsupported-arg=value1", - "--unsupported-bool-arg=true", - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + "--unsupported-arg=value1", + "--unsupported-bool-arg=true", }, - }, + }), }, { - name: "given valid DPA CR with Empty String Unsupported Server Args Annotation, appropriate Velero Deployment is built", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - Annotations: map[string]string{ - "oadp.openshift.io/unsupported-velero-server-args": "", + name: "valid DPA CR with Empty String Unsupported Server Args, Velero Deployment is built with default args", + dpa: createTestDpaWith( + map[string]string{common.UnsupportedVeleroServerArgsAnnotation: ""}, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, }, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), + }, + { + name: "valid DPA CR with Unsupported Server Args and multiple options, Velero Deployment is built with Unsupported Server Args only", + dpa: createTestDpaWith( + map[string]string{common.UnsupportedVeleroServerArgsAnnotation: "unsupported-server-args-cm"}, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{}, + Velero: &oadpv1alpha1.VeleroConfig{ + DisableInformerCache: ptr.To(true), + DefaultSnapshotMoveData: ptr.To(true), + ItemOperationSyncFrequency: "7m", + }, }, }, - }, + ), clientObjects: []client.Object{ &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "unsupported-server-args-cm", - Namespace: "test-ns", + Namespace: testNamespaceName, }, Data: map[string]string{ "unsupported-arg": "value1", @@ -867,2496 +777,327 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: veleroPodAnnotations, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + "--unsupported-arg=value1", + "--unsupported-bool-arg=true", }, - }, + }), }, { - name: "given valid DPA CR with Unsupported Server Args and user added args, appropriate Velero Deployment is built", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - Annotations: map[string]string{ - "oadp.openshift.io/unsupported-velero-server-args": "unsupported-server-args-cm", - }, - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - Args: &server.Args{ - ServerConfig: server.ServerConfig{ - BackupSyncPeriod: ptr.To(time.Duration(1)), - PodVolumeOperationTimeout: ptr.To(time.Duration(1)), - ResourceTerminatingTimeout: ptr.To(time.Duration(1)), - DefaultBackupTTL: ptr.To(time.Duration(1)), - StoreValidationFrequency: ptr.To(time.Duration(1)), - ItemOperationSyncFrequency: ptr.To(time.Duration(1)), - RepoMaintenanceFrequency: ptr.To(time.Duration(1)), - GarbageCollectionFrequency: ptr.To(time.Duration(1)), - DefaultItemOperationTimeout: ptr.To(time.Duration(1)), - ResourceTimeout: ptr.To(time.Duration(1)), - }, - }, - }, - }, - }, - }, - clientObjects: []client.Object{ - &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "unsupported-server-args-cm", - Namespace: "test-ns", - }, - Data: map[string]string{ - "unsupported-arg": "value1", - "unsupported-bool-arg": "True", - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: veleroPodAnnotations, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--unsupported-arg=value1", - "--unsupported-bool-arg=true", - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR with Unsupported Server Args and missing ConfigMap, appropriate Velero Deployment is nil with error", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - Annotations: map[string]string{ - "oadp.openshift.io/unsupported-velero-server-args": "missing-unsupported-server-args-cm", - }, - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Unsupported Server Args and missing ConfigMap, error is returned", + dpa: createTestDpaWith( + map[string]string{"oadp.openshift.io/unsupported-velero-server-args": "missing-unsupported-server-args-cm"}, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{}, }, }, - }, - wantErr: true, - wantVeleroDeployment: nil, - }, - { - name: "given invalid DPA CR because invalid podConfig label, appropriate Velero Deployment is nil with error", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{ - Labels: map[string]string{ - "component": common.NodeAgent, - }, - }, - }, - }, - }, - }, - wantErr: true, - wantVeleroDeployment: nil, - }, - { - name: "given valid DPA CR and ItemOperationSyncFrequency is defined correctly, ItemOperationSyncFrequency is set", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR and Velero Config is defined correctly, SnapshotMovedata is set to false", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", - DefaultSnapshotMoveData: ptr.To(false), - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-snapshot-move-data=false", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR and Velero Config is defined correctly, defaultSnapshotMovedata is set to true", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", - DefaultSnapshotMoveData: ptr.To(true), - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-snapshot-move-data=true", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR and Velero Config is defined correctly, defaultVolumesToFSBackup is set to true", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", - DefaultVolumesToFSBackup: ptr.To(true), - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-volumes-to-fs-backup=true", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR and Velero Config is defined correctly, disableInformerCache is nil and default behaviour of false is supplied to velero", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", - DefaultVolumesToFSBackup: ptr.To(false), - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-volumes-to-fs-backup=false", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, - }, - }, - }, - { - name: "given valid DPA CR and Velero Config is defined correctly, disableInformerCache is set to true", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", - DefaultVolumesToFSBackup: ptr.To(false), - DisableInformerCache: ptr.To(true), - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-volumes-to-fs-backup=false", - "--disable-informer-cache=true", - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + errorMessage: "configmaps \"missing-unsupported-server-args-cm\" not found", }, { - name: "given valid DPA CR and Velero Config is defined correctly, disableInformerCache is set to false", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with ItemOperationSyncFrequency, Velero Deployment is built with ItemOperationSyncFrequency arg", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", - DefaultVolumesToFSBackup: ptr.To(false), - DisableInformerCache: ptr.To(false), + ItemOperationSyncFrequency: "5m", }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-volumes-to-fs-backup=false", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--item-operation-sync-frequency=5m", + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR and Velero Config is defined correctly, defaultVolumesToFSBackup is set to false", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with multiple options, Velero Deployment is built with multiple Args", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ LogLevel: logrus.InfoLevel.String(), ItemOperationSyncFrequency: "5m", DefaultItemOperationTimeout: "2h", - DefaultVolumesToFSBackup: ptr.To(false), + DefaultSnapshotMoveData: ptr.To(false), + NoDefaultBackupLocation: true, + DefaultVolumesToFSBackup: ptr.To(true), + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{oadpv1alpha1.DefaultPluginCSI}, }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-volumes-to-fs-backup=false", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + "--features=EnableCSI", + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--log-level", + logrus.InfoLevel.String(), + "--item-operation-sync-frequency=5m", + "--default-item-operation-timeout=2h", + "--default-snapshot-move-data=false", + "--default-volumes-to-fs-backup=true", + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR and Velero Config is defined correctly, defaultVolumesToFSBackup is set to false, snapshotMoveData is true", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with SnapshotMovedata false, Velero Deployment is built with SnapshotMovedata false", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", - DefaultVolumesToFSBackup: ptr.To(false), - DefaultSnapshotMoveData: ptr.To(true), + DefaultSnapshotMoveData: ptr.To(false), }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - "--default-snapshot-move-data=true", - "--default-volumes-to-fs-backup=false", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--default-snapshot-move-data=false", + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR and DefaultItemOperationTimeout is defined correctly, DefaultItemOperationTimeout is set", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", + name: "valid DPA CR with SnapshotMovedata true, Velero Deployment is built with SnapshotMovedata true", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + DefaultSnapshotMoveData: ptr.To(true), }, }, }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--default-snapshot-move-data=true", + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with DefaultVolumesToFSBackup true, Velero Deployment is built with DefaultVolumesToFSBackup true", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ItemOperationSyncFrequency: "5m", - DefaultItemOperationTimeout: "2h", + DefaultVolumesToFSBackup: ptr.To(true), }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--item-operation-sync-frequency=5m", - "--default-item-operation-timeout=2h", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--default-volumes-to-fs-backup=true", + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR and log level is defined correctly, log level is set", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with DisableInformerCache true, Velero Deployment is built with DisableInformerCache true", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), + DisableInformerCache: ptr.To(true), }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--disable-informer-cache=true", }, - }, + }), }, { - name: "given valid DPA CR and ResourceTimeout is defined correctly, ResourceTimeout is set", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", + name: "valid DPA CR with DisableInformerCache false, Velero Deployment is built with DisableInformerCache false", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + DisableInformerCache: ptr.To(false), }, }, }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with DefaultItemOperationTimeout, Velero Deployment is built with DefaultItemOperationTimeout arg", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - LogLevel: logrus.InfoLevel.String(), - ResourceTimeout: "5m", + DefaultItemOperationTimeout: "2h", }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--default-item-operation-timeout=2h", + defaultDisableInformerCache, }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - }, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - "component": "velero", - "deploy": "velero", - oadpv1alpha1.OadpOperatorLabel: "True", - }, - Annotations: map[string]string{ - "prometheus.io/scrape": "true", - "prometheus.io/port": "8085", - "prometheus.io/path": "/metrics", - }, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{ - { - Name: "metrics", - ContainerPort: 8085, - }, - }, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--log-level", - logrus.InfoLevel.String(), - "--resource-timeout=5m", - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "plugins", - MountPath: "/plugins", - }, - { - Name: "scratch", - MountPath: "/scratch", - }, - { - Name: "certs", - MountPath: "/etc/ssl/certs", - }, - }, - Env: []corev1.EnvVar{ - { - Name: common.VeleroScratchDirEnvKey, - Value: "/scratch", - }, - { - Name: common.VeleroNamespaceEnvKey, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "metadata.namespace", - }, - }, - }, - { - Name: common.LDLibraryPathEnvKey, - Value: "/plugins", - }, - { - Name: "OPENSHIFT_IMAGESTREAM_BACKUP", - Value: "true", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "plugins", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "scratch", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - { - Name: "certs", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - InitContainers: []corev1.Container{}, + }), + }, + { + name: "valid DPA CR with log level, Velero Deployment is built with log level arg", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + LogLevel: logrus.InfoLevel.String(), }, }, }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--log-level", + logrus.InfoLevel.String(), + defaultDisableInformerCache, + }, + }), }, { - name: "given valid DPA CR and log level is defined incorrectly error is returned", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "invalid DPA CR with log level, error is returned", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ LogLevel: logrus.InfoLevel.String() + "typo", }, }, }, - }, - wantErr: true, - wantVeleroDeployment: nil, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + errorMessage: "invalid log level infotypo, use: trace, debug, info, warning, error, fatal, or panic", }, { - name: "given valid DPA CR, velero deployment resource customization", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with ResourceTimeout, Velero Deployment is built with ResourceTimeout arg", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - PodConfig: &oadpv1alpha1.PodConfig{ - ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - }, + ResourceTimeout: "5m", }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--resource-timeout=5m", + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR, velero deployment resource customization only cpu limit", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero resource allocations, Velero Deployment is built with resource allocations", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - }, - }, - }, - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("400Mi"), }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, }, }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, }, }, }, - }, - }, - { - name: "given valid DPA CR, velero deployment resource customization only cpu request", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("700Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("400Mi"), }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with Velero cpu limit, Velero Deployment is built with cpu limit", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ + Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("2"), }, }, @@ -3364,160 +1105,55 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), }, - }, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), }, { - name: "given valid DPA CR, velero deployment resource customization only memory request", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero cpu request, Velero Deployment is built with cpu request", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("256Mi"), + corev1.ResourceCPU: resource.MustParse("2"), }, }, }, }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("128Mi"), }, - }, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), }, { - name: "given valid DPA CR, velero deployment resource customization only memory limit", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero memory limit, Velero Deployment is built with memory limit", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ @@ -3530,569 +1166,179 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("128Mi"), }, - }, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), }, { - name: "given valid DPA CR, velero deployment tolerations", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero memory request, Velero Deployment is built with memory request", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), corev1.ResourceMemory: resource.MustParse("256Mi"), }, }, - Tolerations: []corev1.Toleration{ - { - Key: "key1", - Operator: "Equal", - Value: "value1", - Effect: "NoSchedule", - }, - }, }, }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("256Mi"), }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: veleroPodAnnotations, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Tolerations: []corev1.Toleration{ - { - Key: "key1", - Operator: "Equal", - Value: "value1", - Effect: "NoSchedule", - }, - }, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR, velero deployment nodeselector", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero ephemeral-storage limit, Velero Deployment is built with ephemeral-storage limit", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ PodConfig: &oadpv1alpha1.PodConfig{ ResourceAllocations: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - NodeSelector: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: map[string]string{ - "app.kubernetes.io/name": common.Velero, - "app.kubernetes.io/instance": "test-Velero-CR", - "app.kubernetes.io/managed-by": common.OADPOperator, - "app.kubernetes.io/component": Server, - oadpv1alpha1.OadpOperatorLabel: "True", - "component": "velero", - }, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: veleroPodAnnotations, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - NodeSelector: map[string]string{ - "foo": "bar", - }, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("700Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("1"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - }, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, + corev1.ResourceEphemeralStorage: resource.MustParse("400Mi"), }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, }, }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, }, }, }, - }, - }, - { - name: "given valid DPA CR, appropriate velero deployment is build with aws plugin specific specs", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + resourceLimits: corev1.ResourceList{ + corev1.ResourceEphemeralStorage: resource.MustParse("400Mi"), }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - }, - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: append(baseVolumeMounts, []corev1.VolumeMount{ - {Name: "cloud-credentials", MountPath: "/credentials"}, - }...), - Env: append(baseEnvVars, []corev1.EnvVar{ - {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, - }...), - }, - }, - Volumes: append(baseVolumes, []corev1.Volume{{ - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }}...), - InitContainers: []corev1.Container{ - pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), - }, - }, - }, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - }, + }), }, { - name: "given valid DPA CR, appropriate velero deployment is build with aws and kubevirt plugin specific specs", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ - Configuration: &oadpv1alpha1.ApplicationConfig{ - Velero: &oadpv1alpha1.VeleroConfig{ - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - oadpv1alpha1.DefaultPluginKubeVirt, - }, - }, - }, - }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - {Name: "plugins", MountPath: "/plugins"}, - {Name: "scratch", MountPath: "/scratch"}, - {Name: "certs", MountPath: "/etc/ssl/certs"}, - {Name: "cloud-credentials", MountPath: "/credentials"}, - }, - Env: append(baseEnvVars, []corev1.EnvVar{ - {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, - }...), - }, - }, - Volumes: append(baseVolumes, []corev1.Volume{{ - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", + name: "valid DPA CR with Velero ephemeral-storage request, Velero Deployment is built with ephemeral-storage request", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + PodConfig: &oadpv1alpha1.PodConfig{ + ResourceAllocations: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, }, - }}...), - InitContainers: []corev1.Container{ - pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), - pluginContainer(common.KubeVirtPlugin, common.KubeVirtPluginImage), }, }, }, }, - }, - }, - { - name: "given valid DPA CR with annotations, appropriate velero deployment is build with aws plugin specific specs", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + resourceRequests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + corev1.ResourceEphemeralStorage: resource.MustParse("300Mi"), }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with Velero tolerations, Velero Deployment is built with tolerations", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, + PodConfig: &oadpv1alpha1.PodConfig{ + Tolerations: []corev1.Toleration{ + { + Key: "key1", + Operator: "Equal", + Value: "value1", + Effect: "NoSchedule", + }, + }, }, }, }, - PodAnnotations: map[string]string{ - "test-annotation": "awesome annotation", + }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + toleration: []corev1.Toleration{ + { + Key: "key1", + Operator: "Equal", + Value: "value1", + Effect: "NoSchedule", }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: common.AppendTTMapAsCopy(veleroPodAnnotations, - map[string]string{ - "test-annotation": "awesome annotation", - }, - ), - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - {Name: "plugins", MountPath: "/plugins"}, - {Name: "scratch", MountPath: "/scratch"}, - {Name: "certs", MountPath: "/etc/ssl/certs"}, - {Name: "cloud-credentials", MountPath: "/credentials"}, - }, - Env: append(baseEnvVars, []corev1.EnvVar{ - {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, - }...), - }, - }, - Volumes: append(baseVolumes, []corev1.Volume{{ - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }}...), - InitContainers: []corev1.Container{ - pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), + }, + { + name: "valid DPA CR with Velero nodeselector, Velero Deployment is built with nodeselector", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + PodConfig: &oadpv1alpha1.PodConfig{ + NodeSelector: map[string]string{"foo": "bar"}, }, }, }, }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + nodeSelector: map[string]string{"foo": "bar"}, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), }, { - name: "given valid DPA CR with PodDNS Policy/Config, annotations, appropriate velero deployment is build with aws plugin specific specs", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with aws plugin, Velero Deployment is built with aws plugin", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ @@ -4100,118 +1346,65 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - PodAnnotations: map[string]string{ - "test-annotation": "awesome annotation", - }, - PodDnsPolicy: "None", - PodDnsConfig: corev1.PodDNSConfig{ - Nameservers: []string{ - "1.1.1.1", - "8.8.8.8", - }, - Options: []corev1.PodDNSConfigOption{ - {Name: "ndots", Value: ptr.To("2")}, - { - Name: "edns0", - }, - }, - }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: common.AppendTTMapAsCopy(veleroPodAnnotations, - map[string]string{ - "test-annotation": "awesome annotation", - }, - ), - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - DNSPolicy: "None", - DNSConfig: &corev1.PodDNSConfig{ - Nameservers: []string{"1.1.1.1", "8.8.8.8"}, - Options: []corev1.PodDNSConfigOption{ - {Name: "ndots", Value: ptr.To("2")}, - { - Name: "edns0", - }, - }, - }, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - {Name: "plugins", MountPath: "/plugins"}, - {Name: "scratch", MountPath: "/scratch"}, - {Name: "certs", MountPath: "/etc/ssl/certs"}, - {Name: "cloud-credentials", MountPath: "/credentials"}, - }, - Env: append(baseEnvVars, []corev1.EnvVar{ - {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, - }...), - }, - }, - Volumes: append(baseVolumes, []corev1.Volume{{ - Name: "cloud-credentials", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: "cloud-credentials", - }, - }, - }}...), - InitContainers: []corev1.Container{ - pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + initContainers: []corev1.Container{pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage)}, + volumes: []corev1.Volume{deploymentVolumeSecret("cloud-credentials")}, + volumeMounts: []corev1.VolumeMount{ + {Name: "cloud-credentials", MountPath: "/credentials"}, + }, + env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }...), + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), + }, + { + name: "valid DPA CR with aws and kubevirt plugin, Velero Deployment is built with aws and kubevirt plugin", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, + oadpv1alpha1.DefaultPluginKubeVirt, }, }, }, }, - }, - }, - { - name: "given valid Velero CR with with aws plugin from bucket", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + initContainers: []corev1.Container{ + pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), + pluginContainer(common.KubeVirtPlugin, common.KubeVirtPluginImage), }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + volumes: []corev1.Volume{deploymentVolumeSecret("cloud-credentials")}, + volumeMounts: []corev1.VolumeMount{ + {Name: "cloud-credentials", MountPath: "/credentials"}, }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + env: append(baseEnvVars, []corev1.EnvVar{ + {Name: common.AWSSharedCredentialsFileEnvKey, Value: "/credentials/cloud"}, + }...), + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with aws plugin from CloudStorage, Velero Deployment is built with aws plugin", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ @@ -4225,7 +1418,7 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { CloudStorageRef: corev1.LocalObjectReference{ Name: "bucket-123", }, - Config: map[string]string{}, + Config: nil, Credential: &corev1.SecretKeySelector{ LocalObjectReference: corev1.LocalObjectReference{ Name: "cloud-credentials", @@ -4238,255 +1431,188 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - wantErr: false, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: []corev1.VolumeMount{ - {Name: "plugins", MountPath: "/plugins"}, - {Name: "scratch", MountPath: "/scratch"}, - {Name: "certs", MountPath: "/etc/ssl/certs"}, - { - Name: "bound-sa-token", - MountPath: "/var/run/secrets/openshift/serviceaccount", - ReadOnly: true, - }, - }, - Env: baseEnvVars, - }, - }, - Volumes: append(baseVolumes, []corev1.Volume{ - { - Name: "bound-sa-token", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - DefaultMode: ptr.To(int32(420)), - Sources: []corev1.VolumeProjection{ - { - ServiceAccountToken: &corev1.ServiceAccountTokenProjection{ - Audience: "openshift", - ExpirationSeconds: ptr.To(int64(3600)), - Path: "token", - }, - }, - }, - }, - }, - }}...), - InitContainers: []corev1.Container{ - pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage), - }, - }, - }, - }, - }, + ), clientObjects: []client.Object{ &oadpv1alpha1.CloudStorage{ ObjectMeta: metav1.ObjectMeta{ Name: "bucket-123", - Namespace: "test-ns", + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.CloudStorageSpec{ - EnableSharedConfig: &trueVal, + EnableSharedConfig: ptr.To(true), }, }, }, - }, - { - name: "velero with custom metrics address", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + initContainers: []corev1.Container{pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage)}, + volumes: []corev1.Volume{ + { + Name: "bound-sa-token", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + DefaultMode: ptr.To(int32(420)), + Sources: []corev1.VolumeProjection{ + { + ServiceAccountToken: &corev1.ServiceAccountTokenProjection{ + Audience: "openshift", + ExpirationSeconds: ptr.To(int64(3600)), + Path: "token", + }, + }, + }, + }, + }, + }, }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + volumeMounts: []corev1.VolumeMount{ + {Name: "bound-sa-token", MountPath: "/var/run/secrets/openshift/serviceaccount", ReadOnly: true}, }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with aws plugin and BSL, Velero Deployment is built with aws plugin", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ - Args: &server.Args{ - ServerConfig: server.ServerConfig{ - MetricsAddress: ":" + strconv.Itoa(int(argsMetricsPortTest)), - }, + DefaultPlugins: []oadpv1alpha1.DefaultPlugin{ + oadpv1alpha1.DefaultPluginAWS, }, }, }, - }, - }, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: veleroDeploymentMatchLabels, - Annotations: common.AppendTTMapAsCopy(veleroPodAnnotations, map[string]string{ - "prometheus.io/port": strconv.Itoa(int(argsMetricsPortTest)), - }), - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: argsMetricsPortTest}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--metrics-address=:" + strconv.Itoa(int(argsMetricsPortTest)), - "--fs-backup-timeout=4h0m0s", - defaultRestoreResourcePriorities, - defaultDisableInformerCache, + BackupLocations: []oadpv1alpha1.BackupLocation{ + { + Velero: &velerov1.BackupStorageLocationSpec{ + Provider: AWSProvider, + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + Bucket: "aws-bucket", + }, + }, + Config: map[string]string{ + Region: "aws-region", + S3URL: "https://sr-url-aws-domain.com", + InsecureSkipTLSVerify: "false", + }, + Credential: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "cloud-credentials", }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, }, }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, }, }, }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + initContainers: []corev1.Container{pluginContainer(common.VeleroPluginForAWS, common.AWSPluginImage)}, + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), }, { - name: "Override restore resource priorities", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", + name: "valid DPA CR with PodDNS Policy/Config, Velero Deployment is built with DNS Policy/Config", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + }, + PodDnsPolicy: "None", + PodDnsConfig: corev1.PodDNSConfig{ + Nameservers: []string{"1.1.1.1", "8.8.8.8"}, + Options: []corev1.PodDNSConfigOption{ + {Name: "ndots", Value: ptr.To("2")}, + {Name: "edns0"}, + }, + }, }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + dnsPolicy: corev1.DNSNone, + dnsConfig: &corev1.PodDNSConfig{ + Nameservers: []string{"1.1.1.1", "8.8.8.8"}, + Options: []corev1.PodDNSConfigOption{ + {Name: "ndots", Value: ptr.To("2")}, + {Name: "edns0"}, + }, }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + }), + }, + { + name: "valid DPA CR with metrics address, Velero Deployment is built with metrics address", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ Args: &server.Args{ ServerConfig: server.ServerConfig{ - RestoreResourcePriorities: "securitycontextconstraints,test", + MetricsAddress: fmt.Sprintf(":%v", argsMetricsPortTest), }, }, }, }, }, - }, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--fs-backup-timeout=4h0m0s", - "--restore-resource-priorities=securitycontextconstraints,test", - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + metricsPort: argsMetricsPortTest, + args: []string{ + fmt.Sprintf("--metrics-address=:%v", argsMetricsPortTest), + "--fs-backup-timeout=4h0m0s", + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), + }, + { + name: "valid DPA CR with restore resource priorities, Velero Deployment is built with restore resource priorities", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + Args: &server.Args{ + ServerConfig: server.ServerConfig{ + RestoreResourcePriorities: "securitycontextconstraints,test", }, }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, }, }, }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + "--fs-backup-timeout=4h0m0s", + "--restore-resource-priorities=securitycontextconstraints,test", + defaultDisableInformerCache, + }, + }), }, { - name: "Check values of time fields in Velero args", - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero time fields, Velero Deployment is built with time fields args", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ Args: &server.Args{ @@ -4506,67 +1632,30 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--backup-sync-period=1ns", - "--default-backup-ttl=1ns", - "--default-item-operation-timeout=1ns", - "--resource-timeout=1ns", - "--default-repo-maintain-frequency=1ns", - "--garbage-collection-frequency=1ns", - "--fs-backup-timeout=1ns", - "--item-operation-sync-frequency=1ns", - defaultRestoreResourcePriorities, - "--store-validation-frequency=1ns", - "--terminating-resource-timeout=1ns", - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + "--backup-sync-period=1ns", + "--default-backup-ttl=1ns", + "--default-item-operation-timeout=1ns", + "--resource-timeout=1ns", + "--default-repo-maintain-frequency=1ns", + "--garbage-collection-frequency=1ns", + "--fs-backup-timeout=1ns", + "--item-operation-sync-frequency=1ns", + defaultRestoreResourcePriorities, + "--store-validation-frequency=1ns", + "--terminating-resource-timeout=1ns", + defaultDisableInformerCache, }, - }, + }), }, { - name: "Override burst and qps", - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero burst and qps, Velero Deployment is built with burst and qps args", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ ClientBurst: ptr.To(123), @@ -4577,70 +1666,24 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - "--uploader-type=kopia", - defaultFileSystemBackupTimeout, - defaultRestoreResourcePriorities, - "--client-burst=123", - "--client-qps=123", - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + "--uploader-type=kopia", + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + "--client-burst=123", + "--client-qps=123", + defaultDisableInformerCache, }, - }, + }), }, { - name: "Conflicting burst and qps", - dpa: &oadpv1alpha1.DataProtectionApplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", - }, - Spec: oadpv1alpha1.DataProtectionApplicationSpec{ + name: "valid DPA CR with Velero Args burst and qps, Velero Deployment is built with burst and qps args", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ Velero: &oadpv1alpha1.VeleroConfig{ ClientBurst: ptr.To(123), @@ -4657,110 +1700,40 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }, }, - }, - veleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - }, - }, - wantVeleroDeployment: &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-velero-deployment", - Namespace: "test-ns", - Labels: veleroDeploymentLabel, - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Deployment", - APIVersion: appsv1.SchemeGroupVersion.String(), - }, - Spec: appsv1.DeploymentSpec{ - Selector: &metav1.LabelSelector{MatchLabels: veleroDeploymentMatchLabels}, - Replicas: ptr.To(int32(1)), - Template: corev1.PodTemplateSpec{ - ObjectMeta: veleroPodObjectMeta, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyAlways, - ServiceAccountName: common.Velero, - Containers: []corev1.Container{ - { - Name: common.Velero, - Image: common.VeleroImage, - ImagePullPolicy: corev1.PullAlways, - Ports: []corev1.ContainerPort{{Name: "metrics", ContainerPort: 8085}}, - Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("128Mi")}}, - Command: []string{"/velero"}, - Args: []string{ - "server", - // should be present... "--uploader-type=kopia", - "--client-burst=321", - "--client-qps=321", - "--fs-backup-timeout=4h0m0s", - defaultRestoreResourcePriorities, - defaultDisableInformerCache, - }, - VolumeMounts: baseVolumeMounts, - Env: baseEnvVars, - }, - }, - Volumes: baseVolumes, - InitContainers: []corev1.Container{}, - }, - }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + args: []string{ + // should be present... "--uploader-type=kopia", + "--client-burst=321", + "--client-qps=321", + "--fs-backup-timeout=4h0m0s", + defaultRestoreResourcePriorities, + defaultDisableInformerCache, }, - }, + }), }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - fakeClient, err := getFakeClientFromObjects(tt.clientObjects...) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + fakeClient, err := getFakeClientFromObjects(test.clientObjects...) if err != nil { t.Errorf("error in creating fake client, likely programmer error") } - r := DPAReconciler{ - Client: fakeClient, - } + r := DPAReconciler{Client: fakeClient} oadpclient.SetClient(fakeClient) - if tt.testProxy { - os.Setenv(proxyEnvKey, proxyEnvValue) - defer os.Unsetenv(proxyEnvKey) - } - if err := r.buildVeleroDeployment(tt.veleroDeployment, tt.dpa); err != nil { - if !tt.wantErr { - t.Errorf("buildVeleroDeployment() error = %v, wantErr %v", err, tt.wantErr) - } - if tt.wantErr && tt.wantVeleroDeployment == nil { - // if we expect an error and we got one, and wantVeleroDeployment is not defined, we don't need to compare further. - t.Skip() - } + if test.testProxy { + t.Setenv(proxyEnvKey, proxyEnvValue) } - if tt.dpa != nil { - setPodTemplateSpecDefaults(&tt.wantVeleroDeployment.Spec.Template) - if len(tt.wantVeleroDeployment.Spec.Template.Spec.Containers) > 0 { - setContainerDefaults(&tt.wantVeleroDeployment.Spec.Template.Spec.Containers[0]) + if err := r.buildVeleroDeployment(test.veleroDeployment, test.dpa); err != nil { + if test.errorMessage != err.Error() { + t.Errorf("buildVeleroDeployment() error = %v, errorMessage %v", err, test.errorMessage) } - if tt.wantVeleroDeployment.Spec.Strategy.Type == "" { - tt.wantVeleroDeployment.Spec.Strategy.Type = appsv1.RollingUpdateDeploymentStrategyType - } - if tt.wantVeleroDeployment.Spec.Strategy.RollingUpdate == nil { - tt.wantVeleroDeployment.Spec.Strategy.RollingUpdate = &appsv1.RollingUpdateDeployment{ - MaxUnavailable: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, - MaxSurge: &intstr.IntOrString{Type: intstr.String, StrVal: "25%"}, - } - } - if tt.wantVeleroDeployment.Spec.RevisionHistoryLimit == nil { - tt.wantVeleroDeployment.Spec.RevisionHistoryLimit = ptr.To(int32(10)) - } - if tt.wantVeleroDeployment.Spec.ProgressDeadlineSeconds == nil { - tt.wantVeleroDeployment.Spec.ProgressDeadlineSeconds = ptr.To(int32(600)) + } else { + if !reflect.DeepEqual(test.wantVeleroDeployment, test.veleroDeployment) { + t.Errorf("expected velero deployment diffs.\nDIFF:%v", cmp.Diff(test.wantVeleroDeployment, test.veleroDeployment)) } } - if !reflect.DeepEqual(tt.wantVeleroDeployment, tt.veleroDeployment) { - t.Errorf("expected velero deployment spec to be \n%#v, got \n%#v\nDIFF:%v", tt.wantVeleroDeployment, tt.veleroDeployment, cmp.Diff(tt.wantVeleroDeployment, tt.veleroDeployment)) - } }) } } @@ -4777,8 +1750,8 @@ func TestDPAReconciler_getVeleroImage(t *testing.T) { name: "given Velero image override, custom Velero image should be returned", DpaCR: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ UnsupportedOverrides: map[oadpv1alpha1.UnsupportedImageKey]string{ @@ -4794,8 +1767,8 @@ func TestDPAReconciler_getVeleroImage(t *testing.T) { name: "given default DPA CR with no env var, default velero image should be returned", DpaCR: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, }, pluginName: common.Velero, @@ -4806,8 +1779,8 @@ func TestDPAReconciler_getVeleroImage(t *testing.T) { name: "given default DPA CR with env var set, image should be built via env vars", DpaCR: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, }, pluginName: common.Velero, @@ -4823,8 +1796,7 @@ func TestDPAReconciler_getVeleroImage(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { for key, value := range tt.setEnvVars { - os.Setenv(key, value) - defer os.Unsetenv(key) + t.Setenv(key, value) } gotImage := getVeleroImage(tt.DpaCR) if gotImage != tt.wantImage { @@ -4879,19 +1851,16 @@ func Test_removeDuplicateValues(t *testing.T) { func Test_validateVeleroPlugins(t *testing.T) { tests := []struct { - name string - dpa *oadpv1alpha1.DataProtectionApplication - secret *corev1.Secret - wantErr bool - want bool + name string + dpa *oadpv1alpha1.DataProtectionApplication + secret *corev1.Secret }{ - { name: "given valid Velero default plugin, default secret gets mounted as volume mounts", dpa: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ @@ -4906,18 +1875,16 @@ func Test_validateVeleroPlugins(t *testing.T) { secret: &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "cloud-credentials", - Namespace: "test-ns", + Namespace: testNamespaceName, }, }, - wantErr: false, - want: true, }, { name: "given valid Velero default plugin that is not a cloud provider, no secrets get mounted", dpa: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ @@ -4929,16 +1896,14 @@ func Test_validateVeleroPlugins(t *testing.T) { }, }, }, - secret: &corev1.Secret{}, - wantErr: false, - want: true, + secret: &corev1.Secret{}, }, { name: "given valid multiple Velero default plugins, default secrets gets mounted for each plugin if applicable", dpa: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ @@ -4954,18 +1919,16 @@ func Test_validateVeleroPlugins(t *testing.T) { secret: &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "cloud-credentials", - Namespace: "test-ns", + Namespace: testNamespaceName, }, }, - wantErr: false, - want: true, }, { name: "given aws default plugin without bsl, the valid plugin check passes", dpa: &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ @@ -4977,9 +1940,7 @@ func Test_validateVeleroPlugins(t *testing.T) { }, }, }, - secret: &corev1.Secret{}, - wantErr: false, - want: true, + secret: &corev1.Secret{}, }, } for _, tt := range tests { @@ -5000,25 +1961,16 @@ func Test_validateVeleroPlugins(t *testing.T) { } t.Run(tt.name, func(t *testing.T) { result, err := r.ValidateVeleroPlugins(r.Log) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateVeleroPlugins() error = %v, wantErr %v", err, tt.wantErr) + if err != nil { + t.Errorf("ValidateVeleroPlugins() error = %v", err) } - if !reflect.DeepEqual(result, tt.want) { - t.Errorf("ValidateVeleroPlugins() = %v, want %v", result, tt.want) + if !reflect.DeepEqual(result, true) { + t.Errorf("ValidateVeleroPlugins() = %v, want %v", result, true) } }) } } -var allDefaultPluginsList = []oadpv1alpha1.DefaultPlugin{ - oadpv1alpha1.DefaultPluginAWS, - oadpv1alpha1.DefaultPluginGCP, - oadpv1alpha1.DefaultPluginMicrosoftAzure, - oadpv1alpha1.DefaultPluginKubeVirt, - oadpv1alpha1.DefaultPluginOpenShift, - oadpv1alpha1.DefaultPluginCSI, -} - func TestDPAReconciler_noDefaultCredentials(t *testing.T) { type args struct { dpa oadpv1alpha1.DataProtectionApplication @@ -5035,8 +1987,8 @@ func TestDPAReconciler_noDefaultCredentials(t *testing.T) { args: args{ dpa: oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ @@ -5061,8 +2013,8 @@ func TestDPAReconciler_noDefaultCredentials(t *testing.T) { args: args{ dpa: oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ @@ -5126,21 +2078,14 @@ func TestDPAReconciler_VeleroDebugEnvironment(t *testing.T) { }, } for _, tt := range tests { - var err error if tt.replicas != nil { - err = os.Setenv(VeleroReplicaOverride, strconv.Itoa(*tt.replicas)) - } else { - err = os.Unsetenv(VeleroReplicaOverride) - } - if err != nil { - t.Errorf("DPAReconciler.VeleroDebugEnvironment failed to set debug override: %v", err) - return + t.Setenv(VeleroReplicaOverride, strconv.Itoa(*tt.replicas)) } dpa := &oadpv1alpha1.DataProtectionApplication{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-Velero-CR", - Namespace: "test-ns", + Name: testDpaName, + Namespace: testNamespaceName, }, Spec: oadpv1alpha1.DataProtectionApplicationSpec{ Configuration: &oadpv1alpha1.ApplicationConfig{ diff --git a/pkg/credentials/credentials.go b/pkg/credentials/credentials.go index f63d19eba7..d00d1c4b66 100644 --- a/pkg/credentials/credentials.go +++ b/pkg/credentials/credentials.go @@ -179,6 +179,7 @@ func AppendCloudProviderVolumes(dpa *oadpv1alpha1.DataProtectionApplication, ds dpa.Spec.UnsupportedOverrides[oadpv1alpha1.OperatorTypeKey] == oadpv1alpha1.OperatorTypeMTC) { // OADP is installed via MTC pluginNeedsCheck, foundProviderPlugin := providerNeedsDefaultCreds[string(plugin)] + // duplication with controllers/validator.go if !foundProviderPlugin && !hasCloudStorage { pluginNeedsCheck = true } @@ -221,21 +222,24 @@ func AppendCloudProviderVolumes(dpa *oadpv1alpha1.DataProtectionApplication, ds } } for _, bslSpec := range dpa.Spec.BackupLocations { - if _, ok := bslSpec.Velero.Config["credentialsFile"]; ok { - if secretName, err := GetSecretNameFromCredentialsFileConfigString(bslSpec.Velero.Config["credentialsFile"]); err == nil { - ds.Spec.Template.Spec.Volumes = append( - ds.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: secretName, - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: secretName, + if bslSpec.Velero != nil { + if _, ok := bslSpec.Velero.Config["credentialsFile"]; ok { + if secretName, err := GetSecretNameFromCredentialsFileConfigString(bslSpec.Velero.Config["credentialsFile"]); err == nil { + ds.Spec.Template.Spec.Volumes = append( + ds.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: secretName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secretName, + }, }, }, - }, - ) + ) + } } } + } return nil } diff --git a/pkg/credentials/credentials_test.go b/pkg/credentials/credentials_test.go index 8cdc5170c1..83d276e2b7 100644 --- a/pkg/credentials/credentials_test.go +++ b/pkg/credentials/credentials_test.go @@ -2,7 +2,6 @@ package credentials import ( "context" - "os" "testing" corev1 "k8s.io/api/core/v1" @@ -361,8 +360,7 @@ func TestCredentials_getPluginImage(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { for key, value := range tt.setEnvVars { - os.Setenv(key, value) - defer os.Unsetenv(key) + t.Setenv(key, value) } gotImage := GetPluginImage(tt.pluginName, tt.dpa) if gotImage != tt.wantImage {