github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/step/restore/step_restore_from_backup.go (about) 1 package restore 2 3 import ( 4 "fmt" 5 6 apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 7 8 "github.com/jenkins-x/jx-logging/pkg/log" 9 "github.com/jenkins-x/jx/v2/pkg/cmd/helper" 10 "github.com/jenkins-x/jx/v2/pkg/cmd/opts" 11 "github.com/jenkins-x/jx/v2/pkg/cmd/opts/step" 12 "github.com/jenkins-x/jx/v2/pkg/cmd/templates" 13 "github.com/jenkins-x/jx/v2/pkg/kube/velero" 14 "github.com/jenkins-x/jx/v2/pkg/util" 15 "github.com/pkg/errors" 16 "github.com/spf13/cobra" 17 18 "k8s.io/client-go/kubernetes" 19 ) 20 21 // FromBackupOptions contains the command line options 22 type FromBackupOptions struct { 23 *StepRestoreOptions 24 25 Namespace string 26 UseLatestBackup bool 27 } 28 29 var ( 30 restoreFromBackupLong = templates.LongDesc(` 31 Restores the cluster custom data from the a backup. 32 33 `) 34 35 restoreFromBackupExample = templates.Examples(` 36 # executes the step which restores data from a backup 37 jx step restore from-backup 38 `) 39 ) 40 41 // NewCmdStepRestoreFromBackup creates the command 42 func NewCmdStepRestoreFromBackup(commonOpts *opts.CommonOptions) *cobra.Command { 43 options := &FromBackupOptions{ 44 StepRestoreOptions: &StepRestoreOptions{ 45 StepOptions: step.StepOptions{ 46 CommonOptions: commonOpts, 47 }, 48 }, 49 } 50 51 cmd := &cobra.Command{ 52 Use: "from-backup [flags]", 53 Short: "This step attempts a velero restore from a selected velero backup", 54 Long: restoreFromBackupLong, 55 Example: restoreFromBackupExample, 56 Aliases: []string{"from-backups"}, 57 Run: func(cmd *cobra.Command, args []string) { 58 options.Cmd = cmd 59 options.Args = args 60 err := options.Run() 61 helper.CheckErr(err) 62 }, 63 } 64 cmd.Flags().StringVarP(&options.Namespace, "namespace", "", "velero", "The namespace where velero has been installed") 65 cmd.Flags().BoolVarP(&options.UseLatestBackup, "latest", "", false, "This indicates whether to use the latest velero backup as the restore point") 66 return cmd 67 } 68 69 func performVeleroRestore(apiClient apiextensionsclientset.Interface, kubeClient kubernetes.Interface, backupName string, namespace string) error { 70 log.Logger().Infof("Using backup '%s' as the backup to restore", util.ColorInfo(backupName)) 71 err := velero.RestoreFromBackup(apiClient, kubeClient, namespace, backupName) 72 if err != nil { 73 return errors.Wrap(err, fmt.Sprintf("when attempting to restore from '%s' backup", backupName)) 74 } 75 return nil 76 } 77 78 // Run implements this command 79 func (o *FromBackupOptions) Run() error { 80 81 // create the api extensions client 82 apiClient, err := o.ApiExtensionsClient() 83 if err != nil { 84 return errors.Wrap(err, "while creating api extensions client") 85 } 86 87 // create the kubernetes client 88 kubeClient, err := o.KubeClient() 89 if err != nil { 90 return errors.Wrap(err, "while creating kube client") 91 } 92 93 // check if a velero schedule exists 94 scheduleExists, err := velero.DoesVeleroBackupScheduleExist(apiClient, o.Namespace) 95 if err != nil { 96 return errors.Wrap(err, "when trying to check for velero schedules") 97 } 98 99 // However, if a Velero Schedule exists then we should be confident that this is an existing operational cluster 100 // and therefore abort the restore. 101 if scheduleExists { 102 fmt.Println("A velero schedule exists for this cluster") 103 fmt.Println("Aborting restore as it would be dangerous to apply the a backup") 104 fmt.Println("If you expected this command to execute automatically - perhaps the backup schedule apply step comes before this step?") 105 106 return nil 107 } 108 latestBackupName, err := velero.GetLatestBackupFromBackupResource(apiClient, o.Namespace) 109 if err != nil { 110 return errors.Wrap(err, "when trying to get the latest backup") 111 } 112 if o.UseLatestBackup { 113 if latestBackupName == "" { 114 fmt.Println("unable to locate latest backup - it's possible there may not be any yet") 115 return nil 116 } 117 err = performVeleroRestore(apiClient, kubeClient, latestBackupName, o.Namespace) 118 if err != nil { 119 return errors.Wrap(err, fmt.Sprintf("when attempting to automatically restore from '%s' backup", latestBackupName)) 120 } 121 } else { 122 backupNames, err := velero.GetBackupsFromBackupResource(apiClient, o.Namespace) 123 if err != nil { 124 return errors.Wrap(err, "when attempting to retrieve the backups") 125 } 126 if len(backupNames) == 0 { 127 return errors.Errorf("unable to locate backups") 128 } 129 130 selectedBackup, err := util.PickNameWithDefault(backupNames, "Which backup do you want to restore from?: ", latestBackupName, "", o.GetIOFileHandles()) 131 if err != nil { 132 return err 133 } 134 args := []string{selectedBackup} 135 if len(args) == 0 { 136 return fmt.Errorf("No backup chosen") 137 } 138 selectedBackupName := args[0] 139 err = performVeleroRestore(apiClient, kubeClient, selectedBackupName, o.Namespace) 140 if err != nil { 141 return errors.Wrap(err, fmt.Sprintf("when attempting to automatically restore from '%s' backup", selectedBackupName)) 142 } 143 } 144 return nil 145 }