github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/dataprotection/backup.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 dataprotection
    21  
    22  import (
    23  	"fmt"
    24  
    25  	"github.com/spf13/cobra"
    26  	"k8s.io/cli-runtime/pkg/genericiooptions"
    27  	cmdutil "k8s.io/kubectl/pkg/cmd/util"
    28  	"k8s.io/kubectl/pkg/util/templates"
    29  
    30  	"github.com/1aal/kubeblocks/pkg/cli/cmd/cluster"
    31  	"github.com/1aal/kubeblocks/pkg/cli/create"
    32  	"github.com/1aal/kubeblocks/pkg/cli/delete"
    33  	"github.com/1aal/kubeblocks/pkg/cli/list"
    34  	"github.com/1aal/kubeblocks/pkg/cli/printer"
    35  	"github.com/1aal/kubeblocks/pkg/cli/types"
    36  	"github.com/1aal/kubeblocks/pkg/cli/util"
    37  )
    38  
    39  var (
    40  	createBackupExample = templates.Examples(`
    41  		# Create a backup for the cluster, use the default backup policy and volume snapshot backup method
    42  		kbcli dp backup mybackup --cluster mycluster
    43  
    44  		# create a backup with a specified method, run "kbcli cluster desc-backup-policy mycluster" to show supported backup methods
    45  		kbcli dp backup mybackup --cluster mycluster --method mymethod
    46  
    47  		# create a backup with specified backup policy, run "kbcli cluster list-backup-policy mycluster" to show the cluster supported backup policies
    48  		kbcli dp backup mybackup --cluster mycluster --policy mypolicy
    49  
    50  		# create a backup from a parent backup
    51  		kbcli dp backup mybackup --cluster mycluster --parent-backup myparentbackup
    52  	`)
    53  
    54  	deleteBackupExample = templates.Examples(`
    55  		# delete a backup
    56  		kbcli dp delete-backup mybackup
    57  	`)
    58  
    59  	describeBackupExample = templates.Examples(`
    60  		# describe a backup
    61  		kbcli dp describe-backup mybackup
    62  	`)
    63  
    64  	listBackupExample = templates.Examples(`
    65  		# list all backups
    66  		kbcli dp list-backups
    67  
    68  		# list all backups of specified cluster
    69  		kbcli dp list-backups --cluster mycluster
    70  	`)
    71  )
    72  
    73  func newBackupCommand(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
    74  	customOutPut := func(opt *create.CreateOptions) {
    75  		output := fmt.Sprintf("Backup %s created successfully, you can view the progress:", opt.Name)
    76  		printer.PrintLine(output)
    77  		nextLine := fmt.Sprintf("\tkbcli dp list-backups %s -n %s", opt.Name, opt.Namespace)
    78  		printer.PrintLine(nextLine)
    79  	}
    80  
    81  	clusterName := ""
    82  
    83  	o := &cluster.CreateBackupOptions{
    84  		CreateOptions: create.CreateOptions{
    85  			IOStreams:       streams,
    86  			Factory:         f,
    87  			GVR:             types.BackupGVR(),
    88  			CueTemplateName: "backup_template.cue",
    89  			CustomOutPut:    customOutPut,
    90  		},
    91  	}
    92  	o.CreateOptions.Options = o
    93  
    94  	cmd := &cobra.Command{
    95  		Use:     "backup NAME",
    96  		Short:   "Create a backup for the cluster.",
    97  		Example: createBackupExample,
    98  		Run: func(cmd *cobra.Command, args []string) {
    99  			if len(args) > 0 {
   100  				o.BackupName = args[0]
   101  			}
   102  			if clusterName != "" {
   103  				o.Args = []string{clusterName}
   104  			}
   105  			cmdutil.BehaviorOnFatal(printer.FatalWithRedColor)
   106  			cmdutil.CheckErr(o.CompleteBackup())
   107  			cmdutil.CheckErr(o.Validate())
   108  			cmdutil.CheckErr(o.Run())
   109  		},
   110  	}
   111  
   112  	cmd.Flags().StringVar(&o.BackupMethod, "method", "", "Backup methods are defined in backup policy (required), if only one backup method in backup policy, use it as default backup method, if multiple backup methods in backup policy, use method which volume snapshot is true as default backup method")
   113  	cmd.Flags().StringVar(&clusterName, "cluster", "", "Cluster name")
   114  	cmd.Flags().StringVar(&o.BackupPolicy, "policy", "", "Backup policy name, if not specified, use the cluster default backup policy")
   115  	cmd.Flags().StringVar(&o.DeletionPolicy, "deletion-policy", "Delete", "Deletion policy for backup, determine whether the backup content in backup repo will be deleted after the backup is deleted, supported values: [Delete, Retain]")
   116  	cmd.Flags().StringVar(&o.RetentionPeriod, "retention-period", "", "Retention period for backup, supported values: [1y, 1mo, 1d, 1h, 1m] or combine them [1y1mo1d1h1m], if not specified, the backup will not be automatically deleted, you need to manually delete it.")
   117  	cmd.Flags().StringVar(&o.ParentBackupName, "parent-backup", "", "Parent backup name, used for incremental backup")
   118  	util.RegisterClusterCompletionFunc(cmd, f)
   119  	o.RegisterBackupFlagCompletionFunc(cmd, f)
   120  
   121  	return cmd
   122  }
   123  
   124  func newBackupDeleteCommand(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
   125  	o := delete.NewDeleteOptions(f, streams, types.BackupGVR())
   126  	clusterName := ""
   127  	cmd := &cobra.Command{
   128  		Use:               "delete-backup",
   129  		Short:             "Delete a backup.",
   130  		Example:           deleteBackupExample,
   131  		ValidArgsFunction: util.ResourceNameCompletionFunc(f, types.BackupGVR()),
   132  		Run: func(cmd *cobra.Command, args []string) {
   133  			o.Names = args
   134  			cmdutil.BehaviorOnFatal(printer.FatalWithRedColor)
   135  			util.CheckErr(completeForDeleteBackup(o, clusterName))
   136  			util.CheckErr(o.Run())
   137  		},
   138  	}
   139  
   140  	o.AddFlags(cmd)
   141  	cmd.Flags().StringVar(&clusterName, "cluster", "", "The cluster name.")
   142  	util.RegisterClusterCompletionFunc(cmd, f)
   143  
   144  	return cmd
   145  }
   146  
   147  func completeForDeleteBackup(o *delete.DeleteOptions, cluster string) error {
   148  	if o.Force && len(o.Names) == 0 {
   149  		if cluster == "" {
   150  			return fmt.Errorf("must give a backup name or cluster name")
   151  		}
   152  		o.LabelSelector = util.BuildLabelSelectorByNames(o.LabelSelector, []string{cluster})
   153  	}
   154  	return nil
   155  }
   156  
   157  func newBackupDescribeCommand(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
   158  	o := cluster.DescribeBackupOptions{
   159  		Factory:   f,
   160  		IOStreams: streams,
   161  		Gvr:       types.BackupGVR(),
   162  	}
   163  	cmd := &cobra.Command{
   164  		Use:               "describe-backup NAME",
   165  		Short:             "Describe a backup",
   166  		Aliases:           []string{"desc-backup"},
   167  		ValidArgsFunction: util.ResourceNameCompletionFunc(f, types.BackupGVR()),
   168  		Example:           describeBackupExample,
   169  		Run: func(cmd *cobra.Command, args []string) {
   170  			cmdutil.BehaviorOnFatal(printer.FatalWithRedColor)
   171  			util.CheckErr(o.Complete(args))
   172  			util.CheckErr(o.Run())
   173  		},
   174  	}
   175  	return cmd
   176  }
   177  
   178  func newListBackupCommand(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
   179  	o := &cluster.ListBackupOptions{ListOptions: list.NewListOptions(f, streams, types.BackupGVR())}
   180  	clusterName := ""
   181  	cmd := &cobra.Command{
   182  		Use:               "list-backups",
   183  		Short:             "List backups.",
   184  		Aliases:           []string{"ls-backups"},
   185  		Example:           listBackupExample,
   186  		ValidArgsFunction: util.ResourceNameCompletionFunc(f, o.GVR),
   187  		Run: func(cmd *cobra.Command, args []string) {
   188  			if clusterName != "" {
   189  				o.LabelSelector = util.BuildLabelSelectorByNames(o.LabelSelector, []string{clusterName})
   190  			}
   191  			o.Names = args
   192  			cmdutil.BehaviorOnFatal(printer.FatalWithRedColor)
   193  			cmdutil.CheckErr(o.Complete())
   194  			cmdutil.CheckErr(cluster.PrintBackupList(*o))
   195  		},
   196  	}
   197  	o.AddFlags(cmd, true)
   198  	cmd.Flags().StringVar(&clusterName, "cluster", "", "List backups in the specified cluster")
   199  	util.RegisterClusterCompletionFunc(cmd, f)
   200  
   201  	return cmd
   202  }