diff --git a/changelogs/unreleased/8343-evhan b/changelogs/unreleased/8343-evhan new file mode 100644 index 0000000000..6831f9b4a3 --- /dev/null +++ b/changelogs/unreleased/8343-evhan @@ -0,0 +1 @@ +Copy "envFrom" from Velero server when creating maintenance jobs diff --git a/pkg/exposer/csi_snapshot.go b/pkg/exposer/csi_snapshot.go index 59aabf59e0..bb421a794a 100644 --- a/pkg/exposer/csi_snapshot.go +++ b/pkg/exposer/csi_snapshot.go @@ -553,6 +553,7 @@ func (e *csiSnapshotExposer) createBackupPod( VolumeMounts: volumeMounts, VolumeDevices: volumeDevices, Env: podInfo.env, + EnvFrom: podInfo.envFrom, Resources: resources, }, }, diff --git a/pkg/exposer/generic_restore.go b/pkg/exposer/generic_restore.go index d498470a77..975981d49a 100644 --- a/pkg/exposer/generic_restore.go +++ b/pkg/exposer/generic_restore.go @@ -370,6 +370,7 @@ func (e *genericRestoreExposer) createRestorePod(ctx context.Context, ownerObjec VolumeMounts: volumeMounts, VolumeDevices: volumeDevices, Env: podInfo.env, + EnvFrom: podInfo.envFrom, Resources: resources, }, }, diff --git a/pkg/exposer/image.go b/pkg/exposer/image.go index 8091e12bd4..daf6c1adc0 100644 --- a/pkg/exposer/image.go +++ b/pkg/exposer/image.go @@ -31,6 +31,7 @@ type inheritedPodInfo struct { image string serviceAccount string env []v1.EnvVar + envFrom []v1.EnvFromSource volumeMounts []v1.VolumeMount volumes []v1.Volume logLevelArgs []string @@ -53,6 +54,7 @@ func getInheritedPodInfo(ctx context.Context, client kubernetes.Interface, veler podInfo.serviceAccount = podSpec.ServiceAccountName podInfo.env = podSpec.Containers[0].Env + podInfo.envFrom = podSpec.Containers[0].EnvFrom podInfo.volumeMounts = podSpec.Containers[0].VolumeMounts podInfo.volumes = podSpec.Volumes diff --git a/pkg/exposer/image_test.go b/pkg/exposer/image_test.go index b9aaf51ebc..1a2e038f0d 100644 --- a/pkg/exposer/image_test.go +++ b/pkg/exposer/image_test.go @@ -67,6 +67,22 @@ func TestGetInheritedPodInfo(t *testing.T) { Value: "value-2", }, }, + EnvFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-configmap", + }, + }, + }, + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-secret", + }, + }, + }, + }, VolumeMounts: []v1.VolumeMount{ { Name: "volume-1", @@ -116,6 +132,22 @@ func TestGetInheritedPodInfo(t *testing.T) { Value: "value-2", }, }, + EnvFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-configmap", + }, + }, + }, + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-secret", + }, + }, + }, + }, VolumeMounts: []v1.VolumeMount{ { Name: "volume-1", @@ -191,6 +223,22 @@ func TestGetInheritedPodInfo(t *testing.T) { Value: "value-2", }, }, + envFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-configmap", + }, + }, + }, + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-secret", + }, + }, + }, + }, volumeMounts: []v1.VolumeMount{ { Name: "volume-1", @@ -228,6 +276,22 @@ func TestGetInheritedPodInfo(t *testing.T) { Value: "value-2", }, }, + envFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-configmap", + }, + }, + }, + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-secret", + }, + }, + }, + }, volumeMounts: []v1.VolumeMount{ { Name: "volume-1", diff --git a/pkg/repository/manager/manager.go b/pkg/repository/manager/manager.go index a80d20c583..f590f2b145 100644 --- a/pkg/repository/manager/manager.go +++ b/pkg/repository/manager/manager.go @@ -368,6 +368,9 @@ func (m *manager) buildMaintenanceJob( // Get the environment variables from the Velero server deployment envVars := veleroutil.GetEnvVarsFromVeleroServer(deployment) + // Get the referenced storage from the Velero server deployment + envFromSources := veleroutil.GetEnvFromSourcesFromVeleroServer(deployment) + // Get the volume mounts from the Velero server deployment volumeMounts := veleroutil.GetVolumeMountsFromVeleroServer(deployment) @@ -433,6 +436,7 @@ func (m *manager) buildMaintenanceJob( Args: args, ImagePullPolicy: v1.PullIfNotPresent, Env: envVars, + EnvFrom: envFromSources, VolumeMounts: volumeMounts, Resources: resources, }, diff --git a/pkg/repository/manager/manager_test.go b/pkg/repository/manager/manager_test.go index 0a798120ba..e83f5f5276 100644 --- a/pkg/repository/manager/manager_test.go +++ b/pkg/repository/manager/manager_test.go @@ -70,6 +70,8 @@ func TestBuildMaintenanceJob(t *testing.T) { logFormat *logging.FormatFlag expectedJobName string expectedError bool + expectedEnv []v1.EnvVar + expectedEnvFrom []v1.EnvFromSource }{ { name: "Valid maintenance job", @@ -93,6 +95,28 @@ func TestBuildMaintenanceJob(t *testing.T) { { Name: "velero-repo-maintenance-container", Image: "velero-image", + Env: []v1.EnvVar{ + { + Name: "test-name", + Value: "test-value", + }, + }, + EnvFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-configmap", + }, + }, + }, + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-secret", + }, + }, + }, + }, }, }, }, @@ -103,6 +127,28 @@ func TestBuildMaintenanceJob(t *testing.T) { logFormat: logging.NewFormatFlag(), expectedJobName: "test-123-maintain-job", expectedError: false, + expectedEnv: []v1.EnvVar{ + { + Name: "test-name", + Value: "test-value", + }, + }, + expectedEnvFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-configmap", + }, + }, + }, + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "test-secret", + }, + }, + }, + }, }, { name: "Error getting Velero server deployment", @@ -191,6 +237,10 @@ func TestBuildMaintenanceJob(t *testing.T) { assert.Equal(t, "velero-image", container.Image) assert.Equal(t, v1.PullIfNotPresent, container.ImagePullPolicy) + // Check container env + assert.Equal(t, tc.expectedEnv, container.Env) + assert.Equal(t, tc.expectedEnvFrom, container.EnvFrom) + // Check resources expectedResources := v1.ResourceRequirements{ Requests: v1.ResourceList{ diff --git a/pkg/util/velero/velero.go b/pkg/util/velero/velero.go index bc52253365..79d74422f4 100644 --- a/pkg/util/velero/velero.go +++ b/pkg/util/velero/velero.go @@ -45,6 +45,15 @@ func GetEnvVarsFromVeleroServer(deployment *appsv1.Deployment) []v1.EnvVar { return nil } +// GetEnvFromSourcesFromVeleroServer get the environment sources from the Velero server deployment +func GetEnvFromSourcesFromVeleroServer(deployment *appsv1.Deployment) []v1.EnvFromSource { + for _, container := range deployment.Spec.Template.Spec.Containers { + // We only have one container in the Velero server deployment + return container.EnvFrom + } + return nil +} + // GetVolumeMountsFromVeleroServer get the volume mounts from the Velero server deployment func GetVolumeMountsFromVeleroServer(deployment *appsv1.Deployment) []v1.VolumeMount { for _, container := range deployment.Spec.Template.Spec.Containers { diff --git a/pkg/util/velero/velero_test.go b/pkg/util/velero/velero_test.go index b03a393f56..cdb797ab59 100644 --- a/pkg/util/velero/velero_test.go +++ b/pkg/util/velero/velero_test.go @@ -312,6 +312,105 @@ func TestGetEnvVarsFromVeleroServer(t *testing.T) { } } +func TestGetEnvFromSourcesFromVeleroServer(t *testing.T) { + tests := []struct { + name string + deploy *appsv1.Deployment + expected []v1.EnvFromSource + }{ + { + name: "no env vars", + deploy: &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + EnvFrom: []v1.EnvFromSource{}, + }, + }, + }, + }, + }, + }, + expected: []v1.EnvFromSource{}, + }, + { + name: "configmap", + deploy: &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + EnvFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "foo", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + expected: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "foo", + }, + }, + }, + }, + }, + { + name: "secret", + deploy: &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + EnvFrom: []v1.EnvFromSource{ + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "foo", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + expected: []v1.EnvFromSource{ + { + SecretRef: &v1.SecretEnvSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "foo", + }, + }, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := GetEnvFromSourcesFromVeleroServer(test.deploy) + assert.Equal(t, test.expected, result) + }) + } +} + func TestGetVolumeMountsFromVeleroServer(t *testing.T) { tests := []struct { name string