From 519fe98e6e7798c3ae14ffd60af6ce2316b126a5 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 12 Jan 2024 09:45:59 +0000 Subject: [PATCH] azureblob: implement --azureblob-delete-snapshots This flag controls what happens when we try to delete a blob with a snapshot. The UI follows the azcopy tool. See: https://forum.rclone.org/t/how-to-delete-undeleted-blobs-on-azure/43911/ --- backend/azureblob/azureblob.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/backend/azureblob/azureblob.go b/backend/azureblob/azureblob.go index 89e308aed..22dc063c9 100644 --- a/backend/azureblob/azureblob.go +++ b/backend/azureblob/azureblob.go @@ -401,6 +401,24 @@ rclone does if you know the container exists already. Help: `If set, do not do HEAD before GET when getting objects.`, Default: false, Advanced: true, + }, { + Name: "delete_snapshots", + Help: `Set to specify how to deal with snapshots on blob deletion.`, + Examples: []fs.OptionExample{ + { + Value: "", + Help: "By default, the delete operation fails if a blob has snapshots", + }, { + Value: string(blob.DeleteSnapshotsOptionTypeInclude), + Help: "Specify 'include' to remove the root blob and all its snapshots", + }, { + Value: string(blob.DeleteSnapshotsOptionTypeOnly), + Help: "Specify 'only' to remove only the snapshots but keep the root blob.", + }, + }, + Default: "", + Exclusive: true, + Advanced: true, }}, }) } @@ -437,6 +455,7 @@ type Options struct { DirectoryMarkers bool `config:"directory_markers"` NoCheckContainer bool `config:"no_check_container"` NoHeadObject bool `config:"no_head_object"` + DeleteSnapshots string `config:"delete_snapshots"` } // Fs represents a remote azure server @@ -2356,9 +2375,10 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op // Remove an object func (o *Object) Remove(ctx context.Context) error { blb := o.getBlobSVC() - //only := blob.DeleteSnapshotsOptionTypeOnly - opt := blob.DeleteOptions{ - //DeleteSnapshots: &only, + opt := blob.DeleteOptions{} + if o.fs.opt.DeleteSnapshots != "" { + action := blob.DeleteSnapshotsOptionType(o.fs.opt.DeleteSnapshots) + opt.DeleteSnapshots = &action } return o.fs.pacer.Call(func() (bool, error) { _, err := blb.Delete(ctx, &opt)