diff --git a/api/v1alpha1/dataprotectionapplication_types.go b/api/v1alpha1/dataprotectionapplication_types.go index 75aa1e3808..6135c6852d 100644 --- a/api/v1alpha1/dataprotectionapplication_types.go +++ b/api/v1alpha1/dataprotectionapplication_types.go @@ -362,6 +362,9 @@ type PodConfig struct { // env defines the list of environment variables to be supplied to podSpec // +optional Env []corev1.EnvVar `json:"env,omitempty"` + // priorityClassName defines the PriorityClass name to be applied to the pod + // +optional + PriorityClassName string `json:"priorityClassName,omitempty"` } type NodeAgentCommonFields struct { diff --git a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml index 9a57440e1e..8b2b8ba234 100644 --- a/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml +++ b/bundle/manifests/oadp.openshift.io_dataprotectionapplications.yaml @@ -494,6 +494,9 @@ spec: type: string description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object + priorityClassName: + description: priorityClassName defines the PriorityClass name to be applied to the pod + type: string resourceAllocations: description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true @@ -848,6 +851,9 @@ spec: type: string description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object + priorityClassName: + description: priorityClassName defines the PriorityClass name to be applied to the pod + type: string resourceAllocations: description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true @@ -1365,6 +1371,9 @@ spec: type: string description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object + priorityClassName: + description: priorityClassName defines the PriorityClass name to be applied to the pod + type: string resourceAllocations: description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true diff --git a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml index 4e761b3091..656a3bbcfc 100644 --- a/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml +++ b/config/crd/bases/oadp.openshift.io_dataprotectionapplications.yaml @@ -494,6 +494,9 @@ spec: type: string description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object + priorityClassName: + description: priorityClassName defines the PriorityClass name to be applied to the pod + type: string resourceAllocations: description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true @@ -848,6 +851,9 @@ spec: type: string description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object + priorityClassName: + description: priorityClassName defines the PriorityClass name to be applied to the pod + type: string resourceAllocations: description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true @@ -1365,6 +1371,9 @@ spec: type: string description: nodeSelector defines the nodeSelector to be supplied to podSpec type: object + priorityClassName: + description: priorityClassName defines the PriorityClass name to be applied to the pod + type: string resourceAllocations: description: resourceAllocations defines the CPU, Memory and ephemeral-storage resource allocations for the Pod nullable: true diff --git a/internal/controller/nodeagent.go b/internal/controller/nodeagent.go index 843f30ac3f..43998eed87 100644 --- a/internal/controller/nodeagent.go +++ b/internal/controller/nodeagent.go @@ -359,6 +359,12 @@ func (r *DataProtectionApplicationReconciler) buildNodeAgentDaemonset(ds *appsv1 install.WithServiceAccountName(common.Velero), install.WithNodeAgentConfigMap(configMapName), install.WithLabels(map[string]string{NodeAgentCMVersionLabel: configMapGeneration}), + install.WithPriorityClassName(func() string { + if dpa.Spec.Configuration.NodeAgent != nil && dpa.Spec.Configuration.NodeAgent.PodConfig != nil { + return dpa.Spec.Configuration.NodeAgent.PodConfig.PriorityClassName + } + return "" + }()), ) ds.TypeMeta = installDs.TypeMeta var err error diff --git a/internal/controller/nodeagent_test.go b/internal/controller/nodeagent_test.go index 0e08b7b6a6..ba7138c03a 100644 --- a/internal/controller/nodeagent_test.go +++ b/internal/controller/nodeagent_test.go @@ -255,6 +255,7 @@ type TestBuiltNodeAgentDaemonSetOptions struct { toleration []corev1.Toleration nodeSelector map[string]string disableFsBackup *bool + priorityClassName string } func createTestBuiltNodeAgentDaemonSet(options TestBuiltNodeAgentDaemonSetOptions) *appsv1.DaemonSet { @@ -567,6 +568,10 @@ func createTestBuiltNodeAgentDaemonSet(options TestBuiltNodeAgentDaemonSetOption testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].Args = append(testBuiltNodeAgentDaemonSet.Spec.Template.Spec.Containers[0].Args, fmt.Sprintf("--log-format=%s", *options.logFormat)) } + if len(options.priorityClassName) > 0 { + testBuiltNodeAgentDaemonSet.Spec.Template.Spec.PriorityClassName = options.priorityClassName + } + return testBuiltNodeAgentDaemonSet } @@ -706,6 +711,52 @@ func TestDPAReconciler_buildNodeAgentDaemonset(t *testing.T) { annotations: map[string]string{"test-annotation": "awesome annotation"}, }), }, + { + name: "valid DPA CR with PodConfig PriorityClassName, NodeAgent DaemonSet is built with PriorityClassName", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{ + PriorityClassName: "node-agent-critical", + }, + }, + UploaderType: "kopia", + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + priorityClassName: "node-agent-critical", + }), + }, + { + name: "valid DPA CR with PodConfig but no PriorityClassName, NodeAgent DaemonSet is built without PriorityClassName", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{}, + NodeAgent: &oadpv1alpha1.NodeAgentConfig{ + NodeAgentCommonFields: oadpv1alpha1.NodeAgentCommonFields{ + PodConfig: &oadpv1alpha1.PodConfig{}, + }, + UploaderType: "kopia", + }, + }, + }, + ), + clientObjects: []client.Object{testGenericInfrastructure}, + nodeAgentDaemonSet: testNodeAgentDaemonSet.DeepCopy(), + wantNodeAgentDaemonSet: createTestBuiltNodeAgentDaemonSet(TestBuiltNodeAgentDaemonSetOptions{ + priorityClassName: "", + }), + }, { name: "valid DPA CR with DataMoverPrepareTimeout, NodeAgent DaemonSet is built with DataMoverPrepareTimeout", dpa: createTestDpaWith( diff --git a/internal/controller/velero.go b/internal/controller/velero.go index fe8fee1a12..5c62dee6bc 100644 --- a/internal/controller/velero.go +++ b/internal/controller/velero.go @@ -201,6 +201,12 @@ func (r *DataProtectionApplicationReconciler) buildVeleroDeployment(veleroDeploy // our secrets are appended to containers/volumeMounts in credentials.AppendPluginSpecificSpecs function install.WithSecret(false), install.WithServiceAccountName(common.Velero), + install.WithPriorityClassName(func() string { + if dpa.Spec.Configuration.Velero.PodConfig != nil { + return dpa.Spec.Configuration.Velero.PodConfig.PriorityClassName + } + return "" + }()), ) veleroDeploymentName := veleroDeployment.Name diff --git a/internal/controller/velero_test.go b/internal/controller/velero_test.go index 03b7e49141..05eda987a4 100644 --- a/internal/controller/velero_test.go +++ b/internal/controller/velero_test.go @@ -615,22 +615,23 @@ func createTestDpaWith( } 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 - loadAffinity []corev1.NodeSelectorTerm + 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 + loadAffinity []corev1.NodeSelectorTerm + priorityClassName string } func createTestBuiltVeleroDeployment(options TestBuiltVeleroDeploymentOptions) *appsv1.Deployment { @@ -770,6 +771,10 @@ func createTestBuiltVeleroDeployment(options TestBuiltVeleroDeploymentOptions) * testBuiltVeleroDeployment.Spec.Template.Spec.DNSConfig = options.dnsConfig } + if len(options.priorityClassName) > 0 { + testBuiltVeleroDeployment.Spec.Template.Spec.PriorityClassName = options.priorityClassName + } + return testBuiltVeleroDeployment } @@ -1030,6 +1035,52 @@ func TestDPAReconciler_buildVeleroDeployment(t *testing.T) { }, }), }, + { + name: "valid DPA CR with PodConfig PriorityClassName, Velero Deployment is built with PriorityClassName", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + PodConfig: &oadpv1alpha1.PodConfig{ + PriorityClassName: "velero-critical", + }, + }, + }, + }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + priorityClassName: "velero-critical", + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), + }, + { + name: "valid DPA CR with PodConfig but no PriorityClassName, Velero Deployment is built without PriorityClassName", + dpa: createTestDpaWith( + nil, + oadpv1alpha1.DataProtectionApplicationSpec{ + Configuration: &oadpv1alpha1.ApplicationConfig{ + Velero: &oadpv1alpha1.VeleroConfig{ + PodConfig: &oadpv1alpha1.PodConfig{}, + }, + }, + }, + ), + veleroDeployment: testVeleroDeployment.DeepCopy(), + wantVeleroDeployment: createTestBuiltVeleroDeployment(TestBuiltVeleroDeploymentOptions{ + priorityClassName: "", + args: []string{ + defaultFileSystemBackupTimeout, + defaultRestoreResourcePriorities, + defaultDisableInformerCache, + }, + }), + }, { name: "valid DPA CR with noDefaultBackupLocation, all default plugins and unsupportedOverrides operatorType MTC, Velero Deployment is built with secret volumes", dpa: createTestDpaWith(