add bulk deletion support to ark backup delete
Signed-off-by: Steve Kriss <steve@heptio.com>pull/745/head
parent
1f7a4a1665
commit
5acccaa739
|
@ -31,7 +31,7 @@ Work with backups
|
|||
### SEE ALSO
|
||||
* [ark](ark.md) - Back up and restore Kubernetes cluster resources.
|
||||
* [ark backup create](ark_backup_create.md) - Create a backup
|
||||
* [ark backup delete](ark_backup_delete.md) - Delete a backup
|
||||
* [ark backup delete](ark_backup_delete.md) - Delete backups
|
||||
* [ark backup describe](ark_backup_describe.md) - Describe backups
|
||||
* [ark backup download](ark_backup_download.md) - Download a backup
|
||||
* [ark backup get](ark_backup_get.md) - Get backups
|
||||
|
|
|
@ -1,21 +1,43 @@
|
|||
## ark backup delete
|
||||
|
||||
Delete a backup
|
||||
Delete backups
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Delete a backup
|
||||
Delete backups
|
||||
|
||||
```
|
||||
ark backup delete NAME [flags]
|
||||
ark backup delete [NAMES] [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# delete a backup named "backup-1"
|
||||
ark backup delete backup-1
|
||||
|
||||
# delete a backup named "backup-1" without prompting for confirmation
|
||||
ark backup delete backup-1 --confirm
|
||||
|
||||
# delete backups named "backup-1" and "backup-2"
|
||||
ark backup delete backup-1 backup-2
|
||||
|
||||
# delete all backups triggered by schedule "schedule-1"
|
||||
ark backup delete --selector ark-schedule=schedule-1
|
||||
|
||||
# delete all backups
|
||||
ark backup delete --all
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--confirm Confirm deletion
|
||||
-h, --help help for delete
|
||||
--all Delete all backups
|
||||
--confirm Confirm deletion
|
||||
-h, --help help for delete
|
||||
-l, --selector labelSelector Delete all backups matching this label selector (default <none>)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
|
|
@ -30,7 +30,7 @@ Delete ark resources
|
|||
|
||||
### SEE ALSO
|
||||
* [ark](ark.md) - Back up and restore Kubernetes cluster resources.
|
||||
* [ark delete backup](ark_delete_backup.md) - Delete a backup
|
||||
* [ark delete backup](ark_delete_backup.md) - Delete backups
|
||||
* [ark delete restore](ark_delete_restore.md) - Delete a restore
|
||||
* [ark delete schedule](ark_delete_schedule.md) - Delete a schedule
|
||||
|
||||
|
|
|
@ -1,21 +1,43 @@
|
|||
## ark delete backup
|
||||
|
||||
Delete a backup
|
||||
Delete backups
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Delete a backup
|
||||
Delete backups
|
||||
|
||||
```
|
||||
ark delete backup NAME [flags]
|
||||
ark delete backup [NAMES] [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# delete a backup named "backup-1"
|
||||
ark backup delete backup-1
|
||||
|
||||
# delete a backup named "backup-1" without prompting for confirmation
|
||||
ark backup delete backup-1 --confirm
|
||||
|
||||
# delete backups named "backup-1" and "backup-2"
|
||||
ark backup delete backup-1 backup-2
|
||||
|
||||
# delete all backups triggered by schedule "schedule-1"
|
||||
ark backup delete --selector ark-schedule=schedule-1
|
||||
|
||||
# delete all backups
|
||||
ark backup delete --all
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--confirm Confirm deletion
|
||||
-h, --help help for backup
|
||||
--all Delete all backups
|
||||
--confirm Confirm deletion
|
||||
-h, --help help for backup
|
||||
-l, --selector labelSelector Delete all backups matching this label selector (default <none>)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
|
|
@ -18,20 +18,24 @@ package backup
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
"github.com/heptio/ark/pkg/backup"
|
||||
clientset "github.com/heptio/ark/pkg/generated/clientset/versioned"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
kubeerrs "k8s.io/apimachinery/pkg/util/errors"
|
||||
|
||||
arkv1api "github.com/heptio/ark/pkg/apis/ark/v1"
|
||||
"github.com/heptio/ark/pkg/backup"
|
||||
"github.com/heptio/ark/pkg/client"
|
||||
"github.com/heptio/ark/pkg/cmd"
|
||||
"github.com/heptio/ark/pkg/cmd/util/flag"
|
||||
clientset "github.com/heptio/ark/pkg/generated/clientset/versioned"
|
||||
)
|
||||
|
||||
// NewDeleteCommand creates a new command that deletes a backup.
|
||||
|
@ -39,9 +43,23 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command {
|
|||
o := &DeleteOptions{}
|
||||
|
||||
c := &cobra.Command{
|
||||
Use: fmt.Sprintf("%s NAME", use),
|
||||
Short: "Delete a backup",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Use: fmt.Sprintf("%s [NAMES]", use),
|
||||
Short: "Delete backups",
|
||||
Example: ` # delete a backup named "backup-1"
|
||||
ark backup delete backup-1
|
||||
|
||||
# delete a backup named "backup-1" without prompting for confirmation
|
||||
ark backup delete backup-1 --confirm
|
||||
|
||||
# delete backups named "backup-1" and "backup-2"
|
||||
ark backup delete backup-1 backup-2
|
||||
|
||||
# delete all backups triggered by schedule "schedule-1"
|
||||
ark backup delete --selector ark-schedule=schedule-1
|
||||
|
||||
# delete all backups
|
||||
ark backup delete --all
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
cmd.CheckError(o.Complete(f, args))
|
||||
cmd.CheckError(o.Validate(c, args, f))
|
||||
|
@ -56,23 +74,24 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command {
|
|||
|
||||
// DeleteOptions contains parameters for deleting a backup.
|
||||
type DeleteOptions struct {
|
||||
Name string
|
||||
Confirm bool
|
||||
Names []string
|
||||
All bool
|
||||
Selector flag.LabelSelector
|
||||
Confirm bool
|
||||
|
||||
client clientset.Interface
|
||||
namespace string
|
||||
backup *v1.Backup
|
||||
}
|
||||
|
||||
// BindFlags binds options for this command to flags.
|
||||
func (o *DeleteOptions) BindFlags(flags *pflag.FlagSet) {
|
||||
flags.BoolVar(&o.Confirm, "confirm", o.Confirm, "Confirm deletion")
|
||||
flags.BoolVar(&o.All, "all", o.All, "Delete all backups")
|
||||
flags.VarP(&o.Selector, "selector", "l", "Delete all backups matching this label selector")
|
||||
}
|
||||
|
||||
// Complete fills out the remainder of the parameters based on user input.
|
||||
func (o *DeleteOptions) Complete(f client.Factory, args []string) error {
|
||||
o.Name = args[0]
|
||||
|
||||
o.namespace = f.Namespace()
|
||||
|
||||
client, err := f.Client()
|
||||
|
@ -81,11 +100,7 @@ func (o *DeleteOptions) Complete(f client.Factory, args []string) error {
|
|||
}
|
||||
o.client = client
|
||||
|
||||
backup, err := o.client.ArkV1().Backups(f.Namespace()).Get(o.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.backup = backup
|
||||
o.Names = args
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -96,13 +111,34 @@ func (o *DeleteOptions) Validate(c *cobra.Command, args []string, f client.Facto
|
|||
return errors.New("Ark client is not set; unable to proceed")
|
||||
}
|
||||
|
||||
if o.backup == nil {
|
||||
return errors.New("backup is not set; unable to proceed")
|
||||
var (
|
||||
hasNames = len(o.Names) > 0
|
||||
hasAll = o.All
|
||||
hasSelector = o.Selector.LabelSelector != nil
|
||||
)
|
||||
|
||||
if !xor(hasNames, hasAll, hasSelector) {
|
||||
return errors.New("you must specify exactly one of: specific backup name(s), the --all flag, or the --selector flag")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// xor returns true if exactly one of the provided values is true,
|
||||
// or false otherwise.
|
||||
func xor(val bool, vals ...bool) bool {
|
||||
res := val
|
||||
|
||||
for _, v := range vals {
|
||||
if res && v {
|
||||
return false
|
||||
}
|
||||
res = res || v
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Run performs the delete backup operation.
|
||||
func (o *DeleteOptions) Run() error {
|
||||
if !o.Confirm && !getConfirmation() {
|
||||
|
@ -110,14 +146,56 @@ func (o *DeleteOptions) Run() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
deleteRequest := backup.NewDeleteBackupRequest(o.backup.Name, string(o.backup.UID))
|
||||
var (
|
||||
backups []*arkv1api.Backup
|
||||
errs []error
|
||||
)
|
||||
|
||||
if _, err := o.client.ArkV1().DeleteBackupRequests(o.namespace).Create(deleteRequest); err != nil {
|
||||
return err
|
||||
// get the list of backups to delete
|
||||
switch {
|
||||
case len(o.Names) > 0:
|
||||
for _, name := range o.Names {
|
||||
backup, err := o.client.ArkV1().Backups(o.namespace).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
errs = append(errs, errors.WithStack(err))
|
||||
continue
|
||||
}
|
||||
|
||||
backups = append(backups, backup)
|
||||
}
|
||||
default:
|
||||
selector := labels.Everything().String()
|
||||
if o.Selector.LabelSelector != nil {
|
||||
selector = o.Selector.String()
|
||||
}
|
||||
|
||||
res, err := o.client.ArkV1().Backups(o.namespace).List(metav1.ListOptions{LabelSelector: selector})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
for i := range res.Items {
|
||||
backups = append(backups, &res.Items[i])
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Request to delete backup %q submitted successfully.\nThe backup will be fully deleted after all associated data (disk snapshots, backup files, restores) are removed.\n", o.backup.Name)
|
||||
return nil
|
||||
if len(backups) == 0 {
|
||||
fmt.Println("No backups found")
|
||||
return nil
|
||||
}
|
||||
|
||||
// create a backup deletion request for each
|
||||
for _, b := range backups {
|
||||
deleteRequest := backup.NewDeleteBackupRequest(b.Name, string(b.UID))
|
||||
|
||||
if _, err := o.client.ArkV1().DeleteBackupRequests(o.namespace).Create(deleteRequest); err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("Request to delete backup %q submitted successfully.\nThe backup will be fully deleted after all associated data (disk snapshots, backup files, restores) are removed.\n", b.Name)
|
||||
}
|
||||
|
||||
return kubeerrs.NewAggregate(errs)
|
||||
}
|
||||
|
||||
func getConfirmation() bool {
|
||||
|
|
Loading…
Reference in New Issue