Skip to content

Commit

Permalink
feat: backup cmd support more flags (#5448)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengluodb authored Oct 20, 2023
1 parent bade424 commit 30dbeed
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 37 deletions.
17 changes: 13 additions & 4 deletions docs/user_docs/cli/kbcli_cluster_backup.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,29 @@ kbcli cluster backup NAME [flags]
### Examples

```
# Create a backup for the cluster, use the default backup policy and volume snapshot backup method
kbcli cluster backup mycluster
# create a backup with a specified method, run "kbcli cluster desc-backup-policy mycluster" to show supported backup methods
kbcli cluster backup mycluster --method volume-snapshot
# create a backup with specified backup policy, run "kbcli cluster list-backup-policy mycluster" to show the cluster supported backup policies
kbcli cluster backup mycluster --method volume-snapshot --policy <backup-policy-name>
# create a backup from a parent backup
kbcli cluster backup mycluster --parent-backup parent-backup-name
```

### Options

```
-h, --help help for backup
--method string Backup method that defined in backup policy (required)
--name string Backup name
--policy string Backup policy name, this flag will be ignored when backup-type is snapshot
--deletion-policy string Deletion policy for backup, determine whether the backup content in backup repo will be deleted after the backup is deleted, supported values: [Delete, Retain] (default "Delete")
-h, --help help for backup
--method string 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
--name string Backup name
--parent-backup string Parent backup name, used for incremental backup
--policy string Backup policy name, if not specified, use the cluster default backup policy
--retention-period string 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.
```

### Options inherited from parent commands
Expand Down
22 changes: 14 additions & 8 deletions docs/user_docs/cli/kbcli_dataprotection_backup.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,29 @@ kbcli dataprotection backup NAME [flags]
### Examples

```
# Create a backup for the cluster
# Create a backup for the cluster, use the default backup policy and volume snapshot backup method
kbcli dp backup mybackup --cluster mycluster
# create a snapshot backup
kbcli dp backup mybackup --cluster mycluster --method volume-snapshot
# create a backup with a specified method, run "kbcli cluster desc-backup-policy mycluster" to show supported backup methods
kbcli dp backup mybackup --cluster mycluster --method mymethod
# create a backup with specified policy
# create a backup with specified backup policy, run "kbcli cluster list-backup-policy mycluster" to show the cluster supported backup policies
kbcli dp backup mybackup --cluster mycluster --policy mypolicy
# create a backup from a parent backup
kbcli dp backup mybackup --cluster mycluster --parent-backup myparentbackup
```

### Options

```
--cluster string Cluster name
-h, --help help for backup
--method string Backup method (default "volume-snapshot")
--policy string Backup policy name, this flag will be ignored when backup-type is snapshot
--cluster string Cluster name
--deletion-policy string Deletion policy for backup, determine whether the backup content in backup repo will be deleted after the backup is deleted, supported values: [Delete, Retain] (default "Delete")
-h, --help help for backup
--method string 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
--parent-backup string Parent backup name, used for incremental backup
--policy string Backup policy name, if not specified, use the cluster default backup policy
--retention-period string 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.
```

### Options inherited from parent commands
Expand Down
86 changes: 74 additions & 12 deletions pkg/cli/cmd/cluster/dataprotection.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import (
"github.com/apecloud/kubeblocks/pkg/cli/util"
"github.com/apecloud/kubeblocks/pkg/constant"
dptypes "github.com/apecloud/kubeblocks/pkg/dataprotection/types"
"github.com/apecloud/kubeblocks/pkg/dataprotection/utils/boolptr"
)

var (
Expand All @@ -82,11 +83,17 @@ var (
kbcli cluster edit-bp <backup-policy-name>
`)
createBackupExample = templates.Examples(`
# Create a backup for the cluster, use the default backup policy and volume snapshot backup method
kbcli cluster backup mycluster
# create a backup with a specified method, run "kbcli cluster desc-backup-policy mycluster" to show supported backup methods
kbcli cluster backup mycluster --method volume-snapshot
# create a backup with specified backup policy, run "kbcli cluster list-backup-policy mycluster" to show the cluster supported backup policies
kbcli cluster backup mycluster --method volume-snapshot --policy <backup-policy-name>
# create a backup from a parent backup
kbcli cluster backup mycluster --parent-backup parent-backup-name
`)
listBackupExample = templates.Examples(`
# list all backups
Expand Down Expand Up @@ -116,10 +123,12 @@ var (
const annotationTrueValue = "true"

type CreateBackupOptions struct {
BackupMethod string `json:"backupMethod"`
BackupName string `json:"backupName"`
Role string `json:"role,omitempty"`
BackupPolicy string `json:"backupPolicy"`
BackupMethod string `json:"backupMethod"`
BackupName string `json:"backupName"`
BackupPolicy string `json:"backupPolicy"`
DeletionPolicy string `json:"deletionPolicy"`
RetentionPeriod string `json:"retentionPeriod"`
ParentBackupName string `json:"parentBackupName"`

create.CreateOptions `json:"-"`
}
Expand Down Expand Up @@ -158,22 +167,72 @@ func (o *CreateBackupOptions) Validate() error {
if o.Name == "" {
return fmt.Errorf("missing cluster name")
}

// if backup policy is not specified, use the default backup policy
if o.BackupPolicy == "" {
if err := o.completeDefaultBackupPolicy(); err != nil {
return err
}
} else {
// check if backup policy exists
if _, err := o.Dynamic.Resource(types.BackupPolicyGVR()).Namespace(o.Namespace).Get(context.TODO(), o.BackupPolicy, metav1.GetOptions{}); err != nil {
return err
}
}

// check if backup policy exists
backupPolicyObj, err := o.Dynamic.Resource(types.BackupPolicyGVR()).Namespace(o.Namespace).Get(context.TODO(), o.BackupPolicy, metav1.GetOptions{})
if err != nil {
return err
}
backupPolicy := &dpv1alpha1.BackupPolicy{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(backupPolicyObj.Object, backupPolicy); err != nil {
return err
}

if o.BackupMethod == "" {
// TODO(ldm): if backup policy only has one backup method, use it as default
// backup method.
return fmt.Errorf("missing backup method")
// if backup policy don't have any backup method, return error
if len(backupPolicy.Spec.BackupMethods) == 0 {
return fmt.Errorf("missing backup method")
}

// if backup policy has only one backup method, use it as default backup method
if len(backupPolicy.Spec.BackupMethods) == 1 {
o.BackupMethod = backupPolicy.Spec.BackupMethods[0].Name
}

// if backup policy has multiple backup methods, use method which volume snapshot is true as default backup method
for _, method := range backupPolicy.Spec.BackupMethods {
if boolptr.IsSetToTrue(method.SnapshotVolumes) {
o.BackupMethod = method.Name
break
}
}
}
// TODO: check if pvc exists

// valid retention period
if o.RetentionPeriod != "" {
_, err := dpv1alpha1.RetentionPeriod(o.RetentionPeriod).ToDuration()
if err != nil {
return fmt.Errorf("invalid retention period, please refer to examples [1y, 1m, 1d, 1h, 1m] or combine them [1y1m1d1h1m]")
}
}

// check if parent backup exists
if o.ParentBackupName != "" {
parentBackupObj, err := o.Dynamic.Resource(types.BackupGVR()).Namespace(o.Namespace).Get(context.TODO(), o.ParentBackupName, metav1.GetOptions{})
if err != nil {
return err
}
parentBackup := &dpv1alpha1.Backup{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(parentBackupObj.Object, parentBackup); err != nil {
return err
}
if parentBackup.Status.Phase != dpv1alpha1.BackupPhaseCompleted {
return fmt.Errorf("parent backup %s is not completed", o.ParentBackupName)
}
if parentBackup.Labels[constant.AppInstanceLabelKey] != o.Name {
return fmt.Errorf("parent backup %s is not belong to cluster %s", o.ParentBackupName, o.Name)
}
}
return nil
}

Expand Down Expand Up @@ -255,9 +314,12 @@ func NewCreateBackupCmd(f cmdutil.Factory, streams genericiooptions.IOStreams) *
},
}

cmd.Flags().StringVar(&o.BackupMethod, "method", "", "Backup method that defined in backup policy (required)")
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")
cmd.Flags().StringVar(&o.BackupName, "name", "", "Backup name")
cmd.Flags().StringVar(&o.BackupPolicy, "policy", "", "Backup policy name, this flag will be ignored when backup-type is snapshot")
cmd.Flags().StringVar(&o.BackupPolicy, "policy", "", "Backup policy name, if not specified, use the cluster default backup policy")
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]")
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.")
cmd.Flags().StringVar(&o.ParentBackupName, "parent-backup", "", "Parent backup name, used for incremental backup")

return cmd
}
Expand Down
13 changes: 6 additions & 7 deletions pkg/cli/cmd/cluster/dataprotection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,15 @@ var _ = Describe("DataProtection", func() {

It("run backup command", func() {
defaultBackupPolicy := testing.FakeBackupPolicy(policyName, testing.ClusterName)
initClient(defaultBackupPolicy)
By("test with specified backupPolicy")
otherBackupPolicy := testing.FakeBackupPolicy("otherPolicy", testing.ClusterName)
otherBackupPolicy.Annotations = map[string]string{}
initClient(defaultBackupPolicy, otherBackupPolicy)
By("test backup with default backupPolicy")
cmd := NewCreateBackupCmd(tf, streams)
Expect(cmd).ShouldNot(BeNil())
// must succeed otherwise exit 1 and make test fails
_ = cmd.Flags().Set("policy", defaultBackupPolicy.Name)
_ = cmd.Flags().Set("method", testing.BackupMethodName)
cmd.Run(cmd, []string{testing.ClusterName})

By("test with logfile type")
By("test with specified backupMethod and backupPolicy")
o := &CreateBackupOptions{
CreateOptions: create.CreateOptions{
IOStreams: streams,
Expand All @@ -182,7 +181,7 @@ var _ = Describe("DataProtection", func() {
CueTemplateName: "backup_template.cue",
Name: testing.ClusterName,
},
BackupPolicy: defaultBackupPolicy.Name,
BackupPolicy: otherBackupPolicy.Name,
BackupMethod: testing.BackupMethodName,
}
Expect(o.CompleteBackup()).Should(Succeed())
Expand Down
18 changes: 12 additions & 6 deletions pkg/cli/cmd/dataprotection/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@ import (

var (
createBackupExample = templates.Examples(`
# Create a backup for the cluster
# Create a backup for the cluster, use the default backup policy and volume snapshot backup method
kbcli dp backup mybackup --cluster mycluster
# create a snapshot backup
kbcli dp backup mybackup --cluster mycluster --method volume-snapshot
# create a backup with a specified method, run "kbcli cluster desc-backup-policy mycluster" to show supported backup methods
kbcli dp backup mybackup --cluster mycluster --method mymethod
# create a backup with specified policy
# create a backup with specified backup policy, run "kbcli cluster list-backup-policy mycluster" to show the cluster supported backup policies
kbcli dp backup mybackup --cluster mycluster --policy mypolicy
# create a backup from a parent backup
kbcli dp backup mybackup --cluster mycluster --parent-backup myparentbackup
`)

deleteBackupExample = templates.Examples(`
Expand Down Expand Up @@ -110,9 +113,12 @@ func newBackupCommand(f cmdutil.Factory, streams genericiooptions.IOStreams) *co
},
}

cmd.Flags().StringVar(&o.BackupMethod, "method", "volume-snapshot", "Backup method")
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")
cmd.Flags().StringVar(&clusterName, "cluster", "", "Cluster name")
cmd.Flags().StringVar(&o.BackupPolicy, "policy", "", "Backup policy name, this flag will be ignored when backup-type is snapshot")
cmd.Flags().StringVar(&o.BackupPolicy, "policy", "", "Backup policy name, if not specified, use the cluster default backup policy")
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]")
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.")
cmd.Flags().StringVar(&o.ParentBackupName, "parent-backup", "", "Parent backup name, used for incremental backup")
util.RegisterClusterCompletionFunc(cmd, f)
registerBackupFlagCompletionFunc(cmd, f)

Expand Down
12 changes: 12 additions & 0 deletions pkg/cli/create/template/backup_template.cue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ options: {
namespace: string
backupMethod: string
backupPolicy: string
deletionPolicy: string
retentionPeriod: string
parentBackupName: string
}

// required, k8s api resource content
Expand All @@ -37,5 +40,14 @@ content: {
spec: {
backupMethod: options.backupMethod
backupPolicyName: options.backupPolicy
if options.deletionPolicy != "" {
deletionPolicy: options.deletionPolicy
}
if options.retentionPeriod != "" {
retentionPeriod: options.retentionPeriod
}
if options.parentBackupName != "" {
parentBackupName: options.parentBackupName
}
}
}

0 comments on commit 30dbeed

Please sign in to comment.