github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/dataprotection/utils/backuprepo.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package utils 21 22 import ( 23 "fmt" 24 25 corev1 "k8s.io/api/core/v1" 26 27 dpv1alpha1 "github.com/1aal/kubeblocks/apis/dataprotection/v1alpha1" 28 "github.com/1aal/kubeblocks/pkg/constant" 29 dptypes "github.com/1aal/kubeblocks/pkg/dataprotection/types" 30 viper "github.com/1aal/kubeblocks/pkg/viperx" 31 ) 32 33 const ( 34 datasafedImageEnv = "DATASAFED_IMAGE" 35 defaultDatasafedImage = "apecloud/datasafed:latest" 36 datasafedBinMountPath = "/bin/datasafed" 37 datasafedConfigMountPath = "/etc/datasafed" 38 ) 39 40 func InjectDatasafed(podSpec *corev1.PodSpec, repo *dpv1alpha1.BackupRepo, repoVolumeMountPath string, backupPath string) { 41 if repo.AccessByMount() { 42 InjectDatasafedWithPVC(podSpec, repo.Status.BackupPVCName, repoVolumeMountPath, backupPath) 43 } else if repo.AccessByTool() { 44 InjectDatasafedWithConfig(podSpec, repo.Status.ToolConfigSecretName, backupPath) 45 } 46 } 47 48 func InjectDatasafedWithPVC(podSpec *corev1.PodSpec, pvcName string, mountPath string, backupPath string) { 49 volumeName := "dp-backup-data" 50 volume := corev1.Volume{ 51 Name: volumeName, 52 VolumeSource: corev1.VolumeSource{ 53 PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ 54 ClaimName: pvcName, 55 }, 56 }, 57 } 58 volumeMount := corev1.VolumeMount{ 59 Name: volumeName, 60 MountPath: mountPath, 61 } 62 envs := []corev1.EnvVar{ 63 { 64 // force datasafed to use local backend with the path 65 Name: dptypes.DPDatasafedLocalBackendPath, 66 Value: mountPath, 67 }, 68 } 69 injectElements(podSpec, toSlice(volume), toSlice(volumeMount), envs) 70 injectDatasafedInstaller(podSpec) 71 } 72 73 func InjectDatasafedWithConfig(podSpec *corev1.PodSpec, configSecretName string, backupPath string) { 74 volumeName := "dp-datasafed-config" 75 volume := corev1.Volume{ 76 Name: volumeName, 77 VolumeSource: corev1.VolumeSource{ 78 Secret: &corev1.SecretVolumeSource{ 79 SecretName: configSecretName, 80 }, 81 }, 82 } 83 volumeMount := corev1.VolumeMount{ 84 Name: volumeName, 85 ReadOnly: true, 86 MountPath: datasafedConfigMountPath, 87 } 88 injectElements(podSpec, toSlice(volume), toSlice(volumeMount), nil) 89 injectDatasafedInstaller(podSpec) 90 } 91 92 func injectDatasafedInstaller(podSpec *corev1.PodSpec) { 93 sharedVolumeName := "dp-datasafed-bin" 94 sharedVolume := corev1.Volume{ 95 Name: sharedVolumeName, 96 VolumeSource: corev1.VolumeSource{ 97 EmptyDir: &corev1.EmptyDirVolumeSource{}, 98 }, 99 } 100 sharedVolumeMount := corev1.VolumeMount{ 101 Name: sharedVolumeName, 102 MountPath: datasafedBinMountPath, 103 } 104 env := corev1.EnvVar{ 105 Name: dptypes.DPDatasafedBinPath, 106 Value: datasafedBinMountPath, 107 } 108 109 // copy the datasafed binary from the image to the shared volume 110 datasafedImage := viper.GetString(datasafedImageEnv) 111 if datasafedImage == "" { 112 datasafedImage = defaultDatasafedImage 113 } 114 initContainer := corev1.Container{ 115 Name: "dp-copy-datasafed", 116 Image: datasafedImage, 117 ImagePullPolicy: corev1.PullPolicy(viper.GetString(constant.KBImagePullPolicy)), 118 Command: []string{"/bin/sh", "-c", fmt.Sprintf("/scripts/install-datasafed.sh %s", datasafedBinMountPath)}, 119 VolumeMounts: []corev1.VolumeMount{sharedVolumeMount}, 120 } 121 122 podSpec.InitContainers = append(podSpec.InitContainers, initContainer) 123 injectElements(podSpec, toSlice(sharedVolume), toSlice(sharedVolumeMount), toSlice(env)) 124 } 125 126 func injectElements(podSpec *corev1.PodSpec, volumes []corev1.Volume, volumeMounts []corev1.VolumeMount, envs []corev1.EnvVar) { 127 podSpec.Volumes = append(podSpec.Volumes, volumes...) 128 for i := range podSpec.Containers { 129 container := &podSpec.Containers[i] 130 container.VolumeMounts = append(container.VolumeMounts, volumeMounts...) 131 container.Env = append(container.Env, envs...) 132 } 133 } 134 135 func toSlice[T any](s ...T) []T { 136 return s 137 }