github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/velero/velero.go (about) 1 package velero 2 3 import ( 4 "encoding/json" 5 "fmt" 6 7 "github.com/jenkins-x/jx-logging/pkg/log" 8 "github.com/jenkins-x/jx/v2/pkg/util" 9 "github.com/pkg/errors" 10 apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 "k8s.io/client-go/kubernetes" 13 ) 14 15 type veleroSchedule struct { 16 Metadata veleroScheduleMetadata `json:"metadata"` 17 } 18 19 type veleroScheduleMetadata struct { 20 Name string `json:"name"` 21 } 22 23 type veleroScheduleList struct { 24 Items []veleroSchedule `json:"items"` 25 } 26 27 type veleroBackupMetadata struct { 28 Name string `json:"name"` 29 } 30 31 type veleroBackup struct { 32 Metadata veleroBackupMetadata `json:"metadata"` 33 } 34 35 type veleroBackupList struct { 36 Items []veleroBackup `json:"items"` 37 } 38 39 var ( 40 veleroBackupsResource = "backups.velero.io" 41 veleroSchedulesResource = "schedules.velero.io" 42 ) 43 44 // RestoreFromBackup restores from a named velero backup 45 func RestoreFromBackup(apiClient apiextensionsclientset.Interface, kubeClient kubernetes.Interface, namespace string, backupName string) error { 46 if backupName == "" { 47 return errors.Errorf("") 48 } 49 log.Logger().Infof("Using backup '%s'", backupName) 50 51 args := []string{"create", "restore", "--from-backup", backupName, "--namespace", namespace} 52 cmd := util.Command{ 53 Name: "velero", 54 Args: args, 55 } 56 57 output, err := cmd.RunWithoutRetry() 58 if err != nil { 59 return errors.Wrap(err, fmt.Sprintf("executing '%s %v' command", cmd.Name, cmd.Args)) 60 } 61 62 log.Logger().Infof(output) 63 64 return nil 65 } 66 67 // DoesVeleroBackupScheduleExist checks whether a velero schedule exists 68 func DoesVeleroBackupScheduleExist(apiClient apiextensionsclientset.Interface, namespace string) (bool, error) { 69 70 if doesVeleroSchedulesResourceExist(apiClient) { 71 // kubectl get schedules.velero.io -n velero -o json 72 args := []string{"get", veleroSchedulesResource, "-n", namespace, "-o", "json"} 73 cmd := util.Command{ 74 Name: "kubectl", 75 Args: args, 76 } 77 78 output, err := cmd.RunWithoutRetry() 79 if err != nil { 80 return false, errors.Wrap(err, fmt.Sprintf("executing kubectl get %s command", veleroSchedulesResource)) 81 } 82 83 var veleroShedules veleroScheduleList 84 err = json.Unmarshal([]byte(output), &veleroShedules) 85 if err != nil { 86 return false, errors.Wrap(err, "unmarshalling kubectl response") 87 } 88 89 if len(veleroShedules.Items) > 0 { 90 return true, nil 91 } 92 return false, nil 93 } 94 return false, nil 95 } 96 97 func doesVeleroBackupsResourceExist(apiClient apiextensionsclientset.Interface) bool { 98 listOptions := metav1.ListOptions{ 99 FieldSelector: fmt.Sprintf("metadata.name=%s", veleroBackupsResource), 100 } 101 backupList, err := apiClient.ApiextensionsV1beta1().CustomResourceDefinitions().List(listOptions) 102 if err != nil { 103 return false 104 } 105 106 if len(backupList.Items) > 0 { 107 return true 108 } 109 return false 110 } 111 112 func doesVeleroSchedulesResourceExist(apiClient apiextensionsclientset.Interface) bool { 113 listOptions := metav1.ListOptions{ 114 FieldSelector: fmt.Sprintf("metadata.name=%s", veleroSchedulesResource), 115 } 116 schedulesList, err := apiClient.ApiextensionsV1beta1().CustomResourceDefinitions().List(listOptions) 117 if err != nil { 118 return false 119 } 120 121 if len(schedulesList.Items) > 0 { 122 return true 123 } 124 return false 125 } 126 127 // GetBackupsFromBackupResource returns a list of all velero backups 128 func GetBackupsFromBackupResource(apiClient apiextensionsclientset.Interface, namespace string) ([]string, error) { 129 130 if doesVeleroBackupsResourceExist(apiClient) { 131 // kubectl get backups.velero.io -n velero -o json 132 args := []string{"get", veleroBackupsResource, "-n", namespace, "-o", "json"} 133 cmd := util.Command{ 134 Name: "kubectl", 135 Args: args, 136 } 137 138 output, err := cmd.RunWithoutRetry() 139 if err != nil { 140 return []string{}, errors.Wrap(err, fmt.Sprintf("executing '%s %v' command", cmd.Name, cmd.Args)) 141 } 142 143 var veleroBackups veleroBackupList 144 err = json.Unmarshal([]byte(output), &veleroBackups) 145 if err != nil { 146 return []string{}, errors.Wrap(err, "unmarshalling kubectl response for backups") 147 } 148 149 if len(veleroBackups.Items) > 0 { 150 backups := make([]string, len(veleroBackups.Items)) 151 // there must be a nicer way to do this 152 for index, veleroBackup := range veleroBackups.Items { 153 backups[index] = veleroBackup.Metadata.Name 154 } 155 return backups, nil 156 } 157 return []string{}, nil 158 } 159 return []string{}, nil 160 } 161 162 // GetLatestBackupFromBackupResource returns the latest velero backup name 163 func GetLatestBackupFromBackupResource(apiClient apiextensionsclientset.Interface, namespace string) (string, error) { 164 165 if doesVeleroBackupsResourceExist(apiClient) { 166 167 backups, err := GetBackupsFromBackupResource(apiClient, namespace) 168 if err != nil { 169 return "", errors.Wrap(err, "when attempting to retrieve velero backup list") 170 } 171 172 return backups[len(backups)-1], nil 173 } 174 return "", nil 175 }