diff --git a/changelogs/unreleased/3073-jenting b/changelogs/unreleased/3073-jenting new file mode 100644 index 0000000000..e3b32b00d0 --- /dev/null +++ b/changelogs/unreleased/3073-jenting @@ -0,0 +1 @@ +feat: add delete sub-command for BSL diff --git a/pkg/cmd/cli/backup/create.go b/pkg/cmd/cli/backup/create.go index d883d6077d..e09fdc5448 100644 --- a/pkg/cmd/cli/backup/create.go +++ b/pkg/cmd/cli/backup/create.go @@ -53,23 +53,23 @@ func NewCreateCommand(f client.Factory, use string) *cobra.Command { cmd.CheckError(o.Validate(c, args, f)) cmd.CheckError(o.Run(c, f)) }, - Example: ` # Create a backup containing all resources. - velero backup create backup1 + Example: ` # Create a backup containing all resources. + velero backup create backup1 - # Create a backup including only the nginx namespace. - velero backup create nginx-backup --include-namespaces nginx + # Create a backup including only the nginx namespace. + velero backup create nginx-backup --include-namespaces nginx - # Create a backup excluding the velero and default namespaces. - velero backup create backup2 --exclude-namespaces velero,default + # Create a backup excluding the velero and default namespaces. + velero backup create backup2 --exclude-namespaces velero,default - # Create a backup based on a schedule named daily-backup. - velero backup create --from-schedule daily-backup + # Create a backup based on a schedule named daily-backup. + velero backup create --from-schedule daily-backup - # View the YAML for a backup that doesn't snapshot volumes, without sending it to the server. - velero backup create backup3 --snapshot-volumes=false -o yaml + # View the YAML for a backup that doesn't snapshot volumes, without sending it to the server. + velero backup create backup3 --snapshot-volumes=false -o yaml - # Wait for a backup to complete before returning from the command. - velero backup create backup4 --wait`, + # Wait for a backup to complete before returning from the command. + velero backup create backup4 --wait`, } o.BindFlags(c.Flags()) diff --git a/pkg/cmd/cli/backup/delete.go b/pkg/cmd/cli/backup/delete.go index 20783d8cd1..a3e816bbcc 100644 --- a/pkg/cmd/cli/backup/delete.go +++ b/pkg/cmd/cli/backup/delete.go @@ -40,21 +40,20 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command { c := &cobra.Command{ Use: fmt.Sprintf("%s [NAMES]", use), Short: "Delete backups", - Example: ` # Delete a backup named "backup-1." + Example: ` # Delete a backup named "backup-1". velero backup delete backup-1 # Delete a backup named "backup-1" without prompting for confirmation. velero backup delete backup-1 --confirm - # Delete backups named "backup-1" and "backup-2." + # Delete backups named "backup-1" and "backup-2". velero backup delete backup-1 backup-2 - # Delete all backups triggered by schedule "schedule-1." + # Delete all backups triggered by schedule "schedule-1". velero backup delete --selector velero.io/schedule-name=schedule-1 # Delete all backups. - velero backup delete --all - `, + velero backup delete --all`, Run: func(c *cobra.Command, args []string) { cmd.CheckError(o.Complete(f, args)) cmd.CheckError(o.Validate(c, f, args)) diff --git a/pkg/cmd/cli/backuplocation/backup_location.go b/pkg/cmd/cli/backuplocation/backup_location.go index 0ed814efe7..5bacfeac68 100644 --- a/pkg/cmd/cli/backuplocation/backup_location.go +++ b/pkg/cmd/cli/backuplocation/backup_location.go @@ -1,5 +1,5 @@ /* -Copyright 2018 the Velero contributors. +Copyright 2020 the Velero contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ func NewCommand(f client.Factory) *cobra.Command { c.AddCommand( NewCreateCommand(f, "create"), + NewDeleteCommand(f, "delete"), NewGetCommand(f, "get"), ) diff --git a/pkg/cmd/cli/backuplocation/delete.go b/pkg/cmd/cli/backuplocation/delete.go new file mode 100644 index 0000000000..eecd08f473 --- /dev/null +++ b/pkg/cmd/cli/backuplocation/delete.go @@ -0,0 +1,126 @@ +/* +Copyright 2020 the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package backuplocation + +import ( + "context" + "fmt" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + kubeerrs "k8s.io/apimachinery/pkg/util/errors" + kbclient "sigs.k8s.io/controller-runtime/pkg/client" + + velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/client" + "github.com/vmware-tanzu/velero/pkg/cmd" + "github.com/vmware-tanzu/velero/pkg/cmd/cli" +) + +// NewDeleteCommand creates and returns a new cobra command for deleting backup-locations. +func NewDeleteCommand(f client.Factory, use string) *cobra.Command { + o := cli.NewDeleteOptions("backup-location") + + c := &cobra.Command{ + Use: fmt.Sprintf("%s [NAMES]", use), + Short: "Delete backup storage locations", + Example: ` # Delete a backup storage location named "backup-location-1". + velero backup-location delete backup-location-1 + + # Delete a backup storage location named "backup-location-1" without prompting for confirmation. + velero backup-location delete backup-location-1 --confirm + + # Delete backup storage locations named "backup-location-1" and "backup-location-2". + velero backup-location delete backup-location-1 backup-location-2 + + # Delete all backup storage locations labelled with "foo=bar". + velero backup-location delete --selector foo=bar + + # Delete all backup storage locations. + velero backup-location delete --all`, + Run: func(c *cobra.Command, args []string) { + cmd.CheckError(o.Complete(f, args)) + cmd.CheckError(o.Validate(c, f, args)) + cmd.CheckError(Run(f, o)) + }, + } + + o.BindFlags(c.Flags()) + return c +} + +// Run performs the delete backup-location operation. +func Run(f client.Factory, o *cli.DeleteOptions) error { + if !o.Confirm && !cli.GetConfirmation() { + // Don't do anything unless we get confirmation + return nil + } + + kbClient, err := f.KubebuilderClient() + cmd.CheckError(err) + + locations := new(velerov1api.BackupStorageLocationList) + var errs []error + switch { + case len(o.Names) > 0: + for _, name := range o.Names { + location := &velerov1api.BackupStorageLocation{} + err = kbClient.Get(context.Background(), kbclient.ObjectKey{ + Namespace: f.Namespace(), + Name: name, + }, location) + if err != nil { + errs = append(errs, errors.WithStack(err)) + continue + } + + locations.Items = append(locations.Items, *location) + } + default: + selector := labels.Everything().String() + if o.Selector.LabelSelector != nil { + selector = o.Selector.String() + } + + err := kbClient.List(context.Background(), locations, &kbclient.ListOptions{ + Namespace: f.Namespace(), + Raw: &metav1.ListOptions{LabelSelector: selector}, + }) + if err != nil { + return errors.WithStack(err) + } + } + + if len(locations.Items) == 0 { + fmt.Println("No backup-locations found") + return nil + } + + // Create a backup-location deletion request for each + for _, location := range locations.Items { + if err := kbClient.Delete(context.Background(), &location, &kbclient.DeleteOptions{}); err != nil { + errs = append(errs, errors.WithStack(err)) + continue + } + fmt.Printf("Backup storage location %q deleted successfully.\n", location.Name) + } + + return kubeerrs.NewAggregate(errs) +} diff --git a/pkg/cmd/cli/backuplocation/get.go b/pkg/cmd/cli/backuplocation/get.go index 422459b40d..823e9c4148 100644 --- a/pkg/cmd/cli/backuplocation/get.go +++ b/pkg/cmd/cli/backuplocation/get.go @@ -20,8 +20,8 @@ import ( "context" "github.com/spf13/cobra" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kbclient "sigs.k8s.io/controller-runtime/pkg/client" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" @@ -57,6 +57,7 @@ func NewGetCommand(f client.Factory, use string) *cobra.Command { } else { err := kbClient.List(context.Background(), locations, &kbclient.ListOptions{ Namespace: f.Namespace(), + Raw: &listOptions, }) cmd.CheckError(err) } diff --git a/pkg/cmd/cli/delete/delete.go b/pkg/cmd/cli/delete/delete.go index a37050caad..1eb910307b 100644 --- a/pkg/cmd/cli/delete/delete.go +++ b/pkg/cmd/cli/delete/delete.go @@ -1,5 +1,5 @@ /* -Copyright 2017 the Velero contributors. +Copyright 2020 the Velero contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/client" "github.com/vmware-tanzu/velero/pkg/cmd/cli/backup" + "github.com/vmware-tanzu/velero/pkg/cmd/cli/backuplocation" "github.com/vmware-tanzu/velero/pkg/cmd/cli/restore" "github.com/vmware-tanzu/velero/pkg/cmd/cli/schedule" ) @@ -35,6 +36,9 @@ func NewCommand(f client.Factory) *cobra.Command { backupCommand := backup.NewDeleteCommand(f, "backup") backupCommand.Aliases = []string{"backups"} + backuplocationCommand := backuplocation.NewDeleteCommand(f, "backup-location") + backuplocationCommand.Aliases = []string{"backup-locations"} + restoreCommand := restore.NewDeleteCommand(f, "restore") restoreCommand.Aliases = []string{"restores"} @@ -43,6 +47,7 @@ func NewCommand(f client.Factory) *cobra.Command { c.AddCommand( backupCommand, + backuplocationCommand, restoreCommand, scheduleCommand, ) diff --git a/pkg/cmd/cli/install/install.go b/pkg/cmd/cli/install/install.go index 1065a1729d..20e34c6c97 100644 --- a/pkg/cmd/cli/install/install.go +++ b/pkg/cmd/cli/install/install.go @@ -216,24 +216,21 @@ Use '--wait' to wait for the Velero Deployment to be ready before proceeding. Use '-o yaml' or '-o json' with '--dry-run' to output all generated resources as text instead of sending the resources to the server. This is useful as a starting point for more customized installations. `, - Example: ` # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket mybucket --secret-file ./gcp-service-account.json + Example: ` # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket mybucket --secret-file ./gcp-service-account.json - # velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.0.0 --bucket backups --secret-file ./aws-iam-creds --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 + # velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.0.0 --bucket backups --secret-file ./aws-iam-creds --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 - # velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.0.0 --bucket backups --secret-file ./aws-iam-creds --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 --use-restic + # velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.0.0 --bucket backups --secret-file ./aws-iam-creds --backup-location-config region=us-east-2 --snapshot-location-config region=us-east-2 --use-restic - # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket gcp-backups --secret-file ./gcp-creds.json --wait + # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket gcp-backups --secret-file ./gcp-creds.json --wait - # velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.0.0 --bucket backups --backup-location-config region=us-west-2 --snapshot-location-config region=us-west-2 --no-secret --pod-annotations iam.amazonaws.com/role=arn:aws:iam:::role/ + # velero install --provider aws --plugins velero/velero-plugin-for-aws:v1.0.0 --bucket backups --backup-location-config region=us-west-2 --snapshot-location-config region=us-west-2 --no-secret --pod-annotations iam.amazonaws.com/role=arn:aws:iam:::role/ - # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket gcp-backups --secret-file ./gcp-creds.json --velero-pod-cpu-request=1000m --velero-pod-cpu-limit=5000m --velero-pod-mem-request=512Mi --velero-pod-mem-limit=1024Mi + # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket gcp-backups --secret-file ./gcp-creds.json --velero-pod-cpu-request=1000m --velero-pod-cpu-limit=5000m --velero-pod-mem-request=512Mi --velero-pod-mem-limit=1024Mi - # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket gcp-backups --secret-file ./gcp-creds.json --restic-pod-cpu-request=1000m --restic-pod-cpu-limit=5000m --restic-pod-mem-request=512Mi --restic-pod-mem-limit=1024Mi + # velero install --provider gcp --plugins velero/velero-plugin-for-gcp:v1.0.0 --bucket gcp-backups --secret-file ./gcp-creds.json --restic-pod-cpu-request=1000m --restic-pod-cpu-limit=5000m --restic-pod-mem-request=512Mi --restic-pod-mem-limit=1024Mi - # velero install --provider azure --plugins velero/velero-plugin-for-microsoft-azure:v1.0.0 --bucket $BLOB_CONTAINER --secret-file ./credentials-velero \ - --backup-location-config resourceGroup=$AZURE_BACKUP_RESOURCE_GROUP,storageAccount=$AZURE_STORAGE_ACCOUNT_ID[,subscriptionId=$AZURE_BACKUP_SUBSCRIPTION_ID] --snapshot-location-config apiTimeout=[,resourceGroup=$AZURE_BACKUP_RESOURCE_GROUP,subscriptionId=$AZURE_BACKUP_SUBSCRIPTION_ID] - - `, + # velero install --provider azure --plugins velero/velero-plugin-for-microsoft-azure:v1.0.0 --bucket $BLOB_CONTAINER --secret-file ./credentials-velero --backup-location-config resourceGroup=$AZURE_BACKUP_RESOURCE_GROUP,storageAccount=$AZURE_STORAGE_ACCOUNT_ID[,subscriptionId=$AZURE_BACKUP_SUBSCRIPTION_ID] --snapshot-location-config apiTimeout=[,resourceGroup=$AZURE_BACKUP_RESOURCE_GROUP,subscriptionId=$AZURE_BACKUP_SUBSCRIPTION_ID]`, Run: func(c *cobra.Command, args []string) { cmd.CheckError(o.Validate(c, args, f)) cmd.CheckError(o.Complete(args, f)) diff --git a/pkg/cmd/cli/restore/create.go b/pkg/cmd/cli/restore/create.go index 487eaa6294..f557322849 100644 --- a/pkg/cmd/cli/restore/create.go +++ b/pkg/cmd/cli/restore/create.go @@ -44,21 +44,20 @@ func NewCreateCommand(f client.Factory, use string) *cobra.Command { c := &cobra.Command{ Use: use + " [RESTORE_NAME] [--from-backup BACKUP_NAME | --from-schedule SCHEDULE_NAME]", Short: "Create a restore", - Example: ` # Create a restore named "restore-1" from backup "backup-1." + Example: ` # Create a restore named "restore-1" from backup "backup-1". velero restore create restore-1 --from-backup backup-1 - # Create a restore with a default name ("backup-1-") from backup "backup-1." + # Create a restore with a default name ("backup-1-") from backup "backup-1". velero restore create --from-backup backup-1 - # Create a restore from the latest successful backup triggered by schedule "schedule-1." + # Create a restore from the latest successful backup triggered by schedule "schedule-1". velero restore create --from-schedule schedule-1 - # Create a restore from the latest successful OR partially-failed backup triggered by schedule "schedule-1." + # Create a restore from the latest successful OR partially-failed backup triggered by schedule "schedule-1". velero restore create --from-schedule schedule-1 --allow-partially-failed # Create a restore for only persistentvolumeclaims and persistentvolumes within a backup. - velero restore create --from-backup backup-2 --include-resources persistentvolumeclaims,persistentvolumes - `, + velero restore create --from-backup backup-2 --include-resources persistentvolumeclaims,persistentvolumes`, Args: cobra.MaximumNArgs(1), Run: func(c *cobra.Command, args []string) { cmd.CheckError(o.Complete(args, f)) diff --git a/pkg/cmd/cli/restore/delete.go b/pkg/cmd/cli/restore/delete.go index 6140c756fe..e0f907f389 100644 --- a/pkg/cmd/cli/restore/delete.go +++ b/pkg/cmd/cli/restore/delete.go @@ -39,21 +39,20 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command { c := &cobra.Command{ Use: fmt.Sprintf("%s [NAMES]", use), Short: "Delete restores", - Example: ` # Delete a restore named "restore-1." - velero restore delete restore-1 + Example: ` # Delete a restore named "restore-1". + velero restore delete restore-1 - # Delete a restore named "restore-1" without prompting for confirmation. - velero restore delete restore-1 --confirm + # Delete a restore named "restore-1" without prompting for confirmation. + velero restore delete restore-1 --confirm - # Delete restores named "restore-1" and "restore-2." - velero restore delete restore-1 restore-2 + # Delete restores named "restore-1" and "restore-2". + velero restore delete restore-1 restore-2 - # Delete all restores labelled with foo=bar." - velero restore delete --selector foo=bar + # Delete all restores labelled with "foo=bar". + velero restore delete --selector foo=bar - # Delete all restores. - velero restore delete --all`, - + # Delete all restores. + velero restore delete --all`, Run: func(c *cobra.Command, args []string) { cmd.CheckError(o.Complete(f, args)) cmd.CheckError(o.Validate(c, f, args)) diff --git a/pkg/cmd/cli/schedule/create.go b/pkg/cmd/cli/schedule/create.go index 8871440473..7604c2c75e 100644 --- a/pkg/cmd/cli/schedule/create.go +++ b/pkg/cmd/cli/schedule/create.go @@ -1,5 +1,5 @@ /* -Copyright 2017 the Velero contributors. +Copyright 2020 the Velero contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -52,18 +52,17 @@ The schedule can also be expressed using "@every " syntax. The duratio can be specified using a combination of seconds (s), minutes (m), and hours (h), for example: "@every 2h30m".`, - Example: ` # Create a backup every 6 hours - velero create schedule NAME --schedule="0 */6 * * *" + Example: ` # Create a backup every 6 hours. + velero create schedule NAME --schedule="0 */6 * * *" - # Create a backup every 6 hours with the @every notation - velero create schedule NAME --schedule="@every 6h" + # Create a backup every 6 hours with the @every notation. + velero create schedule NAME --schedule="@every 6h" - # Create a daily backup of the web namespace - velero create schedule NAME --schedule="@every 24h" --include-namespaces web + # Create a daily backup of the web namespace. + velero create schedule NAME --schedule="@every 24h" --include-namespaces web - # Create a weekly backup, each living for 90 days (2160 hours) - velero create schedule NAME --schedule="@every 168h" --ttl 2160h0m0s - `, + # Create a weekly backup, each living for 90 days (2160 hours). + velero create schedule NAME --schedule="@every 168h" --ttl 2160h0m0s`, Args: cobra.ExactArgs(1), Run: func(c *cobra.Command, args []string) { cmd.CheckError(o.Complete(args, f)) diff --git a/pkg/cmd/cli/schedule/delete.go b/pkg/cmd/cli/schedule/delete.go index 63fd72297a..5776e9d26a 100644 --- a/pkg/cmd/cli/schedule/delete.go +++ b/pkg/cmd/cli/schedule/delete.go @@ -39,21 +39,20 @@ func NewDeleteCommand(f client.Factory, use string) *cobra.Command { c := &cobra.Command{ Use: fmt.Sprintf("%s [NAMES]", use), Short: "Delete schedules", - Example: ` # Delete a schedule named "schedule-1." - velero schedule delete schedule-1 - - # Delete a schedule named "schedule-1" without prompting for confirmation. - velero schedule delete schedule-1 --confirm - - # Delete schedules named "schedule-1" and "schedule-2." - velero schedule delete schedule-1 schedule-2 - - # Delete all schedules labelled with foo=bar." - velero schedule delete --selector foo=bar - - # Delete all schedules. - velero schedule delete --all`, + Example: ` # Delete a schedule named "schedule-1". + velero schedule delete schedule-1 + # Delete a schedule named "schedule-1" without prompting for confirmation. + velero schedule delete schedule-1 --confirm + + # Delete schedules named "schedule-1" and "schedule-2". + velero schedule delete schedule-1 schedule-2 + + # Delete all schedules labelled with "foo=bar". + velero schedule delete --selector foo=bar + + # Delete all schedules. + velero schedule delete --all`, Run: func(c *cobra.Command, args []string) { cmd.CheckError(o.Complete(f, args)) cmd.CheckError(o.Validate(c, f, args))